mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-29 18:27:29 +02:00
Refactor Poly1305 AEAD / MAC to reduce duplicate code. Tested with TLS v1.3 interop and AEAD test vectors.
This commit is contained in:
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
Reference in New Issue
Block a user