Browse Source

Merge pull request #5942 from bandi13/evpaesccm

Evpaesccm
John Safranek 1 year ago
parent
commit
86aa3cc836
4 changed files with 833 additions and 94 deletions
  1. 10 2
      src/ssl.c
  2. 250 3
      tests/api.c
  3. 543 77
      wolfcrypt/src/evp.c
  4. 30 12
      wolfssl/openssl/evp.h

+ 10 - 2
src/ssl.c

@@ -39315,7 +39315,7 @@ int wolfSSL_RAND_poll(void)
             case AES_192_CBC_TYPE :
             case AES_256_CBC_TYPE :
                 WOLFSSL_MSG("AES CBC");
-                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz);
                 break;
 #endif
 #ifdef HAVE_AESGCM
@@ -39323,9 +39323,17 @@ int wolfSSL_RAND_poll(void)
             case AES_192_GCM_TYPE :
             case AES_256_GCM_TYPE :
                 WOLFSSL_MSG("AES GCM");
-                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE);
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz);
                 break;
 #endif /* HAVE_AESGCM */
+#ifdef HAVE_AESCCM
+            case AES_128_CCM_TYPE :
+            case AES_192_CCM_TYPE :
+            case AES_256_CCM_TYPE :
+                WOLFSSL_MSG("AES CCM");
+                XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, ctx->ivSz);
+                break;
+#endif /* HAVE_AESCCM */
 #ifdef HAVE_AES_ECB
             case AES_128_ECB_TYPE :
             case AES_192_ECB_TYPE :

+ 250 - 3
tests/api.c

@@ -45475,12 +45475,47 @@ static int test_wolfSSL_EVP_md4(void)
 
 static int test_wolfSSL_EVP_aes_256_gcm(void)
 {
-    return TEST_RES_CHECK(wolfSSL_EVP_aes_256_gcm() != NULL);
+    int res = TEST_SKIPPED;
+#ifdef HAVE_AESGCM
+    res = TEST_RES_CHECK(wolfSSL_EVP_aes_256_gcm() != NULL);
+#endif
+    return res;
 }
 
 static int test_wolfSSL_EVP_aes_192_gcm(void)
 {
-    return TEST_RES_CHECK(wolfSSL_EVP_aes_192_gcm() != NULL);
+    int res = TEST_SKIPPED;
+#ifdef HAVE_AESGCM
+    res = TEST_RES_CHECK(wolfSSL_EVP_aes_192_gcm() != NULL);
+#endif
+    return res;
+}
+
+static int test_wolfSSL_EVP_aes_256_ccm(void)
+{
+    int res = TEST_SKIPPED;
+#ifdef HAVE_AESCCM
+    res = TEST_RES_CHECK(wolfSSL_EVP_aes_256_ccm() != NULL);
+#endif
+    return res;
+}
+
+static int test_wolfSSL_EVP_aes_192_ccm(void)
+{
+    int res = TEST_SKIPPED;
+#ifdef HAVE_AESCCM
+    res = TEST_RES_CHECK(wolfSSL_EVP_aes_192_ccm() != NULL);
+#endif
+    return res;
+}
+
+static int test_wolfSSL_EVP_aes_128_ccm(void)
+{
+    int res = TEST_SKIPPED;
+#ifdef HAVE_AESCCM
+    res = TEST_RES_CHECK(wolfSSL_EVP_aes_128_ccm() != NULL);
+#endif
+    return res;
 }
 
 static int test_wolfSSL_EVP_ripemd160(void)
@@ -45642,6 +45677,21 @@ static int test_wolfSSL_EVP_CIPHER_block_size(void)
     }
 #endif
 
+#ifdef HAVE_AESCCM
+    if (res == TEST_SKIPPED || res == TEST_SUCCESS) {
+        #ifdef WOLFSSL_AES_128
+        AssertIntEQ(EVP_CIPHER_block_size(EVP_aes_128_ccm()), 1);
+        #endif
+        #ifdef WOLFSSL_AES_192
+        AssertIntEQ(EVP_CIPHER_block_size(EVP_aes_192_ccm()), 1);
+        #endif
+        #ifdef WOLFSSL_AES_256
+        AssertIntEQ(EVP_CIPHER_block_size(EVP_aes_256_ccm()), 1);
+        #endif
+        res = TEST_RES_CHECK(1);
+    }
+#endif
+
 #ifdef WOLFSSL_AES_COUNTER
     if (res == TEST_SKIPPED || res == TEST_SUCCESS) {
         #ifdef WOLFSSL_AES_128
@@ -46151,7 +46201,7 @@ static int test_evp_cipher_aes_gcm(void)
 
             /*
              * The call to EVP_CipherInit below (with NULL key) should clear the
-             * gcmIvGenEnable flag set by EVP_CTRL_GCM_SET_IV_FIXED. As such, a
+             * authIvGenEnable flag set by EVP_CTRL_GCM_SET_IV_FIXED. As such, a
              * subsequent EVP_CTRL_GCM_IV_GEN should fail. This matches OpenSSL
              * behavior.
              */
@@ -52162,6 +52212,198 @@ static int test_wolfssl_EVP_aes_gcm(void)
     return res;
 }
 
