<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19142">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

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

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: I5c738756de75fd27ebad54be144c0ac6193f21b2 </div>
<div style="display:none"> Gerrit-Change-Number: 19142 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Philip Prindeville <philipp@redfish-solutions.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>