diff --git a/src/ssl.c b/src/ssl.c index 61925bcd8..9a8a13987 100644 --- a/src/ssl.c +++ b/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 : diff --git a/tests/api.c b/tests/api.c index 71fda4e00..b1036481c 100644 --- a/tests/api.c +++ b/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), diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index d831ff93b..b89f33966 100644 --- a/wolfcrypt/src/evp.c +++ b/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 diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index b2f2a78e8..561230f12 100644 --- a/wolfssl/openssl/evp.h +++ b/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)