+static int test_wolfssl_EVP_aes_ccm_zeroLen(void)
+{
+    int res = TEST_SKIPPED;
+#if defined(OPENSSL_EXTRA) && !defined(NO_AES) && defined(HAVE_AESCCM) && \
+    !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+    /* Zero length plain text */
+
+    byte key[] = {
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+    }; /* align */
+    byte iv[]  = {
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+    }; /* align */
+    byte plaintxt[1];
+    int ivSz  = 12;
+    int plaintxtSz = 0;
+    unsigned char tag[16];
+
+    byte ciphertxt[AES_BLOCK_SIZE * 4] = {0};
+    byte decryptedtxt[AES_BLOCK_SIZE * 4] = {0};
+    int ciphertxtSz = 0;
+    int decryptedtxtSz = 0;
+    int len = 0;
+
+    EVP_CIPHER_CTX *en = EVP_CIPHER_CTX_new();
+    EVP_CIPHER_CTX *de = EVP_CIPHER_CTX_new();
+
+    AssertIntEQ(1, EVP_EncryptInit_ex(en, EVP_aes_256_ccm(), NULL, key, iv));
+    AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_CCM_SET_IVLEN, ivSz, NULL));
+    AssertIntEQ(1, EVP_EncryptUpdate(en, ciphertxt, &ciphertxtSz , plaintxt,
+                                     plaintxtSz));
+    AssertIntEQ(1, EVP_EncryptFinal_ex(en, ciphertxt, &len));
+    ciphertxtSz += len;
+    AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(en, EVP_CTRL_CCM_GET_TAG, 16, tag));
+    AssertIntEQ(1, EVP_CIPHER_CTX_cleanup(en));
+
+    AssertIntEQ(0, ciphertxtSz);
+
+    EVP_CIPHER_CTX_init(de);
+    AssertIntEQ(1, EVP_DecryptInit_ex(de, EVP_aes_256_ccm(), NULL, key, iv));
+    AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(de, EVP_CTRL_CCM_SET_IVLEN, ivSz, NULL));
+    AssertIntEQ(1, EVP_DecryptUpdate(de, NULL, &len, ciphertxt, len));
+    decryptedtxtSz = len;
+    AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(de, EVP_CTRL_CCM_SET_TAG, 16, tag));
+    AssertIntEQ(1, EVP_DecryptFinal_ex(de, decryptedtxt, &len));
+    decryptedtxtSz += len;
+    AssertIntEQ(0, decryptedtxtSz);
+
+    EVP_CIPHER_CTX_free(en);
+    EVP_CIPHER_CTX_free(de);
+
+    res = TEST_RES_CHECK(1);
+#endif
+    return res;
+}
+
+static int test_wolfssl_EVP_aes_ccm(void)
+{
+    int res = TEST_SKIPPED;
+#if defined(OPENSSL_EXTRA) && !defined(NO_AES) && defined(HAVE_AESCCM) && \
+    !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS)
+
+    /* A 256 bit key, AES_128 will use the first 128 bit*/
+    byte *key = (byte*)"01234567890123456789012345678901";
+    /* A 128 bit IV */
+    byte *iv = (byte*)"0123456789012";
+    int ivSz = (int)XSTRLEN((char*)iv);
+    /* Message to be encrypted */
+    byte *plaintxt = (byte*)"for things to change you have to change";
+    /* Additional non-confidential data */
+    byte *aad = (byte*)"Don't spend major time on minor things.";
+
+    unsigned char tag[AES_BLOCK_SIZE] = {0};
+    int plaintxtSz = (int)XSTRLEN((char*)plaintxt);
+    int aadSz = (int)XSTRLEN((char*)aad);
+    byte ciphertxt[AES_BLOCK_SIZE * 4] = {0};
+    byte decryptedtxt[AES_BLOCK_SIZE * 4] = {0};
+    int ciphertxtSz = 0;
+    int decryptedtxtSz = 0;
+    int len = 0;
+    int i = 0;
+    EVP_CIPHER_CTX en[2];
+    EVP_CIPHER_CTX de[2];
+
+    for (i = 0; i < 2; i++) {
+
+        EVP_CIPHER_CTX_init(&en[i]);
+
+        if (i == 0) {
+            /* Default uses 96-bits IV length */
+#ifdef WOLFSSL_AES_128
+            AssertIntEQ(1, EVP_EncryptInit_ex(&en[i],
+                        EVP_aes_128_ccm(), NULL, key, iv));
+#elif defined(WOLFSSL_AES_192)
+            AssertIntEQ(1, EVP_EncryptInit_ex(&en[i],
+                        EVP_aes_192_ccm(), NULL, key, iv));
+#elif defined(WOLFSSL_AES_256)
+            AssertIntEQ(1, EVP_EncryptInit_ex(&en[i],
+                        EVP_aes_256_ccm(), NULL, key, iv));
+#endif
+        }
+        else {
+#ifdef WOLFSSL_AES_128
+            AssertIntEQ(1, EVP_EncryptInit_ex(&en[i],
+                        EVP_aes_128_ccm(), NULL, NULL, NULL));
+#elif defined(WOLFSSL_AES_192)
+            AssertIntEQ(1, EVP_EncryptInit_ex(&en[i],
+                        EVP_aes_192_ccm(), NULL, NULL, NULL));
+#elif defined(WOLFSSL_AES_256)
+            AssertIntEQ(1, EVP_EncryptInit_ex(&en[i],
+                        EVP_aes_256_ccm(), NULL, NULL, NULL));
+#endif
+             /* non-default must to set the IV length first */
+            AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&en[i],
+                        EVP_CTRL_CCM_SET_IVLEN, ivSz, NULL));
+            AssertIntEQ(1, EVP_EncryptInit_ex(&en[i],
+                        NULL, NULL, key, iv));
+        }
+        AssertIntEQ(1, EVP_EncryptUpdate(&en[i], NULL, &len, aad, aadSz));
+        AssertIntEQ(1, EVP_EncryptUpdate(&en[i],
+                    ciphertxt, &len, plaintxt, plaintxtSz));
+        ciphertxtSz = len;
+        AssertIntEQ(1, EVP_EncryptFinal_ex(&en[i], ciphertxt, &len));
+        ciphertxtSz += len;
+        AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&en[i],
+                    EVP_CTRL_CCM_GET_TAG, AES_BLOCK_SIZE, tag));
+        AssertIntEQ(wolfSSL_EVP_CIPHER_CTX_cleanup(&en[i]), 1);
+
+        EVP_CIPHER_CTX_init(&de[i]);
+        if (i == 0) {
+            /* Default uses 96-bits IV length */
+#ifdef WOLFSSL_AES_128
+            AssertIntEQ(1, EVP_DecryptInit_ex(&de[i],
+                        EVP_aes_128_ccm(), NULL, key, iv));
+#elif defined(WOLFSSL_AES_192)
+            AssertIntEQ(1, EVP_DecryptInit_ex(&de[i],
+                        EVP_aes_192_ccm(), NULL, key, iv));
+#elif defined(WOLFSSL_AES_256)
+            AssertIntEQ(1, EVP_DecryptInit_ex(&de[i],
+                        EVP_aes_256_ccm(), NULL, key, iv));
+#endif
+        }
+        else {
+#ifdef WOLFSSL_AES_128
+            AssertIntEQ(1, EVP_DecryptInit_ex(&de[i],
+                        EVP_aes_128_ccm(), NULL, NULL, NULL));
+#elif defined(WOLFSSL_AES_192)
+            AssertIntEQ(1, EVP_DecryptInit_ex(&de[i],
+                        EVP_aes_192_ccm(), NULL, NULL, NULL));
+#elif defined(WOLFSSL_AES_256)
+            AssertIntEQ(1, EVP_DecryptInit_ex(&de[i],
+                        EVP_aes_256_ccm(), NULL, NULL, NULL));
+#endif
+            /* non-default must to set the IV length first */
+            AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i],
+                        EVP_CTRL_CCM_SET_IVLEN, ivSz, NULL));
+            AssertIntEQ(1, EVP_DecryptInit_ex(&de[i], NULL, NULL, key, iv));
+
+        }
+        AssertIntEQ(1, EVP_DecryptUpdate(&de[i], NULL, &len, aad, aadSz));
+        AssertIntEQ(1, EVP_DecryptUpdate(&de[i],
+                    decryptedtxt, &len, ciphertxt, ciphertxtSz));
+        decryptedtxtSz = len;
+        AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i],
+                    EVP_CTRL_CCM_SET_TAG, AES_BLOCK_SIZE, tag));
+        AssertIntEQ(1, EVP_DecryptFinal_ex(&de[i],
+                    decryptedtxt, &len));
+        decryptedtxtSz += len;
+        AssertIntEQ(ciphertxtSz, decryptedtxtSz);
+        AssertIntEQ(0, XMEMCMP(plaintxt, decryptedtxt, decryptedtxtSz));
+
+        /* modify tag*/
+        tag[AES_BLOCK_SIZE-1]+=0xBB;
+        AssertIntEQ(1, EVP_DecryptUpdate(&de[i], NULL, &len, aad, aadSz));
+        AssertIntEQ(1, EVP_CIPHER_CTX_ctrl(&de[i],
+                    EVP_CTRL_CCM_SET_TAG, AES_BLOCK_SIZE, tag));
+        /* fail due to wrong tag */
+        AssertIntEQ(1, EVP_DecryptUpdate(&de[i],
+                    decryptedtxt, &len, ciphertxt, ciphertxtSz));
+        AssertIntEQ(0, EVP_DecryptFinal_ex(&de[i], decryptedtxt, &len));
+        AssertIntEQ(0, len);
+        AssertIntEQ(wolfSSL_EVP_CIPHER_CTX_cleanup(&de[i]), 1);
+    }
+
+    res = TEST_RES_CHECK(1);
+#endif /* OPENSSL_EXTRA && !NO_AES && HAVE_AESCCM */
+    return res;
+}
+
 static int test_wolfssl_EVP_chacha20_poly1305(void)
 {
     int res = TEST_SKIPPED;
@@ -60090,6 +60332,8 @@ TEST_CASE testCases[] = {
     TEST_DECL(test_wolfssl_EVP_aes_gcm_AAD_2_parts),
     TEST_DECL(test_wolfssl_EVP_aes_gcm),
     TEST_DECL(test_wolfssl_EVP_aes_gcm_zeroLen),
+    TEST_DECL(test_wolfssl_EVP_aes_ccm),
+    TEST_DECL(test_wolfssl_EVP_aes_ccm_zeroLen),
     TEST_DECL(test_wolfssl_EVP_chacha20_poly1305),
     TEST_DECL(test_wolfssl_EVP_chacha20),
     TEST_DECL(test_wolfSSL_EVP_PKEY_hkdf),
@@ -60148,6 +60392,9 @@ TEST_CASE testCases[] = {
     TEST_DECL(test_wolfSSL_EVP_md4),
     TEST_DECL(test_wolfSSL_EVP_aes_256_gcm),
     TEST_DECL(test_wolfSSL_EVP_aes_192_gcm),
+    TEST_DECL(test_wolfSSL_EVP_aes_256_ccm),
+    TEST_DECL(test_wolfSSL_EVP_aes_192_ccm),
+    TEST_DECL(test_wolfSSL_EVP_aes_128_ccm),
     TEST_DECL(test_wolfSSL_EVP_ripemd160),
     TEST_DECL(test_wolfSSL_EVP_get_digestbynid),
     TEST_DECL(test_wolfSSL_EVP_MD_nid),

+ 543 - 77
wolfcrypt/src/evp.c

@@ -125,6 +125,18 @@
         #endif
     #endif /* HAVE_AESGCM */
 
+    #ifdef HAVE_AESCCM
+        #ifdef WOLFSSL_AES_128
+            static const char EVP_AES_128_CCM[] = "AES-128-CCM";
+        #endif
+        #ifdef WOLFSSL_AES_192
+            static const char EVP_AES_192_CCM[] = "AES-192-CCM";
+        #endif
+        #ifdef WOLFSSL_AES_256
+            static const char EVP_AES_256_CCM[] = "AES-256-CCM";
+        #endif
+    #endif /* HAVE_AESCCM */
+
     #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128
         static const char EVP_AES_128_CTR[] = "AES-128-CTR";
@@ -231,6 +243,11 @@ int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c)
       case AES_192_GCM_TYPE: return 24;
       case AES_256_GCM_TYPE: return 32;
   #endif
+  #if defined(HAVE_AESCCM)
+      case AES_128_CCM_TYPE: return 16;
+      case AES_192_CCM_TYPE: return 24;
+      case AES_256_CCM_TYPE: return 32;
+  #endif
   #if defined(WOLFSSL_AES_COUNTER)
       case AES_128_CTR_TYPE: return 16;
       case AES_192_CTR_TYPE: return 24;
@@ -567,12 +584,12 @@ static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx,
 static int wolfSSL_EVP_CipherUpdate_GCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx,
         const unsigned char *in, int inl) {
     if (in && inl > 0) {
-        byte* tmp = (byte*)XREALLOC(ctx->gcmAuthIn,
-                ctx->gcmAuthInSz + inl, NULL, DYNAMIC_TYPE_OPENSSL);
+        byte* tmp = (byte*)XREALLOC(ctx->authIn,
+                ctx->authInSz + inl, NULL, DYNAMIC_TYPE_OPENSSL);
         if (tmp) {
-            ctx->gcmAuthIn = tmp;
-            XMEMCPY(ctx->gcmAuthIn + ctx->gcmAuthInSz, in, inl);
-            ctx->gcmAuthInSz += inl;
+            ctx->authIn = tmp;
+            XMEMCPY(ctx->authIn + ctx->authInSz, in, inl);
+            ctx->authInSz += inl;
         }
         else {
             WOLFSSL_MSG("realloc error");
@@ -595,13 +612,13 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
         /* Buffer input for one-shot API */
         if (inl > 0) {
             byte* tmp;
-            tmp = (byte*)XREALLOC(ctx->gcmBuffer,
-                    ctx->gcmBufferLen + inl, NULL,
+            tmp = (byte*)XREALLOC(ctx->authBuffer,
+                    ctx->authBufferLen + inl, NULL,
                     DYNAMIC_TYPE_OPENSSL);
             if (tmp) {
-                XMEMCPY(tmp + ctx->gcmBufferLen, in, inl);
-                ctx->gcmBufferLen += inl;
-                ctx->gcmBuffer = tmp;
+                XMEMCPY(tmp + ctx->authBufferLen, in, inl);
+                ctx->authBufferLen += inl;
+                ctx->authBuffer = tmp;
                 *outl = 0;
             }
             else {
@@ -656,6 +673,63 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
 }
 #endif /* HAVE_AESGCM */
 
+#if defined(HAVE_AESCCM)
+static int wolfSSL_EVP_CipherUpdate_CCM_AAD(WOLFSSL_EVP_CIPHER_CTX *ctx,
+        const unsigned char *in, int inl) {
+    if (in && inl > 0) {
+        byte* tmp = (byte*)XREALLOC(ctx->authIn,
+                ctx->authInSz + inl, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (tmp) {
+            ctx->authIn = tmp;
+            XMEMCPY(ctx->authIn + ctx->authInSz, in, inl);
+            ctx->authInSz += inl;
+        }
+        else {
+            WOLFSSL_MSG("realloc error");
+            return MEMORY_E;
+        }
+    }
+    return 0;
+}
+
+static int wolfSSL_EVP_CipherUpdate_CCM(WOLFSSL_EVP_CIPHER_CTX *ctx,
+                                   unsigned char *out, int *outl,
+                                   const unsigned char *in, int inl)
+{
+    int ret = 0;
+
+    *outl = inl;
+    if (out) {
+        /* Buffer input for one-shot API */
+        if (inl > 0) {
+            byte* tmp;
+            tmp = (byte*)XREALLOC(ctx->authBuffer,
+                    ctx->authBufferLen + inl, NULL,
+                    DYNAMIC_TYPE_OPENSSL);
+            if (tmp) {
+                XMEMCPY(tmp + ctx->authBufferLen, in, inl);
+                ctx->authBufferLen += inl;
+                ctx->authBuffer = tmp;
+                *outl = 0;
+            }
+            else {
+                ret = MEMORY_E;
+            }
+        }
+    }
+    else {
+        ret = wolfSSL_EVP_CipherUpdate_CCM_AAD(ctx, in, inl);
+    }
+
+    if (ret != 0) {
+        *outl = 0;
+        return WOLFSSL_FAILURE;
+    }
+
+    return WOLFSSL_SUCCESS;
+}
+#endif /* HAVE_AESCCM */
+
 /* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */
 int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
                                    unsigned char *out, int *outl,
@@ -682,9 +756,17 @@ int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
         case AES_128_GCM_TYPE:
         case AES_192_GCM_TYPE:
         case AES_256_GCM_TYPE:
-            /* if out == NULL, in/inl contains the additional authenticated data             * for GCM */
+            /* if out == NULL, in/inl contains the additional auth data */
             return wolfSSL_EVP_CipherUpdate_GCM(ctx, out, outl, in, inl);
 #endif /* !defined(NO_AES) && defined(HAVE_AESGCM) */
+#if !defined(NO_AES) && defined(HAVE_AESCCM)
+        case AES_128_CCM_TYPE:
+        case AES_192_CCM_TYPE:
+        case AES_256_CCM_TYPE:
+            /* if out == NULL, in/inl contains the
+             * additional auth data */
+            return wolfSSL_EVP_CipherUpdate_CCM(ctx, out, outl, in, inl);
+#endif /* !defined(NO_AES) && defined(HAVE_AESCCM) */
 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
         case CHACHA20_POLY1305_TYPE:
             if (out == NULL) {
@@ -842,8 +924,9 @@ static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff)
     return ctx->block_size - n;
 }
 
-#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
-    || FIPS_VERSION_GE(2,0))
+#if (defined(HAVE_AESGCM) || defined(HAVE_AESCCM)) && \
+        ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+            || FIPS_VERSION_GE(2,0))
 static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz)
 {
     int i;
@@ -860,8 +943,9 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
 {
     int fl;
     int ret = WOLFSSL_SUCCESS;
-#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
-    || FIPS_VERSION_GE(2,0))
+#if (defined(HAVE_AESGCM) || defined(HAVE_AESCCM)) && \
+        ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+            || FIPS_VERSION_GE(2,0))
     byte tmp = 0;
 #endif
 
@@ -876,36 +960,36 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
         case AES_192_GCM_TYPE:
         case AES_256_GCM_TYPE:
 #ifndef WOLFSSL_AESGCM_STREAM
-            if ((ctx->gcmBuffer && ctx->gcmBufferLen > 0)
-             || (ctx->gcmBufferLen == 0)) {
+            if ((ctx->authBuffer && ctx->authBufferLen > 0)
+             || (ctx->authBufferLen == 0)) {
                 if (ctx->enc)
                     ret = wc_AesGcmEncrypt(&ctx->cipher.aes, out,
-                            ctx->gcmBuffer, ctx->gcmBufferLen,
+                            ctx->authBuffer, ctx->authBufferLen,
                             ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                            ctx->gcmAuthIn, ctx->gcmAuthInSz);
+                            ctx->authIn, ctx->authInSz);
                 else
                     ret = wc_AesGcmDecrypt(&ctx->cipher.aes, out,
-                            ctx->gcmBuffer, ctx->gcmBufferLen,
+                            ctx->authBuffer, ctx->authBufferLen,
                             ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
-                            ctx->gcmAuthIn, ctx->gcmAuthInSz);
+                            ctx->authIn, ctx->authInSz);
 
                 if (ret == 0) {
                     ret = WOLFSSL_SUCCESS;
-                    *outl = ctx->gcmBufferLen;
+                    *outl = ctx->authBufferLen;
                 }
                 else {
                     ret = WOLFSSL_FAILURE;
                     *outl = 0;
                 }
 
-                XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
-                ctx->gcmBuffer = NULL;
-                ctx->gcmBufferLen = 0;
+                XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
+                ctx->authBuffer = NULL;
+                ctx->authBufferLen = 0;
 
-                if (ctx->gcmIncIv) {
+                if (ctx->authIncIv) {
                     IncCtr((byte*)ctx->cipher.aes.reg,
                            ctx->cipher.aes.nonceSz);
-                    ctx->gcmIncIv = 0;
+                    ctx->authIncIv = 0;
                 }
             }
             else {
@@ -921,7 +1005,7 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
             else {
                 ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes, ctx->authTag,
                     ctx->authTagSz);
-                if (ctx->gcmIncIv) {
+                if (ctx->authIncIv) {
                     IncCtr((byte*)ctx->cipher.aes.reg, ctx->cipher.aes.nonceSz);
                 }
             }
@@ -942,8 +1026,8 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
             }
 #endif /* WOLFSSL_AESGCM_STREAM */
             if (ret == WOLFSSL_SUCCESS) {
-                if (ctx->gcmIncIv) {
-                    ctx->gcmIncIv = 0;
+                if (ctx->authIncIv) {
+                    ctx->authIncIv = 0;
                 }
                 else {
                     /* Clear IV, since IV reuse is not recommended for AES GCM. */
@@ -956,6 +1040,62 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
             break;
 #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
         * HAVE_FIPS_VERSION >= 2 */
+#if defined(HAVE_AESCCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+    || FIPS_VERSION_GE(2,0))
+        case AES_128_CCM_TYPE:
+        case AES_192_CCM_TYPE:
+        case AES_256_CCM_TYPE:
+            if ((ctx->authBuffer && ctx->authBufferLen > 0)
+             || (ctx->authBufferLen == 0)) {
+                if (ctx->enc)
+                    ret = wc_AesCcmEncrypt(&ctx->cipher.aes, out,
+                            ctx->authBuffer, ctx->authBufferLen,
+                            ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                            ctx->authIn, ctx->authInSz);
+                else
+                    ret = wc_AesCcmDecrypt(&ctx->cipher.aes, out,
+                            ctx->authBuffer, ctx->authBufferLen,
+                            ctx->iv, ctx->ivSz, ctx->authTag, ctx->authTagSz,
+                            ctx->authIn, ctx->authInSz);
+
+                if (ret == 0) {
+                    ret = WOLFSSL_SUCCESS;
+                    *outl = ctx->authBufferLen;
+                }
+                else {
+                    ret = WOLFSSL_FAILURE;
+                    *outl = 0;
+                }
+
+                XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
+                ctx->authBuffer = NULL;
+                ctx->authBufferLen = 0;
+
+                if (ctx->authIncIv) {
+                    IncCtr((byte*)ctx->cipher.aes.reg,
+                           ctx->cipher.aes.nonceSz);
+                    ctx->authIncIv = 0;
+                }
+            }
+            else {
+                *outl = 0;
+            }
+            if (ret == WOLFSSL_SUCCESS) {
+                if (ctx->authIncIv) {
+                    ctx->authIncIv = 0;
+                }
+                else {
+                    /* Clear IV, since IV reuse is not recommended
+                     * for AES CCM. */
+                    XMEMSET(ctx->iv, 0, AES_BLOCK_SIZE);
+                }
+                if (wolfSSL_StoreExternalIV(ctx) != WOLFSSL_SUCCESS) {
+                    ret = WOLFSSL_FAILURE;
+                }
+            }
+            break;
+#endif /* HAVE_AESCCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
+        * HAVE_FIPS_VERSION >= 2 */
 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
         case CHACHA20_POLY1305_TYPE:
             if (wc_ChaCha20Poly1305_Final(&ctx->cipher.chachaPoly,
@@ -1029,29 +1169,49 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out,
     }
 
     if (ret == WOLFSSL_SUCCESS) {
-#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
-    || FIPS_VERSION_GE(2,0))
+#if (defined(HAVE_AESGCM) || defined(HAVE_AESCCM)) && \
+        ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+            || FIPS_VERSION_GE(2,0))
         /*
          * This flag needs to retain its value between wolfSSL_EVP_CipherFinal
          * calls. wolfSSL_EVP_CipherInit will clear it, so we save and restore
          * it here.
          */
-        if (ctx->cipherType == AES_128_GCM_TYPE ||
+        if (FALSE
+        #ifdef HAVE_AESGCM
+            || ctx->cipherType == AES_128_GCM_TYPE ||
             ctx->cipherType == AES_192_GCM_TYPE ||
-            ctx->cipherType == AES_256_GCM_TYPE) {
-            tmp = ctx->gcmIvGenEnable;
+            ctx->cipherType == AES_256_GCM_TYPE
+        #endif
+        #ifdef HAVE_AESCCM
+            || ctx->cipherType == AES_128_CCM_TYPE ||
+            ctx->cipherType == AES_192_CCM_TYPE ||
+            ctx->cipherType == AES_256_CCM_TYPE
+        #endif
+            ) {
+            tmp = ctx->authIvGenEnable;
         }
 #endif
 
         /* reset cipher state after final */
         ret = wolfSSL_EVP_CipherInit(ctx, NULL, NULL, NULL, -1);
 
-#if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
-    || FIPS_VERSION_GE(2,0))
-        if (ctx->cipherType == AES_128_GCM_TYPE ||
+#if (defined(HAVE_AESGCM) || defined(HAVE_AESCCM)) && \
+        ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+            || FIPS_VERSION_GE(2,0))
+        if (FALSE
+        #ifdef HAVE_AESGCM
+            || ctx->cipherType == AES_128_GCM_TYPE ||
             ctx->cipherType == AES_192_GCM_TYPE ||
-            ctx->cipherType == AES_256_GCM_TYPE) {
-            ctx->gcmIvGenEnable = tmp;
+            ctx->cipherType == AES_256_GCM_TYPE
+        #endif
+        #ifdef HAVE_AESCCM
+            || ctx->cipherType == AES_128_CCM_TYPE ||
+            ctx->cipherType == AES_192_CCM_TYPE ||
+            ctx->cipherType == AES_256_CCM_TYPE
+        #endif
+            ) {
+            ctx->authIvGenEnable = tmp;
         }
 #endif
     }
@@ -1125,6 +1285,11 @@ int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx)
     case AES_192_GCM_TYPE:
     case AES_256_GCM_TYPE:
 #endif
+#if defined(HAVE_AESCCM)
+    case AES_128_CCM_TYPE:
+    case AES_192_CCM_TYPE:
+    case AES_256_CCM_TYPE:
+#endif
 #if defined(WOLFSSL_AES_COUNTER)
     case AES_128_CTR_TYPE:
     case AES_192_CTR_TYPE:
@@ -1212,6 +1377,20 @@ static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher)
         return AES_256_GCM_TYPE;
     #endif
 #endif /* HAVE_AESGCM */
+#if defined(HAVE_AESCCM)
+    #ifdef WOLFSSL_AES_128
+    else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_CCM))
+        return AES_128_CCM_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_192_CCM))
+        return AES_192_CCM_TYPE;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_256_CCM))
+        return AES_256_CCM_TYPE;
+    #endif
+#endif /* HAVE_AESCCM */
 #if defined(WOLFSSL_AES_COUNTER)
     #ifdef WOLFSSL_AES_128
     else if (EVP_CIPHER_TYPE_MATCHES(cipher, EVP_AES_128_CTR))
