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: 413586 $")
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 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 }
00131
00132
00133
00134
00135
00136 struct ast_key * AST_OPTIONAL_API_NAME(ast_key_get)(const char *kname, int ktype)
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 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
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
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
00182 snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
00183
00184
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
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
00204 AST_RWLIST_TRAVERSE(&keys, key, list) {
00205 if (!strcasecmp(key->fn, ffname)) {
00206 break;
00207 }
00208 }
00209
00210 if (key) {
00211
00212
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
00220 ktype = key->ktype;
00221
00222 found++;
00223 }
00224 }
00225
00226
00227 *c = '\0';
00228 if (!key) {
00229 if (!(key = ast_calloc(1, sizeof(*key)))) {
00230 fclose(f);
00231 return NULL;
00232 }
00233 }
00234
00235 ast_copy_string(key->fn, ffname, sizeof(key->fn));
00236
00237 ast_copy_string(key->name, fname, sizeof(key->name));
00238 key->ktype = ktype;
00239
00240 key->delme = 1;
00241
00242 memcpy(key->digest, digest, 16);
00243
00244 key->infd = ifd;
00245 key->outfd = ofd;
00246
00247 rewind(f);
00248
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
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
00282 key->delme = 0;
00283
00284 *not2 = 1;
00285 }
00286
00287
00288 if (!found) {
00289 AST_RWLIST_INSERT_TAIL(&keys, key, list);
00290 }
00291
00292 return key;
00293 }
00294
00295
00296
00297
00298
00299 int AST_OPTIONAL_API_NAME(ast_sign_bin)(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
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
00311 SHA1((unsigned char *)msg, msglen, digest);
00312
00313
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 }
00326
00327
00328
00329
00330
00331 int AST_OPTIONAL_API_NAME(ast_decrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *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
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 }
00358
00359
00360
00361
00362
00363 int AST_OPTIONAL_API_NAME(ast_encrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *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
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 }
00389
00390
00391
00392
00393
00394 int AST_OPTIONAL_API_NAME(ast_sign)(struct ast_key *key, char *msg, char *sig)
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
00401 ast_base64encode(sig, dsig, siglen, 256);
00402 }
00403
00404 return res;
00405 }
00406
00407
00408
00409
00410
00411 int AST_OPTIONAL_API_NAME(ast_check_signature_bin)(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
00412 {
00413 unsigned char digest[20];
00414 int res;
00415
00416 if (key->ktype != AST_KEY_PUBLIC) {
00417
00418
00419 ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
00420 return -1;
00421 }
00422
00423
00424 SHA1((unsigned char *)msg, msglen, digest);
00425
00426
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
00433 return 0;
00434 }
00435
00436
00437
00438
00439
00440 int AST_OPTIONAL_API_NAME(ast_check_signature)(struct ast_key *key, const char *msg, const char *sig)
00441 {
00442 unsigned char dsig[128];
00443 int res;
00444
00445
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 }
00455
00456 int AST_OPTIONAL_API_NAME(ast_crypto_loaded)(void)
00457 {
00458 return 1;
00459 }
00460
00461 int AST_OPTIONAL_API_NAME(ast_aes_set_encrypt_key)(const unsigned char *key, ast_aes_encrypt_key *ctx)
00462 {
00463 return AES_set_encrypt_key(key, 128, ctx);
00464 }
00465
00466 int AST_OPTIONAL_API_NAME(ast_aes_set_decrypt_key)(const unsigned char *key, ast_aes_decrypt_key *ctx)
00467 {
00468 return AES_set_decrypt_key(key, 128, ctx);
00469 }
00470
00471 void AST_OPTIONAL_API_NAME(ast_aes_encrypt)(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx)
00472 {
00473 return AES_encrypt(in, out, ctx);
00474 }
00475
00476 void AST_OPTIONAL_API_NAME(ast_aes_decrypt)(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx)
00477 {
00478 return AES_decrypt(in, out, ctx);
00479 }
00480
00481
00482
00483
00484
00485
00486
00487 static void crypto_load(int ifd, int ofd)
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
00497 AST_RWLIST_TRAVERSE(&keys, key, list) {
00498 key->delme = 1;
00499 }
00500
00501
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
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 }
00530
00531 static void md52sum(char *sum, unsigned char *md5)
00532 {
00533 int x;
00534 for (x = 0; x < 16; x++) {
00535 sum += sprintf(sum, "%02x", (unsigned)*(md5++));
00536 }
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546 static char *handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 }
00584
00585
00586
00587
00588
00589
00590
00591
00592 static char *handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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
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 }
00628
00629 static struct ast_cli_entry cli_crypto[] = {
00630 AST_CLI_DEFINE(handle_cli_keys_show, "Displays RSA key information"),
00631 AST_CLI_DEFINE(handle_cli_keys_init, "Initialize RSA key passcodes")
00632 };
00633
00634
00635 static int crypto_init(void)
00636 {
00637 ast_cli_register_multiple(cli_crypto, ARRAY_LEN(cli_crypto));
00638 return 0;
00639 }
00640
00641 static int reload(void)
00642 {
00643 crypto_load(-1, -1);
00644 return 0;
00645 }
00646
00647 static int load_module(void)
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 }
00657
00658 static int unload_module(void)
00659 {
00660
00661 return -1;
00662 }
00663
00664
00665 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Cryptographic Digital Signatures",
00666 .load = load_module,
00667 .unload = unload_module,
00668 .reload = reload,
00669 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00670 );