#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 = "ac1f6a56484a8820659555499174e588" , .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 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.
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().
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 471 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 466 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 461 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 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.
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 | ) |
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 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.
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.
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.
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.
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
ifd | file descriptor | |
ofd | file descriptor |
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, ¬e); 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
e | CLI command | |
cmd | ||
a | list of CLI arguments |
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
e | CLI command | |
cmd | ||
a | list of CLI arguments |
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
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 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
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 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] |
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().