@@ -1339,6 +1518,12 @@ int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher)
       case AES_256_GCM_TYPE:
           return 1;
   #endif
+  #if defined(HAVE_AESCCM)
+      case AES_128_CCM_TYPE:
+      case AES_192_CCM_TYPE:
+      case AES_256_CCM_TYPE:
+          return 1;
+  #endif
   #if defined(WOLFSSL_AES_COUNTER)
       case AES_128_CTR_TYPE:
       case AES_192_CTR_TYPE:
@@ -1420,6 +1605,13 @@ unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher)
             return WOLFSSL_EVP_CIPH_GCM_MODE |
                     WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
     #endif
+    #if defined(HAVE_AESCCM)
+        case AES_128_CCM_TYPE:
+        case AES_192_CCM_TYPE:
+        case AES_256_CCM_TYPE:
+            return WOLFSSL_EVP_CIPH_CCM_MODE |
+                    WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
+    #endif
     #if defined(WOLFSSL_AES_COUNTER)
         case AES_128_CTR_TYPE:
         case AES_192_CTR_TYPE:
@@ -4220,6 +4412,18 @@ static const struct cipher{
     #endif
     #endif
 
+    #ifdef HAVE_AESCCM
+    #ifdef WOLFSSL_AES_128
+    {AES_128_CCM_TYPE, EVP_AES_128_CCM, NID_aes_128_ccm},
+    #endif
+    #ifdef WOLFSSL_AES_192
+    {AES_192_CCM_TYPE, EVP_AES_192_CCM, NID_aes_192_ccm},
+    #endif
+    #ifdef WOLFSSL_AES_256
+    {AES_256_CCM_TYPE, EVP_AES_256_CCM, NID_aes_256_ccm},
+    #endif
+    #endif
+
     #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128
         {AES_128_CTR_TYPE, EVP_AES_128_CTR, NID_aes_128_ctr},
@@ -4358,6 +4562,20 @@ const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name)
             {EVP_AES_256_GCM, "id-aes256-GCM"},
         #endif
     #endif
