Mon Oct 8 12:39:27 2012

Asterisk developer's documentation


res_crypto.c File Reference

Provide Cryptographic Signature capability. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/aes.h>
#include <dirent.h>
#include "asterisk/module.h"
#include "asterisk/md5.h"
#include "asterisk/cli.h"
#include "asterisk/io.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/crypto.h"

Go to the source code of this file.

Data Structures

struct  ast_key
struct  keys

Defines

#define AST_API_MODULE
#define FORMAT   "%-18s %-8s %-16s %-33s\n"
#define KEY_NEEDS_PASSCODE   (1 << 16)

Functions

static void __reg_module (void)
static void __unreg_module (void)
void AST_OPTIONAL_API_NAME() ast_aes_decrypt (const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
 AES decrypt data.
void AST_OPTIONAL_API_NAME() ast_aes_encrypt (const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
 AES encrypt data.
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key (const unsigned char *key, ast_aes_decrypt_key *ctx)
 Set a decryption key.
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key (const unsigned char *key, ast_aes_encrypt_key *ctx)
 Set an encryption key.
int AST_OPTIONAL_API_NAME() ast_check_signature (struct ast_key *key, const char *msg, const char *sig)
 Check the authenticity of a message signature using a given public key.
int AST_OPTIONAL_API_NAME() ast_check_signature_bin (struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
 Check the authenticity of a message signature using a given public key.
int AST_OPTIONAL_API_NAME() ast_crypto_loaded (void)
int AST_OPTIONAL_API_NAME() ast_decrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
 Decrypt a message using a given private key.
int AST_OPTIONAL_API_NAME() ast_encrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
 Encrypt a message using a given private key.
ast_key *AST_OPTIONAL_API_NAME() ast_key_get (const char *kname, int ktype)
 Retrieve a key.
int AST_OPTIONAL_API_NAME() ast_sign (struct ast_key *key, char *msg, char *sig)
 Sign a message signature using a given private key.
int AST_OPTIONAL_API_NAME() ast_sign_bin (struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
 Sign a message signature using a given private key.
static int crypto_init (void)
 initialise the res_crypto module
static void crypto_load (int ifd, int ofd)
 refresh RSA keys from file
static char * handle_cli_keys_init (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 initialize all RSA keys
static char * handle_cli_keys_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 show the list of RSA keys
static int load_module (void)
static void md52sum (char *sum, unsigned char *md5)
static int pw_cb (char *buf, int size, int rwflag, void *userdata)
 setting of priv key
static int reload (void)
static struct ast_keytry_load_key (const char *dir, const char *fname, int ifd, int ofd, int *not2)
 load RSA key from file
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Cryptographic Digital Signatures" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_crypto []


Detailed Description

Provide Cryptographic Signature capability.

Author:
Mark Spencer <markster@digium.com>
ExtRef:
Uses the OpenSSL library, available at http://www.openssl.org/

Definition in file res_crypto.c.


Define Documentation

#define AST_API_MODULE

Definition at line 51 of file res_crypto.c.

#define FORMAT   "%-18s %-8s %-16s %-33s\n"

#define KEY_NEEDS_PASSCODE   (1 << 16)

Definition at line 67 of file res_crypto.c.

Referenced by handle_cli_keys_init(), handle_cli_keys_show(), and try_load_key().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 670 of file res_crypto.c.

static void __unreg_module ( void   )  [static]

Definition at line 670 of file res_crypto.c.

void AST_OPTIONAL_API_NAME() ast_aes_decrypt ( const unsigned char *  in,
unsigned char *  out,
const ast_aes_decrypt_key ctx 
)

AES decrypt data.

Parameters:
in encrypted data
out pointer to a buffer to hold the decrypted output
ctx address of an aes encryption context filled in with ast_aes_set_decrypt_key

Definition at line 476 of file res_crypto.c.

Referenced by aes_helper(), decrypt_memcpy(), and memcpy_decrypt().

00477 {
00478    return AES_decrypt(in, out, ctx);
00479 }

void AST_OPTIONAL_API_NAME() ast_aes_encrypt ( const unsigned char *  in,
unsigned char *  out,
const ast_aes_encrypt_key ctx 
)

AES encrypt data.

Parameters:
in data to be encrypted
out pointer to a buffer to hold the encrypted output
ctx address of an aes encryption context filled in with ast_aes_set_encrypt_key

Definition at line 471 of file res_crypto.c.

Referenced by aes_helper(), encrypt_memcpy(), and memcpy_encrypt().

00472 {
00473    return AES_encrypt(in, out, ctx);
00474 }

int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key ( const unsigned char *  key,
ast_aes_decrypt_key ctx 
)

Set a decryption key.

Parameters:
key a 16 char key
ctx address of an aes encryption context
Return values:
0 success
nonzero failure

Definition at line 466 of file res_crypto.c.

Referenced by aes_helper(), build_ecx_key(), build_encryption_keys(), check_key(), socket_process(), and update_key().

00467 {
00468    return AES_set_decrypt_key(key, 128, ctx);
00469 }

int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key ( const unsigned char *  key,
ast_aes_encrypt_key ctx 
)

Set an encryption key.

Parameters:
key a 16 char key
ctx address of an aes encryption context
Return values:
0 success
nonzero failure

Definition at line 461 of file res_crypto.c.

Referenced by aes_helper(), build_ecx_key(), check_key(), and update_key().

00462 {
00463    return AES_set_encrypt_key(key, 128, ctx);
00464 }

int AST_OPTIONAL_API_NAME() ast_check_signature ( struct ast_key key,
const char *  msg,
const char *  sig 
)

Check the authenticity of a message signature using a given public key.

See also:
ast_check_signature

Definition at line 440 of file res_crypto.c.

References ast_base64decode(), ast_check_signature_bin(), ast_log(), and LOG_WARNING.

Referenced by authenticate_verify(), and register_verify().

00441 {
00442    unsigned char dsig[128];
00443    int res;
00444 
00445    /* Decode signature */
00446    if ((res = ast_base64decode(dsig, sig, sizeof(dsig))) != sizeof(dsig)) {
00447       ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res);
00448       return -1;
00449    }
00450 
00451    res = ast_check_signature_bin(key, msg, strlen(msg), dsig);
00452 
00453    return res;
00454 }

int AST_OPTIONAL_API_NAME() ast_check_signature_bin ( struct ast_key key,
const char *  msg,
int  msglen,
const unsigned char *  dsig 
)

Check the authenticity of a message signature using a given public key.

See also:
ast_check_signature_bin

Definition at line 411 of file res_crypto.c.

References ast_debug, AST_KEY_PUBLIC, ast_log(), ast_key::digest, LOG_WARNING, and SHA1.

Referenced by ast_check_signature(), and check_key().

00412 {
00413    unsigned char digest[20];
00414    int res;
00415 
00416    if (key->ktype != AST_KEY_PUBLIC) {
00417       /* Okay, so of course you really *can* but for our purposes
00418          we're going to say you can't */
00419       ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
00420       return -1;
00421    }
00422 
00423    /* Calculate digest of message */
00424    SHA1((unsigned char *)msg, msglen, digest);
00425 
00426    /* Verify signature */
00427    if (!(res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa))) {
00428       ast_debug(1, "Key failed verification: %s\n", key->name);
00429       return -1;
00430    }
00431 
00432    /* Pass */
00433    return 0;
00434 }

int AST_OPTIONAL_API_NAME() ast_crypto_loaded ( void   ) 

Definition at line 456 of file res_crypto.c.

00457 {
00458    return 1;
00459 }

int AST_OPTIONAL_API_NAME() ast_decrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

Decrypt a message using a given private key.

See also:
ast_decrypt_bin

Definition at line 331 of file res_crypto.c.

References AST_KEY_PRIVATE, ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by check_key().

00332 {
00333    int res, pos = 0;
00334 
00335    if (key->ktype != AST_KEY_PRIVATE) {
00336       ast_log(LOG_WARNING, "Cannot decrypt with a public key\n");
00337       return -1;
00338    }
00339 
00340    if (srclen % 128) {
00341       ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n");
00342       return -1;
00343    }
00344 
00345    while (srclen) {
00346       /* Process chunks 128 bytes at a time */
00347       if ((res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) < 0) {
00348          return -1;
00349       }
00350       pos += res;
00351       src += 128;
00352       srclen -= 128;
00353       dst += res;
00354    }
00355 
00356    return pos;
00357 }

int AST_OPTIONAL_API_NAME() ast_encrypt_bin ( unsigned char *  dst,
const unsigned char *  src,
int  srclen,
struct ast_key key 
)

Encrypt a message using a given private key.

See also:
ast_encrypt_bin

Definition at line 363 of file res_crypto.c.

References AST_KEY_PUBLIC, ast_log(), LOG_NOTICE, and LOG_WARNING.

Referenced by update_key().

00364 {
00365    int res, bytes, pos = 0;
00366 
00367    if (key->ktype != AST_KEY_PUBLIC) {
00368       ast_log(LOG_WARNING, "Cannot encrypt with a private key\n");
00369       return -1;
00370    }
00371 
00372    while (srclen) {
00373       bytes = srclen;
00374       if (bytes > 128 - 41) {
00375          bytes = 128 - 41;
00376       }
00377       /* Process chunks 128-41 bytes at a time */
00378       if ((res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) != 128) {
00379          ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res);
00380          return -1;
00381       }
00382       src += bytes;
00383       srclen -= bytes;
00384       pos += res;
00385       dst += res;
00386    }
00387    return pos;
00388 }

struct ast_key* AST_OPTIONAL_API_NAME() ast_key_get ( const char *  kname,
int  ktype 
)

Retrieve a key.

See also:
ast_key_get

Definition at line 136 of file res_crypto.c.

References AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_key::ktype, and ast_key::list.

Referenced by authenticate(), authenticate_verify(), check_key(), register_verify(), and update_key().

00137 {
00138    struct ast_key *key;
00139 
00140    AST_RWLIST_RDLOCK(&keys);
00141    AST_RWLIST_TRAVERSE(&keys, key, list) {
00142       if (!strcmp(kname, key->name) &&
00143           (ktype == key->ktype)) {
00144          break;
00145       }
00146    }
00147    AST_RWLIST_UNLOCK(&keys);
00148 
00149    return key;
00150 }

int AST_OPTIONAL_API_NAME() ast_sign ( struct ast_key key,
char *  msg,
char *  sig 
)

Sign a message signature using a given private key.

See also:
ast_sign

Definition at line 394 of file res_crypto.c.

References ast_base64encode(), and ast_sign_bin().

Referenced by authenticate().

00395 {
00396    unsigned char dsig[128];
00397    int siglen = sizeof(dsig), res;
00398 
00399    if (!(res = ast_sign_bin(key, msg, strlen(msg), dsig))) {
00400       /* Success -- encode (256 bytes max as documented) */
00401       ast_base64encode(sig, dsig, siglen, 256);
00402    }
00403 
00404    return res;
00405 }

int AST_OPTIONAL_API_NAME() ast_sign_bin ( struct ast_key key,
const char *  msg,
int  msglen,
unsigned char *  dsig 
)

Sign a message signature using a given private key.

See also:
ast_sign_bin

Definition at line 299 of file res_crypto.c.

References AST_KEY_PRIVATE, ast_log(), ast_key::digest, LOG_WARNING, and SHA1.

Referenced by ast_sign(), and update_key().

00300 {
00301    unsigned char digest[20];
00302    unsigned int siglen = 128;
00303    int res;
00304 
00305    if (key->ktype != AST_KEY_PRIVATE) {
00306       ast_log(LOG_WARNING, "Cannot sign with a public key\n");
00307       return -1;
00308    }
00309 
00310    /* Calculate digest of message */
00311    SHA1((unsigned char *)msg, msglen, digest);
00312 
00313    /* Verify signature */
00314    if (!(res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa))) {
00315       ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name);
00316       return -1;
00317    }
00318 
00319    if (siglen != 128) {
00320       ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128);
00321       return -1;
00322    }
00323 
00324    return 0;
00325 }

