39 #include <openssl/err.h>
40 #include <openssl/ssl.h>
41 #include <openssl/evp.h>
42 #include <openssl/md5.h>
43 #include <openssl/sha.h>
57 #define AST_API_MODULE
73 #define KEY_NEEDS_PASSCODE (1 << 16)
78 #define RSA_PKCS1_OAEP_PADDING_SIZE (1 + 2 * SHA_DIGEST_LENGTH)
96 unsigned char digest[MD5_DIGEST_LENGTH];
112 static
int pw_cb(
char *buf,
int size,
int rwflag,
void *userdata)
114 struct ast_key *key = (
struct ast_key *)userdata;
125 snprintf(prompt,
sizeof(prompt),
">>>> passcode for %s key '%s': ",
126 key->
ktype == AST_KEY_PRIVATE ?
"PRIVATE" :
"PUBLIC", key->
name);
127 if (write(key->
outfd, prompt, strlen(prompt)) < 0) {
128 ast_log(LOG_WARNING,
"write() failed: %s\n", strerror(errno));
133 memset(buf, 0, size);
134 res = read(key->
infd, buf, size);
136 ast_log(LOG_WARNING,
"read() failed: %s\n", strerror(errno));
139 if (buf[strlen(buf) -1] ==
'\n') {
140 buf[strlen(buf) - 1] =
'\0';
154 AST_RWLIST_TRAVERSE(&
keys, key, list) {
155 if (!strcmp(kname, key->
name) &&
156 (ktype == key->
ktype)) {
177 int n, ktype = 0, found = 0;
178 const char *c = NULL;
180 unsigned char digest[MD5_DIGEST_LENGTH];
183 EVP_MD_CTX *ctx = NULL;
185 static int notice = 0;
187 size_t fnamelen = strlen(fname);
190 if (fnamelen > 4 && !strcmp((c = &fname[fnamelen - 4]),
".pub")) {
191 ktype = AST_KEY_PUBLIC;
192 }
else if (fnamelen > 4 && !strcmp((c = &fname[fnamelen - 4]),
".key")) {
193 ktype = AST_KEY_PRIVATE;
199 n = snprintf(ffname,
sizeof(ffname),
"%s/%s", dir, fname);
200 if (n >=
sizeof(ffname)) {
202 "Key filenames can be up to %zu bytes long, but the filename for the"
203 " key we are currently trying to load (%s/%s) is %d bytes long.",
204 sizeof(ffname) - 1, dir, fname, n);
209 if (!(f = fopen(ffname,
"r"))) {
210 ast_log(LOG_WARNING,
"Unable to open key file %s: %s\n", ffname, strerror(errno));
214 n = fstat(fileno(f), &st);
216 ast_log(LOG_ERROR,
"Unable to stat key file: %s: %s\n", ffname, strerror(errno));
221 if (!S_ISREG(st.st_mode)) {
222 ast_log(LOG_ERROR,
"Key file is not a regular file: %s\n", ffname);
230 #define FILE_MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
233 if (ktype == AST_KEY_PRIVATE &&
234 ((st.st_mode & FILE_MODE_BITS) & ~(S_IRUSR | S_IWUSR)) != 0) {
235 ast_log(LOG_ERROR,
"Private key file has bad permissions: %s: %#4o\n", ffname, st.st_mode & FILE_MODE_BITS);
240 ctx = EVP_MD_CTX_create();
242 ast_log(LOG_ERROR,
"Out of memory\n");
246 EVP_DigestInit(ctx, EVP_md5());
251 if (!fgets(buf,
sizeof(buf), f)) {
255 EVP_DigestUpdate(ctx, (
unsigned char *)buf, strlen(buf));
258 EVP_DigestFinal(ctx, digest, &digestlen);
259 EVP_MD_CTX_destroy(ctx);
262 AST_RWLIST_TRAVERSE(&
keys, key, list) {
263 if (!strcasecmp(key->
fn, ffname)) {
271 if (!memcmp(digest, key->
digest,
sizeof(digest)) &&
272 !(key->
ktype & KEY_NEEDS_PASSCODE)) {
293 snprintf(key->
name,
sizeof(key->
name),
"%.*s", (
int)(c - fname), fname);
305 if (ktype == AST_KEY_PUBLIC) {
306 PEM_read_PUBKEY(f, &key->
pkey,
pw_cb, key);
308 PEM_read_PrivateKey(f, &key->
pkey,
pw_cb, key);
312 if (EVP_PKEY_size(key->
pkey) == (AST_CRYPTO_RSA_KEY_BITS / 8)) {
314 key->
ktype &= ~KEY_NEEDS_PASSCODE;
315 ast_verb(3,
"Loaded %s key '%s'\n", key->
ktype == AST_KEY_PUBLIC ?
"PUBLIC" :
"PRIVATE", key->
name);
319 ast_log(LOG_NOTICE,
"Key '%s' is not expected size.\n", key->
name);
321 }
else if (key->
infd != -2) {
322 ast_log(LOG_WARNING,
"Key load %s '%s' failed\n", key->
ktype == AST_KEY_PUBLIC ?
"PUBLIC" :
"PRIVATE", key->
name);
324 ERR_print_errors_fp(stderr);
326 ERR_print_errors_fp(stderr);
329 ast_log(LOG_NOTICE,
"Key '%s' needs passcode.\n", key->
name);
330 key->
ktype |= KEY_NEEDS_PASSCODE;
332 if (!ast_opt_init_keys) {
333 ast_log(LOG_NOTICE,
"Add the '-i' flag to the asterisk command line if you want to automatically initialize passcodes at launch.\n");
345 AST_RWLIST_INSERT_TAIL(&
keys, key, list);
351 static int evp_pkey_sign(EVP_PKEY *pkey,
const unsigned char *in,
unsigned inlen,
unsigned char *sig,
unsigned *siglen,
unsigned padding)
353 EVP_PKEY_CTX *ctx = NULL;
357 if (*siglen < EVP_PKEY_size(pkey)) {
361 if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
366 if ((res = EVP_PKEY_sign_init(ctx)) <= 0) {
369 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
372 if ((res = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1())) <= 0) {
376 if ((res = EVP_PKEY_sign(ctx, sig, &_siglen, in, inlen)) <= 0) {
382 EVP_PKEY_CTX_free(ctx);
392 unsigned char digest[SHA_DIGEST_LENGTH];
393 unsigned digestlen, siglen = 128;
395 EVP_MD_CTX *ctx = NULL;
397 if (key->
ktype != AST_KEY_PRIVATE) {
398 ast_log(LOG_WARNING,
"Cannot sign with a public key\n");
402 if (siglen < EVP_PKEY_size(key->
pkey)) {
403 ast_log(LOG_WARNING,
"Signature buffer too small\n");
408 ctx = EVP_MD_CTX_create();
410 ast_log(LOG_ERROR,
"Out of memory\n");
413 EVP_DigestInit(ctx, EVP_sha1());
414 EVP_DigestUpdate(ctx, msg, msglen);
415 EVP_DigestFinal(ctx, digest, &digestlen);
416 EVP_MD_CTX_destroy(ctx);
419 if ((res = evp_pkey_sign(key->
pkey, digest,
sizeof(digest), dsig, &siglen, RSA_PKCS1_PADDING)) <= 0) {
420 ast_log(LOG_WARNING,
"RSA Signature (key %s) failed %d\n", key->
name, res);
424 if (siglen != EVP_PKEY_size(key->
pkey)) {
425 ast_log(LOG_WARNING,
"Unexpected signature length %u, expecting %d\n", siglen, EVP_PKEY_size(key->
pkey));
432 static int evp_pkey_decrypt(EVP_PKEY *pkey,
const unsigned char *in,
unsigned inlen,
unsigned char *out,
unsigned *outlen,
unsigned padding)
434 EVP_PKEY_CTX *ctx = NULL;
438 if (*outlen < EVP_PKEY_size(pkey)) {
442 if (inlen != EVP_PKEY_size(pkey)) {
446 if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
451 if ((res = EVP_PKEY_decrypt_init(ctx)) <= 0) {
454 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
458 if ((res = EVP_PKEY_decrypt(ctx, out, &_outlen, in, inlen)) <= 0) {
461 res = *outlen = _outlen;
464 EVP_PKEY_CTX_free(ctx);
475 unsigned pos = 0, dstlen, blocksize;
477 if (key->
ktype != AST_KEY_PRIVATE) {
478 ast_log(LOG_WARNING,
"Cannot decrypt with a public key\n");
482 blocksize = EVP_PKEY_size(key->
pkey);
484 if (srclen % blocksize) {
485 ast_log(LOG_NOTICE,
"Tried to decrypt something not a multiple of %u bytes\n", blocksize);
492 if ((res = evp_pkey_decrypt(key->
pkey, src, blocksize, dst, &dstlen, RSA_PKCS1_OAEP_PADDING)) <= 0) {
504 static int evp_pkey_encrypt(EVP_PKEY *pkey,
const unsigned char *in,
unsigned inlen,
unsigned char *out,
unsigned *outlen,
unsigned padding)
506 EVP_PKEY_CTX *ctx = NULL;
510 if (padding != RSA_PKCS1_OAEP_PADDING) {
511 ast_log(LOG_WARNING,
"Only OAEP padding is supported for now\n");
515 if (inlen > EVP_PKEY_size(pkey) - RSA_PKCS1_OAEP_PADDING_SIZE) {
519 if (*outlen < EVP_PKEY_size(pkey)) {
524 if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
528 if ((res = EVP_PKEY_encrypt_init(ctx)) <= 0) {
531 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
535 if ((res = EVP_PKEY_encrypt(ctx, out, &_outlen, in, inlen)) <= 0) {
538 res = *outlen = _outlen;
541 EVP_PKEY_CTX_free(ctx);
551 unsigned bytes, pos = 0, dstlen, blocksize;
554 if (key->
ktype != AST_KEY_PUBLIC) {
555 ast_log(LOG_WARNING,
"Cannot encrypt with a private key\n");
559 blocksize = EVP_PKEY_size(key->
pkey);
563 if (bytes > blocksize - RSA_PKCS1_OAEP_PADDING_SIZE) {
564 bytes = blocksize - RSA_PKCS1_OAEP_PADDING_SIZE;
568 if ((res = evp_pkey_encrypt(key->
pkey, src, bytes, dst, &dstlen, RSA_PKCS1_OAEP_PADDING)) != blocksize) {
569 ast_log(LOG_NOTICE,
"How odd, encrypted size is %d\n", res);
587 unsigned char dsig[128];
588 int siglen =
sizeof(dsig), res;
590 if (!(res =
ast_sign_bin(key, msg, strlen(msg), dsig))) {
598 static int evp_pkey_verify(EVP_PKEY *pkey,
const unsigned char *in,
unsigned inlen,
const unsigned char *sig,
unsigned siglen,
unsigned padding)
600 EVP_PKEY_CTX *ctx = NULL;
603 if (siglen < EVP_PKEY_size(pkey)) {
607 if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) {
612 if ((res = EVP_PKEY_verify_init(ctx)) <= 0) {
615 if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) {
618 if ((res = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1())) <= 0) {
621 if ((res = EVP_PKEY_verify(ctx, sig, siglen, in, inlen)) <= 0) {
626 EVP_PKEY_CTX_free(ctx);
636 unsigned char digest[SHA_DIGEST_LENGTH];
639 EVP_MD_CTX *ctx = NULL;
641 if (key->
ktype != AST_KEY_PUBLIC) {
644 ast_log(LOG_WARNING,
"Cannot check message signature with a private key\n");
649 ctx = EVP_MD_CTX_create();
651 ast_log(LOG_ERROR,
"Out of memory\n");
654 EVP_DigestInit(ctx, EVP_sha1());
655 EVP_DigestUpdate(ctx, msg, msglen);
656 EVP_DigestFinal(ctx, digest, &digestlen);
657 EVP_MD_CTX_destroy(ctx);
660 if (!(res = evp_pkey_verify(key->
pkey, (
const unsigned char *)digest,
sizeof(digest), (
unsigned char *)dsig, 128, RSA_PKCS1_PADDING))) {
675 unsigned char dsig[128];
680 ast_log(LOG_WARNING,
"Signature improper length (expect %d, got %d)\n", (
int)
sizeof(dsig), (
int)res);
702 if (key == NULL || ctx == NULL) {
705 memcpy(ctx->raw, key, AST_CRYPTO_AES_BLOCKSIZE / 8);
711 if (key == NULL || ctx == NULL) {
714 memcpy(ctx->raw, key, AST_CRYPTO_AES_BLOCKSIZE / 8);
718 static int evp_cipher_aes_encrypt(
const unsigned char *in,
unsigned char *out,
unsigned inlen,
const ast_aes_encrypt_key *key)
720 EVP_CIPHER_CTX *ctx = NULL;
721 int res, outlen, finallen;
722 unsigned char final[AST_CRYPTO_AES_BLOCKSIZE / 8];
724 if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
729 if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(), key->raw, NULL, 1)) <= 0) {
732 EVP_CIPHER_CTX_set_padding(ctx, 0);
733 if ((res = EVP_CipherUpdate(ctx, out, &outlen, in, inlen)) <= 0) {
737 if ((res = EVP_CipherFinal(ctx,
final, &finallen)) <= 0) {
744 EVP_CIPHER_CTX_free(ctx);
753 if ((res = evp_cipher_aes_encrypt(in, out, AST_CRYPTO_AES_BLOCKSIZE / 8, key)) <= 0) {
754 ast_log(LOG_ERROR,
"AES encryption failed\n");
759 static int evp_cipher_aes_decrypt(
const unsigned char *in,
unsigned char *out,
unsigned inlen,
const ast_aes_decrypt_key *key)
761 EVP_CIPHER_CTX *ctx = NULL;
762 int res, outlen, finallen;
763 unsigned char final[AST_CRYPTO_AES_BLOCKSIZE / 8];
765 if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
770 if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(), key->raw, NULL, 0)) <= 0) {
773 EVP_CIPHER_CTX_set_padding(ctx, 0);
774 if ((res = EVP_CipherUpdate(ctx, out, &outlen, in, inlen)) <= 0) {
778 if ((res = EVP_CipherFinal(ctx,
final, &finallen)) <= 0) {
785 EVP_CIPHER_CTX_free(ctx);
794 if ((res = evp_cipher_aes_decrypt(in, out, AST_CRYPTO_AES_BLOCKSIZE / 8, key)) <= 0) {
795 ast_log(LOG_ERROR,
"AES decryption failed\n");
806 static int crypto_load_cb(
const char *directory,
const char *file,
void *obj)
810 try_load_key(directory, file, on_file->ifd, on_file->ofd, &on_file->note);
827 AST_RWLIST_TRAVERSE(&
keys, key, list) {
832 ast_log(LOG_WARNING,
"Unable to open key directory '%s'\n", ast_config_AST_KEY_DIR);
836 ast_log(LOG_NOTICE,
"Please run the command 'keys init' to enter the passcodes for the keys\n");
840 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&
keys, key, list) {
843 AST_RWLIST_REMOVE_CURRENT(list);
845 EVP_PKEY_free(key->
pkey);
850 AST_RWLIST_TRAVERSE_SAFE_END;
855 static void md52sum(
char *sum,
unsigned char *md5)
858 for (x = 0; x < MD5_DIGEST_LENGTH; x++) {
859 sum += sprintf(sum,
"%02hhx", *(md5++));
872 #define FORMAT "%-18s %-8s %-16s %-33s\n"
875 char sum[MD5_DIGEST_LENGTH * 2 + 1];
883 " Displays information about RSA keys known by Asterisk\n";
889 ast_cli(a->fd, FORMAT,
"Key Name",
"Type",
"Status",
"Sum");
890 ast_cli(a->fd, FORMAT,
"------------------",
"--------",
"----------------",
"--------------------------------");
893 AST_RWLIST_TRAVERSE(&
keys, key, list) {
894 md52sum(sum, key->
digest);
895 ast_cli(a->fd, FORMAT, key->
name,
896 (key->
ktype & 0xf) == AST_KEY_PUBLIC ?
"PUBLIC" :
"PRIVATE",
897 key->
ktype & KEY_NEEDS_PASSCODE ?
"[Needs Passcode]" :
"[Loaded]", sum);
902 ast_cli(a->fd,
"\n%d known RSA keys.\n", count_keys);
920 char *kn, tmp[256] =
"";
927 " Initializes private keys (by reading in pass code from\n"
935 return CLI_SHOWUSAGE;
939 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&
keys, key, list) {
941 if (key->
ktype & KEY_NEEDS_PASSCODE) {
942 kn = key->
fn + strlen(ast_config_AST_KEY_DIR) + 1;
944 try_load_key(ast_config_AST_KEY_DIR, tmp, a->fd, a->fd, &ign);
947 AST_RWLIST_TRAVERSE_SAFE_END
965 static int reload(
void)
971 static int load_module(
void)
974 if (ast_opt_init_keys) {
983 static int unload_module(
void)
990 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"Cryptographic Digital Signatures",
991 .support_level = AST_MODULE_SUPPORT_CORE,
993 .unload = unload_module,
Asterisk main include file. File version handling, generic pbx functions.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static struct ast_key * try_load_key(const char *dir, const char *fname, int ifd, int ofd, int *not2)
load RSA key from file
descriptor for a cli entry.
int ast_hide_password(int fd)
Hide password.
Provide cryptographic signature routines.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
I/O Management (derived from Cheops-NG)
static char * handle_cli_keys_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
initialize all RSA keys
int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj, int max_depth)
Recursively iterate through files and directories up to max_depth.
int AST_OPTIONAL_API_NAME() ast_check_signature(struct ast_key *key, const char *msg, const char *sig)
base64 decode then sent to __ast_check_signature_bin
int ast_restore_tty(int fd, int oldstatus)
Restores TTY mode.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Asterisk file paths, configured in asterisk.conf.
int AST_OPTIONAL_API_NAME() ast_sign(struct ast_key *key, char *msg, char *sig)
wrapper for __ast_sign_bin then base64 encode it
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
int AST_OPTIONAL_API_NAME() ast_encrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
encrypt a message
General Definitions for Asterisk top level program Included by asterisk.h to handle platform-specific...
#define ast_calloc(num, len)
A wrapper for calloc()
int AST_OPTIONAL_API_NAME() ast_sign_bin(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig)
signs outgoing message with public key
int AST_OPTIONAL_API_NAME() ast_check_signature_bin(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig)
check signature of a message
Support for logging to various files, console and syslog Configuration in file logger.conf.
static void crypto_load(int ifd, int ofd)
refresh RSA keys from file
static char * handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
show the list of RSA keys
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_key *AST_OPTIONAL_API_NAME() ast_key_get(const char *kname, int ktype)
return the ast_key structure for name
Options provided by main asterisk program.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_OPTIONAL_API_NAME(name)
Expands to the name of the implementation function.
static int pw_cb(char *buf, int size, int rwflag, void *userdata)
setting of priv key
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
unsigned char digest[MD5_DIGEST_LENGTH]
int AST_OPTIONAL_API_NAME() ast_decrypt_bin(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key)
decrypt a message
static int crypto_init(void)
initialise the res_crypto module