+    #ifdef HAVE_AESCCM
+        #ifdef WOLFSSL_AES_128
+            {EVP_AES_128_CCM, "aes-128-ccm"},
+            {EVP_AES_128_CCM, "id-aes128-CCM"},
+        #endif
+        #ifdef WOLFSSL_AES_192
+            {EVP_AES_192_CCM, "aes-192-ccm"},
+            {EVP_AES_192_CCM, "id-aes192-CCM"},
+        #endif
+        #ifdef WOLFSSL_AES_256
+            {EVP_AES_256_CCM, "aes-256-ccm"},
+            {EVP_AES_256_CCM, "id-aes256-CCM"},
+        #endif
+    #endif
 #endif
 #ifndef NO_RC4
         {EVP_ARC4, "RC4"},
@@ -4464,6 +4682,20 @@ const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id)
             return wolfSSL_EVP_aes_256_gcm();
         #endif
     #endif
+    #ifdef HAVE_AESCCM
+        #ifdef WOLFSSL_AES_128
+        case NID_aes_128_ccm:
+            return wolfSSL_EVP_aes_128_ccm();
+        #endif
+        #ifdef WOLFSSL_AES_192
+        case NID_aes_192_ccm:
+            return wolfSSL_EVP_aes_192_ccm();
+        #endif
+        #ifdef WOLFSSL_AES_256
+        case NID_aes_256_ccm:
+            return wolfSSL_EVP_aes_256_ccm();
+        #endif
+    #endif
 #endif
 
 #ifndef NO_DES3
