#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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 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().
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.
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().
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 467 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 462 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 457 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 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.
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 | ) |
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 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.
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.
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.
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.
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
ifd | file descriptor | |
ofd | file descriptor |
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, ¬e); 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
e | CLI command | |
cmd | ||
a | list of CLI arguments |
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
e | CLI command | |
cmd | ||
a | list of CLI arguments |
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
buf | ||
size | ||
rwflag | ||
userdata |
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
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 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] |
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().