00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 328209 $")
00037
00038 #include "asterisk/paths.h"
00039 #include <openssl/ssl.h>
00040 #include <openssl/err.h>
00041 #include <openssl/aes.h>
00042 #include <dirent.h>
00043
00044 #include "asterisk/module.h"
00045 #include "asterisk/md5.h"
00046 #include "asterisk/cli.h"
00047 #include "asterisk/io.h"
00048 #include "asterisk/lock.h"
00049 #include "asterisk/utils.h"
00050
00051 #define AST_API_MODULE
00052 #include "asterisk/crypto.h"
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #define KEY_NEEDS_PASSCODE (1 << 16)
00068
00069 struct ast_key {
00070
00071 char name[80];
00072
00073 char fn[256];
00074
00075 int ktype;
00076
00077 RSA *rsa;
00078
00079 int delme;
00080
00081 int infd;
00082
00083 int outfd;
00084
00085 unsigned char digest[16];
00086 AST_RWLIST_ENTRY(ast_key) list;
00087 };
00088
00089 static AST_RWLIST_HEAD_STATIC(keys, ast_key);
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 static int pw_cb(char *buf, int size, int rwflag, void *userdata)
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
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 }
00132
00133
00134
00135
00136
00137 struct ast_key * AST_OPTIONAL_API_NAME(ast_key_get)(const char *kname, int ktype)
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 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
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
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
00183 snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
00184
00185
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
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
00205 AST_RWLIST_TRAVERSE(&keys, key, list) {
00206 if (!strcasecmp(key->fn, ffname)) {
00207 break;
00208 }
00209 }
00210
00211 if (key) {
00212
00213
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
00221 ktype = key->ktype;
00222
00223 found++;
00224 }
00225 }
00226
00227
00228 *c = '\0';
00229 if (!key) {
00230 if (!(key = ast_calloc(1, sizeof(*key)))) {
00231 fclose(f);
00232 return NULL;
00233 }
00234 }
00235
00236 ast_copy_string(key->fn, ffname, sizeof(key->fn));
00237
00238 ast_copy_string(key->name, fname, sizeof(key->name));
00239 key->ktype = ktype;
00240
00241 key->delme = 1;
00242
00243 memcpy(key->digest, digest, 16);
00244
00245 key->infd = ifd;
00246 key->outfd = ofd;
00247
00248 rewind(f);
00249
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
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
00283 key->delme = 0;
00284
00285 *not2 = 1;
00286 }
00287
00288
00289 if (!found) {
00290 AST_RWLIST_INSERT_TAIL(&keys, key, list);
00291 }
00292
00293 return key;
00294 }
00295
00296
00297
00298
00299
00300 int AST_OPTIONAL_API_NAME(ast_sign_bin)(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
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
00312 SHA1((unsigned char *)msg, msglen, digest);
00313
00314
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 }
00327
00328
00329
00330
00331
00332 int AST_OPTIONAL_API_NAME(ast_decrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *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
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 }
00359
00360
00361
00362
00363
00364 int AST_OPTIONAL_API_NAME(ast_encrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *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
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 }
00390
00391
00392
00393
00394
00395 int AST_OPTIONAL_API_NAME(ast_sign)(struct ast_key *key, char *msg, char *sig)
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
00402 ast_base64encode(sig, dsig, siglen, 256);
00403 }
00404
00405 return res;
00406 }
00407
00408
00409
00410
00411
00412 int AST_OPTIONAL_API_NAME(ast_check_signature_bin)(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
00413 {
00414 unsigned char digest[20];
00415 int res;
00416
00417 if (key->ktype != AST_KEY_PUBLIC) {
00418
00419
00420 ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
00421 return -1;
00422 }
00423
00424
00425 SHA1((unsigned char *)msg, msglen, digest);
00426
00427
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
00434 return 0;
00435 }
00436
00437
00438
00439
00440
00441 int AST_OPTIONAL_API_NAME(ast_check_signature)(struct ast_key *key, const char *msg, const char *sig)
00442 {
00443 unsigned char dsig[128];
00444 int res;
00445
00446
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 }
00456
00457 int AST_OPTIONAL_API_NAME(ast_crypto_loaded)(void)
00458 {
00459 return 1;
00460 }
00461
00462 int AST_OPTIONAL_API_NAME(ast_aes_set_encrypt_key)(const unsigned char *key, ast_aes_encrypt_key *ctx)
00463 {
00464 return AES_set_encrypt_key(key, 128, ctx);
00465 }
00466
00467 int AST_OPTIONAL_API_NAME(ast_aes_set_decrypt_key)(const unsigned char *key, ast_aes_decrypt_key *ctx)
00468 {
00469 return AES_set_decrypt_key(key, 128, ctx);
00470 }
00471
00472 void AST_OPTIONAL_API_NAME(ast_aes_encrypt)(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
00473 {
00474 return AES_encrypt(in, out, ctx);
00475 }
00476
00477 void AST_OPTIONAL_API_NAME(ast_aes_decrypt)(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
00478 {
00479 return AES_decrypt(in, out, ctx);
00480 }
00481
00482
00483
00484
00485
00486
00487
00488 static void crypto_load(int ifd, int ofd)
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
00498 AST_RWLIST_TRAVERSE(&keys, key, list) {
00499 key->delme = 1;
00500 }
00501
00502
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
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 }
00531
00532 static void md52sum(char *sum, unsigned char *md5)
00533 {
00534 int x;
00535 for (x = 0; x < 16; x++) {
00536 sum += sprintf(sum, "%02x", *(md5++));
00537 }
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547 static char *handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 }
00585
00586
00587
00588
00589
00590
00591
00592
00593 static char *handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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
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 }
00629
00630 static struct ast_cli_entry cli_crypto[] = {
00631 AST_CLI_DEFINE(handle_cli_keys_show, "Displays RSA key information"),
00632 AST_CLI_DEFINE(handle_cli_keys_init, "Initialize RSA key passcodes")
00633 };
00634
00635
00636 static int crypto_init(void)
00637 {
00638 ast_cli_register_multiple(cli_crypto, ARRAY_LEN(cli_crypto));
00639 return 0;
00640 }
00641
00642 static int reload(void)
00643 {
00644 crypto_load(-1, -1);
00645 return 0;
00646 }
00647
00648 static int load_module(void)
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 }
00658
00659 static int unload_module(void)
00660 {
00661
00662 return -1;
00663 }
00664
00665
00666 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Cryptographic Digital Signatures",
00667 .load = load_module,
00668 .unload = unload_module,
00669 .reload = reload,
00670 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00671 );