@@ -5295,6 +5527,32 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
     #endif /* WOLFSSL_AES_256 */
     #endif /* HAVE_AESGCM */
 
+    #ifdef HAVE_AESCCM
+    #ifdef WOLFSSL_AES_128
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ccm(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ccm");
+        return EVP_AES_128_CCM;
+    }
+    #endif /* WOLFSSL_CCM_128 */
+
+    #ifdef WOLFSSL_AES_192
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ccm(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ccm");
+        return EVP_AES_192_CCM;
+    }
+    #endif /* WOLFSSL_AES_192 */
+
+    #ifdef WOLFSSL_AES_256
+    const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ccm(void)
+    {
+        WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ccm");
+        return EVP_AES_256_CCM;
+    }
+    #endif /* WOLFSSL_AES_256 */
+    #endif /* HAVE_AESCCM */
+
     #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128
     const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void)
@@ -5549,7 +5807,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
             case EVP_CTRL_SET_KEY_LENGTH:
                 ret = wolfSSL_EVP_CIPHER_CTX_set_key_length(ctx, arg);
                 break;
-#if defined(HAVE_AESGCM) || (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \
+        (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
             case EVP_CTRL_AEAD_SET_IVLEN:
                 if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0)
                     break;
@@ -5568,6 +5827,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                 ret = wolfSSL_EVP_CIPHER_CTX_set_iv_length(ctx, arg);
                 break;
 
+#if defined(HAVE_AESGCM) || (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
             case EVP_CTRL_AEAD_SET_IV_FIXED:
                 if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0)
                     break;
@@ -5613,11 +5873,12 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                      * command be issued before a EVP_CTRL_GCM_IV_GEN command.
                      * This flag is used to enforce that.
                      */
-                    ctx->gcmIvGenEnable = 1;
+                    ctx->authIvGenEnable = 1;
                 }
             #endif
 #endif /* !WC_NO_RNG */
                 break;
