mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 10:47:28 +02:00
Merge pull request #2706 from dgarske/chapoly_aead_iuf
New API's for ChaCha20/Poly1305 AEAD init/update/final
This commit is contained in:
@ -32,8 +32,6 @@
|
|||||||
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
|
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
|
||||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||||
#include <wolfssl/wolfcrypt/logging.h>
|
#include <wolfssl/wolfcrypt/logging.h>
|
||||||
#include <wolfssl/wolfcrypt/chacha.h>
|
|
||||||
#include <wolfssl/wolfcrypt/poly1305.h>
|
|
||||||
|
|
||||||
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
||||||
#include <wolfssl/wolfcrypt/misc.h>
|
#include <wolfssl/wolfcrypt/misc.h>
|
||||||
@ -42,20 +40,7 @@
|
|||||||
#include <wolfcrypt/src/misc.c>
|
#include <wolfcrypt/src/misc.c>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CHACHA_AEAD_TEST
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0
|
#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]);
|
|
||||||
|
|
||||||
int wc_ChaCha20Poly1305_Encrypt(
|
int wc_ChaCha20Poly1305_Encrypt(
|
||||||
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
|
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
|
||||||
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
|
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
|
||||||
@ -64,12 +49,10 @@ int wc_ChaCha20Poly1305_Encrypt(
|
|||||||
byte* outCiphertext,
|
byte* outCiphertext,
|
||||||
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
|
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
|
||||||
{
|
{
|
||||||
int err;
|
int ret;
|
||||||
byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
|
ChaChaPoly_Aead aead;
|
||||||
ChaCha chaChaCtx;
|
|
||||||
|
|
||||||
/* Validate function arguments */
|
/* Validate function arguments */
|
||||||
|
|
||||||
if (!inKey || !inIV ||
|
if (!inKey || !inIV ||
|
||||||
!inPlaintext || !inPlaintextLen ||
|
!inPlaintext || !inPlaintextLen ||
|
||||||
!outCiphertext ||
|
!outCiphertext ||
|
||||||
@ -78,35 +61,18 @@ int wc_ChaCha20Poly1305_Encrypt(
|
|||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
|
ret = wc_ChaCha20Poly1305_Init(&aead, inKey, inIV,
|
||||||
|
CHACHA20_POLY1305_AEAD_ENCRYPT);
|
||||||
/* Create the Poly1305 key */
|
if (ret == 0)
|
||||||
err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
|
ret = wc_ChaCha20Poly1305_UpdateAad(&aead, inAAD, inAADLen);
|
||||||
if (err != 0) return err;
|
if (ret == 0)
|
||||||
|
ret = wc_ChaCha20Poly1305_UpdateData(&aead, inPlaintext, outCiphertext,
|
||||||
err = wc_Chacha_SetIV(&chaChaCtx, inIV,
|
inPlaintextLen);
|
||||||
CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
|
if (ret == 0)
|
||||||
if (err != 0) return err;
|
ret = wc_ChaCha20Poly1305_Final(&aead, outAuthTag);
|
||||||
|
return ret;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wc_ChaCha20Poly1305_Decrypt(
|
int wc_ChaCha20Poly1305_Decrypt(
|
||||||
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
|
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
|
||||||
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
|
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
|
||||||
@ -115,13 +81,11 @@ int wc_ChaCha20Poly1305_Decrypt(
|
|||||||
const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
|
const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
|
||||||
byte* outPlaintext)
|
byte* outPlaintext)
|
||||||
{
|
{
|
||||||
int err;
|
int ret;
|
||||||
byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
|
ChaChaPoly_Aead aead;
|
||||||
ChaCha chaChaCtx;
|
|
||||||
byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
|
byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
|
||||||
|
|
||||||
/* Validate function arguments */
|
/* Validate function arguments */
|
||||||
|
|
||||||
if (!inKey || !inIV ||
|
if (!inKey || !inIV ||
|
||||||
!inCiphertext || !inCiphertextLen ||
|
!inCiphertext || !inCiphertextLen ||
|
||||||
!inAuthTag ||
|
!inAuthTag ||
|
||||||
@ -131,121 +95,186 @@ int wc_ChaCha20Poly1305_Decrypt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag));
|
XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag));
|
||||||
XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
|
|
||||||
|
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(
|
||||||
|
const byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
|
||||||
|
const byte authTagChk[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if (authTag == NULL || authTagChk == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
if (ConstantCompare(authTag, authTagChk,
|
||||||
|
CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0) {
|
||||||
|
ret = MAC_CMP_FAILED_E;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead,
|
||||||
|
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
|
||||||
|
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
|
||||||
|
int isEncrypt)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
byte authKey[CHACHA20_POLY1305_AEAD_KEYSIZE];
|
||||||
|
|
||||||
|
/* check arguments */
|
||||||
|
if (aead == NULL || inKey == NULL || inIV == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup aead context */
|
||||||
|
XMEMSET(aead, 0, sizeof(ChaChaPoly_Aead));
|
||||||
|
XMEMSET(authKey, 0, sizeof(authKey));
|
||||||
|
aead->isEncrypt = isEncrypt;
|
||||||
|
|
||||||
|
/* Initialize the ChaCha20 context (key and iv) */
|
||||||
|
ret = wc_Chacha_SetKey(&aead->chacha, inKey,
|
||||||
|
CHACHA20_POLY1305_AEAD_KEYSIZE);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_Chacha_SetIV(&aead->chacha, inIV,
|
||||||
|
CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create the Poly1305 key */
|
/* Create the Poly1305 key */
|
||||||
err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
|
if (ret == 0) {
|
||||||
if (err != 0) return err;
|
ret = wc_Chacha_Process(&aead->chacha, authKey, authKey,
|
||||||
|
CHACHA20_POLY1305_AEAD_KEYSIZE);
|
||||||
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 && ConstantCompare(inAuthTag, calculatedAuthTag,
|
|
||||||
CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0)
|
|
||||||
{
|
|
||||||
err = MAC_CMP_FAILED_E;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decrypt the received ciphertext */
|
/* Initialize Poly1305 context */
|
||||||
if (err == 0)
|
if (ret == 0) {
|
||||||
err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext,
|
ret = wc_Poly1305SetKey(&aead->poly, authKey,
|
||||||
inCiphertextLen);
|
CHACHA20_POLY1305_AEAD_KEYSIZE);
|
||||||
ForceZero(poly1305Key, sizeof(poly1305Key));
|
}
|
||||||
|
|
||||||
return err;
|
if (ret == 0) {
|
||||||
|
aead->state = CHACHA20_POLY1305_STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* optional additional authentication data */
|
||||||
static int calculateAuthTag(
|
int wc_ChaCha20Poly1305_UpdateAad(ChaChaPoly_Aead* aead,
|
||||||
const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
|
const byte* inAAD, word32 inAADLen)
|
||||||
const byte *inAAD, const word32 inAADLen,
|
|
||||||
const byte *inCiphertext, const word32 inCiphertextLen,
|
|
||||||
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
|
|
||||||
{
|
{
|
||||||
int err;
|
int ret = 0;
|
||||||
Poly1305 poly1305Ctx;
|
|
||||||
byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1];
|
|
||||||
word32 paddingLen;
|
|
||||||
byte little64[16];
|
|
||||||
|
|
||||||
XMEMSET(padding, 0, sizeof(padding));
|
if (aead == NULL || (inAAD == NULL && inAADLen > 0)) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
/* Initialize Poly1305 */
|
}
|
||||||
err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey,
|
if (aead->state != CHACHA20_POLY1305_STATE_READY &&
|
||||||
CHACHA20_POLY1305_AEAD_KEYSIZE);
|
aead->state != CHACHA20_POLY1305_STATE_AAD) {
|
||||||
if (err)
|
return BAD_STATE_E;
|
||||||
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 */
|
if (inAAD && inAADLen > 0) {
|
||||||
err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen);
|
ret = wc_Poly1305Update(&aead->poly, inAAD, inAADLen);
|
||||||
if (err)
|
if (ret == 0) {
|
||||||
return err;
|
aead->aadLen += inAADLen;
|
||||||
|
aead->state = CHACHA20_POLY1305_STATE_AAD;
|
||||||
/* -- 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 */
|
return ret;
|
||||||
word32ToLittle64(inAADLen, little64);
|
}
|
||||||
/* -- Ciphertext length as a 64-bit little endian integer */
|
|
||||||
word32ToLittle64(inCiphertextLen, little64 + 8);
|
/* inData and outData can be same pointer (inline) */
|
||||||
err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
|
int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead,
|
||||||
if (err)
|
const byte* inData, byte* outData, word32 dataLen)
|
||||||
return err;
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (aead == NULL || inData == NULL || outData == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
if (aead->state != CHACHA20_POLY1305_STATE_READY &&
|
||||||
|
aead->state != CHACHA20_POLY1305_STATE_AAD &&
|
||||||
|
aead->state != CHACHA20_POLY1305_STATE_DATA) {
|
||||||
|
return BAD_STATE_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad the AAD */
|
||||||
|
if (aead->state == CHACHA20_POLY1305_STATE_AAD) {
|
||||||
|
ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* advance state */
|
||||||
|
aead->state = CHACHA20_POLY1305_STATE_DATA;
|
||||||
|
|
||||||
|
/* Perform ChaCha20 encrypt/decrypt and Poly1305 auth calc */
|
||||||
|
if (ret == 0) {
|
||||||
|
if (aead->isEncrypt) {
|
||||||
|
ret = wc_Chacha_Process(&aead->chacha, outData, inData, dataLen);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Poly1305Update(&aead->poly, outData, dataLen);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = wc_Poly1305Update(&aead->poly, inData, dataLen);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Chacha_Process(&aead->chacha, outData, inData, dataLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
aead->dataLen += dataLen;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead,
|
||||||
|
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (aead == NULL || outAuthTag == NULL) {
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
if (aead->state != CHACHA20_POLY1305_STATE_AAD &&
|
||||||
|
aead->state != CHACHA20_POLY1305_STATE_DATA) {
|
||||||
|
return BAD_STATE_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad the AAD - Make sure it is done */
|
||||||
|
if (aead->state == CHACHA20_POLY1305_STATE_AAD) {
|
||||||
|
ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pad the ciphertext to 16 bytes */
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_Poly1305_Pad(&aead->poly, aead->dataLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the aad length and plaintext/ciphertext length */
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = wc_Poly1305_EncodeSizes(&aead->poly, aead->aadLen,
|
||||||
|
aead->dataLen);
|
||||||
|
}
|
||||||
|
|
||||||
/* Finalize the auth tag */
|
/* Finalize the auth tag */
|
||||||
err = wc_Poly1305Final(&poly1305Ctx, outAuthTag);
|
if (ret == 0) {
|
||||||
|
ret = wc_Poly1305Final(&aead->poly, outAuthTag);
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
/* reset and cleanup sensitive context */
|
||||||
|
ForceZero(aead, sizeof(ChaChaPoly_Aead));
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
|
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
|
||||||
|
@ -235,16 +235,24 @@ extern void poly1305_final_avx2(Poly1305* ctx, byte* mac);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* convert 32-bit unsigned to little endian 64 bit type as byte array */
|
||||||
static void U32TO64(word32 v, byte* p)
|
static WC_INLINE void u32tole64(const word32 inLe32, byte outLe64[8])
|
||||||
{
|
{
|
||||||
XMEMSET(p, 0, 8);
|
#ifndef WOLFSSL_X86_64_BUILD
|
||||||
p[0] = (v & 0xFF);
|
outLe64[0] = (byte)(inLe32 & 0x000000FF);
|
||||||
p[1] = (v >> 8) & 0xFF;
|
outLe64[1] = (byte)((inLe32 & 0x0000FF00) >> 8);
|
||||||
p[2] = (v >> 16) & 0xFF;
|
outLe64[2] = (byte)((inLe32 & 0x00FF0000) >> 16);
|
||||||
p[3] = (v >> 24) & 0xFF;
|
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__)
|
#if !defined(WOLFSSL_ARMASM) || !defined(__aarch64__)
|
||||||
void poly1305_blocks(Poly1305* ctx, const unsigned char *m,
|
void poly1305_blocks(Poly1305* ctx, const unsigned char *m,
|
||||||
size_t bytes)
|
size_t bytes)
|
||||||
@ -749,6 +757,56 @@ int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes)
|
|||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
if (lenToPad == 0) {
|
||||||
|
return 0; /* nothing needs to be done */
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
/* Takes in an initialized Poly1305 struct that has a key loaded and creates
|
||||||
a MAC (tag) using recent TLS AEAD padding scheme.
|
a MAC (tag) using recent TLS AEAD padding scheme.
|
||||||
@ -765,11 +823,6 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
|
|||||||
byte* input, word32 sz, byte* tag, word32 tagSz)
|
byte* input, word32 sz, byte* tag, word32 tagSz)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
byte padding[WC_POLY1305_PAD_SZ - 1];
|
|
||||||
word32 paddingLen;
|
|
||||||
byte little64[16];
|
|
||||||
|
|
||||||
XMEMSET(padding, 0, sizeof(padding));
|
|
||||||
|
|
||||||
/* sanity check on arguments */
|
/* sanity check on arguments */
|
||||||
if (ctx == NULL || input == NULL || tag == NULL ||
|
if (ctx == NULL || input == NULL || tag == NULL ||
|
||||||
@ -786,11 +839,9 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
|
|||||||
if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) {
|
if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1);
|
/* pad additional data */
|
||||||
if (paddingLen) {
|
if ((ret = wc_Poly1305_Pad(ctx, addSz)) != 0) {
|
||||||
if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) {
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,19 +849,13 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
|
|||||||
if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) {
|
if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1);
|
/* pad input data */
|
||||||
if (paddingLen) {
|
if ((ret = wc_Poly1305_Pad(ctx, sz)) != 0) {
|
||||||
if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) {
|
return ret;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* size of additional data and input as little endian 64 bit types */
|
/* encode size of AAD and input data as little endian 64 bit types */
|
||||||
U32TO64(addSz, little64);
|
if ((ret = wc_Poly1305_EncodeSizes(ctx, addSz, sz)) != 0) {
|
||||||
U32TO64(sz, little64 + 8);
|
|
||||||
ret = wc_Poly1305Update(ctx, little64, sizeof(little64));
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5030,11 +5030,17 @@ int chacha20_poly1305_aead_test(void)
|
|||||||
0x39, 0x23, 0x36, 0xfe, 0xa1, 0x85, 0x1f, 0x38
|
0x39, 0x23, 0x36, 0xfe, 0xa1, 0x85, 0x1f, 0x38
|
||||||
};
|
};
|
||||||
|
|
||||||
byte generatedCiphertext[272];
|
byte generatedCiphertext[265]; /* max plaintext2/cipher2 */
|
||||||
byte generatedPlaintext[272];
|
byte generatedPlaintext[265]; /* max plaintext2/cipher2 */
|
||||||
byte generatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
|
byte generatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
ChaChaPoly_Aead aead;
|
||||||
|
#define TEST_SMALL_CHACHA_CHUNKS 64
|
||||||
|
#ifdef TEST_SMALL_CHACHA_CHUNKS
|
||||||
|
word32 testLen;
|
||||||
|
#endif
|
||||||
|
|
||||||
XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
|
XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
|
||||||
XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
|
XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
|
||||||
XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
|
XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
|
||||||
@ -5092,8 +5098,8 @@ int chacha20_poly1305_aead_test(void)
|
|||||||
if (err != BAD_FUNC_ARG)
|
if (err != BAD_FUNC_ARG)
|
||||||
return -4511;
|
return -4511;
|
||||||
|
|
||||||
/* Test #1 */
|
|
||||||
|
|
||||||
|
/* Test #1 */
|
||||||
err = wc_ChaCha20Poly1305_Encrypt(key1, iv1,
|
err = wc_ChaCha20Poly1305_Encrypt(key1, iv1,
|
||||||
aad1, sizeof(aad1),
|
aad1, sizeof(aad1),
|
||||||
plaintext1, sizeof(plaintext1),
|
plaintext1, sizeof(plaintext1),
|
||||||
@ -5103,17 +5109,14 @@ int chacha20_poly1305_aead_test(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -- Check the ciphertext and authtag */
|
/* -- Check the ciphertext and authtag */
|
||||||
|
|
||||||
if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) {
|
if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) {
|
||||||
return -4512;
|
return -4512;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) {
|
if (XMEMCMP(generatedAuthTag, authTag1, sizeof(authTag1))) {
|
||||||
return -4513;
|
return -4513;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Verify decryption works */
|
/* -- Verify decryption works */
|
||||||
|
|
||||||
err = wc_ChaCha20Poly1305_Decrypt(key1, iv1,
|
err = wc_ChaCha20Poly1305_Decrypt(key1, iv1,
|
||||||
aad1, sizeof(aad1),
|
aad1, sizeof(aad1),
|
||||||
cipher1, sizeof(cipher1),
|
cipher1, sizeof(cipher1),
|
||||||
@ -5121,17 +5124,16 @@ int chacha20_poly1305_aead_test(void)
|
|||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
if (XMEMCMP(generatedPlaintext, plaintext1, sizeof(plaintext1))) {
|
||||||
if (XMEMCMP(generatedPlaintext, plaintext1, sizeof( plaintext1))) {
|
|
||||||
return -4514;
|
return -4514;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
|
XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
|
||||||
XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
|
XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
|
||||||
XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
|
XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
|
||||||
|
|
||||||
/* Test #2 */
|
/* Test #2 */
|
||||||
|
|
||||||
err = wc_ChaCha20Poly1305_Encrypt(key2, iv2,
|
err = wc_ChaCha20Poly1305_Encrypt(key2, iv2,
|
||||||
aad2, sizeof(aad2),
|
aad2, sizeof(aad2),
|
||||||
plaintext2, sizeof(plaintext2),
|
plaintext2, sizeof(plaintext2),
|
||||||
@ -5141,17 +5143,14 @@ int chacha20_poly1305_aead_test(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -- Check the ciphertext and authtag */
|
/* -- Check the ciphertext and authtag */
|
||||||
|
|
||||||
if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) {
|
if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) {
|
||||||
return -4515;
|
return -4515;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) {
|
if (XMEMCMP(generatedAuthTag, authTag2, sizeof(authTag2))) {
|
||||||
return -4516;
|
return -4516;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Verify decryption works */
|
/* -- Verify decryption works */
|
||||||
|
|
||||||
err = wc_ChaCha20Poly1305_Decrypt(key2, iv2,
|
err = wc_ChaCha20Poly1305_Decrypt(key2, iv2,
|
||||||
aad2, sizeof(aad2),
|
aad2, sizeof(aad2),
|
||||||
cipher2, sizeof(cipher2),
|
cipher2, sizeof(cipher2),
|
||||||
@ -5164,6 +5163,214 @@ int chacha20_poly1305_aead_test(void)
|
|||||||
return -4517;
|
return -4517;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* AEAD init/update/final */
|
||||||
|
err = wc_ChaCha20Poly1305_Init(NULL, key1, iv1,
|
||||||
|
CHACHA20_POLY1305_AEAD_DECRYPT);
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4520;
|
||||||
|
err = wc_ChaCha20Poly1305_Init(&aead, NULL, iv1,
|
||||||
|
CHACHA20_POLY1305_AEAD_DECRYPT);
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4521;
|
||||||
|
err = wc_ChaCha20Poly1305_Init(&aead, key1, NULL,
|
||||||
|
CHACHA20_POLY1305_AEAD_DECRYPT);
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4522;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(NULL, aad1, sizeof(aad1));
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4523;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(&aead, NULL, sizeof(aad1));
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4524;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(NULL, generatedPlaintext,
|
||||||
|
generatedPlaintext, sizeof(plaintext1));
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4525;
|
||||||
|
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);
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4527;
|
||||||
|
err = wc_ChaCha20Poly1305_Final(&aead, NULL);
|
||||||
|
if (err != BAD_FUNC_ARG)
|
||||||
|
return -4528;
|
||||||
|
|
||||||
|
/* AEAD init/update/final - state tests */
|
||||||
|
aead.state = CHACHA20_POLY1305_STATE_INIT;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1));
|
||||||
|
if (err != BAD_STATE_E)
|
||||||
|
return -4529;
|
||||||
|
aead.state = CHACHA20_POLY1305_STATE_DATA;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1));
|
||||||
|
if (err != BAD_STATE_E)
|
||||||
|
return -4530;
|
||||||
|
aead.state = CHACHA20_POLY1305_STATE_INIT;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedPlaintext,
|
||||||
|
generatedPlaintext, sizeof(plaintext1));
|
||||||
|
if (err != BAD_STATE_E)
|
||||||
|
return -4531;
|
||||||
|
aead.state = CHACHA20_POLY1305_STATE_INIT;
|
||||||
|
err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag);
|
||||||
|
if (err != BAD_STATE_E)
|
||||||
|
return -4532;
|
||||||
|
aead.state = CHACHA20_POLY1305_STATE_READY;
|
||||||
|
err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag);
|
||||||
|
if (err != BAD_STATE_E)
|
||||||
|
return -4533;
|
||||||
|
|
||||||
|
XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
|
||||||
|
XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
|
||||||
|
XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
|
||||||
|
|
||||||
|
/* Test 1 - Encrypt */
|
||||||
|
err = wc_ChaCha20Poly1305_Init(&aead, key1, iv1,
|
||||||
|
CHACHA20_POLY1305_AEAD_ENCRYPT);
|
||||||
|
if (err != 0)
|
||||||
|
return -4537;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1));
|
||||||
|
if (err != 0)
|
||||||
|
return -4538;
|
||||||
|
#ifdef TEST_SMALL_CHACHA_CHUNKS
|
||||||
|
/* test doing data in smaller chunks */
|
||||||
|
for (testLen=0; testLen<sizeof(plaintext1); ) {
|
||||||
|
word32 dataLen = sizeof(plaintext1) - testLen;
|
||||||
|
if (dataLen > TEST_SMALL_CHACHA_CHUNKS)
|
||||||
|
dataLen = TEST_SMALL_CHACHA_CHUNKS;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead, &plaintext1[testLen],
|
||||||
|
&generatedCiphertext[testLen], dataLen);
|
||||||
|
if (err != 0)
|
||||||
|
return -4539;
|
||||||
|
testLen += dataLen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead, plaintext1,
|
||||||
|
generatedCiphertext, sizeof(plaintext1));
|
||||||
|
#endif
|
||||||
|
err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag);
|
||||||
|
if (err != 0)
|
||||||
|
return -4540;
|
||||||
|
err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag1);
|
||||||
|
if (err != 0)
|
||||||
|
return -4541;
|
||||||
|
if (XMEMCMP(generatedCiphertext, cipher1, sizeof(cipher1))) {
|
||||||
|
return -4542;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test 1 - Decrypt */
|
||||||
|
err = wc_ChaCha20Poly1305_Init(&aead, key1, iv1,
|
||||||
|
CHACHA20_POLY1305_AEAD_DECRYPT);
|
||||||
|
if (err != 0)
|
||||||
|
return -4543;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad1, sizeof(aad1));
|
||||||
|
if (err != 0)
|
||||||
|
return -4544;
|
||||||
|
#ifdef TEST_SMALL_CHACHA_CHUNKS
|
||||||
|
/* test doing data in smaller chunks */
|
||||||
|
for (testLen=0; testLen<sizeof(plaintext1); ) {
|
||||||
|
word32 dataLen = sizeof(plaintext1) - testLen;
|
||||||
|
if (dataLen > TEST_SMALL_CHACHA_CHUNKS)
|
||||||
|
dataLen = TEST_SMALL_CHACHA_CHUNKS;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead,
|
||||||
|
&generatedCiphertext[testLen], &generatedPlaintext[testLen],
|
||||||
|
dataLen);
|
||||||
|
if (err != 0)
|
||||||
|
return -4545;
|
||||||
|
testLen += dataLen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext,
|
||||||
|
generatedPlaintext, sizeof(cipher1));
|
||||||
|
#endif
|
||||||
|
err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag);
|
||||||
|
if (err != 0)
|
||||||
|
return -4546;
|
||||||
|
err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag1);
|
||||||
|
if (err != 0)
|
||||||
|
return -4547;
|
||||||
|
if (XMEMCMP(generatedPlaintext, plaintext1, sizeof(plaintext1))) {
|
||||||
|
return -4548;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMSET(generatedCiphertext, 0, sizeof(generatedCiphertext));
|
||||||
|
XMEMSET(generatedAuthTag, 0, sizeof(generatedAuthTag));
|
||||||
|
XMEMSET(generatedPlaintext, 0, sizeof(generatedPlaintext));
|
||||||
|
|
||||||
|
/* Test 2 - Encrypt */
|
||||||
|
err = wc_ChaCha20Poly1305_Init(&aead, key2, iv2,
|
||||||
|
CHACHA20_POLY1305_AEAD_ENCRYPT);
|
||||||
|
if (err != 0)
|
||||||
|
return -4550;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad2, sizeof(aad2));
|
||||||
|
if (err != 0)
|
||||||
|
return -4551;
|
||||||
|
#ifdef TEST_SMALL_CHACHA_CHUNKS
|
||||||
|
/* test doing data in smaller chunks */
|
||||||
|
for (testLen=0; testLen<sizeof(plaintext2); ) {
|
||||||
|
word32 dataLen = sizeof(plaintext2) - testLen;
|
||||||
|
if (dataLen > TEST_SMALL_CHACHA_CHUNKS)
|
||||||
|
dataLen = TEST_SMALL_CHACHA_CHUNKS;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead, &plaintext2[testLen],
|
||||||
|
&generatedCiphertext[testLen], dataLen);
|
||||||
|
if (err != 0)
|
||||||
|
return -4552;
|
||||||
|
testLen += dataLen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead, plaintext2, generatedCiphertext,
|
||||||
|
sizeof(plaintext2));
|
||||||
|
#endif
|
||||||
|
err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag);
|
||||||
|
if (err != 0)
|
||||||
|
return -4553;
|
||||||
|
err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag2);
|
||||||
|
if (err != 0)
|
||||||
|
return -4554;
|
||||||
|
if (XMEMCMP(generatedCiphertext, cipher2, sizeof(cipher2))) {
|
||||||
|
return -4555;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test 2 - Decrypt */
|
||||||
|
err = wc_ChaCha20Poly1305_Init(&aead, key2, iv2,
|
||||||
|
CHACHA20_POLY1305_AEAD_DECRYPT);
|
||||||
|
if (err != 0)
|
||||||
|
return -4556;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateAad(&aead, aad2, sizeof(aad2));
|
||||||
|
if (err != 0)
|
||||||
|
return -4557;
|
||||||
|
#ifdef TEST_SMALL_CHACHA_CHUNKS
|
||||||
|
/* test doing data in smaller chunks */
|
||||||
|
for (testLen=0; testLen<sizeof(plaintext2); ) {
|
||||||
|
word32 dataLen = sizeof(plaintext2) - testLen;
|
||||||
|
if (dataLen > TEST_SMALL_CHACHA_CHUNKS)
|
||||||
|
dataLen = TEST_SMALL_CHACHA_CHUNKS;
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead,
|
||||||
|
&generatedCiphertext[testLen], &generatedPlaintext[testLen],
|
||||||
|
dataLen);
|
||||||
|
if (err != 0)
|
||||||
|
return -4558;
|
||||||
|
testLen += dataLen;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
err = wc_ChaCha20Poly1305_UpdateData(&aead, generatedCiphertext,
|
||||||
|
generatedPlaintext, sizeof(cipher2));
|
||||||
|
#endif
|
||||||
|
err = wc_ChaCha20Poly1305_Final(&aead, generatedAuthTag);
|
||||||
|
if (err != 0)
|
||||||
|
return -4559;
|
||||||
|
err = wc_ChaCha20Poly1305_CheckTag(generatedAuthTag, authTag2);
|
||||||
|
if (err != 0)
|
||||||
|
return -4560;
|
||||||
|
if (XMEMCMP(generatedPlaintext, plaintext2, sizeof(plaintext2))) {
|
||||||
|
return -4561;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
|
#endif /* HAVE_CHACHA && HAVE_POLY1305 */
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#define WOLF_CRYPT_CHACHA20_POLY1305_H
|
#define WOLF_CRYPT_CHACHA20_POLY1305_H
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/types.h>
|
#include <wolfssl/wolfcrypt/types.h>
|
||||||
|
#include <wolfssl/wolfcrypt/chacha.h>
|
||||||
|
#include <wolfssl/wolfcrypt/poly1305.h>
|
||||||
|
|
||||||
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
|
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
|
||||||
|
|
||||||
@ -45,18 +47,40 @@
|
|||||||
#define CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE 16
|
#define CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE 16
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CHACHA20_POLY_1305_ENC_TYPE = 8 /* cipher unique type */
|
CHACHA20_POLY_1305_ENC_TYPE = 8, /* cipher unique type */
|
||||||
|
|
||||||
|
/* AEAD Cipher Direction */
|
||||||
|
CHACHA20_POLY1305_AEAD_DECRYPT = 0,
|
||||||
|
CHACHA20_POLY1305_AEAD_ENCRYPT = 1,
|
||||||
|
|
||||||
|
/* AEAD State */
|
||||||
|
CHACHA20_POLY1305_STATE_INIT = 0,
|
||||||
|
CHACHA20_POLY1305_STATE_READY = 1,
|
||||||
|
CHACHA20_POLY1305_STATE_AAD = 2,
|
||||||
|
CHACHA20_POLY1305_STATE_DATA = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
typedef struct ChaChaPoly_Aead {
|
||||||
* The IV for this implementation is 96 bits to give the most flexibility.
|
ChaCha chacha;
|
||||||
*
|
Poly1305 poly;
|
||||||
* Some protocols may have unique per-invocation inputs that are not
|
|
||||||
* 96-bit in length. For example, IPsec may specify a 64-bit nonce. In
|
word32 aadLen;
|
||||||
* such a case, it is up to the protocol document to define how to
|
word32 dataLen;
|
||||||
* transform the protocol nonce into a 96-bit nonce, for example by
|
|
||||||
* concatenating a constant value.
|
byte state;
|
||||||
*/
|
byte isEncrypt:1;
|
||||||
|
} ChaChaPoly_Aead;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IV for this implementation is 96 bits to give the most flexibility.
|
||||||
|
*
|
||||||
|
* Some protocols may have unique per-invocation inputs that are not
|
||||||
|
* 96-bit in length. For example, IPsec may specify a 64-bit nonce. In
|
||||||
|
* such a case, it is up to the protocol document to define how to
|
||||||
|
* transform the protocol nonce into a 96-bit nonce, for example by
|
||||||
|
* concatenating a constant value.
|
||||||
|
*/
|
||||||
|
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_ChaCha20Poly1305_Encrypt(
|
int wc_ChaCha20Poly1305_Encrypt(
|
||||||
@ -76,6 +100,27 @@ int wc_ChaCha20Poly1305_Decrypt(
|
|||||||
const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
|
const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
|
||||||
byte* outPlaintext);
|
byte* outPlaintext);
|
||||||
|
|
||||||
|
WOLFSSL_API
|
||||||
|
int wc_ChaCha20Poly1305_CheckTag(
|
||||||
|
const byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
|
||||||
|
const byte authTagChk[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Implementation of AEAD, which includes support for adding
|
||||||
|
data, then final calculation of authentication tag */
|
||||||
|
WOLFSSL_API int wc_ChaCha20Poly1305_Init(ChaChaPoly_Aead* aead,
|
||||||
|
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
|
||||||
|
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
|
||||||
|
int isEncrypt);
|
||||||
|
WOLFSSL_API int wc_ChaCha20Poly1305_UpdateAad(ChaChaPoly_Aead* aead,
|
||||||
|
const byte* inAAD, word32 inAADLen);
|
||||||
|
WOLFSSL_API int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead,
|
||||||
|
const byte* inData, byte* outData, word32 dataLen);
|
||||||
|
WOLFSSL_API int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead,
|
||||||
|
byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
@ -112,6 +112,10 @@ WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key,
|
|||||||
word32 kySz);
|
word32 kySz);
|
||||||
WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32);
|
WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32);
|
||||||
WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag);
|
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,
|
WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz,
|
||||||
byte* input, word32 sz, byte* tag, word32 tagSz);
|
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 /* HAVE_POLY1305 */
|
||||||
#endif /* WOLF_CRYPT_POLY1305_H */
|
#endif /* WOLF_CRYPT_POLY1305_H */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user