[Asterisk-code-review] res_crypto: Use EVP API's instead of legacy API's (asterisk[master])

Friendly Automation asteriskteam at digium.com
Mon Sep 12 18:07:35 CDT 2022


Friendly Automation has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/18534 )

Change subject: res_crypto: Use EVP API's instead of legacy API's
......................................................................

res_crypto: Use EVP API's instead of legacy API's

ASTERISK-30046 #close

Change-Id: I5c738756de75fd27ebad54be144c0ac6193f21b2
---
M channels/chan_iax2.c
M include/asterisk/crypto.h
M res/res_crypto.c
M tests/test_crypto.c
4 files changed, 363 insertions(+), 78 deletions(-)

Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit




diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 0d42250..ab6bd61 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -6394,7 +6394,7 @@
 #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 da6add9..2a7ecf0 100644
--- a/include/asterisk/crypto.h
+++ b/include/asterisk/crypto.h
@@ -30,26 +30,22 @@
 #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 @@
  * \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 2a6a0e9..efcee7c 100644
--- a/res/res_crypto.c
+++ b/res/res_crypto.c
@@ -35,14 +35,11 @@
 
 #include <dirent.h>                 /* for closedir, opendir, readdir, DIR */
 
-#define OPENSSL_SUPPRESS_DEPRECATED 1
-
-#include <openssl/aes.h>            /* for AES_decrypt, AES_encrypt, AES_set... */
 #include <openssl/err.h>            /* for ERR_print_errors_fp */
 #include <openssl/ssl.h>            /* for NID_sha1, RSA */
-#include <openssl/pem.h>            /* for PEM_read_RSAPrivateKey, PEM_read_... */
-#include <openssl/rsa.h>            /* for RSA_free, RSA_private_decrypt, RSA */
-#include <openssl/sha.h>            /* for SHA1 */
+#include <openssl/evp.h>            /* for EVP_PKEY, EVP_sha1(), ... */
+#include <openssl/md5.h>            /* for MD5_DIGEST_LENGTH */
+#include <openssl/sha.h>            /* 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 @@
 	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 @@
 	/*! 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 @@
 {
 	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 @@
 		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 @@
 			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 @@
 	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 @@
 	/* 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 @@
 	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 @@
 	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;
 	}
 
-	/* Calculate digest of message */
-	SHA1((unsigned char *)msg, msglen, digest);
-
-	/* 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 (siglen < EVP_PKEY_size(key->pkey)) {
+		ast_log(LOG_WARNING, "Signature buffer too small\n");
 		return -1;
 	}
 
-	if (siglen != 128) {
-		ast_log(LOG_WARNING, "Unexpected signature length %d, expecting %d\n", (int)siglen, (int)128);
+	/* Calculate digest of message */
+	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 = 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 != 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_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 @@
 	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 @@
 	}
 
 	/* 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_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 @@
 		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 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 @@
 #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 55497d6..141781b 100644
--- a/tests/test_crypto.c
+++ b/tests/test_crypto.c
@@ -498,7 +498,10 @@
 
 	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 @@
 
 	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");

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/18534
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I5c738756de75fd27ebad54be144c0ac6193f21b2
Gerrit-Change-Number: 18534
Gerrit-PatchSet: 30
Gerrit-Owner: Philip Prindeville <philipp at redfish-solutions.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at sangoma.com>
Gerrit-Reviewer: Sean Bright <sean at seanbright.com>
Gerrit-CC: Stanislav Abramenkov <stas.abramenkov at gmail.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220912/80f7120a/attachment-0001.html>


More information about the asterisk-code-review mailing list