static int crypto_init ( void   )  [static]

initialise the res_crypto module

Definition at line 635 of file res_crypto.c.

References ARRAY_LEN, ast_cli_register_multiple(), and cli_crypto.

Referenced by load_module().

00636 {
00637    ast_cli_register_multiple(cli_crypto, ARRAY_LEN(cli_crypto));
00638    return 0;
00639 }

static void crypto_load ( int  ifd,
int  ofd 
) [static]

refresh RSA keys from file

Parameters:
ifd file descriptor
ofd file descriptor
Returns:
void

Definition at line 487 of file res_crypto.c.

References ast_config_AST_KEY_DIR, ast_debug, ast_free, ast_log(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_key::delme, ast_key::ktype, ast_key::list, LOG_NOTICE, LOG_WARNING, ast_key::name, ast_key::rsa, and try_load_key().

Referenced by load_module(), and reload().

00488 {
00489    struct ast_key *key;
00490    DIR *dir = NULL;
00491    struct dirent *ent;
00492    int note = 0;
00493 
00494    AST_RWLIST_WRLOCK(&keys);
00495 
00496    /* Mark all keys for deletion */
00497    AST_RWLIST_TRAVERSE(&keys, key, list) {
00498       key->delme = 1;
00499    }
00500 
00501    /* Load new keys */
00502    if ((dir = opendir(ast_config_AST_KEY_DIR))) {
00503       while ((ent = readdir(dir))) {
00504          try_load_key(ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, &note);
00505       }
00506       closedir(dir);
00507    } else {
00508       ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", ast_config_AST_KEY_DIR);
00509    }
00510 
00511    if (note) {
00512       ast_log(LOG_NOTICE, "Please run the command 'keys init' to enter the passcodes for the keys\n");
00513    }
00514 
00515    /* Delete any keys that are no longer present */
00516    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
00517       if (key->delme) {
00518          ast_debug(1, "Deleting key %s type %d\n", key->name, key->ktype);
00519          AST_RWLIST_REMOVE_CURRENT(list);
00520          if (key->rsa) {
00521             RSA_free(key->rsa);
00522          }
00523          ast_free(key);
00524       }
00525    }
00526    AST_RWLIST_TRAVERSE_SAFE_END;
00527 
00528    AST_RWLIST_UNLOCK(&keys);
00529 }

