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 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 47051 $")
00033
00034 #include <sys/types.h>
00035 #include <openssl/ssl.h>
00036 #include <openssl/err.h>
00037 #include <stdio.h>
00038 #include <dirent.h>
00039 #include <string.h>
00040 #include <errno.h>
00041 #include <unistd.h>
00042 #include <fcntl.h>
00043
00044 #include "asterisk/file.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/logger.h"
00047 #include "asterisk/say.h"
00048 #include "asterisk/module.h"
00049 #include "asterisk/options.h"
00050 #include "asterisk/crypto.h"
00051 #include "asterisk/md5.h"
00052 #include "asterisk/cli.h"
00053 #include "asterisk/io.h"
00054 #include "asterisk/lock.h"
00055 #include "asterisk/utils.h"
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 AST_MUTEX_DEFINE_STATIC(keylock);
00080
00081 #define KEY_NEEDS_PASSCODE (1 << 16)
00082
00083 struct ast_key {
00084
00085 char name[80];
00086
00087 char fn[256];
00088
00089 int ktype;
00090
00091 RSA *rsa;
00092
00093 int delme;
00094
00095 int infd;
00096
00097 int outfd;
00098
00099 unsigned char digest[16];
00100 struct ast_key *next;
00101 };
00102
00103 static struct ast_key *keys = NULL;
00104
00105
00106 #if 0
00107 static int fdprint(int fd, char *s)
00108 {
00109 return write(fd, s, strlen(s) + 1);
00110 }
00111 #endif
00112 static int pw_cb(char *buf, int size, int rwflag, void *userdata)
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
00132 key->infd = -2;
00133 }
00134 return -1;
00135 }
00136
00137 static struct ast_key *__ast_key_get(const char *kname, int ktype)
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 }
00151
00152 static struct ast_key *try_load_key (char *dir, char *fname, int ifd, int ofd, int *not2)
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
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
00174 snprintf(ffname, sizeof(ffname), "%s/%s", dir, fname);
00175
00176 ast_mutex_lock(&keylock);
00177 key = keys;
00178 while(key) {
00179
00180 if (!strcasecmp(key->fn, ffname))
00181 break;
00182 key = key->next;
00183 }
00184 ast_mutex_unlock(&keylock);
00185
00186
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
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
00205
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
00213 ktype = key->ktype;
00214
00215 found++;
00216 }
00217 }
00218
00219
00220 *c = '\0';
00221 if (!key) {
00222 if (!(key = ast_calloc(1, sizeof(*key)))) {
00223 fclose(f);
00224 return NULL;
00225 }
00226 }
00227
00228
00229
00230 if (found)
00231 ast_mutex_lock(&keylock);
00232
00233 ast_copy_string(key->fn, ffname, sizeof(key->fn));
00234
00235 ast_copy_string(key->name, fname, sizeof(key->name));
00236 key->ktype = ktype;
00237
00238 key->delme = 1;
00239
00240 memcpy(key->digest, digest, 16);
00241
00242 key->infd = ifd;
00243 key->outfd = ofd;
00244
00245 rewind(f);
00246
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
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
00278 key->delme = 0;
00279
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 }
00292
00293 #if 0
00294
00295 static void dump(unsigned char *src, int len)
00296 {
00297 int x;
00298 for (x=0;x<len;x++)
00299 printf("%02x", *(src++));
00300 printf("\n");
00301 }
00302
00303 static char *binary(int y, int len)
00304 {
00305 static char res[80];
00306 int x;
00307 memset(res, 0, sizeof(res));
00308 for (x=0;x<len;x++) {
00309 if (y & (1 << x))
00310 res[(len - x - 1)] = '1';
00311 else
00312 res[(len - x - 1)] = '0';
00313 }
00314 return res;
00315 }
00316
00317 #endif
00318
00319 static int __ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
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
00331 SHA1((unsigned char *)msg, msglen, digest);
00332
00333
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 }
00349
00350 static int __ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
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
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 }
00375
00376 static int __ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
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
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 }
00403
00404 static int __ast_sign(struct ast_key *key, char *msg, char *sig)
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
00412 ast_base64encode(sig, dsig, siglen, 256);
00413 return res;
00414
00415 }
00416
00417 static int __ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
00418 {
00419 unsigned char digest[20];
00420 int res;
00421
00422 if (key->ktype != AST_KEY_PUBLIC) {
00423
00424
00425 ast_log(LOG_WARNING, "Cannot check message signature with a private key\n");
00426 return -1;
00427 }
00428
00429
00430 SHA1((unsigned char *)msg, msglen, digest);
00431
00432
00433 res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa);
00434
00435 if (!res) {
00436 ast_log(LOG_DEBUG, "Key failed verification: %s\n", key->name);
00437 return -1;
00438 }
00439
00440 return 0;
00441 }
00442
00443 static int __ast_check_signature(struct ast_key *key, const char *msg, const char *sig)
00444 {
00445 unsigned char dsig[128];
00446 int res;
00447
00448
00449 res = ast_base64decode(dsig, sig, sizeof(dsig));
00450 if (res != sizeof(dsig)) {
00451 ast_log(LOG_WARNING, "Signature improper length (expect %d, got %d)\n", (int)sizeof(dsig), (int)res);
00452 return -1;
00453 }
00454 res = ast_check_signature_bin(key, msg, strlen(msg), dsig);
00455 return res;
00456 }
00457
00458 static void crypto_load(int ifd, int ofd)
00459 {
00460 struct ast_key *key, *nkey, *last;
00461 DIR *dir = NULL;
00462 struct dirent *ent;
00463 int note = 0;
00464
00465 ast_mutex_lock(&keylock);
00466 key = keys;
00467 while(key) {
00468 key->delme = 1;
00469 key = key->next;
00470 }
00471 ast_mutex_unlock(&keylock);
00472
00473 dir = opendir((char *)ast_config_AST_KEY_DIR);
00474 if (dir) {
00475 while((ent = readdir(dir))) {
00476 try_load_key((char *)ast_config_AST_KEY_DIR, ent->d_name, ifd, ofd, ¬e);
00477 }
00478 closedir(dir);
00479 } else
00480 ast_log(LOG_WARNING, "Unable to open key directory '%s'\n", (char *)ast_config_AST_KEY_DIR);
00481 if (note) {
00482 ast_log(LOG_NOTICE, "Please run the command 'init keys' to enter the passcodes for the keys\n");
00483 }
00484 ast_mutex_lock(&keylock);
00485 key = keys;
00486 last = NULL;
00487 while(key) {
00488 nkey = key->next;
00489 if (key->delme) {
00490 ast_log(LOG_DEBUG, "Deleting key %s type %d\n", key->name, key->ktype);
00491
00492 if (last)
00493 last->next = nkey;
00494 else
00495 keys = nkey;
00496 if (key->rsa)
00497 RSA_free(key->rsa);
00498 free(key);
00499 } else
00500 last = key;
00501 key = nkey;
00502 }
00503 ast_mutex_unlock(&keylock);
00504 }
00505
00506 static void md52sum(char *sum, unsigned char *md5)
00507 {
00508 int x;
00509 for (x=0;x<16;x++)
00510 sum += sprintf(sum, "%02x", *(md5++));
00511 }
00512
00513 static int show_keys(int fd, int argc, char *argv[])
00514 {
00515 struct ast_key *key;
00516 char sum[16 * 2 + 1];
00517 int count_keys = 0;
00518
00519 ast_mutex_lock(&keylock);
00520 key = keys;
00521 ast_cli(fd, "%-18s %-8s %-16s %-33s\n", "Key Name", "Type", "Status", "Sum");
00522 while(key) {
00523 md52sum(sum, key->digest);
00524 ast_cli(fd, "%-18s %-8s %-16s %-33s\n", key->name,
00525 (key->ktype & 0xf) == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE",
00526 key->ktype & KEY_NEEDS_PASSCODE ? "[Needs Passcode]" : "[Loaded]", sum);
00527
00528 key = key->next;
00529 count_keys++;
00530 }
00531 ast_mutex_unlock(&keylock);
00532 ast_cli(fd, "%d known RSA keys.\n", count_keys);
00533 return RESULT_SUCCESS;
00534 }
00535
00536 static int init_keys(int fd, int argc, char *argv[])
00537 {
00538 struct ast_key *key;
00539 int ign;
00540 char *kn;
00541 char tmp[256] = "";
00542
00543 key = keys;
00544 while(key) {
00545
00546 if (key->ktype & KEY_NEEDS_PASSCODE) {
00547 kn = key->fn + strlen(ast_config_AST_KEY_DIR) + 1;
00548 ast_copy_string(tmp, kn, sizeof(tmp));
00549 try_load_key((char *)ast_config_AST_KEY_DIR, tmp, fd, fd, &ign);
00550 }
00551 key = key->next;
00552 }
00553 return RESULT_SUCCESS;
00554 }
00555
00556 static char show_key_usage[] =
00557 "Usage: keys show\n"
00558 " Displays information about RSA keys known by Asterisk\n";
00559
00560 static char init_keys_usage[] =
00561 "Usage: keys init\n"
00562 " Initializes private keys (by reading in pass code from the user)\n";
00563
00564 static struct ast_cli_entry cli_show_keys_deprecated = {
00565 { "show", "keys", NULL },
00566 show_keys, NULL,
00567 NULL };
00568
00569 static struct ast_cli_entry cli_init_keys_deprecated = {
00570 { "init", "keys", NULL },
00571 init_keys, NULL,
00572 NULL };
00573
00574 static struct ast_cli_entry cli_crypto[] = {
00575 { { "keys", "show", NULL },
00576 show_keys, "Displays RSA key information",
00577 show_key_usage, NULL, &cli_show_keys_deprecated },
00578
00579 { { "keys", "init", NULL },
00580 init_keys, "Initialize RSA key passcodes",
00581 init_keys_usage, NULL, &cli_init_keys_deprecated },
00582 };
00583
00584 static int crypto_init(void)
00585 {
00586 SSL_library_init();
00587 ERR_load_crypto_strings();
00588 ast_cli_register_multiple(cli_crypto, sizeof(cli_crypto) / sizeof(struct ast_cli_entry));
00589
00590
00591 ast_key_get = __ast_key_get;
00592 ast_check_signature = __ast_check_signature;
00593 ast_check_signature_bin = __ast_check_signature_bin;
00594 ast_sign = __ast_sign;
00595 ast_sign_bin = __ast_sign_bin;
00596 ast_encrypt_bin = __ast_encrypt_bin;
00597 ast_decrypt_bin = __ast_decrypt_bin;
00598 return 0;
00599 }
00600
00601 static int reload(void)
00602 {
00603 crypto_load(-1, -1);
00604 return 0;
00605 }
00606
00607 static int load_module(void)
00608 {
00609 crypto_init();
00610 if (ast_opt_init_keys)
00611 crypto_load(STDIN_FILENO, STDOUT_FILENO);
00612 else
00613 crypto_load(-1, -1);
00614 return 0;
00615 }
00616
00617 static int unload_module(void)
00618 {
00619
00620 return -1;
00621 }
00622
00623
00624 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Cryptographic Digital Signatures",
00625 .load = load_module,
00626 .unload = unload_module,
00627 .reload = reload
00628 );