From 56e57f32166cd8a8e66d28e5f8e4ff1c87d33e84 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 7 Jan 2020 07:04:01 -0800 Subject: [PATCH] Refactor Poly1305 AEAD / MAC to reduce duplicate code. Tested with TLS v1.3 interop and AEAD test vectors. --- wolfcrypt/src/chacha20_poly1305.c | 70 +++------------------- wolfcrypt/src/poly1305.c | 98 ++++++++++++++++++++++--------- wolfssl/wolfcrypt/poly1305.h | 5 +- 3 files changed, 82 insertions(+), 91 deletions(-) diff --git a/wolfcrypt/src/chacha20_poly1305.c b/wolfcrypt/src/chacha20_poly1305.c index 91b45d16e..ddd3a576f 100644 --- a/wolfcrypt/src/chacha20_poly1305.c +++ b/wolfcrypt/src/chacha20_poly1305.c @@ -40,28 +40,7 @@ #include #endif -#ifdef CHACHA_AEAD_TEST -#include -#endif - #define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0 -#define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16 - - -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], const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], @@ -94,7 +73,6 @@ int wc_ChaCha20Poly1305_Encrypt( return ret; } - int wc_ChaCha20Poly1305_Decrypt( const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], @@ -217,23 +195,6 @@ int wc_ChaCha20Poly1305_UpdateAad(ChaChaPoly_Aead* aead, return ret; } -static int wc_ChaCha20Poly1305_CalcAad(ChaChaPoly_Aead* aead) -{ - int ret = 0; - word32 paddingLen; - byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1]; - - XMEMSET(padding, 0, sizeof(padding)); - - /* Pad the AAD to 16 bytes */ - paddingLen = -(int)aead->aadLen & - (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); - if (paddingLen > 0) { - ret = wc_Poly1305Update(&aead->poly, padding, paddingLen); - } - return ret; -} - /* inData and outData can be same pointer (inline) */ int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, const byte* inData, byte* outData, word32 dataLen) @@ -249,9 +210,9 @@ int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead, return BAD_STATE_E; } - /* calculate AAD */ + /* Pad the AAD */ if (aead->state == CHACHA20_POLY1305_STATE_AAD) { - ret = wc_ChaCha20Poly1305_CalcAad(aead); + ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen); } /* advance state */ @@ -280,9 +241,6 @@ int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) { int ret = 0; - word32 paddingLen; - byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1]; - byte little64[16]; /* word64 * 2 */ if (aead == NULL || outAuthTag == NULL) { return BAD_FUNC_ARG; @@ -292,31 +250,20 @@ int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, return BAD_STATE_E; } - XMEMSET(padding, 0, sizeof(padding)); - XMEMSET(little64, 0, sizeof(little64)); - - /* make sure AAD is calculated */ + /* Pad the AAD - Make sure it is done */ if (aead->state == CHACHA20_POLY1305_STATE_AAD) { - ret = wc_ChaCha20Poly1305_CalcAad(aead); + ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen); } /* Pad the ciphertext to 16 bytes */ if (ret == 0) { - paddingLen = -(int)aead->dataLen & - (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); - if (paddingLen > 0) { - ret = wc_Poly1305Update(&aead->poly, padding, paddingLen); - } + ret = wc_Poly1305_Pad(&aead->poly, aead->dataLen); } - /* Add the aad and ciphertext length */ + /* Add the aad length and plaintext/ciphertext length */ if (ret == 0) { - /* AAD length as a 64-bit little endian integer */ - word32ToLittle64(aead->aadLen, little64); - /* Ciphertext length as a 64-bit little endian integer */ - word32ToLittle64(aead->dataLen, little64 + 8); - - ret = wc_Poly1305Update(&aead->poly, little64, sizeof(little64)); + ret = wc_Poly1305_EncodeSizes(&aead->poly, aead->aadLen, + aead->dataLen); } /* Finalize the auth tag */ @@ -330,5 +277,4 @@ int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead, return ret; } - #endif /* HAVE_CHACHA && HAVE_POLY1305 */ diff --git a/wolfcrypt/src/poly1305.c b/wolfcrypt/src/poly1305.c index b3a4752b8..c43b7ba55 100644 --- a/wolfcrypt/src/poly1305.c +++ b/wolfcrypt/src/poly1305.c @@ -235,16 +235,24 @@ extern void poly1305_final_avx2(Poly1305* ctx, byte* mac); } #endif - -static void U32TO64(word32 v, byte* p) +/* convert 32-bit unsigned to little endian 64 bit type as byte array */ +static WC_INLINE void u32tole64(const word32 inLe32, byte outLe64[8]) { - XMEMSET(p, 0, 8); - p[0] = (v & 0xFF); - p[1] = (v >> 8) & 0xFF; - p[2] = (v >> 16) & 0xFF; - p[3] = (v >> 24) & 0xFF; +#ifndef WOLFSSL_X86_64_BUILD + outLe64[0] = (byte)(inLe32 & 0x000000FF); + outLe64[1] = (byte)((inLe32 & 0x0000FF00) >> 8); + outLe64[2] = (byte)((inLe32 & 0x00FF0000) >> 16); + outLe64[3] = (byte)((inLe32 & 0xFF000000) >> 24); + outLe64[4] = 0; + outLe64[5] = 0; + outLe64[6] = 0; + outLe64[7] = 0; +#else + *(word64*)outLe64 = inLe32; +#endif } + #if !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) void poly1305_blocks(Poly1305* ctx, const unsigned char *m, size_t bytes) @@ -749,6 +757,53 @@ int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) return 0; } +/* Takes a Poly1305 struct that has a key loaded and pads the provided length + ctx : Initialized Poly1305 struct to use + lenToPad : Current number of bytes updated that needs padding to 16 + */ +int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad) +{ + int ret = 0; + word32 paddingLen; + byte padding[WC_POLY1305_PAD_SZ - 1]; + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(padding, 0, sizeof(padding)); + + /* Pad length to 16 bytes */ + paddingLen = -(int)lenToPad & (WC_POLY1305_PAD_SZ - 1); + if (paddingLen > 0) { + ret = wc_Poly1305Update(ctx, padding, paddingLen); + } + return ret; +} + +/* Takes a Poly1305 struct that has a key loaded and adds the AEAD length + encoding in 64-bit little endian + aadSz : Size of the additional authentication data + dataSz : Size of the plaintext or ciphertext + */ +int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz) +{ + int ret; + byte little64[16]; /* sizeof(word64) * 2 */ + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(little64, 0, sizeof(little64)); + + /* size of additional data and input data as little endian 64 bit types */ + u32tole64(aadSz, little64); + u32tole64(dataSz, little64 + 8); + ret = wc_Poly1305Update(ctx, little64, sizeof(little64)); + + return ret; +} /* Takes in an initialized Poly1305 struct that has a key loaded and creates a MAC (tag) using recent TLS AEAD padding scheme. @@ -765,11 +820,6 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, byte* input, word32 sz, byte* tag, word32 tagSz) { int ret; - byte padding[WC_POLY1305_PAD_SZ - 1]; - word32 paddingLen; - byte little64[16]; - - XMEMSET(padding, 0, sizeof(padding)); /* sanity check on arguments */ if (ctx == NULL || input == NULL || tag == NULL || @@ -786,11 +836,9 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { return ret; } - paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1); - if (paddingLen) { - if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { - return ret; - } + /* pad additional data */ + if ((ret = wc_Poly1305_Pad(ctx, addSz)) != 0) { + return ret; } } @@ -798,19 +846,13 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) { return ret; } - paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1); - if (paddingLen) { - if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { - return ret; - } + /* pad input data */ + if ((ret = wc_Poly1305_Pad(ctx, sz)) != 0) { + return ret; } - /* size of additional data and input as little endian 64 bit types */ - U32TO64(addSz, little64); - U32TO64(sz, little64 + 8); - ret = wc_Poly1305Update(ctx, little64, sizeof(little64)); - if (ret) - { + /* encode size of AAD and input data as little endian 64 bit types */ + if ((ret = wc_Poly1305_EncodeSizes(ctx, addSz, sz)) != 0) { return ret; } diff --git a/wolfssl/wolfcrypt/poly1305.h b/wolfssl/wolfcrypt/poly1305.h index 0f81ca0e7..99fefd47d 100644 --- a/wolfssl/wolfcrypt/poly1305.h +++ b/wolfssl/wolfcrypt/poly1305.h @@ -112,6 +112,10 @@ WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key, word32 kySz); WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32); WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag); + +/* AEAD Functions */ +WOLFSSL_API int wc_Poly1305_Pad(Poly1305* ctx, word32 lenToPad); +WOLFSSL_API int wc_Poly1305_EncodeSizes(Poly1305* ctx, word32 aadSz, word32 dataSz); WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, byte* input, word32 sz, byte* tag, word32 tagSz); @@ -124,4 +128,3 @@ void poly1305_blocks(Poly1305* ctx, const unsigned char *m, #endif /* HAVE_POLY1305 */ #endif /* WOLF_CRYPT_POLY1305_H */ -