Refactor Poly1305 AEAD / MAC to reduce duplicate code. Tested with TLS v1.3 interop and AEAD test vectors.

This commit is contained in:
David Garske
2020-01-07 07:04:01 -08:00
parent d68d5229e1
commit 56e57f3216
3 changed files with 82 additions and 91 deletions

View File

@ -40,28 +40,7 @@
#include <wolfcrypt/src/misc.c>
#endif
#ifdef CHACHA_AEAD_TEST
#include <stdio.h>
#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 */

View File

@ -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;
}

View File

@ -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 */