From b8a019dedde82b6cb47e4b3f14cae7b87d29061a Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Thu, 4 Feb 2021 22:48:00 -0600 Subject: [PATCH] AES-CCM: allow null payload buffers in wc_AesCcmEncrypt() and wc_AesCcmDecrypt() when inSz is zero, and add to aesccm_test() a test for this, tolerating early BAD_FUNC_ARG (for FIPS and arch-specific 3rd party code), and a test for the zero-length string, that must succeed. --- wolfcrypt/src/aes.c | 13 +++++++++---- wolfcrypt/test/test.c | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 8ba1582ef..3caa725b7 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -7640,7 +7640,7 @@ int wc_AesCcmCheckTagSize(int sz) /* implemented in wolfcrypt/src/port/caam_aes.c */ #elif defined(WOLFSSL_SILABS_SE_ACCEL) - /* implemented in wolfcrypt/src/port/silabs/silabs_hash.c */ + /* implemented in wolfcrypt/src/port/silabs/silabs_aes.c */ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, const byte* nonce, word32 nonceSz, byte* authTag, word32 authTagSz, @@ -7679,6 +7679,10 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, status_t status; /* sanity check on arguments */ + /* note, LTC_AES_EncryptTagCcm() doesn't allow null src or dst + * ptrs even if inSz is zero (ltc_aes_ccm_check_input_args()), so + * don't allow it here either. + */ if (aes == NULL || out == NULL || in == NULL || nonce == NULL || authTag == NULL || nonceSz < 7 || nonceSz > 13) { return BAD_FUNC_ARG; @@ -7879,7 +7883,7 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, const word32 wordSz = (word32)sizeof(word32); /* sanity check on arguments */ - if (aes == NULL || out == NULL || in == NULL || nonce == NULL + if (aes == NULL || (inSz != 0 && (in == NULL || out == NULL)) || nonce == NULL || authTag == NULL || nonceSz < 7 || nonceSz > 13 || authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; @@ -7981,7 +7985,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, const word32 wordSz = (word32)sizeof(word32); /* sanity check on arguments */ - if (aes == NULL || out == NULL || in == NULL || nonce == NULL + if (aes == NULL || (inSz != 0 && (in == NULL || out == NULL)) || nonce == NULL || authTag == NULL || nonceSz < 7 || nonceSz > 13 || authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; @@ -8075,7 +8079,8 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, defined(ACVP_VECTOR_TESTING) WOLFSSL_MSG("Preserve output for vector responses"); #else - XMEMSET(out, 0, inSz); + if (inSz > 0) + XMEMSET(out, 0, inSz); #endif result = AES_CCM_AUTH_E; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b924cd9d4..44ac7ee83 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -10233,6 +10233,12 @@ WOLFSSL_TEST_SUBROUTINE int aesccm_test(void) 0x89, 0xd8, 0xd2, 0x02, 0xc5, 0xcf, 0xae, 0xf4 }; + /* tag - authentication - empty plaintext */ + WOLFSSL_SMALL_STACK_STATIC const byte t_empty[] = + { + 0xe4, 0x28, 0x8a, 0xc3, 0x78, 0x00, 0x0f, 0xf5 + }; + byte t2[sizeof(t)]; byte p2[sizeof(p)]; byte c2[sizeof(c)]; @@ -10240,6 +10246,7 @@ WOLFSSL_TEST_SUBROUTINE int aesccm_test(void) byte pl2[sizeof(pl)]; byte cl2[sizeof(cl)]; byte tl2[sizeof(tl)]; + byte t_empty2[sizeof(t_empty)]; int result; @@ -10343,6 +10350,40 @@ WOLFSSL_TEST_SUBROUTINE int aesccm_test(void) if (XMEMCMP(pl, pl2, sizeof(pl2))) ERROR_OUT(-6520, out); + /* test empty message as null input and output -- + * must work, or fail early with BAD_FUNC_ARG. + */ + result = wc_AesCcmEncrypt(enc, NULL /* out */, NULL /* in */, 0 /* inSz */, + iv, sizeof(iv), t_empty2, sizeof(t_empty2), + a, sizeof(a)); + if (result != BAD_FUNC_ARG) { + if (result != 0) + ERROR_OUT(-6521, out); + if (XMEMCMP(t_empty, t_empty2, sizeof(t_empty2))) + ERROR_OUT(-6522, out); + + result = wc_AesCcmDecrypt(enc, NULL /* out */, NULL /* in */, + 0 /* inSz */, iv, sizeof(iv), t_empty2, + sizeof(t_empty2), a, sizeof(a)); + if (result != 0) + ERROR_OUT(-6523, out); + } + + /* test empty message as zero-length string -- must work. */ + result = wc_AesCcmEncrypt(enc, pl2, (const byte *)"", 0 /* inSz */, iv, + sizeof(iv), t_empty2, sizeof(t_empty2), a, + sizeof(a)); + if (result != 0) + ERROR_OUT(-6524, out); + if (XMEMCMP(t_empty, t_empty2, sizeof(t_empty2))) + ERROR_OUT(-6525, out); + + result = wc_AesCcmDecrypt(enc, pl2, (const byte *)"", 0 /* inSz */, + iv, sizeof(iv), t_empty2, sizeof(t_empty2), a, + sizeof(a)); + if (result != 0) + ERROR_OUT(-6526, out); + ret = 0; out: