#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_key * | try_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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_crypto [] |
Definition in file res_crypto.c.
#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().
static void __reg_module | ( | void | ) | [static] |
Definition at line 671 of file res_crypto.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 671 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.
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 477 of file res_crypto.c.
Referenced by aes_helper(), decrypt_memcpy(), and memcpy_decrypt().
void AST_OPTIONAL_API_NAME() ast_aes_encrypt | ( | const unsigned char * | in, | |
unsigned char * | out, | |||
const ast_aes_encrypt_key * | ctx | |||
) |
AES encrypt data.
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 472 of file res_crypto.c.
Referenced by aes_helper(), encrypt_memcpy(), and memcpy_encrypt().
int AST_OPTIONAL_API_NAME() ast_aes_set_decrypt_key | ( | const unsigned char * | key, | |
ast_aes_decrypt_key * | ctx | |||
) |
Set a decryption key.
key | a 16 char key | |
ctx | address of an aes encryption context |
0 | success | |
nonzero | failure |
Definition at line 467 of file res_crypto.c.
Referenced by aes_helper(), build_ecx_key(), build_encryption_keys(), check_key(), socket_process(), and update_key().
int AST_OPTIONAL_API_NAME() ast_aes_set_encrypt_key | ( | const unsigned char * | key, | |
ast_aes_encrypt_key * | ctx | |||
) |
Set an encryption key.
key | a 16 char key | |
ctx | address of an aes encryption context |
0 | success | |
nonzero | failure |
Definition at line 462 of file res_crypto.c.
Referenced by aes_helper(), build_ecx_key(), check_key(), and update_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.
Definition at line 441 of file res_crypto.c.
References ast_base64decode(), ast_check_signature_bin(), ast_log(), and LOG_WARNING.
Referenced by authenticate_verify(), and register_verify().
00442 { 00443 unsigned char dsig[128]; 00444 int res; 00445 00446 /* Decode signature */ 00447 if ((res = ast_base64decode(dsig, sig, sizeof(dsig))) != sizeof(dsig)) { 00448 ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res); 00449 return -1; 00450 } 00451 00452 res = ast_check_signature_bin(key, msg, strlen(msg), dsig); 00453 00454 return res; 00455 }
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.
Definition at line 412 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().
00413 { 00414 unsigned char digest[20]; 00415 int res; 00416 00417 if (key->ktype != AST_KEY_PUBLIC) { 00418 /* Okay, so of course you really *can* but for our purposes 00419 we're going to say you can't */ 00420 ast_log(LOG_WARNING, "Cannot check message signature with a private key\n"); 00421 return -1; 00422 } 00423 00424 /* Calculate digest of message */ 00425 SHA1((unsigned char *)msg, msglen, digest); 00426 00427 /* Verify signature */ 00428 if (!(res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa))) { 00429 ast_debug(1, "Key failed verification: %s\n", key->name); 00430 return -1; 00431 } 00432 00433 /* Pass */ 00434 return 0; 00435 }
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.
Definition at line 332 of file res_crypto.c.
References AST_KEY_PRIVATE, ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by check_key().
00333 { 00334 int res, pos = 0; 00335 00336 if (key->ktype != AST_KEY_PRIVATE) { 00337 ast_log(LOG_WARNING, "Cannot decrypt with a public key\n"); 00338 return -1; 00339 } 00340 00341 if (srclen % 128) { 00342 ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n"); 00343 return -1; 00344 } 00345 00346 while (srclen) { 00347 /* Process chunks 128 bytes at a time */ 00348 if ((res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) < 0) { 00349 return -1; 00350 } 00351 pos += res; 00352 src += 128; 00353 srclen -= 128; 00354 dst += res; 00355 } 00356 00357 return pos; 00358 }
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.
Definition at line 364 of file res_crypto.c.
References AST_KEY_PUBLIC, ast_log(), LOG_NOTICE, and LOG_WARNING.
Referenced by update_key().
00365 { 00366 int res, bytes, pos = 0; 00367 00368 if (key->ktype != AST_KEY_PUBLIC) { 00369 ast_log(LOG_WARNING, "Cannot encrypt with a private key\n"); 00370 return -1; 00371 } 00372 00373 while (srclen) { 00374 bytes = srclen; 00375 if (bytes > 128 - 41) { 00376 bytes = 128 - 41; 00377 } 00378 /* Process chunks 128-41 bytes at a time */ 00379 if ((res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) != 128) { 00380 ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res); 00381 return -1; 00382 } 00383 src += bytes; 00384 srclen -= bytes; 00385 pos += res; 00386 dst += res; 00387 } 00388 return pos; 00389 }
struct ast_key* AST_OPTIONAL_API_NAME() ast_key_get | ( | const char * | kname, | |
int | ktype | |||
) |
Retrieve a key.
Definition at line 137 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().
00138 { 00139 struct ast_key *key; 00140 00141 AST_RWLIST_RDLOCK(&keys); 00142 AST_RWLIST_TRAVERSE(&keys, key, list) { 00143 if (!strcmp(kname, key->name) && 00144 (ktype == key->ktype)) { 00145 break; 00146 } 00147 } 00148 AST_RWLIST_UNLOCK(&keys); 00149 00150 return key; 00151 }
int AST_OPTIONAL_API_NAME() ast_sign | ( | struct ast_key * | key, | |
char * | msg, | |||
char * | sig | |||
) |
Sign a message signature using a given private key.
Definition at line 395 of file res_crypto.c.
References ast_base64encode(), and ast_sign_bin().
Referenced by authenticate().
00396 { 00397 unsigned char dsig[128]; 00398 int siglen = sizeof(dsig), res; 00399 00400 if (!(res = ast_sign_bin(key, msg, strlen(msg), dsig))) { 00401 /* Success -- encode (256 bytes max as documented) */ 00402 ast_base64encode(sig, dsig, siglen, 256); 00403 } 00404 00405 return res; 00406 }
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.
Definition at line 300 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().
00301 { 00302 unsigned char digest[20]; 00303 unsigned int siglen = 128; 00304 int res; 00305 00306 if (key->ktype != AST_KEY_PRIVATE) { 00307 ast_log(LOG_WARNING, "Cannot sign with a public key\n"); 00308 return -1; 00309 } 00310 00311 /* Calculate digest of message */ 00312 SHA1((unsigned char *)msg, msglen, digest); 00313 00314 /* Verify signature */ 00315 if (!(res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa))) { 00316 ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name); 00317 return -1; 00318 } 00319 00320 if (siglen != 128) { 00321 ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128); 00322 return -1; 00323 } 00324 00325 return 0; 00326 }
static int crypto_init | ( | void | ) | [static] |
initialise the res_crypto module
Definition at line 636 of file res_crypto.c.
References ARRAY_LEN, ast_cli_register_multiple(), and cli_crypto.
Referenced by load_module().
00637 { 00638 ast_cli_register_multiple(cli_crypto, ARRAY_LEN(cli_crypto)); 00639 return 0; 00640 }
static void crypto_load | ( | int | ifd, | |
int | ofd | |||
) | [static] |
refresh RSA keys from file
ifd | file descriptor | |
ofd | file descriptor |
Definition at line 488 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().
00489 { 00490 struct ast_key *key; 00491 DIR *dir = NULL; 00492 struct dirent *ent; 00493 int note = 0; 00494 00495 AST_RWLIST_WRLOCK(&keys); 00496 00497 /* Mark all keys for deletion */ 00498 AST_RWLIST_TRAVERSE(&keys, key, list) { 00499 key->delme = 1; 00500 } 00501 00502 /* Load new keys */ 00503 if ((dir = opendir(ast_config_AST_KEY_DIR))) { 00504 while ((ent = readdir(dir))) { 00505 try_load_key(ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, ¬e); 00506 } 00507 closedir(dir); 00508 } else { 00509 ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", ast_config_AST_KEY_DIR); 00510 } 00511 00512 if (note) { 00513 ast_log(LOG_NOTICE, "Please run the command 'keys init' to enter the passcodes for the keys\n"); 00514 } 00515 00516 /* Delete any keys that are no longer present */ 00517 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) { 00518 if (key->delme) { 00519 ast_debug(1, "Deleting key %s type %d\n", key->name, key->ktype); 00520 AST_RWLIST_REMOVE_CURRENT(list); 00521 if (key->rsa) { 00522 RSA_free(key->rsa); 00523 } 00524 ast_free(key); 00525 } 00526 } 00527 AST_RWLIST_TRAVERSE_SAFE_END; 00528 00529 AST_RWLIST_UNLOCK(&keys); 00530 }
static char* handle_cli_keys_init | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
initialize all RSA keys
e | CLI command | |
cmd | ||
a | list of CLI arguments |
Definition at line 593 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.
00594 { 00595 struct ast_key *key; 00596 int ign; 00597 char *kn, tmp[256] = ""; 00598 00599 switch (cmd) { 00600 case CLI_INIT: 00601 e->command = "keys init"; 00602 e->usage = 00603 "Usage: keys init\n" 00604 " Initializes private keys (by reading in pass code from\n" 00605 " the user)\n"; 00606 return NULL; 00607 case CLI_GENERATE: 00608 return NULL; 00609 } 00610 00611 if (a->argc != 2) { 00612 return CLI_SHOWUSAGE; 00613 } 00614 00615 AST_RWLIST_WRLOCK(&keys); 00616 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&keys, key, list) { 00617 /* Reload keys that need pass codes now */ 00618 if (key->ktype & KEY_NEEDS_PASSCODE) { 00619 kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1; 00620 ast_copy_string(tmp, kn, sizeof(tmp)); 00621 try_load_key(ast_config_AST_KEY_DIR, tmp, a->fd, a->fd, &ign); 00622 } 00623 } 00624 AST_RWLIST_TRAVERSE_SAFE_END 00625 AST_RWLIST_UNLOCK(&keys); 00626 00627 return CLI_SUCCESS; 00628 }
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
e | CLI command | |
cmd | ||
a | list of CLI arguments |
Definition at line 547 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.
00548 { 00549 #define FORMAT "%-18s %-8s %-16s %-33s\n" 00550 00551 struct ast_key *key; 00552 char sum[16 * 2 + 1]; 00553 int count_keys = 0; 00554 00555 switch (cmd) { 00556 case CLI_INIT: 00557 e->command = "keys show"; 00558 e->usage = 00559 "Usage: keys show\n" 00560 " Displays information about RSA keys known by Asterisk\n"; 00561 return NULL; 00562 case CLI_GENERATE: 00563 return NULL; 00564 } 00565 00566 ast_cli(a->fd, FORMAT, "Key Name", "Type", "Status", "Sum"); 00567 ast_cli(a->fd, FORMAT, "------------------", "--------", "----------------", "--------------------------------"); 00568 00569 AST_RWLIST_RDLOCK(&keys); 00570 AST_RWLIST_TRAVERSE(&keys, key, list) { 00571 md52sum(sum, key->digest); 00572 ast_cli(a->fd, FORMAT, key->name, 00573 (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", 00574 key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum); 00575 count_keys++; 00576 } 00577 AST_RWLIST_UNLOCK(&keys); 00578 00579 ast_cli(a->fd, "\n%d known RSA keys.\n", count_keys); 00580 00581 return CLI_SUCCESS; 00582 00583 #undef FORMAT 00584 }
static int load_module | ( | void | ) | [static] |
Definition at line 648 of file res_crypto.c.
References AST_MODULE_LOAD_SUCCESS, ast_opt_init_keys, crypto_init(), and crypto_load().
00649 { 00650 crypto_init(); 00651 if (ast_opt_init_keys) { 00652 crypto_load(STDIN_FILENO, STDOUT_FILENO); 00653 } else { 00654 crypto_load(-1, -1); 00655 } 00656 return AST_MODULE_LOAD_SUCCESS; 00657 }
static void md52sum | ( | char * | sum, | |
unsigned char * | md5 | |||
) | [static] |
Definition at line 532 of file res_crypto.c.
Referenced by handle_cli_keys_show().
00533 { 00534 int x; 00535 for (x = 0; x < 16; x++) { 00536 sum += sprintf(sum, "%02x", *(md5++)); 00537 } 00538 }
static int pw_cb | ( | char * | buf, | |
int | size, | |||
int | rwflag, | |||
void * | userdata | |||
) | [static] |
setting of priv key
buf | ||
size | ||
rwflag | ||
userdata |
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 memset(buf, 0, sizeof(buf)); 00120 tmp = ast_hide_password(key->infd); 00121 memset(buf, 0, size); 00122 res = read(key->infd, buf, size); 00123 if (res == -1) { 00124 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 00125 } 00126 ast_restore_tty(key->infd, tmp); 00127 if (buf[strlen(buf) -1] == '\n') { 00128 buf[strlen(buf) - 1] = '\0'; 00129 } 00130 return strlen(buf); 00131 }
static int reload | ( | void | ) | [static] |
Definition at line 642 of file res_crypto.c.
References crypto_load().
00643 { 00644 crypto_load(-1, -1); 00645 return 0; 00646 }
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
dir | directory string | |
fname | name of file | |
ifd | incoming file descriptor | |
ofd | outgoing file descriptor | |
not2 |
key | on success. | |
NULL | on failure. |
Definition at line 163 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().
00164 { 00165 int ktype = 0, found = 0; 00166 char *c = NULL, ffname[256]; 00167 unsigned char digest[16]; 00168 FILE *f; 00169 struct MD5Context md5; 00170 struct ast_key *key; 00171 static int notice = 0; 00172 00173 /* Make sure its name is a public or private key */ 00174 if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) { 00175 ktype = AST_KEY_PUBLIC; 00176 } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) { 00177 ktype = AST_KEY_PRIVATE; 00178 } else { 00179 return NULL; 00180 } 00181 00182 /* Get actual filename */ 00183 snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname); 00184 00185 /* Open file */ 00186 if (!(f = fopen(ffname, "r"))) { 00187 ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno)); 00188 return NULL; 00189 } 00190 00191 MD5Init(&md5); 00192 while (!feof(f)) { 00193 /* Calculate a "whatever" quality md5sum of the key */ 00194 char buf[256] = ""; 00195 if (!fgets(buf, sizeof(buf), f)) { 00196 continue; 00197 } 00198 if (!feof(f)) { 00199 MD5Update(&md5, (unsigned char *) buf, strlen(buf)); 00200 } 00201 } 00202 MD5Final(digest, &md5); 00203 00204 /* Look for an existing key */ 00205 AST_RWLIST_TRAVERSE(&keys, key, list) { 00206 if (!strcasecmp(key->fn, ffname)) { 00207 break; 00208 } 00209 } 00210 00211 if (key) { 00212 /* If the MD5 sum is the same, and it isn't awaiting a passcode 00213 then this is far enough */ 00214 if (!memcmp(digest, key->digest, 16) && 00215 !(key->ktype & KEY_NEEDS_PASSCODE)) { 00216 fclose(f); 00217 key->delme = 0; 00218 return NULL; 00219 } else { 00220 /* Preserve keytype */ 00221 ktype = key->ktype; 00222 /* Recycle the same structure */ 00223 found++; 00224 } 00225 } 00226 00227 /* Make fname just be the normal name now */ 00228 *c = '\0'; 00229 if (!key) { 00230 if (!(key = ast_calloc(1, sizeof(*key)))) { 00231 fclose(f); 00232 return NULL; 00233 } 00234 } 00235 /* First the filename */ 00236 ast_copy_string(key->fn, ffname, sizeof(key->fn)); 00237 /* Then the name */ 00238 ast_copy_string(key->name, fname, sizeof(key->name)); 00239 key->ktype = ktype; 00240 /* Yes, assume we're going to be deleted */ 00241 key->delme = 1; 00242 /* Keep the key type */ 00243 memcpy(key->digest, digest, 16); 00244 /* Can I/O takes the FD we're given */ 00245 key->infd = ifd; 00246 key->outfd = ofd; 00247 /* Reset the file back to the beginning */ 00248 rewind(f); 00249 /* Now load the key with the right method */ 00250 if (ktype == AST_KEY_PUBLIC) { 00251 key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key); 00252 } else { 00253 key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key); 00254 } 00255 fclose(f); 00256 if (key->rsa) { 00257 if (RSA_size(key->rsa) == 128) { 00258 /* Key loaded okay */ 00259 key->ktype &= ~KEY_NEEDS_PASSCODE; 00260 ast_verb(3, "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); 00261 ast_debug(1, "Key '%s' loaded OK\n", key->name); 00262 key->delme = 0; 00263 } else { 00264 ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name); 00265 } 00266 } else if (key->infd != -2) { 00267 ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); 00268 if (ofd > -1) { 00269 ERR_print_errors_fp(stderr); 00270 } else { 00271 ERR_print_errors_fp(stderr); 00272 } 00273 } else { 00274 ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name); 00275 key->ktype |= KEY_NEEDS_PASSCODE; 00276 if (!notice) { 00277 if (!ast_opt_init_keys) { 00278 ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n"); 00279 } 00280 notice++; 00281 } 00282 /* Keep it anyway */ 00283 key->delme = 0; 00284 /* Print final notice about "keys init" when done */ 00285 *not2 = 1; 00286 } 00287 00288 /* If this is a new key add it to the list */ 00289 if (!found) { 00290 AST_RWLIST_INSERT_TAIL(&keys, key, list); 00291 } 00292 00293 return key; 00294 }
static int unload_module | ( | void | ) | [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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 671 of file res_crypto.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 671 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 630 of file res_crypto.c.
Referenced by crypto_init().