From 97b3459bd249eb3ad4c5fc96732fadf447cd8e6d Mon Sep 17 00:00:00 2001 From: Philip Prindeville Date: Thu, 24 Mar 2022 13:22:05 -0600 Subject: [PATCH] res_crypto: Use EVP API's instead of legacy API's ASTERISK-30046 #close Change-Id: I5c738756de75fd27ebad54be144c0ac6193f21b2 --- channels/chan_iax2.c | 2 +- include/asterisk/crypto.h | 34 ++-- res/res_crypto.c | 378 ++++++++++++++++++++++++++++++++------ tests/test_crypto.c | 10 +- 4 files changed, 349 insertions(+), 75 deletions(-) diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 0d422507b8..ab6bd61638 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -6394,7 +6394,7 @@ static int invalid_key(ast_aes_decrypt_key *ecx) #ifdef HAVE_OPENSSL int i; for (i = 0; i < 60; i++) { - if (ecx->rd_key[i]) { + if (ecx->raw[i]) { return 0; /* stop if we encounter anything non-zero */ } } diff --git a/include/asterisk/crypto.h b/include/asterisk/crypto.h index da6add91b7..2a7ecf06ea 100644 --- a/include/asterisk/crypto.h +++ b/include/asterisk/crypto.h @@ -30,26 +30,22 @@ extern "C" { #include "asterisk/optional_api.h" #include "asterisk/logger.h" -#ifdef HAVE_CRYPTO -#include "openssl/aes.h" -typedef AES_KEY ast_aes_encrypt_key; -typedef AES_KEY ast_aes_decrypt_key; -#else /* !HAVE_CRYPTO */ -typedef char ast_aes_encrypt_key; -typedef char ast_aes_decrypt_key; -#endif /* HAVE_CRYPTO */ - /* We previously used the key length explicitly; replace with constant. * For now, Asterisk is limited to 1024 bit (128 byte) RSA keys. */ #define AST_CRYPTO_RSA_KEY_BITS 1024 #define AST_CRYPTO_AES_BLOCKSIZE 128 +struct aes_key { + unsigned char raw[AST_CRYPTO_AES_BLOCKSIZE / 8]; +}; + +typedef struct aes_key ast_aes_encrypt_key; +typedef struct aes_key ast_aes_decrypt_key; + #define AST_KEY_PUBLIC (1 << 0) #define AST_KEY_PRIVATE (1 << 1) -struct ast_key; - /*! * \brief Retrieve a key * \param kname Name of the key we are retrieving @@ -169,20 +165,24 @@ AST_OPTIONAL_API(int, ast_aes_set_decrypt_key, * \param in data to be encrypted * \param out pointer to a buffer to hold the encrypted output * \param ctx address of an aes encryption context filled in with ast_aes_set_encrypt_key + * \retval <= 0 failure + * \retval otherwise number of bytes in output buffer */ -AST_OPTIONAL_API(void, ast_aes_encrypt, - (const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx), - { ast_log(LOG_WARNING, "AES encryption disabled. Install OpenSSL.\n");return; }); +AST_OPTIONAL_API(int, ast_aes_encrypt, + (const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *key), + { ast_log(LOG_WARNING, "AES encryption disabled. Install OpenSSL.\n");return -1; }); /*! * \brief AES decrypt data * \param in encrypted data * \param out pointer to a buffer to hold the decrypted output * \param ctx address of an aes encryption context filled in with ast_aes_set_decrypt_key + * \retval <= 0 failure + * \retval otherwise number of bytes in output buffer */ -AST_OPTIONAL_API(void, ast_aes_decrypt, - (const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx), - { ast_log(LOG_WARNING, "AES encryption disabled. Install OpenSSL.\n");return; }); +AST_OPTIONAL_API(int, ast_aes_decrypt, + (const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *key), + { ast_log(LOG_WARNING, "AES encryption disabled. Install OpenSSL.\n");return -1; }); AST_OPTIONAL_API(int, ast_crypto_loaded, (void), { return 0; }); diff --git a/res/res_crypto.c b/res/res_crypto.c index 2a6a0e9339..efcee7cffd 100644 --- a/res/res_crypto.c +++ b/res/res_crypto.c @@ -35,14 +35,11 @@ #include /* for closedir, opendir, readdir, DIR */ -#define OPENSSL_SUPPRESS_DEPRECATED 1 - -#include /* for AES_decrypt, AES_encrypt, AES_set... */ #include /* for ERR_print_errors_fp */ #include /* for NID_sha1, RSA */ -#include /* for PEM_read_RSAPrivateKey, PEM_read_... */ -#include /* for RSA_free, RSA_private_decrypt, RSA */ -#include /* for SHA1 */ +#include /* for EVP_PKEY, EVP_sha1(), ... */ +#include /* for MD5_DIGEST_LENGTH */ +#include /* for SHA_DIGEST_LENGTH */ #include "asterisk/cli.h" /* for ast_cli, ast_cli_args, ast_cli_entry */ #include "asterisk/compat.h" /* for strcasecmp */ @@ -73,6 +70,11 @@ #define KEY_NEEDS_PASSCODE (1 << 16) +/* From RFC-2437, section 9.1.1 the padding size is 1+2*hLen, where + * the hLen for SHA-1 is 20 bytes (or 160 bits). + */ +#define RSA_PKCS1_OAEP_PADDING_SIZE (1 + 2 * SHA_DIGEST_LENGTH) + struct ast_key { /*! Name of entity */ char name[80]; @@ -80,8 +82,8 @@ struct ast_key { char fn[256]; /*! Key type (AST_KEY_PUB or AST_KEY_PRIV, along with flags from above) */ int ktype; - /*! RSA structure (if successfully loaded) */ - RSA *rsa; + /*! RSA key structure (if successfully loaded) */ + EVP_PKEY *pkey; /*! Whether we should be deleted */ int delme; /*! FD for input (or -1 if no input allowed, or -2 if we needed input) */ @@ -89,7 +91,7 @@ struct ast_key { /*! FD for output */ int outfd; /*! Last MD5 Digest */ - unsigned char digest[16]; + unsigned char digest[MD5_DIGEST_LENGTH]; AST_RWLIST_ENTRY(ast_key) list; }; @@ -172,9 +174,10 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, { int ktype = 0, found = 0; char *c = NULL, ffname[256]; - unsigned char digest[16]; + unsigned char digest[MD5_DIGEST_LENGTH]; + unsigned digestlen; FILE *f; - struct MD5Context md5; + EVP_MD_CTX *ctx = NULL; struct ast_key *key; static int notice = 0; @@ -196,7 +199,14 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, return NULL; } - MD5Init(&md5); + ctx = EVP_MD_CTX_create(); + if (ctx == NULL) { + ast_log(LOG_ERROR, "Out of memory\n"); + fclose(f); + return NULL; + } + EVP_DigestInit(ctx, EVP_md5()); + while (!feof(f)) { /* Calculate a "whatever" quality md5sum of the key */ char buf[256] = ""; @@ -204,10 +214,11 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, continue; } if (!feof(f)) { - MD5Update(&md5, (unsigned char *) buf, strlen(buf)); + EVP_DigestUpdate(ctx, (unsigned char *)buf, strlen(buf)); } } - MD5Final(digest, &md5); + EVP_DigestFinal(ctx, digest, &digestlen); + EVP_MD_CTX_destroy(ctx); /* Look for an existing key */ AST_RWLIST_TRAVERSE(&keys, key, list) { @@ -219,7 +230,7 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, if (key) { /* If the MD5 sum is the same, and it isn't awaiting a passcode then this is far enough */ - if (!memcmp(digest, key->digest, 16) && + if (!memcmp(digest, key->digest, sizeof(digest)) && !(key->ktype & KEY_NEEDS_PASSCODE)) { fclose(f); key->delme = 0; @@ -248,7 +259,7 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, /* Yes, assume we're going to be deleted */ key->delme = 1; /* Keep the key type */ - memcpy(key->digest, digest, 16); + memcpy(key->digest, digest, sizeof(key->digest)); /* Can I/O takes the FD we're given */ key->infd = ifd; key->outfd = ofd; @@ -256,13 +267,13 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, rewind(f); /* Now load the key with the right method */ if (ktype == AST_KEY_PUBLIC) { - key->rsa = PEM_read_RSA_PUBKEY(f, NULL, pw_cb, key); + PEM_read_PUBKEY(f, &key->pkey, pw_cb, key); } else { - key->rsa = PEM_read_RSAPrivateKey(f, NULL, pw_cb, key); + PEM_read_PrivateKey(f, &key->pkey, pw_cb, key); } fclose(f); - if (key->rsa) { - if (RSA_size(key->rsa) == 128) { + if (key->pkey) { + if (EVP_PKEY_size(key->pkey) == (AST_CRYPTO_RSA_KEY_BITS / 8)) { /* Key loaded okay */ key->ktype &= ~KEY_NEEDS_PASSCODE; ast_verb(3, "Loaded %s key '%s'\n", key->ktype == AST_KEY_PUBLIC ? "PUBLIC" : "PRIVATE", key->name); @@ -301,97 +312,231 @@ static struct ast_key *try_load_key(const char *dir, const char *fname, int ifd, return key; } +static int evp_pkey_sign(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, unsigned char *sig, unsigned *siglen, unsigned padding) +{ + EVP_PKEY_CTX *ctx = NULL; + int res = -1; + size_t _siglen; + + if (*siglen < EVP_PKEY_size(pkey)) { + return -1; + } + + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + return -1; + } + + do { + if ((res = EVP_PKEY_sign_init(ctx)) <= 0) { + break; + } + if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) { + break; + } + if ((res = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1())) <= 0) { + break; + } + _siglen = *siglen; + if ((res = EVP_PKEY_sign(ctx, sig, &_siglen, in, inlen)) <= 0) { + break; + } + *siglen = _siglen; + } while (0); + + EVP_PKEY_CTX_free(ctx); + return res; +} + /*! * \brief signs outgoing message with public key * \see ast_sign_bin */ int AST_OPTIONAL_API_NAME(ast_sign_bin)(struct ast_key *key, const char *msg, int msglen, unsigned char *dsig) { - unsigned char digest[20]; - unsigned int siglen = 128; + unsigned char digest[SHA_DIGEST_LENGTH]; + unsigned digestlen, siglen = 128; int res; + EVP_MD_CTX *ctx = NULL; if (key->ktype != AST_KEY_PRIVATE) { ast_log(LOG_WARNING, "Cannot sign with a public key\n"); return -1; } + if (siglen < EVP_PKEY_size(key->pkey)) { + ast_log(LOG_WARNING, "Signature buffer too small\n"); + return -1; + } + /* Calculate digest of message */ - SHA1((unsigned char *)msg, msglen, digest); + ctx = EVP_MD_CTX_create(); + if (ctx == NULL) { + ast_log(LOG_ERROR, "Out of memory\n"); + return -1; + } + EVP_DigestInit(ctx, EVP_sha1()); + EVP_DigestUpdate(ctx, msg, msglen); + EVP_DigestFinal(ctx, digest, &digestlen); + EVP_MD_CTX_destroy(ctx); /* Verify signature */ - if ((res = RSA_sign(NID_sha1, digest, sizeof(digest), dsig, &siglen, key->rsa)) != 1) { - ast_log(LOG_WARNING, "RSA Signature (key %s) failed\n", key->name); + if ((res = evp_pkey_sign(key->pkey, digest, sizeof(digest), dsig, &siglen, RSA_PKCS1_PADDING)) <= 0) { + ast_log(LOG_WARNING, "RSA Signature (key %s) failed %d\n", key->name, res); return -1; } - if (siglen != 128) { - ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128); + if (siglen != EVP_PKEY_size(key->pkey)) { + ast_log(LOG_WARNING, "Unexpected signature length %u, expecting %d\n", siglen, EVP_PKEY_size(key->pkey)); return -1; } return 0; } +static int evp_pkey_decrypt(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, unsigned char *out, unsigned *outlen, unsigned padding) +{ + EVP_PKEY_CTX *ctx = NULL; + int res = -1; + size_t _outlen; + + if (*outlen < EVP_PKEY_size(pkey)) { + return -1; + } + + if (inlen != EVP_PKEY_size(pkey)) { + return -1; + } + + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + return -1; + } + + do { + if ((res = EVP_PKEY_decrypt_init(ctx)) <= 0) { + break; + } + if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) { + break; + } + _outlen = *outlen; + if ((res = EVP_PKEY_decrypt(ctx, out, &_outlen, in, inlen)) <= 0) { + break; + } + res = *outlen = _outlen; + } while (0); + + EVP_PKEY_CTX_free(ctx); + return res; +} + /*! * \brief decrypt a message * \see ast_decrypt_bin */ int AST_OPTIONAL_API_NAME(ast_decrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) { - int res, pos = 0; + int res; + unsigned pos = 0, dstlen, blocksize; if (key->ktype != AST_KEY_PRIVATE) { ast_log(LOG_WARNING, "Cannot decrypt with a public key\n"); return -1; } - if (srclen % 128) { - ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of 128 bytes\n"); + blocksize = EVP_PKEY_size(key->pkey); + + if (srclen % blocksize) { + ast_log(LOG_NOTICE, "Tried to decrypt something not a multiple of %u bytes\n", blocksize); return -1; } - while (srclen) { + while (srclen > 0) { /* Process chunks 128 bytes at a time */ - if ((res = RSA_private_decrypt(128, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) < 0) { + dstlen = blocksize; + if ((res = evp_pkey_decrypt(key->pkey, src, blocksize, dst, &dstlen, RSA_PKCS1_OAEP_PADDING)) <= 0) { return -1; } - pos += res; - src += 128; - srclen -= 128; - dst += res; + pos += dstlen; + src += blocksize; + srclen -= blocksize; + dst += dstlen; } return pos; } +static int evp_pkey_encrypt(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, unsigned char *out, unsigned *outlen, unsigned padding) +{ + EVP_PKEY_CTX *ctx = NULL; + int res = -1; + size_t _outlen; + + if (padding != RSA_PKCS1_OAEP_PADDING) { + ast_log(LOG_WARNING, "Only OAEP padding is supported for now\n"); + return -1; + } + + if (inlen > EVP_PKEY_size(pkey) - RSA_PKCS1_OAEP_PADDING_SIZE) { + return -1; + } + + if (*outlen < EVP_PKEY_size(pkey)) { + return -1; + } + + do { + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + break; + } + + if ((res = EVP_PKEY_encrypt_init(ctx)) <= 0) { + break; + } + if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) { + break; + } + _outlen = *outlen; + if ((res = EVP_PKEY_encrypt(ctx, out, &_outlen, in, inlen)) <= 0) { + break; + } + res = *outlen = _outlen; + } while (0); + + EVP_PKEY_CTX_free(ctx); + return res; +} + /*! * \brief encrypt a message * \see ast_encrypt_bin */ int AST_OPTIONAL_API_NAME(ast_encrypt_bin)(unsigned char *dst, const unsigned char *src, int srclen, struct ast_key *key) { - int res, bytes, pos = 0; + unsigned bytes, pos = 0, dstlen, blocksize; + int res; if (key->ktype != AST_KEY_PUBLIC) { ast_log(LOG_WARNING, "Cannot encrypt with a private key\n"); return -1; } + blocksize = EVP_PKEY_size(key->pkey); + while (srclen) { bytes = srclen; - if (bytes > 128 - 41) { - bytes = 128 - 41; + if (bytes > blocksize - RSA_PKCS1_OAEP_PADDING_SIZE) { + bytes = blocksize - RSA_PKCS1_OAEP_PADDING_SIZE; } /* Process chunks 128-41 bytes at a time */ - if ((res = RSA_public_encrypt(bytes, src, dst, key->rsa, RSA_PKCS1_OAEP_PADDING)) != 128) { + dstlen = blocksize; + if ((res = evp_pkey_encrypt(key->pkey, src, bytes, dst, &dstlen, RSA_PKCS1_OAEP_PADDING)) != blocksize) { ast_log(LOG_NOTICE, "How odd, encrypted size is %d\n", res); return -1; } src += bytes; srclen -= bytes; - pos += res; - dst += res; + pos += dstlen; + dst += dstlen; } return pos; } @@ -402,6 +547,7 @@ int AST_OPTIONAL_API_NAME(ast_encrypt_bin)(unsigned char *dst, const unsigned ch */ int AST_OPTIONAL_API_NAME(ast_sign)(struct ast_key *key, char *msg, char *sig) { + /* assumes 1024 bit RSA key size */ unsigned char dsig[128]; int siglen = sizeof(dsig), res; @@ -413,14 +559,48 @@ int AST_OPTIONAL_API_NAME(ast_sign)(struct ast_key *key, char *msg, char *sig) return res; } +static int evp_pkey_verify(EVP_PKEY *pkey, const unsigned char *in, unsigned inlen, const unsigned char *sig, unsigned siglen, unsigned padding) +{ + EVP_PKEY_CTX *ctx = NULL; + int res = -1; + + if (siglen < EVP_PKEY_size(pkey)) { + return -1; + } + + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + return -1; + } + + do { + if ((res = EVP_PKEY_verify_init(ctx)) <= 0) { + break; + } + if ((res = EVP_PKEY_CTX_set_rsa_padding(ctx, padding)) <= 0) { + break; + } + if ((res = EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1())) <= 0) { + break; + } + if ((res = EVP_PKEY_verify(ctx, sig, siglen, in, inlen)) <= 0) { + break; + } + } while (0); + + EVP_PKEY_CTX_free(ctx); + return res; +} + /*! * \brief check signature of a message * \see ast_check_signature_bin */ int AST_OPTIONAL_API_NAME(ast_check_signature_bin)(struct ast_key *key, const char *msg, int msglen, const unsigned char *dsig) { - unsigned char digest[20]; + unsigned char digest[SHA_DIGEST_LENGTH]; + unsigned digestlen; int res; + EVP_MD_CTX *ctx = NULL; if (key->ktype != AST_KEY_PUBLIC) { /* Okay, so of course you really *can* but for our purposes @@ -430,10 +610,18 @@ int AST_OPTIONAL_API_NAME(ast_check_signature_bin)(struct ast_key *key, const ch } /* Calculate digest of message */ - SHA1((unsigned char *)msg, msglen, digest); + ctx = EVP_MD_CTX_create(); + if (ctx == NULL) { + ast_log(LOG_ERROR, "Out of memory\n"); + return -1; + } + EVP_DigestInit(ctx, EVP_sha1()); + EVP_DigestUpdate(ctx, msg, msglen); + EVP_DigestFinal(ctx, digest, &digestlen); + EVP_MD_CTX_destroy(ctx); /* Verify signature */ - if ((res = RSA_verify(NID_sha1, digest, sizeof(digest), (unsigned char *)dsig, 128, key->rsa)) != 1) { + if (!(res = evp_pkey_verify(key->pkey, (const unsigned char *)digest, sizeof(digest), (unsigned char *)dsig, 128, RSA_PKCS1_PADDING))) { ast_debug(1, "Key failed verification: %s\n", key->name); return -1; } @@ -475,22 +663,102 @@ int AST_OPTIONAL_API_NAME(ast_crypto_reload)(void) int AST_OPTIONAL_API_NAME(ast_aes_set_encrypt_key)(const unsigned char *key, ast_aes_encrypt_key *ctx) { - return AES_set_encrypt_key(key, 128, ctx); + if (key == NULL || ctx == NULL) { + return -1; + } + memcpy(ctx->raw, key, AST_CRYPTO_AES_BLOCKSIZE / 8); + return 0; } int AST_OPTIONAL_API_NAME(ast_aes_set_decrypt_key)(const unsigned char *key, ast_aes_decrypt_key *ctx) { - return AES_set_decrypt_key(key, 128, ctx); + if (key == NULL || ctx == NULL) { + return -1; + } + memcpy(ctx->raw, key, AST_CRYPTO_AES_BLOCKSIZE / 8); + return 0; } -void AST_OPTIONAL_API_NAME(ast_aes_encrypt)(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *ctx) +static int evp_cipher_aes_encrypt(const unsigned char *in, unsigned char *out, unsigned inlen, const ast_aes_encrypt_key *key) { - return AES_encrypt(in, out, ctx); + EVP_CIPHER_CTX *ctx = NULL; + int res, outlen, finallen; + unsigned char final[AST_CRYPTO_AES_BLOCKSIZE / 8]; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + return -1; + } + + do { + if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(), key->raw, NULL, 1)) <= 0) { + break; + } + EVP_CIPHER_CTX_set_padding(ctx, 0); + if ((res = EVP_CipherUpdate(ctx, out, &outlen, in, inlen)) <= 0) { + break; + } + /* for ECB, this is a no-op */ + if ((res = EVP_CipherFinal(ctx, final, &finallen)) <= 0) { + break; + } + + res = outlen; + } while (0); + + EVP_CIPHER_CTX_free(ctx); + + return res; } -void AST_OPTIONAL_API_NAME(ast_aes_decrypt)(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *ctx) +int AST_OPTIONAL_API_NAME(ast_aes_encrypt)(const unsigned char *in, unsigned char *out, const ast_aes_encrypt_key *key) { - return AES_decrypt(in, out, ctx); + int res; + + if ((res = evp_cipher_aes_encrypt(in, out, AST_CRYPTO_AES_BLOCKSIZE / 8, key)) <= 0) { + ast_log(LOG_ERROR, "AES encryption failed\n"); + } + return res; +} + +static int evp_cipher_aes_decrypt(const unsigned char *in, unsigned char *out, unsigned inlen, const ast_aes_decrypt_key *key) +{ + EVP_CIPHER_CTX *ctx = NULL; + int res, outlen, finallen; + unsigned char final[AST_CRYPTO_AES_BLOCKSIZE / 8]; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + return -1; + } + + do { + if ((res = EVP_CipherInit(ctx, EVP_aes_128_ecb(), key->raw, NULL, 0)) <= 0) { + break; + } + EVP_CIPHER_CTX_set_padding(ctx, 0); + if ((res = EVP_CipherUpdate(ctx, out, &outlen, in, inlen)) <= 0) { + break; + } + /* for ECB, this is a no-op */ + if ((res = EVP_CipherFinal(ctx, final, &finallen)) <= 0) { + break; + } + + res = outlen; + } while (0); + + EVP_CIPHER_CTX_free(ctx); + + return res; +} + +int AST_OPTIONAL_API_NAME(ast_aes_decrypt)(const unsigned char *in, unsigned char *out, const ast_aes_decrypt_key *key) +{ + int res; + + if ((res = evp_cipher_aes_decrypt(in, out, AST_CRYPTO_AES_BLOCKSIZE / 8, key)) <= 0) { + ast_log(LOG_ERROR, "AES decryption failed\n"); + } + return res; } /*! @@ -538,8 +806,8 @@ static void crypto_load(int ifd, int ofd) if (key->delme) { ast_debug(1, "Deleting key %s type %d\n", key->name, key->ktype); AST_RWLIST_REMOVE_CURRENT(list); - if (key->rsa) { - RSA_free(key->rsa); + if (key->pkey) { + EVP_PKEY_free(key->pkey); } ast_free(key); } @@ -552,7 +820,7 @@ static void crypto_load(int ifd, int ofd) static void md52sum(char *sum, unsigned char *md5) { int x; - for (x = 0; x < 16; x++) { + for (x = 0; x < MD5_DIGEST_LENGTH; x++) { sum += sprintf(sum, "%02hhx", *(md5++)); } } @@ -569,7 +837,7 @@ static char *handle_cli_keys_show(struct ast_cli_entry *e, int cmd, struct ast_c #define FORMAT "%-18s %-8s %-16s %-33s\n" struct ast_key *key; - char sum[16 * 2 + 1]; + char sum[MD5_DIGEST_LENGTH * 2 + 1]; int count_keys = 0; switch (cmd) { diff --git a/tests/test_crypto.c b/tests/test_crypto.c index 55497d611f..141781bfe0 100644 --- a/tests/test_crypto.c +++ b/tests/test_crypto.c @@ -498,7 +498,10 @@ AST_TEST_DEFINE(crypto_aes_encrypt) memset(buf, 0, sizeof(buf)); ast_aes_set_encrypt_key(key, &aes_key); - ast_aes_encrypt(plaintext, buf, &aes_key); + if (ast_aes_encrypt(plaintext, buf, &aes_key) <= 0) { + ast_test_status_update(test, "ast_aes_encrypt() failed\n"); + goto cleanup; + } args[KEY] = hexstring(key, sizeof(key)); if (ast_test_capture_command(&cap, command, args, (const char *)buf, sizeof(buf)) != 1) { @@ -594,7 +597,10 @@ AST_TEST_DEFINE(crypto_aes_decrypt) memset(buf, 0, sizeof(buf)); ast_aes_set_decrypt_key(key, &aes_key); - ast_aes_decrypt((const unsigned char *)cap.outbuf, buf, &aes_key); + if (ast_aes_decrypt((const unsigned char *)cap.outbuf, buf, &aes_key) <= 0) { + ast_test_status_update(test, "ast_aes_decrypt() failed\n"); + goto cleanup; + } if (memcmp(plaintext, buf, sizeof(plaintext))) { ast_test_status_update(test, "AES decryption mismatch\n");