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 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 280058 $")
00036
00037 #include "asterisk/paths.h"
00038 #include <openssl/ssl.h>
00039 #include <openssl/err.h>
00040 #include <openssl/aes.h>
00041 #include <dirent.h>
00042
00043 #include "asterisk/module.h"
00044 #include "asterisk/md5.h"
00045 #include "asterisk/cli.h"
00046 #include "asterisk/io.h"
00047 #include "asterisk/lock.h"
00048 #include "asterisk/utils.h"
00049
00050 #define AST_API_MODULE
00051 #include "asterisk/crypto.h"
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #define KEY_NEEDS_PASSCODE (1 << 16)
00067
00068 struct ast_key {
00069
00070 char name[80];
00071
00072 char fn[256];
00073
00074 int ktype;
00075
00076 RSA *rsa;
00077
00078 int delme;
00079
00080 int infd;
00081
00082 int outfd;
00083
00084 unsigned char digest[16];
00085 AST_RWLIST_ENTRY(ast_key) list;
00086 };
00087
00088 static AST_RWLIST_HEAD_STATIC(keys, ast_key);
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 static int pw_cb(char *buf, int size, int rwflag, void *userdata)
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
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 }
00127
00128
00129
00130
00131
00132 struct ast_key * AST_OPTIONAL_API_NAME(ast_key_get)(const char *kname, int ktype)
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 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
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
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
00178 snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
00179
00180
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
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
00200 AST_RWLIST_TRAVERSE(&keys, key, list) {
00201 if (!strcasecmp(key->fn, ffname)) {
00202 break;
00203 }
00204 }
00205
00206 if (key) {
00207
00208
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
00216 ktype = key->ktype;
00217
00218 found++;
00219 }
00220 }
00221
00222
00223 *c = '\0';
00224 if (!key) {
00225 if (!(key = ast_calloc(1, sizeof(*key)))) {
00226 fclose(f);
00227 return NULL;
00228 }
00229 }
00230
00231 ast_copy_string(key->fn, ffname, sizeof(key->fn));
00232
00233 ast_copy_string(key->name, fname, sizeof(key->name));
00234 key->ktype = ktype;
00235
00236 key->delme = 1;
00237
00238 memcpy(key->digest, digest, 16);
00239
00240 key->infd = ifd;
00241 key->outfd = ofd;
00242
00243 rewind(f);
00244
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
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
00278 key->delme = 0;
00279
00280 *not2 = 1;
00281 }
00282
00283
00284 if (!found) {
00285 AST_RWLIST_INSERT_TAIL(&keys, key, list);
00286 }
00287
00288 return key;
00289 }
00290
00291
00292
00293
00294
00295 int AST_OPTIONAL_API_NAME(ast_sign_bin)(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
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
00307 SHA1((unsigned char *)msg, msglen, digest);
00308
00309
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 }
00322
00323
00324
00325
00326
00327 int AST_OPTIONAL_API_NAME(ast_decrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *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
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 }
00354
00355
00356
00357
00358
00359 int AST_OPTIONAL_API_NAME(ast_encrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *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
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 }
00385
00386
00387
00388
00389
00390 int AST_OPTIONAL_API_NAME(ast_sign)(struct ast_key *key, char *msg, char *sig)
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
00397 ast_base64encode(sig, dsig, siglen, 256);
00398 }
00399
00400 return res;
00401 }
00402
00403
00404
00405
00406
00407 int AST_OPTIONAL_API_NAME(ast_check_signature_bin)(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
00408 {
00409 unsigned char digest[20];
00410 int res;
00411
00412 if (key->ktype != AST_KEY_PUBLIC) {
00413
00414
00415 ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
00416 return -1;
00417 }
00418
00419
00420 SHA1((unsigned char *)msg, msglen, digest);
00421
00422
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
00429 return 0;
00430 }
00431
00432
00433
00434
00435
00436 int AST_OPTIONAL_API_NAME(ast_check_signature)(struct ast_key *key, const char *msg, const char *sig)
00437 {
00438 unsigned char dsig[128];
00439 int res;
00440
00441
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 }
00451
00452 int AST_OPTIONAL_API_NAME(ast_crypto_loaded)(void)
00453 {
00454 return 1;
00455 }
00456
00457 int AST_OPTIONAL_API_NAME(ast_aes_set_encrypt_key)(const unsigned char *key, ast_aes_encrypt_key *ctx)
00458 {
00459 return AES_set_encrypt_key(key, 128, ctx);
00460 }
00461
00462 int AST_OPTIONAL_API_NAME(ast_aes_set_decrypt_key)(const unsigned char *key, ast_aes_decrypt_key *ctx)
00463 {
00464 return AES_set_decrypt_key(key, 128, ctx);
00465 }
00466
00467 void AST_OPTIONAL_API_NAME(ast_aes_encrypt)(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
00468 {
00469 return AES_encrypt(in, out, ctx);
00470 }
00471
00472 void AST_OPTIONAL_API_NAME(ast_aes_decrypt)(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
00473 {
00474 return AES_decrypt(in, out, ctx);
00475 }
00476
00477
00478
00479
00480
00481
00482
00483 static void crypto_load(int ifd, int ofd)
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
00493 AST_RWLIST_TRAVERSE(&keys, key, list) {
00494 key->delme = 1;
00495 }
00496
00497
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
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 }
00526
00527 static void md52sum(char *sum, unsigned char *md5)
00528 {
00529 int x;
00530 for (x = 0; x < 16; x++) {
00531 sum += sprintf(sum, "%02x", *(md5++));
00532 }
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542 static char *handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 }
00580
00581
00582
00583
00584
00585
00586
00587
00588 static char *handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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
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 }
00624
00625 static struct ast_cli_entry cli_crypto[] = {
00626 AST_CLI_DEFINE(handle_cli_keys_show, "Displays RSA key information"),
00627 AST_CLI_DEFINE(handle_cli_keys_init, "Initialize RSA key passcodes")
00628 };
00629
00630
00631 static int crypto_init(void)
00632 {
00633 ast_cli_register_multiple(cli_crypto, ARRAY_LEN(cli_crypto));
00634 return 0;
00635 }
00636
00637 static int reload(void)
00638 {
00639 crypto_load(-1, -1);
00640 return 0;
00641 }
00642
00643 static int load_module(void)
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 }
00653
00654 static int unload_module(void)
00655 {
00656
00657 return -1;
00658 }
00659
00660
00661 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Cryptographic Digital Signatures",
00662 .load = load_module,
00663 .unload = unload_module,
00664 .reload = reload,
00665 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00666 );