+#endif /* HAVE_AESGCM || (HAVE_CHACHA && HAVE_POLY1305) */
 #if defined(HAVE_AESGCM) && !defined(_WIN32) && !defined(HAVE_SELFTEST) && \
     (!defined(HAVE_FIPS) || FIPS_VERSION_GE(2,0))
             /*
@@ -5629,7 +5890,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
             case EVP_CTRL_GCM_IV_GEN:
                 if ((ctx->flags & WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER) == 0)
                     break;
-                if (!ctx->gcmIvGenEnable) {
+                if (!ctx->authIvGenEnable) {
                     WOLFSSL_MSG("Must use EVP_CTRL_AEAD_SET_IV_FIXED before "
                                 "EVP_CTRL_GCM_IV_GEN");
                     break;
@@ -5657,7 +5918,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                  * The gcmIncIV flag indicates that the IV should be incremented
                  * after the next cipher operation.
                  */
-                ctx->gcmIncIv = 1;
+                ctx->authIncIv = 1;
                 ret = WOLFSSL_SUCCESS;
                 break;
 #endif /* HAVE_AESGCM && !_WIN32 && !HAVE_SELFTEST && (!HAVE_FIPS ||
@@ -5710,7 +5971,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                     ret = WOLFSSL_SUCCESS;
                 }
                 break;
-#endif /* HAVE_AESGCM || (HAVE_CHACHA && HAVE_POLY1305) */
+#endif /* HAVE_AESGCM || HAVE_AESCCM || (HAVE_CHACHA && HAVE_POLY1305) */
             default:
                 WOLFSSL_MSG("EVP_CIPHER_CTX_ctrl operation not yet handled");
                 break;
@@ -5732,6 +5993,13 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                 wc_AesFree(&ctx->cipher.aes);
             }
     #endif /* HAVE_AESGCM && WOLFSSL_AESGCM_STREAM */
+    #if defined(HAVE_AESCCM)
+            if ((ctx->cipherType == AES_128_CCM_TYPE) ||
+                (ctx->cipherType == AES_192_CCM_TYPE) ||
+                (ctx->cipherType == AES_256_CCM_TYPE)) {
+                wc_AesFree(&ctx->cipher.aes);
+            }
+    #endif /* HAVE_AESCCM */
 #endif /* not FIPS or FIPS v2+ */
             ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT;  /* not yet initialized  */
 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
@@ -5742,19 +6010,19 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
             }
 #endif
             ctx->keyLen     = 0;
-#ifdef HAVE_AESGCM
-            if (ctx->gcmBuffer) {
-                XFREE(ctx->gcmBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
-                ctx->gcmBuffer = NULL;
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
+            if (ctx->authBuffer) {
+                XFREE(ctx->authBuffer, NULL, DYNAMIC_TYPE_OPENSSL);
+                ctx->authBuffer = NULL;
             }
-            ctx->gcmBufferLen = 0;
-            if (ctx->gcmAuthIn) {
-                XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL);
-                ctx->gcmAuthIn = NULL;
+            ctx->authBufferLen = 0;
+            if (ctx->authIn) {
+                XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL);
+                ctx->authIn = NULL;
             }
-            ctx->gcmAuthInSz = 0;
-            ctx->gcmIvGenEnable = 0;
-            ctx->gcmIncIv = 0;
+            ctx->authInSz = 0;
+            ctx->authIvGenEnable = 0;
+            ctx->authIncIv = 0;
 #endif
         }
 
@@ -5873,11 +6141,11 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
     {
         int ret = WOLFSSL_SUCCESS;
 
-        if (ctx->gcmAuthIn) {
-            XFREE(ctx->gcmAuthIn, NULL, DYNAMIC_TYPE_OPENSSL);
-            ctx->gcmAuthIn = NULL;
+        if (ctx->authIn) {
+            XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL);
+            ctx->authIn = NULL;
         }
-        ctx->gcmAuthInSz = 0;
+        ctx->authInSz = 0;
 
         ctx->block_size = AES_BLOCK_SIZE;
         ctx->authTagSz = AES_BLOCK_SIZE;
@@ -5949,7 +6217,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
          * If a key is provided, the flag retains its value.
          */
         if (ret == WOLFSSL_SUCCESS && key == NULL) {
-            ctx->gcmIvGenEnable = 0;
+            ctx->authIvGenEnable = 0;
         }
 
         return ret;
@@ -5969,19 +6237,19 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
             if (ctx->enc) {
                 ret = wc_AesGcmEncrypt(&ctx->cipher.aes, dst, src,
                         len, ctx->iv, ctx->ivSz, ctx->authTag,
-                        ctx->authTagSz, ctx->gcmAuthIn,
-                        ctx->gcmAuthInSz);
+                        ctx->authTagSz, ctx->authIn,
+                        ctx->authInSz);
             }
             else {
                 ret = wc_AesGcmDecrypt(&ctx->cipher.aes, dst, src,
                         len, ctx->iv, ctx->ivSz, ctx->authTag,
-                        ctx->authTagSz, ctx->gcmAuthIn,
-                        ctx->gcmAuthInSz);
+                        ctx->authTagSz, ctx->authIn,
+                        ctx->authInSz);
             }
-            if (ctx->gcmIncIv) {
+            if (ctx->authIncIv) {
                 IncCtr((byte*)ctx->cipher.aes.reg,
                        ctx->cipher.aes.nonceSz);
-                ctx->gcmIncIv = 0;
+                ctx->authIncIv = 0;
             }
         }
     #else
@@ -6030,7 +6298,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                 /* Calculate authentication tag and compare. */
                 ret = wc_AesGcmDecryptFinal(&ctx->cipher.aes,
                     ctx->authTag, ctx->authTagSz);
-                if (ctx->gcmIncIv) {
+                if (ctx->authIncIv) {
                     IncCtr((byte*)ctx->cipher.aes.reg,
                            ctx->cipher.aes.nonceSz);
                 }
@@ -6042,7 +6310,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                 WOLFSSL_MSG("wc_AesGcmInit failed");
                 return WOLFSSL_FATAL_ERROR;
             }