static char* handle_cli_keys_init ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

initialize all RSA keys

Parameters:
e CLI command
cmd 
a list of CLI arguments
Returns:
CLI_SUCCESS

Definition at line 592 of file res_crypto.c.

References ast_cli_args::argc, ast_config_AST_KEY_DIR, ast_copy_string(), AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_key::fn, KEY_NEEDS_PASSCODE, ast_key::ktype, ast_key::list, try_load_key(), and ast_cli_entry::usage.

00593 {
00594    struct ast_key *key;
00595    int ign;
00596    char *kn, tmp[256] = "";
00597 
00598    switch (cmd) {
00599    case CLI_INIT:
00600       e->command = "keys init";
00601       e->usage =
00602          "Usage: keys init\n"
00603          "       Initializes private keys (by reading in pass code from\n"
00604          "       the user)\n";
00605       return NULL;
00606    case CLI_GENERATE:
00607       return NULL;
00608    }
00609 
00610    if (a->argc != 2) {
00611       return CLI_SHOWUSAGE;
00612    }
00613 
00614    AST_RWLIST_WRLOCK(&keys);
00615    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) {
00616       /* Reload keys that need pass codes now */
00617       if (key->ktype & KEY_NEEDS_PASSCODE) {
00618          kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
00619          ast_copy_string(tmp, kn, sizeof(tmp));
00620          try_load_key(ast_config_AST_KEY_DIR, tmp, a->fd, a->fd, &ign);
00621       }
00622    }
00623    AST_RWLIST_TRAVERSE_SAFE_END
00624    AST_RWLIST_UNLOCK(&keys);
00625 
00626    return CLI_SUCCESS;
00627 }

