![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
res_crypto.c File Reference
Definition in file res_crypto.c.
#include "asterisk.h"
#include <sys/types.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/crypto.h"
#include "asterisk/md5.h"
#include "asterisk/cli.h"
#include "asterisk/io.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
Include dependency graph for res_crypto.c:

Go to the source code of this file.
Data Structures | |
| struct | ast_key |
Defines | |
| #define | KEY_NEEDS_PASSCODE (1 << 16) |
Functions | |
| static int | __ast_check_signature (struct ast_key *key, const char *msg, const char *sig) |
| static int | __ast_check_signature_bin (struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig) |
| static int | __ast_decrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) |
| static int | __ast_encrypt_bin (unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) |
| static struct ast_key * | __ast_key_get (const char *kname, int ktype) |
| static int | __ast_sign (struct ast_key *key, char *msg, char *sig) |
| static int | __ast_sign_bin (struct ast_key *key, const char *msg, int msglen, unsigned char *dsig) |
| AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,"Cryptographic Digital Signatures",.load=load_module,.unload=unload_module,.reload=reload) | |
| AST_MUTEX_DEFINE_STATIC (keylock) | |
| static int | crypto_init (void) |
| static void | crypto_load (int ifd, int ofd) |
| static int | init_keys (int fd, int argc, char *argv[]) |
| 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) |
| static int | reload (void) |
| static int | show_keys (int fd, int argc, char *argv[]) |
| static struct ast_key * | try_load_key (char *dir, char *fname, int ifd, int ofd, int *not2) |
| static int | unload_module (void) |
Variables | |
| static struct ast_cli_entry | cli_crypto [] |
| static const char | init_keys_usage [] |
| static struct ast_key * | keys = NULL |
| static const char | show_key_usage [] |
|
|
Definition at line 81 of file res_crypto.c. Referenced by init_keys(), show_keys(), and try_load_key(). |
|
||||||||||||||||
|
Definition at line 444 of file res_crypto.c. References ast_base64decode(), ast_check_signature_bin, ast_log(), key(), and LOG_WARNING. Referenced by crypto_init(). 00445 { 00446 unsigned char dsig[128]; 00447 int res; 00448 00449 /* Decode signature */ 00450 res = ast_base64decode(dsig, sig, sizeof(dsig)); 00451 if (res != sizeof(dsig)) { 00452 ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res); 00453 return -1; 00454 } 00455 res = ast_check_signature_bin(key, msg, strlen(msg), dsig); 00456 return res; 00457 }
|
|
||||||||||||||||||||
|
Definition at line 417 of file res_crypto.c. References AST_KEY_PUBLIC, ast_log(), ast_key::digest, key(), LOG_DEBUG, LOG_WARNING, and option_debug. Referenced by crypto_init(). 00418 { 00419 unsigned char digest[20]; 00420 int res; 00421 00422 if (key->ktype != AST_KEY_PUBLIC) { 00423 /* Okay, so of course you really *can* but for our purposes 00424 we're going to say you can't */ 00425 ast_log(LOG_WARNING, "Cannot check message signature with a private key\n"); 00426 return -1; 00427 } 00428 00429 /* Calculate digest of message */ 00430 SHA1((unsigned char *)msg, msglen, digest); 00431 00432 /* Verify signature */ 00433 res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa); 00434 00435 if (!res) { 00436 if (option_debug) 00437 ast_log(LOG_DEBUG, "Key failed verification: %s\n", key->name); 00438 return -1; 00439 } 00440 /* Pass */ 00441 return 0; 00442 }
|
|
||||||||||||||||||||
|
Definition at line 350 of file res_crypto.c. References AST_KEY_PRIVATE, ast_log(), key(), LOG_NOTICE, and LOG_WARNING. Referenced by crypto_init(). 00351 { 00352 int res; 00353 int pos = 0; 00354 if (key->ktype != AST_KEY_PRIVATE) { 00355 ast_log(LOG_WARNING, "Cannot decrypt with a public key\n"); 00356 return -1; 00357 } 00358 00359 if (srclen % 128) { 00360 ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n"); 00361 return -1; 00362 } 00363 while(srclen) { 00364 /* Process chunks 128 bytes at a time */ 00365 res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING); 00366 if (res < 0) 00367 return -1; 00368 pos += res; 00369 src += 128; 00370 srclen -= 128; 00371 dst += res; 00372 } 00373 return pos; 00374 }
|
|
||||||||||||||||||||
|
Definition at line 376 of file res_crypto.c. References AST_KEY_PUBLIC, ast_log(), key(), LOG_NOTICE, and LOG_WARNING. Referenced by crypto_init(). 00377 { 00378 int res; 00379 int bytes; 00380 int pos = 0; 00381 if (key->ktype != AST_KEY_PUBLIC) { 00382 ast_log(LOG_WARNING, "Cannot encrypt with a private key\n"); 00383 return -1; 00384 } 00385 00386 while(srclen) { 00387 bytes = srclen; 00388 if (bytes > 128 - 41) 00389 bytes = 128 - 41; 00390 /* Process chunks 128-41 bytes at a time */ 00391 res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING); 00392 if (res != 128) { 00393 ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res); 00394 return -1; 00395 } 00396 src += bytes; 00397 srclen -= bytes; 00398 pos += res; 00399 dst += res; 00400 } 00401 return pos; 00402 }
|
|
||||||||||||
|
Definition at line 137 of file res_crypto.c. References ast_mutex_lock(), ast_mutex_unlock(), key(), and keys. Referenced by crypto_init(). 00138 { 00139 struct ast_key *key; 00140 ast_mutex_lock(&keylock); 00141 key = keys; 00142 while(key) { 00143 if (!strcmp(kname, key->name) && 00144 (ktype == key->ktype)) 00145 break; 00146 key = key->next; 00147 } 00148 ast_mutex_unlock(&keylock); 00149 return key; 00150 }
|
|
||||||||||||||||
|
Definition at line 404 of file res_crypto.c. References ast_base64encode(), ast_sign_bin, and key(). Referenced by crypto_init(). 00405 { 00406 unsigned char dsig[128]; 00407 int siglen = sizeof(dsig); 00408 int res; 00409 res = ast_sign_bin(key, msg, strlen(msg), dsig); 00410 if (!res) 00411 /* Success -- encode (256 bytes max as documented) */ 00412 ast_base64encode(sig, dsig, siglen, 256); 00413 return res; 00414 00415 }
|
|
||||||||||||||||||||
|
Definition at line 319 of file res_crypto.c. References AST_KEY_PRIVATE, ast_log(), ast_key::digest, key(), and LOG_WARNING. Referenced by crypto_init(). 00320 { 00321 unsigned char digest[20]; 00322 unsigned int siglen = 128; 00323 int res; 00324 00325 if (key->ktype != AST_KEY_PRIVATE) { 00326 ast_log(LOG_WARNING, "Cannot sign with a public key\n"); 00327 return -1; 00328 } 00329 00330 /* Calculate digest of message */ 00331 SHA1((unsigned char *)msg, msglen, digest); 00332 00333 /* Verify signature */ 00334 res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa); 00335 00336 if (!res) { 00337 ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name); 00338 return -1; 00339 } 00340 00341 if (siglen != 128) { 00342 ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128); 00343 return -1; 00344 } 00345 00346 return 0; 00347 00348 }
|
|
||||||||||||||||||||||||||||
|
|
|
|
|
|
|
Definition at line 576 of file res_crypto.c. References __ast_check_signature(), __ast_check_signature_bin(), __ast_decrypt_bin(), __ast_encrypt_bin(), __ast_key_get(), __ast_sign(), __ast_sign_bin(), ast_check_signature, ast_check_signature_bin, ast_cli_register_multiple(), ast_decrypt_bin, ast_encrypt_bin, ast_key_get, ast_sign, ast_sign_bin, and cli_crypto. Referenced by load_module(). 00577 { 00578 SSL_library_init(); 00579 ERR_load_crypto_strings(); 00580 ast_cli_register_multiple(cli_crypto, sizeof(cli_crypto) / sizeof(struct ast_cli_entry)); 00581 00582 /* Install ourselves into stubs */ 00583 ast_key_get = __ast_key_get; 00584 ast_check_signature = __ast_check_signature; 00585 ast_check_signature_bin = __ast_check_signature_bin; 00586 ast_sign = __ast_sign; 00587 ast_sign_bin = __ast_sign_bin; 00588 ast_encrypt_bin = __ast_encrypt_bin; 00589 ast_decrypt_bin = __ast_decrypt_bin; 00590 return 0; 00591 }
|
|
||||||||||||
|
Definition at line 459 of file res_crypto.c. References ast_config_AST_KEY_DIR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), free, key(), keys, last, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, option_debug, and try_load_key(). Referenced by load_module(), and reload(). 00460 { 00461 struct ast_key *key, *nkey, *last; 00462 DIR *dir = NULL; 00463 struct dirent *ent; 00464 int note = 0; 00465 /* Mark all keys for deletion */ 00466 ast_mutex_lock(&keylock); 00467 key = keys; 00468 while(key) { 00469 key->delme = 1; 00470 key = key->next; 00471 } 00472 ast_mutex_unlock(&keylock); 00473 /* Load new keys */ 00474 dir = opendir((char *)ast_config_AST_KEY_DIR); 00475 if (dir) { 00476 while((ent = readdir(dir))) { 00477 try_load_key((char *)ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, ¬e); 00478 } 00479 closedir(dir); 00480 } else 00481 ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", (char *)ast_config_AST_KEY_DIR); 00482 if (note) { 00483 ast_log(LOG_NOTICE, "Please run the command 'init keys' to enter the passcodes for the keys\n"); 00484 } 00485 ast_mutex_lock(&keylock); 00486 key = keys; 00487 last = NULL; 00488 while(key) { 00489 nkey = key->next; 00490 if (key->delme) { 00491 if (option_debug) 00492 ast_log(LOG_DEBUG, "Deleting key %s type %d\n", key->name, key->ktype); 00493 /* Do the delete */ 00494 if (last) 00495 last->next = nkey; 00496 else 00497 keys = nkey; 00498 if (key->rsa) 00499 RSA_free(key->rsa); 00500 free(key); 00501 } else 00502 last = key; 00503 key = nkey; 00504 } 00505 ast_mutex_unlock(&keylock); 00506 }
|
|
||||||||||||||||
|
Definition at line 538 of file res_crypto.c. References ast_config_AST_KEY_DIR, key(), KEY_NEEDS_PASSCODE, keys, RESULT_SUCCESS, and try_load_key(). 00539 { 00540 struct ast_key *key; 00541 int ign; 00542 char *kn; 00543 char tmp[256] = ""; 00544 00545 key = keys; 00546 while(key) { 00547 /* Reload keys that need pass codes now */ 00548 if (key->ktype & KEY_NEEDS_PASSCODE) { 00549 kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1; 00550 ast_copy_string(tmp, kn, sizeof(tmp)); 00551 try_load_key((char *)ast_config_AST_KEY_DIR, tmp, fd, fd, &ign); 00552 } 00553 key = key->next; 00554 } 00555 return RESULT_SUCCESS; 00556 }
|
|
|
Definition at line 599 of file res_crypto.c. References ast_opt_init_keys, crypto_init(), and crypto_load(). 00600 { 00601 crypto_init(); 00602 if (ast_opt_init_keys) 00603 crypto_load(STDIN_FILENO, STDOUT_FILENO); 00604 else 00605 crypto_load(-1, -1); 00606 return 0; 00607 }
|
|
||||||||||||
|
Definition at line 508 of file res_crypto.c. Referenced by show_keys().
|
|
||||||||||||||||||||
|
Definition at line 112 of file res_crypto.c. References ast_hide_password(), AST_KEY_PRIVATE, ast_restore_tty(), and key(). Referenced by try_load_key(). 00113 { 00114 struct ast_key *key = (struct ast_key *)userdata; 00115 char prompt[256]; 00116 int res; 00117 int tmp; 00118 if (key->infd > -1) { 00119 snprintf(prompt, sizeof(prompt), ">>>> passcode for %s key '%s': ", 00120 key->ktype == AST_KEY_PRIVATE ? "PRIVATE" : "PUBLIC", key->name); 00121 write(key->outfd, prompt, strlen(prompt)); 00122 memset(buf, 0, sizeof(buf)); 00123 tmp = ast_hide_password(key->infd); 00124 memset(buf, 0, size); 00125 res = read(key->infd, buf, size); 00126 ast_restore_tty(key->infd, tmp); 00127 if (buf[strlen(buf) -1] == '\n') 00128 buf[strlen(buf) - 1] = '\0'; 00129 return strlen(buf); 00130 } else { 00131 /* Note that we were at least called */ 00132 key->infd = -2; 00133 } 00134 return -1; 00135 }
|
|
|
Definition at line 593 of file res_crypto.c. References crypto_load(). 00594 { 00595 crypto_load(-1, -1); 00596 return 0; 00597 }
|
|
||||||||||||||||
|
Definition at line 515 of file res_crypto.c. References ast_cli(), AST_KEY_PUBLIC, ast_mutex_lock(), ast_mutex_unlock(), key(), KEY_NEEDS_PASSCODE, keys, md52sum(), and RESULT_SUCCESS. 00516 { 00517 struct ast_key *key; 00518 char sum[16 * 2 + 1]; 00519 int count_keys = 0; 00520 00521 ast_mutex_lock(&keylock); 00522 key = keys; 00523 ast_cli(fd, "%-18s %-8s %-16s %-33s\n", "Key Name", "Type", "Status", "Sum"); 00524 while(key) { 00525 md52sum(sum, key->digest); 00526 ast_cli(fd, "%-18s %-8s %-16s %-33s\n", key->name, 00527 (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", 00528 key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum); 00529 00530 key = key->next; 00531 count_keys++; 00532 } 00533 ast_mutex_unlock(&keylock); 00534 ast_cli(fd, "%d known RSA keys.\n", count_keys); 00535 return RESULT_SUCCESS; 00536 }
|
|
||||||||||||||||||||||||
|
Definition at line 152 of file res_crypto.c. References ast_calloc, AST_KEY_PRIVATE, AST_KEY_PUBLIC, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_opt_init_keys, ast_verbose(), ast_key::digest, key(), KEY_NEEDS_PASSCODE, keys, ast_key::ktype, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, MD5Final(), MD5Init(), MD5Update(), option_debug, option_verbose, pw_cb(), and VERBOSE_PREFIX_3. Referenced by crypto_load(), and init_keys(). 00153 { 00154 int ktype = 0; 00155 char *c = NULL; 00156 char ffname[256]; 00157 unsigned char digest[16]; 00158 FILE *f; 00159 struct MD5Context md5; 00160 struct ast_key *key; 00161 static int notice = 0; 00162 int found = 0; 00163 00164 /* Make sure its name is a public or private key */ 00165 00166 if ((c = strstr(fname, ".pub")) && !strcmp(c, ".pub")) { 00167 ktype = AST_KEY_PUBLIC; 00168 } else if ((c = strstr(fname, ".key")) && !strcmp(c, ".key")) { 00169 ktype = AST_KEY_PRIVATE; 00170 } else 00171 return NULL; 00172 00173 /* Get actual filename */ 00174 snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname); 00175 00176 ast_mutex_lock(&keylock); 00177 key = keys; 00178 while(key) { 00179 /* Look for an existing version already */ 00180 if (!strcasecmp(key->fn, ffname)) 00181 break; 00182 key = key->next; 00183 } 00184 ast_mutex_unlock(&keylock); 00185 00186 /* Open file */ 00187 f = fopen(ffname, "r"); 00188 if (!f) { 00189 ast_log(LOG_WARNING, "Unable to open key file %s: %s\n", ffname, strerror(errno)); 00190 return NULL; 00191 } 00192 MD5Init(&md5); 00193 while(!feof(f)) { 00194 /* Calculate a "whatever" quality md5sum of the key */ 00195 char buf[256]; 00196 memset(buf, 0, 256); 00197 fgets(buf, sizeof(buf), f); 00198 if (!feof(f)) { 00199 MD5Update(&md5, (unsigned char *) buf, strlen(buf)); 00200 } 00201 } 00202 MD5Final(digest, &md5); 00203 if (key) { 00204 /* If the MD5 sum is the same, and it isn't awaiting a passcode 00205 then this is far enough */ 00206 if (!memcmp(digest, key->digest, 16) && 00207 !(key->ktype & KEY_NEEDS_PASSCODE)) { 00208 fclose(f); 00209 key->delme = 0; 00210 return NULL; 00211 } else { 00212 /* Preserve keytype */ 00213 ktype = key->ktype; 00214 /* Recycle the same structure */ 00215 found++; 00216 } 00217 } 00218 00219 /* Make fname just be the normal name now */ 00220 *c = '\0'; 00221 if (!key) { 00222 if (!(key = ast_calloc(1, sizeof(*key)))) { 00223 fclose(f); 00224 return NULL; 00225 } 00226 } 00227 /* At this point we have a key structure (old or new). Time to 00228 fill it with what we know */ 00229 /* Gotta lock if this one already exists */ 00230 if (found) 00231 ast_mutex_lock(&keylock); 00232 /* First the filename */ 00233 ast_copy_string(key->fn, ffname, sizeof(key->fn)); 00234 /* Then the name */ 00235 ast_copy_string(key->name, fname, sizeof(key->name)); 00236 key->ktype = ktype; 00237 /* Yes, assume we're going to be deleted */ 00238 key->delme = 1; 00239 /* Keep the key type */ 00240 memcpy(key->digest, digest, 16); 00241 /* Can I/O takes the FD we're given */ 00242 key->infd = ifd; 00243 key->outfd = ofd; 00244 /* Reset the file back to the beginning */ 00245 rewind(f); 00246 /* Now load the key with the right method */ 00247 if (ktype == AST_KEY_PUBLIC) 00248 key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key); 00249 else 00250 key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key); 00251 fclose(f); 00252 if (key->rsa) { 00253 if (RSA_size(key->rsa) == 128) { 00254 /* Key loaded okay */ 00255 key->ktype &= ~KEY_NEEDS_PASSCODE; 00256 if (option_verbose > 2) 00257 ast_verbose(VERBOSE_PREFIX_3 "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); 00258 if (option_debug) 00259 ast_log(LOG_DEBUG, "Key '%s' loaded OK\n", key->name); 00260 key->delme = 0; 00261 } else 00262 ast_log(LOG_NOTICE, "Key '%s' is not expected size.\n", key->name); 00263 } else if (key->infd != -2) { 00264 ast_log(LOG_WARNING, "Key load %s '%s' failed\n",key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); 00265 if (ofd > -1) { 00266 ERR_print_errors_fp(stderr); 00267 } else 00268 ERR_print_errors_fp(stderr); 00269 } else { 00270 ast_log(LOG_NOTICE, "Key '%s' needs passcode.\n", key->name); 00271 key->ktype |= KEY_NEEDS_PASSCODE; 00272 if (!notice) { 00273 if (!ast_opt_init_keys) 00274 ast_log(LOG_NOTICE, "Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n"); 00275 notice++; 00276 } 00277 /* Keep it anyway */ 00278 key->delme = 0; 00279 /* Print final notice about "init keys" when done */ 00280 *not2 = 1; 00281 } 00282 if (found) 00283 ast_mutex_unlock(&keylock); 00284 if (!found) { 00285 ast_mutex_lock(&keylock); 00286 key->next = keys; 00287 keys = key; 00288 ast_mutex_unlock(&keylock); 00289 } 00290 return key; 00291 }
|
|
|
Definition at line 609 of file res_crypto.c.
|
|
|
Definition at line 566 of file res_crypto.c. Referenced by crypto_init(). |
|
|
Initial value: "Usage: keys init\n" " Initializes private keys (by reading in pass code from the user)\n" Definition at line 562 of file res_crypto.c. |
|
|
Definition at line 103 of file res_crypto.c. Referenced by __ast_key_get(), ast_db_deltree(), ast_db_gettree(), check_auth(), crypto_load(), database_show(), database_showkey(), init_keys(), reply_digest(), show_keys(), and try_load_key(). |
|
|
Initial value: "Usage: keys show\n" " Displays information about RSA keys known by Asterisk\n" Definition at line 558 of file res_crypto.c. |