Mon Jun 27 16:51:19 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 50 of file res_crypto.c.

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

#define KEY_NEEDS_PASSCODE   (1 << 16)

Definition at line 66 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 666 of file res_crypto.c.

static void __unreg_module ( void   )  [static]

Definition at line 666 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 472 of file res_crypto.c.

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

00473 {
00474    return AES_decrypt(in, out, ctx);
00475 }

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 467 of file res_crypto.c.

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

00468 {
00469    return AES_encrypt(in, out, ctx);
00470 }

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 462 of file res_crypto.c.

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

00463 {
00464    return AES_set_decrypt_key(key, 128, ctx);
00465 }

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 457 of file res_crypto.c.

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

00458 {
00459    return AES_set_encrypt_key(key, 128, ctx);
00460 }

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 436 of file res_crypto.c.

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

Referenced by authenticate_verify(), and register_verify().

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

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 407 of file res_crypto.c.

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

Referenced by ast_check_signature(), and check_key().

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

int AST_OPTIONAL_API_NAME() ast_crypto_loaded ( void   ) 

Definition at line 452 of file res_crypto.c.

00453 {
00454    return 1;
00455 }

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 327 of file res_crypto.c.

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

Referenced by check_key().

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

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 359 of file res_crypto.c.

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

Referenced by update_key().

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

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 132 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().

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

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 390 of file res_crypto.c.

References ast_base64encode(), and ast_sign_bin().

Referenced by authenticate().

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

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 295 of file res_crypto.c.

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

Referenced by ast_sign(), and update_key().

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

static int crypto_init ( void   )  [static]

initialise the res_crypto module

Definition at line 631 of file res_crypto.c.

References ARRAY_LEN, ast_cli_register_multiple(), and cli_crypto.

Referenced by load_module().

00632 {
00633    ast_cli_register_multiple(cli_crypto, ARRAY_LEN(cli_crypto));
00634    return 0;
00635 }

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 483 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().

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

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 588 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.

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

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 542 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.

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

static int load_module ( void   )  [static]

Definition at line 643 of file res_crypto.c.

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

00644 {
00645    crypto_init();
00646    if (ast_opt_init_keys) {
00647       crypto_load(STDIN_FILENO, STDOUT_FILENO);
00648    } else {
00649       crypto_load(-1, -1);
00650    }
00651    return AST_MODULE_LOAD_SUCCESS;
00652 }

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

Definition at line 527 of file res_crypto.c.

Referenced by handle_cli_keys_show().

00528 {
00529    int x;
00530    for (x = 0; x < 16; x++) {
00531       sum += sprintf(sum, "%02x", *(md5++));
00532    }
00533 }

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 98 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().

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

static int reload ( void   )  [static]

Definition at line 637 of file res_crypto.c.

References crypto_load().

00638 {
00639    crypto_load(-1, -1);
00640    return 0;
00641 }

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 158 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().

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

static int unload_module ( void   )  [static]

Definition at line 654 of file res_crypto.c.

00655 {
00656    /* Can't unload this once we're loaded */
00657    return -1;
00658 }


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 666 of file res_crypto.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 666 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 625 of file res_crypto.c.

Referenced by crypto_init().


Generated on Mon Jun 27 16:51:19 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7