-            ctx->gcmIncIv = 0;
+            ctx->authIncIv = 0;
         }
     #endif /* WOLFSSL_AESGCM_STREAM */
         if (src == NULL) {
@@ -6050,10 +6318,10 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
              * Clear any leftover AAD on final (final is when src is
              * NULL).
              */
-            if (ctx->gcmAuthIn != NULL) {
-                XMEMSET(ctx->gcmAuthIn, 0, ctx->gcmAuthInSz);
+            if (ctx->authIn != NULL) {
+                XMEMSET(ctx->authIn, 0, ctx->authInSz);
             }
-            ctx->gcmAuthInSz = 0;
+            ctx->authInSz = 0;
         }
         if (ret == 0) {
             ret = len;
@@ -6065,6 +6333,128 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
         * HAVE_FIPS_VERSION >= 2 */
 
     /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */
+#if defined(HAVE_AESCCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+    || FIPS_VERSION_GE(2,0))
+    static int EvpCipherInitAesCCM(WOLFSSL_EVP_CIPHER_CTX* ctx,
+                                   const WOLFSSL_EVP_CIPHER* type,
+                                   const byte* key, const byte* iv, int enc)
+    {
+        int ret = WOLFSSL_SUCCESS;
+
+        if (ctx->authIn) {
+            XFREE(ctx->authIn, NULL, DYNAMIC_TYPE_OPENSSL);
+            ctx->authIn = NULL;
+        }
+        ctx->authInSz = 0;
+
+        ctx->block_size = AES_BLOCK_SIZE;
+        ctx->authTagSz = AES_BLOCK_SIZE;
+        if (ctx->ivSz == 0) {
+            ctx->ivSz = GCM_NONCE_MID_SZ;
+        }
+        ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE;
+        ctx->flags |= WOLFSSL_EVP_CIPH_CCM_MODE |
+                      WOLFSSL_EVP_CIPH_FLAG_AEAD_CIPHER;
+        if (enc == 0 || enc == 1) {
+            ctx->enc = enc ? 1 : 0;
+        }
+
+    #ifdef WOLFSSL_AES_128
+        if (ctx->cipherType == AES_128_CCM_TYPE ||
+            (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_CCM))) {
+            WOLFSSL_MSG("EVP_AES_128_CCM");
+            ctx->cipherType = AES_128_CCM_TYPE;
+            ctx->keyLen = AES_128_KEY_SIZE;
+        }
+    #endif
+    #ifdef WOLFSSL_AES_192
+        if (ctx->cipherType == AES_192_CCM_TYPE ||
+            (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_CCM))) {
+            WOLFSSL_MSG("EVP_AES_192_CCM");
+            ctx->cipherType = AES_192_CCM_TYPE;
+            ctx->keyLen = AES_192_KEY_SIZE;
+        }
+    #endif
+    #ifdef WOLFSSL_AES_256
+        if (ctx->cipherType == AES_256_CCM_TYPE ||
+            (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_CCM))) {
+            WOLFSSL_MSG("EVP_AES_256_CCM");
+            ctx->cipherType = AES_256_CCM_TYPE;
+            ctx->keyLen = AES_256_KEY_SIZE;
+        }
+    #endif
+
+        if (ret == WOLFSSL_SUCCESS && key &&
+            wc_AesCcmSetKey(&ctx->cipher.aes, key, ctx->keyLen)) {
+            WOLFSSL_MSG("wc_AesCcmSetKey() failed");
+            ret = WOLFSSL_FAILURE;
+        }
+        if (ret == WOLFSSL_SUCCESS && iv &&
+            wc_AesCcmSetNonce(&ctx->cipher.aes, iv, ctx->ivSz)) {
+            WOLFSSL_MSG("wc_AesCcmSetNonce() failed");
+            ret = WOLFSSL_FAILURE;
+        }
+
+        /*
+         * OpenSSL clears this flag, which permits subsequent use of
+         * EVP_CTRL_CCM_IV_GEN, when EVP_CipherInit is called with no key.
+         * If a key is provided, the flag retains its value.
+         */
+        if (ret == WOLFSSL_SUCCESS && key == NULL) {
+            ctx->authIvGenEnable = 0;
+        }
+
+        return ret;
+    }
+
+    static int EvpCipherAesCCM(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst,
+                               byte* src, word32 len)
+    {
+        int ret = WOLFSSL_FAILURE;
+
+        /* No destination means only AAD. */
+        if (src != NULL && dst == NULL) {
+            ret = wolfSSL_EVP_CipherUpdate_CCM_AAD(ctx, src, len);
+        }
+        else if (src != NULL && dst != NULL) {
+            if (ctx->enc) {
+                ret = wc_AesCcmEncrypt(&ctx->cipher.aes, dst, src,
+                        len, ctx->iv, ctx->ivSz, ctx->authTag,
+                        ctx->authTagSz, ctx->authIn,
+                        ctx->authInSz);
+            }
+            else {
+                ret = wc_AesCcmDecrypt(&ctx->cipher.aes, dst, src,
+                        len, ctx->iv, ctx->ivSz, ctx->authTag,
+                        ctx->authTagSz, ctx->authIn,
+                        ctx->authInSz);
+            }
+            if (ctx->authIncIv) {
+                IncCtr((byte*)ctx->cipher.aes.reg,
+                       ctx->cipher.aes.nonceSz);
+                ctx->authIncIv = 0;
+            }
+        }
+        if (src == NULL) {
+            /*
+             * Clear any leftover AAD on final (final is when src is
+             * NULL).
+             */
+            if (ctx->authIn != NULL) {
+                XMEMSET(ctx->authIn, 0, ctx->authInSz);
+            }
+            ctx->authInSz = 0;
+        }
+        if (ret == 0) {
+            ret = len;
+        }
+
+        return ret;
+    }
+#endif /* HAVE_AESCCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
+        * HAVE_FIPS_VERSION >= 2 */
+
+    /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */
     int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
                                const WOLFSSL_EVP_CIPHER* type, const byte* key,
                                const byte* iv, int enc)
@@ -6183,9 +6573,9 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
     #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */
     #if defined(HAVE_AESGCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
         || FIPS_VERSION_GE(2,0))
-        if (
+        if (FALSE
         #ifdef WOLFSSL_AES_128
-            ctx->cipherType == AES_128_GCM_TYPE ||
+            || ctx->cipherType == AES_128_GCM_TYPE ||
             (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_GCM))
         #endif
         #ifdef WOLFSSL_AES_192
@@ -6204,6 +6594,30 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
         }
     #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
             * HAVE_FIPS_VERSION >= 2 */
+    #if defined(HAVE_AESCCM) && \
+        ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+            || FIPS_VERSION_GE(2,0))
+        if (FALSE
+        #ifdef WOLFSSL_AES_128
+            || ctx->cipherType == AES_128_CCM_TYPE ||
+            (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_128_CCM))
+        #endif
+        #ifdef WOLFSSL_AES_192
+            || ctx->cipherType == AES_192_CCM_TYPE ||
+            (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_192_CCM))
+        #endif
+        #ifdef WOLFSSL_AES_256
+            || ctx->cipherType == AES_256_CCM_TYPE ||
+            (type && EVP_CIPHER_TYPE_MATCHES(type, EVP_AES_256_CCM))
+        #endif
+          ) {
+            if (EvpCipherInitAesCCM(ctx, type, key, iv, enc)
+                != WOLFSSL_SUCCESS) {
+                return WOLFSSL_FAILURE;
+            }
+        }
+    #endif /* HAVE_AESCCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
+            * HAVE_FIPS_VERSION >= 2 */
 #ifdef WOLFSSL_AES_COUNTER
         #ifdef WOLFSSL_AES_128
         if (ctx->cipherType == AES_128_CTR_TYPE ||
@@ -6935,6 +7349,14 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
             case AES_256_GCM_TYPE :
                 return NID_aes_256_gcm;
 #endif
+#ifdef HAVE_AESCCM
+            case AES_128_CCM_TYPE :
+                return NID_aes_128_ccm;
+            case AES_192_CCM_TYPE :
+                return NID_aes_192_ccm;
+            case AES_256_CCM_TYPE :
+                return NID_aes_256_ccm;
+#endif
 #ifdef HAVE_AES_ECB
             case AES_128_ECB_TYPE :
                 return NID_aes_128_ecb;
@@ -7027,7 +7449,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
     }
 #endif
 
-#if defined(HAVE_AESGCM) || (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \
+    (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
     /* returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */
     int wolfSSL_EVP_CIPHER_CTX_set_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* iv,
                                              int ivLen)
@@ -7085,9 +7508,18 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
         WOLFSSL_ENTER("wolfSSL_EVP_Cipher");
 
         if (ctx == NULL || ((src == NULL || dst == NULL) &&
-            (ctx->cipherType != AES_128_GCM_TYPE &&
+            (TRUE 
+        #ifdef HAVE_AESGCM
+            && ctx->cipherType != AES_128_GCM_TYPE &&
              ctx->cipherType != AES_192_GCM_TYPE &&
-             ctx->cipherType != AES_256_GCM_TYPE))) {
+             ctx->cipherType != AES_256_GCM_TYPE
+        #endif
+        #ifdef HAVE_AESCCM
+            && ctx->cipherType != AES_128_CCM_TYPE &&
+             ctx->cipherType != AES_192_CCM_TYPE &&
+             ctx->cipherType != AES_256_CCM_TYPE
+        #endif
+            ))) {
             WOLFSSL_MSG("Bad argument.");
             return WOLFSSL_FATAL_ERROR;
         }