static char* handle_cli_keys_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

show the list of RSA keys

Parameters:
e CLI command
cmd 
a list of CLI arguments
Returns:
CLI_SUCCESS

Definition at line 546 of file res_crypto.c.

References ast_cli(), AST_KEY_PUBLIC, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_key::digest, ast_cli_args::fd, FORMAT, KEY_NEEDS_PASSCODE, ast_key::ktype, ast_key::list, md52sum(), ast_key::name, and ast_cli_entry::usage.

00547 {
00548 #define FORMAT "%-18s %-8s %-16s %-33s\n"
00549 
00550    struct ast_key *key;
00551    char sum[16 * 2 + 1];
00552    int count_keys = 0;
00553 
00554    switch (cmd) {
00555    case CLI_INIT:
00556       e->command = "keys show";
00557       e->usage =
00558          "Usage: keys show\n"
00559          "       Displays information about RSA keys known by Asterisk\n";
00560       return NULL;
00561    case CLI_GENERATE:
00562       return NULL;
00563    }
00564 
00565    ast_cli(a->fd, FORMAT, "Key Name", "Type", "Status", "Sum");
00566    ast_cli(a->fd, FORMAT, "------------------", "--------", "----------------", "--------------------------------");
00567 
00568    AST_RWLIST_RDLOCK(&keys);
00569    AST_RWLIST_TRAVERSE(&keys, key, list) {
00570       md52sum(sum, key->digest);
00571       ast_cli(a->fd, FORMAT, key->name,
00572          (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE",
00573          key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum);
00574       count_keys++;
00575    }
00576    AST_RWLIST_UNLOCK(&keys);
00577 
00578    ast_cli(a->fd, "\n%d known RSA keys.\n", count_keys);
00579 
00580    return CLI_SUCCESS;
00581 
00582 #undef FORMAT
00583 }

static int load_module ( void   )  [static]

Definition at line 647 of file res_crypto.c.

References AST_MODULE_LOAD_SUCCESS, ast_opt_init_keys, crypto_init(), and crypto_load().

00648 {
00649    crypto_init();
00650    if (ast_opt_init_keys) {
00651       crypto_load(STDIN_FILENO, STDOUT_FILENO);
00652    } else {
00653       crypto_load(-1, -1);
00654    }
00655    return AST_MODULE_LOAD_SUCCESS;
00656 }

static void md52sum ( char *  sum,
unsigned char *  md5 
) [static]

Definition at line 531 of file res_crypto.c.

Referenced by handle_cli_keys_show().

00532 {
00533    int x;
00534    for (x = 0; x < 16; x++) {
00535       sum += sprintf(sum, "%02x", *(md5++));
00536    }
00537 }

static int pw_cb ( char *  buf,
int  size,
int  rwflag,
void *  userdata 
) [static]

setting of priv key

Parameters:
buf 
size 
rwflag 
userdata 
Returns:
length of string,-1 on failure

Definition at line 99 of file res_crypto.c.

References ast_hide_password(), AST_KEY_PRIVATE, ast_log(), ast_restore_tty(), errno, ast_key::infd, ast_key::ktype, LOG_WARNING, ast_key::name, ast_key::outfd, and prompt.

Referenced by try_load_key().

00100 {
00101    struct ast_key *key = (struct ast_key *)userdata;
00102    char prompt[256];
00103    int tmp;
00104    int res;
00105 
00106    if (key->infd < 0) {
00107       /* Note that we were at least called */
00108       key->infd = -2;
00109       return -1;
00110    }
00111 
00112    snprintf(prompt, sizeof(prompt), ">>>> passcode for %s key '%s': ",
00113        key->ktype == AST_KEY_PRIVATE ? "PRIVATE" : "PUBLIC", key->name);
00114    if (write(key->outfd, prompt, strlen(prompt)) < 0) {
00115       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00116       key->infd = -2;
00117       return -1;
00118    }
00119    tmp = ast_hide_password(key->infd);
00120    memset(buf, 0, size);
00121    res = read(key->infd, buf, size);
00122    if (res == -1) {
00123       ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
00124    }
00125    ast_restore_tty(key->infd, tmp);
00126    if (buf[strlen(buf) -1] == '\n') {
00127       buf[strlen(buf) - 1] = '\0';
00128    }
00129    return strlen(buf);
00130 }

static int reload ( void   )  [static]

Definition at line 641 of file res_crypto.c.

References crypto_load().

00642 {
00643    crypto_load(-1, -1);
00644    return 0;
00645 }

static struct ast_key* try_load_key ( const char *  dir,
const char *  fname,
int  ifd,
int  ofd,
int *  not2 
) [static]

load RSA key from file

Parameters:
dir directory string
fname name of file
ifd incoming file descriptor
ofd outgoing file descriptor
not2 
Return values:
key on success.
NULL on failure.

Definition at line 162 of file res_crypto.c.

References ast_calloc, ast_copy_string(), ast_debug, AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), ast_opt_init_keys, AST_RWLIST_INSERT_TAIL, AST_RWLIST_TRAVERSE, ast_verb, ast_key::delme, ast_key::digest, errno, f, ast_key::fn, ast_key::infd, KEY_NEEDS_PASSCODE, ast_key::ktype, ast_key::list, LOG_NOTICE, LOG_WARNING, md5(), MD5Final(), MD5Init(), MD5Update(), ast_key::name, ast_key::outfd, pw_cb(), and ast_key::rsa.

