diff --git a/wolfcrypt/src/chacha20_poly1305.c b/wolfcrypt/src/chacha20_poly1305.c index b645861f1..91b45d16e 100644 --- a/wolfcrypt/src/chacha20_poly1305.c +++ b/wolfcrypt/src/chacha20_poly1305.c @@ -47,12 +47,20 @@ #define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0 #define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16 -static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]); -static int calculateAuthTag( - const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], - const byte* inAAD, const word32 inAADLen, - const byte *inCiphertext, const word32 inCiphertextLen, - byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); + +static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]) +{ +#ifndef WOLFSSL_X86_64_BUILD + XMEMSET(outLittle64 + 4, 0, 4); + + outLittle64[0] = (byte)(inLittle32 & 0x000000FF); + outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8); + outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16); + outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24); +#else + *(word64*)outLittle64 = inLittle32; +#endif +} int wc_ChaCha20Poly1305_Encrypt( const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], @@ -62,12 +70,10 @@ int wc_ChaCha20Poly1305_Encrypt( byte* outCiphertext, byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) { - int err; - byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; - ChaCha chaChaCtx; + int ret; + ChaChaPoly_Aead aead; /* Validate function arguments */ - if (!inKey || !inIV || !inPlaintext || !inPlaintextLen || !outCiphertext || @@ -76,32 +82,16 @@ int wc_ChaCha20Poly1305_Encrypt( return BAD_FUNC_ARG; } - XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); - - /* Create the Poly1305 key */ - err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - err = wc_Chacha_SetIV(&chaChaCtx, inIV, - CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); - if (err != 0) return err; - - err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, - CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - /* Encrypt the plaintext using ChaCha20 */ - err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext, - inPlaintextLen); - /* Calculate the Poly1305 auth tag */ - if (err == 0) - err = calculateAuthTag(poly1305Key, - inAAD, inAADLen, - outCiphertext, inPlaintextLen, - outAuthTag); - ForceZero(poly1305Key, sizeof(poly1305Key)); - - return err; + ret = wc_ChaCha20Poly1305_Init(&aead, inKey, inIV, + CHACHA20_POLY1305_AEAD_ENCRYPT); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateAad(&aead, inAAD, inAADLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateData(&aead, inPlaintext, outCiphertext, + inPlaintextLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_Final(&aead, outAuthTag); + return ret; } @@ -113,9 +103,8 @@ int wc_ChaCha20Poly1305_Decrypt( const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], byte* outPlaintext) { - int err; - byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; - ChaCha chaChaCtx; + int ret; + ChaChaPoly_Aead aead; byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; /* Validate function arguments */ @@ -128,37 +117,19 @@ int wc_ChaCha20Poly1305_Decrypt( } XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag)); - XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); - /* Create the Poly1305 key */ - err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - err = wc_Chacha_SetIV(&chaChaCtx, inIV, - CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); - if (err != 0) return err; - - err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, - CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err != 0) return err; - - /* Calculate the Poly1305 auth tag */ - err = calculateAuthTag(poly1305Key, - inAAD, inAADLen, - inCiphertext, inCiphertextLen, - calculatedAuthTag); - - /* Compare the calculated auth tag with the received one */ - if (err == 0) - err = wc_ChaCha20Poly1305_CheckTag(inAuthTag, calculatedAuthTag); - - /* Decrypt the received ciphertext */ - if (err == 0) - err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext, - inCiphertextLen); - ForceZero(poly1305Key, sizeof(poly1305Key)); - - return err; + ret = wc_ChaCha20Poly1305_Init(&aead, inKey, inIV, + CHACHA20_POLY1305_AEAD_DECRYPT); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateAad(&aead, inAAD, inAADLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_UpdateData(&aead, inCiphertext, outPlaintext, + inCiphertextLen); + if (ret == 0) + ret = wc_ChaCha20Poly1305_Final(&aead, calculatedAuthTag); + if (ret == 0) + ret = wc_ChaCha20Poly1305_CheckTag(inAuthTag, calculatedAuthTag); + return ret; } int wc_ChaCha20Poly1305_CheckTag( @@ -176,87 +147,6 @@ int wc_ChaCha20Poly1305_CheckTag( return ret; } -static int calculateAuthTag( - const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], - const byte *inAAD, const word32 inAADLen, - const byte *inCiphertext, const word32 inCiphertextLen, - byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) -{ - int err; - Poly1305 poly1305Ctx; - byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1]; - word32 paddingLen; - byte little64[16]; - - XMEMSET(padding, 0, sizeof(padding)); - - /* Initialize Poly1305 */ - err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey, - CHACHA20_POLY1305_AEAD_KEYSIZE); - if (err) - return err; - - /* Create the authTag by MAC'ing the following items: */ - /* -- AAD */ - if (inAAD && inAADLen) - { - err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen); - /* -- padding1: pad the AAD to 16 bytes */ - paddingLen = -(int)inAADLen & - (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); - if (paddingLen) - err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); - - if (err) - return err; - } - - /* -- Ciphertext */ - err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen); - if (err) - return err; - - /* -- padding2: pad the ciphertext to 16 bytes */ - paddingLen = -(int)inCiphertextLen & - (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); - if (paddingLen) - { - err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); - if (err) - return err; - } - - /* -- AAD length as a 64-bit little endian integer */ - word32ToLittle64(inAADLen, little64); - /* -- Ciphertext length as a 64-bit little endian integer */ - word32ToLittle64(inCiphertextLen, little64 + 8); - err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); - if (err) - return err; - - /* Finalize the auth tag */ - err = wc_Poly1305Final(&poly1305Ctx, outAuthTag); - - return err; -} - - -static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]) -{ -#ifndef WOLFSSL_X86_64_BUILD - XMEMSET(outLittle64 + 4, 0, 4); - - outLittle64[0] = (byte)(inLittle32 & 0x000000FF); - outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8); - outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16); - outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24); -#else - *(word64*)outLittle64 = inLittle32; -#endif -} - - -#ifndef NO_CHACHAPOLY_AEAD_IUF int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead, const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], @@ -344,12 +234,13 @@ static int wc_ChaCha20Poly1305_CalcAad(ChaChaPoly_Aead* aead) return ret; } +/* inData and outData can be same pointer (inline) */ int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, - byte* data, word32 dataLen) + const byte* inData, byte* outData, word32 dataLen) { int ret = 0; - if (aead == NULL || data == NULL) { + if (aead == NULL || inData == NULL || outData == NULL) { return BAD_FUNC_ARG; } if (aead->state != CHACHA20_POLY1305_STATE_READY && @@ -366,17 +257,17 @@ int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, /* advance state */ aead->state = CHACHA20_POLY1305_STATE_DATA; + /* Perform ChaCha20 encrypt or decrypt inline and Poly1305 auth calc */ if (ret == 0) { - /* Perform ChaCha20 encrypt or decrypt inline and Poly1305 auth calc */ if (aead->isEncrypt) { - ret = wc_Chacha_Process(&aead->chacha, data, data, dataLen); + ret = wc_Chacha_Process(&aead->chacha, outData, inData, dataLen); if (ret == 0) - ret = wc_Poly1305Update(&aead->poly, data, dataLen); + ret = wc_Poly1305Update(&aead->poly, outData, dataLen); } else { - ret = wc_Poly1305Update(&aead->poly, data, dataLen); + ret = wc_Poly1305Update(&aead->poly, inData, dataLen); if (ret == 0) - ret = wc_Chacha_Process(&aead->chacha, data, data, dataLen); + ret = wc_Chacha_Process(&aead->chacha, outData, inData, dataLen); } } if (ret == 0) { @@ -439,6 +330,5 @@ int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, return ret; } -#endif /* !NO_CHACHAPOLY_AEAD_IUF */ #endif /* HAVE_CHACHA && HAVE_POLY1305 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 0b749cfdf..66b28d5d5 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -5034,13 +5034,12 @@ int chacha20_poly1305_aead_test(void) byte generatedPlaintext[265]; /* max plaintext2/cipher2 */ byte generatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; int err; -#ifndef NO_CHACHAPOLY_AEAD_IUF + ChaChaPoly_Aead aead; #define TEST_SMALL_CHACHA_CHUNKS 64 #ifdef TEST_SMALL_CHACHA_CHUNKS word32 testLen; #endif -#endif XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext)); XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag)); @@ -5165,7 +5164,6 @@ int chacha20_poly1305_aead_test(void) } -#ifndef NO_CHACHAPOLY_AEAD_IUF /* AEAD init/update/final */ err = wc_ChaCha20Poly1305_Init(NULL, key1, iv1, CHACHA20_POLY1305_AEAD_DECRYPT); @@ -5186,10 +5184,15 @@ int chacha20_poly1305_aead_test(void) if (err != BAD_FUNC_ARG) return -4524; err = wc_ChaCha20Poly1305_UpdateData(NULL, generatedPlaintext, - sizeof(plaintext1)); + generatedPlaintext, sizeof(plaintext1)); if (err != BAD_FUNC_ARG) return -4525; - err = wc_ChaCha20Poly1305_UpdateData(&aead, NULL, sizeof(plaintext1)); + err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedPlaintext, NULL, + sizeof(plaintext1)); + if (err != BAD_FUNC_ARG) + return -4526; + err = wc_ChaCha20Poly1305_UpdateData(&aead, NULL, generatedPlaintext, + sizeof(plaintext1)); if (err != BAD_FUNC_ARG) return -4526; err = wc_ChaCha20Poly1305_Final(NULL, generatedAuthTag); @@ -5210,7 +5213,7 @@ int chacha20_poly1305_aead_test(void) return -4530; aead.state = CHACHA20_POLY1305_STATE_INIT; err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedPlaintext, - sizeof(plaintext1)); + generatedPlaintext, sizeof(plaintext1)); if (err != BAD_STATE_E) return -4531; aead.state = CHACHA20_POLY1305_STATE_INIT; @@ -5240,17 +5243,15 @@ int chacha20_poly1305_aead_test(void) word32 dataLen = sizeof(plaintext1) - testLen; if (dataLen > TEST_SMALL_CHACHA_CHUNKS) dataLen = TEST_SMALL_CHACHA_CHUNKS; - XMEMCPY(&generatedCiphertext[testLen], &plaintext1[testLen], dataLen); - err = wc_ChaCha20Poly1305_UpdateData(&aead, + err = wc_ChaCha20Poly1305_UpdateData(&aead, &plaintext1[testLen], &generatedCiphertext[testLen], dataLen); if (err != 0) return -4539; testLen += dataLen; } #else - XMEMCPY(generatedCiphertext, plaintext1, sizeof(plaintext1)); - err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext, - sizeof(plaintext1)); + err = wc_ChaCha20Poly1305_UpdateData(&aead, plaintext1, + generatedCiphertext, sizeof(plaintext1)); #endif err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); if (err != 0) @@ -5276,18 +5277,16 @@ int chacha20_poly1305_aead_test(void) word32 dataLen = sizeof(plaintext1) - testLen; if (dataLen > TEST_SMALL_CHACHA_CHUNKS) dataLen = TEST_SMALL_CHACHA_CHUNKS; - XMEMCPY(&generatedPlaintext[testLen], &generatedCiphertext[testLen], - dataLen); err = wc_ChaCha20Poly1305_UpdateData(&aead, - &generatedPlaintext[testLen], dataLen); + &generatedCiphertext[testLen], &generatedPlaintext[testLen], + dataLen); if (err != 0) return -4545; testLen += dataLen; } #else - XMEMCPY(generatedPlaintext, generatedCiphertext, sizeof(cipher1)); - err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedPlaintext, - sizeof(cipher1)); + err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext, + generatedPlaintext, sizeof(cipher1)); #endif err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); if (err != 0) @@ -5317,16 +5316,14 @@ int chacha20_poly1305_aead_test(void) word32 dataLen = sizeof(plaintext2) - testLen; if (dataLen > TEST_SMALL_CHACHA_CHUNKS) dataLen = TEST_SMALL_CHACHA_CHUNKS; - XMEMCPY(&generatedCiphertext[testLen], &plaintext2[testLen], dataLen); - err = wc_ChaCha20Poly1305_UpdateData(&aead, + err = wc_ChaCha20Poly1305_UpdateData(&aead, &plaintext2[testLen], &generatedCiphertext[testLen], dataLen); if (err != 0) return -4552; testLen += dataLen; } #else - XMEMCPY(generatedCiphertext, plaintext2, sizeof(plaintext2)); - err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext, + err = wc_ChaCha20Poly1305_UpdateData(&aead, plaintext2, generatedCiphertext, sizeof(plaintext2)); #endif err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); @@ -5353,18 +5350,16 @@ int chacha20_poly1305_aead_test(void) word32 dataLen = sizeof(plaintext2) - testLen; if (dataLen > TEST_SMALL_CHACHA_CHUNKS) dataLen = TEST_SMALL_CHACHA_CHUNKS; - XMEMCPY(&generatedPlaintext[testLen], &generatedCiphertext[testLen], - dataLen); err = wc_ChaCha20Poly1305_UpdateData(&aead, - &generatedPlaintext[testLen], dataLen); + &generatedCiphertext[testLen], &generatedPlaintext[testLen], + dataLen); if (err != 0) return -4558; testLen += dataLen; } #else - XMEMCPY(generatedPlaintext, generatedCiphertext, sizeof(cipher2)); - err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedPlaintext, - sizeof(cipher2)); + err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext, + generatedPlaintext, sizeof(cipher2)); #endif err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag); if (err != 0) @@ -5375,7 +5370,6 @@ int chacha20_poly1305_aead_test(void) if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2))) { return -4561; } -#endif /* !NO_CHACHAPOLY_AEAD_IUF */ return err; } diff --git a/wolfssl/wolfcrypt/chacha20_poly1305.h b/wolfssl/wolfcrypt/chacha20_poly1305.h index d19aafae2..f654658ac 100644 --- a/wolfssl/wolfcrypt/chacha20_poly1305.h +++ b/wolfssl/wolfcrypt/chacha20_poly1305.h @@ -106,7 +106,7 @@ int wc_ChaCha20Poly1305_CheckTag( const byte authTagChk[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); -#ifndef NO_CHACHAPOLY_AEAD_IUF + /* Implementation of AEAD, which includes support for adding data, then final calculation of authentication tag */ WOLFSSL_API int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead, @@ -116,10 +116,10 @@ WOLFSSL_API int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead, WOLFSSL_API int wc_ChaCha20Poly1305_UpdateAad(ChaChaPoly_Aead* aead, const byte* inAAD, word32 inAADLen); WOLFSSL_API int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, - byte* data, word32 dataLen); + const byte* inData, byte* outData, word32 dataLen); WOLFSSL_API int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); -#endif /* !NO_CHACHAPOLY_AEAD_IUF */ + #ifdef __cplusplus } /* extern "C" */