@@ -7190,6 +7622,16 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
                 break;
 #endif /* HAVE_AESGCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
         * HAVE_FIPS_VERSION >= 2 */
+#if defined(HAVE_AESCCM) && ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) \
+    || FIPS_VERSION_GE(2,0))
+            case AES_128_CCM_TYPE :
+            case AES_192_CCM_TYPE :
+            case AES_256_CCM_TYPE :
+                WOLFSSL_MSG("AES CCM");
+                ret = EvpCipherAesCCM(ctx, dst, src, len);
+                break;
+#endif /* HAVE_AESCCM && ((!HAVE_FIPS && !HAVE_SELFTEST) ||
+        * HAVE_FIPS_VERSION >= 2 */
 #ifdef HAVE_AES_ECB
             case AES_128_ECB_TYPE :
             case AES_192_ECB_TYPE :
@@ -8593,6 +9035,16 @@ int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx)
             }
             return GCM_NONCE_MID_SZ;
 #endif
+#ifdef HAVE_AESCCM
+        case AES_128_CCM_TYPE :
+        case AES_192_CCM_TYPE :
+        case AES_256_CCM_TYPE :
+            WOLFSSL_MSG("AES CCM");
+            if (ctx->ivSz != 0) {
+                return ctx->ivSz;
+            }
+            return CCM_NONCE_MIN_SZ;
+#endif
 #endif /* (HAVE_FIPS && !HAVE_SELFTEST) || HAVE_FIPS_VERSION >= 2 */
 #ifdef WOLFSSL_AES_COUNTER
         case AES_128_CTR_TYPE :
@@ -8705,6 +9157,20 @@ int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher)
         return GCM_NONCE_MID_SZ;
     #endif
 #endif /* HAVE_AESGCM */
+#ifdef HAVE_AESCCM
+    #ifdef WOLFSSL_AES_128
+    if (XSTRCMP(name, EVP_AES_128_CCM) == 0)
+        return CCM_NONCE_MIN_SZ;
+    #endif
+    #ifdef WOLFSSL_AES_192
+    if (XSTRCMP(name, EVP_AES_192_CCM) == 0)
+        return CCM_NONCE_MIN_SZ;
+    #endif
+    #ifdef WOLFSSL_AES_256
+    if (XSTRCMP(name, EVP_AES_256_CCM) == 0)
+        return CCM_NONCE_MIN_SZ;
+    #endif
+#endif /* HAVE_AESCCM */
 #endif /* (HAVE_FIPS && !HAVE_SELFTEST) || HAVE_FIPS_VERSION >= 2 */
 #ifdef WOLFSSL_AES_COUNTER
     #ifdef WOLFSSL_AES_128

+ 30 - 12
wolfssl/openssl/evp.h

@@ -126,6 +126,11 @@ WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_gcm(void);
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_gcm(void);
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_gcm(void);
 #endif
+#if !defined(NO_AES) && defined(HAVE_AESCCM)
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ccm(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ccm(void);
+WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ccm(void);
+#endif
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void);
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void);
 WOLFSSL_API const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void);
@@ -228,6 +233,7 @@ typedef union {
 #define NID_aes_192_cbc                 423
 #define NID_aes_256_cbc                 427
 #define NID_aes_128_ccm                 896
+#define NID_aes_192_ccm                 899
 #define NID_aes_256_ccm                 902
 #define NID_aes_128_gcm                 895
 #define NID_aes_192_gcm                 898
@@ -395,7 +401,10 @@ enum {
     AES_128_XTS_TYPE = 36,
     AES_256_XTS_TYPE = 37,
     CHACHA20_POLY1305_TYPE = 38,
-    CHACHA20_TYPE    = 39
+    CHACHA20_TYPE    = 39,
+    AES_128_CCM_TYPE  = 40,
+    AES_192_CCM_TYPE  = 41,
+    AES_256_CCM_TYPE  = 42
 };
 
 #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
@@ -423,29 +432,30 @@ struct WOLFSSL_EVP_CIPHER_CTX {
     int  lastUsed;
 #if !defined(NO_AES) || !defined(NO_DES3) || defined(HAVE_AESGCM) || \
     defined (WOLFSSL_AES_XTS) || (defined(HAVE_CHACHA) || \
-    defined(HAVE_POLY1305))
+    defined(HAVE_POLY1305) || defined(HAVE_AESCCM))
 #define HAVE_WOLFSSL_EVP_CIPHER_CTX_IV
     int    ivSz;
-#ifdef HAVE_AESGCM
-    byte*   gcmBuffer;
-    int     gcmBufferLen;
-    byte*   gcmAuthIn;
-    int     gcmAuthInSz;
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
+    byte*   authBuffer;
+    int     authBufferLen;
+    byte*   authIn;
+    int     authInSz;
 #endif
 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
     byte*   key;                 /* used in partial Init()s */
 #endif
-#if defined(HAVE_AESGCM) || (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
-#ifdef HAVE_AESGCM
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \
+        (defined(HAVE_CHACHA) && defined(HAVE_POLY1305))
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
     ALIGN16 unsigned char authTag[AES_BLOCK_SIZE];
 #else
     ALIGN16 unsigned char authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
 #endif
     int     authTagSz;
 #endif
-#ifdef HAVE_AESGCM
-    byte    gcmIvGenEnable:1;
-    byte    gcmIncIv:1;
+#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
+    byte    authIvGenEnable:1;
+    byte    authIncIv:1;
 #endif
 #endif
 };
@@ -896,6 +906,9 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
 #define EVP_aes_128_gcm       wolfSSL_EVP_aes_128_gcm
 #define EVP_aes_192_gcm       wolfSSL_EVP_aes_192_gcm
 #define EVP_aes_256_gcm       wolfSSL_EVP_aes_256_gcm
+#define EVP_aes_128_ccm       wolfSSL_EVP_aes_128_ccm
+#define EVP_aes_192_ccm       wolfSSL_EVP_aes_192_ccm
+#define EVP_aes_256_ccm       wolfSSL_EVP_aes_256_ccm
 #define EVP_aes_128_ecb       wolfSSL_EVP_aes_128_ecb
 #define EVP_aes_192_ecb       wolfSSL_EVP_aes_192_ecb
 #define EVP_aes_256_ecb       wolfSSL_EVP_aes_256_ecb
@@ -1103,6 +1116,11 @@ WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx,
 #define EVP_CTRL_GCM_GET_TAG           EVP_CTRL_AEAD_GET_TAG
 #define EVP_CTRL_GCM_SET_TAG           EVP_CTRL_AEAD_SET_TAG
 #define EVP_CTRL_GCM_SET_IV_FIXED      EVP_CTRL_AEAD_SET_IV_FIXED
+#define EVP_CTRL_CCM_SET_IVLEN         EVP_CTRL_AEAD_SET_IVLEN
+#define EVP_CTRL_CCM_GET_TAG           EVP_CTRL_AEAD_GET_TAG
+#define EVP_CTRL_CCM_SET_TAG           EVP_CTRL_AEAD_SET_TAG
+#define EVP_CTRL_CCM_SET_L             0x14
+#define EVP_CTRL_CCM_SET_MSGLEN        0x15
 
 #define EVP_PKEY_print_public           wolfSSL_EVP_PKEY_print_public
 #define EVP_PKEY_print_private(arg1, arg2, arg3, arg4)