Referenced by crypto_load(), and handle_cli_keys_init().

00163 {
00164    int ktype = 0, found = 0;
00165    char *c = NULL, ffname[256];
00166    unsigned char digest[16];
00167    FILE *f;
00168    struct MD5Context md5;
00169    struct ast_key *key;
00170    static int notice = 0;
00171 
00172    /* Make sure its name is a public or private key */
00173    if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) {
00174       ktype = AST_KEY_PUBLIC;
00175    } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) {
00176       ktype = AST_KEY_PRIVATE;
00177    } else {
00178       return NULL;
00179    }
00180 
00181    /* Get actual filename */
00182    snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
00183 
00184    /* Open file */
00185    if (!(f = fopen(ffname, "r"))) {
00186       ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno));
00187       return NULL;
00188    }
00189 
00190    MD5Init(&md5);
00191    while (!feof(f)) {
00192       /* Calculate a "whatever" quality md5sum of the key */
00193       char buf[256] = "";
00194       if (!fgets(buf, sizeof(buf), f)) {
00195          continue;
00196       }
00197       if (!feof(f)) {
00198          MD5Update(&md5, (unsigned char *) buf, strlen(buf));
00199       }
00200    }
00201    MD5Final(digest, &md5);
00202 
00203    /* Look for an existing key */
00204    AST_RWLIST_TRAVERSE(&keys, key, list) {
00205       if (!strcasecmp(key->fn, ffname)) {
00206          break;
00207       }
00208    }
00209 
00210    if (key) {
00211       /* If the MD5 sum is the same, and it isn't awaiting a passcode
00212          then this is far enough */
00213       if (!memcmp(digest, key->digest, 16) &&
00214           !(key->ktype & KEY_NEEDS_PASSCODE)) {
00215          fclose(f);
00216          key->delme = 0;
00217          return NULL;
00218       } else {
00219          /* Preserve keytype */
00220          ktype = key->ktype;
00221          /* Recycle the same structure */
00222          found++;
00223       }
00224    }
00225 
00226    /* Make fname just be the normal name now */
00227    *c = '\0';
00228    if (!key) {
00229       if (!(key = ast_calloc(1, sizeof(*key)))) {
00230          fclose(f);
00231          return NULL;
00232       }
00233    }
00234    /* First the filename */
00235    ast_copy_string(key->fn, ffname, sizeof(key->fn));
00236    /* Then the name */
00237    ast_copy_string(key->name, fname, sizeof(key->name));
00238    key->ktype = ktype;
00239    /* Yes, assume we're going to be deleted */
00240    key->delme = 1;
00241    /* Keep the key type */
00242    memcpy(key->digest, digest, 16);
00243    /* Can I/O takes the FD we're given */
00244    key->infd = ifd;
00245    key->outfd = ofd;
00246    /* Reset the file back to the beginning */
00247    rewind(f);
00248    /* Now load the key with the right method */
00249    if (ktype == AST_KEY_PUBLIC) {
00250       key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key);
00251    } else {
00252       key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key);
00253    }
00254    fclose(f);
00255    if (key->rsa) {
00256       if (RSA_size(key->rsa) == 128) {
00257          /* Key loaded okay */
00258          key->ktype &= ~KEY_NEEDS_PASSCODE;
00259          ast_verb(3, "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
00260          ast_debug(1, "Key '%s' loaded OK\n", key->name);
00261          key->delme = 0;
00262       } else {
00263          ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name);
00264       }
00265    } else if (key->infd != -2) {
00266       ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name);
00267       if (ofd > -1) {
00268          ERR_print_errors_fp(stderr);
00269       } else {
00270          ERR_print_errors_fp(stderr);
00271       }
00272    } else {
00273       ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name);
00274       key->ktype |= KEY_NEEDS_PASSCODE;
00275       if (!notice) {
00276          if (!ast_opt_init_keys) {
00277             ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n");
00278          }
00279          notice++;
00280       }
00281       /* Keep it anyway */
00282       key->delme = 0;
00283       /* Print final notice about "keys init" when done */
00284       *not2 = 1;
00285    }
00286 
00287    /* If this is a new key add it to the list */
00288    if (!found) {
00289       AST_RWLIST_INSERT_TAIL(&keys, key, list);
00290    }
00291 
00292    return key;
00293 }

static int unload_module ( void   )  [static]

Definition at line 658 of file res_crypto.c.

00659 {
00660    /* Can't unload this once we're loaded */
00661    return -1;
00662 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Cryptographic Digital Signatures" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

< Since we don't have a config file, we could move up to REALTIME_DEPEND, if necessary

Definition at line 670 of file res_crypto.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 670 of file res_crypto.c.

struct ast_cli_entry cli_crypto[] [static]

Initial value:

 {
   { .handler =  handle_cli_keys_show , .summary =  "Displays RSA key information" ,__VA_ARGS__ },
   { .handler =  handle_cli_keys_init , .summary =  "Initialize RSA key passcodes" ,__VA_ARGS__ }
}

Definition at line 629 of file res_crypto.c.

Referenced by crypto_init().


Generated on Mon Oct 8 12:39:27 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7