summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c')
-rw-r--r--FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c328
1 files changed, 170 insertions, 158 deletions
diff --git a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c
index 4a2b1be22..64bc4c199 100644
--- a/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c
+++ b/FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/chacha20_poly1305.c
@@ -1,8 +1,8 @@
/* chacha.c
*
- * Copyright (C) 2006-2015 wolfSSL Inc.
+ * Copyright (C) 2006-2020 wolfSSL Inc.
*
- * This file is part of wolfSSL. (formerly known as CyaSSL)
+ * This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,10 +16,11 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -31,29 +32,15 @@
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
-#include <wolfssl/wolfcrypt/chacha.h>
-#include <wolfssl/wolfcrypt/poly1305.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
+#define WOLFSSL_MISC_INCLUDED
#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]);
-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(
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
@@ -62,12 +49,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,35 +61,18 @@ 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;
}
-
int wc_ChaCha20Poly1305_Decrypt(
const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
@@ -113,13 +81,11 @@ 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 */
-
if (!inKey || !inIV ||
!inCiphertext || !inCiphertextLen ||
!inAuthTag ||
@@ -129,146 +95,192 @@ 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 && ConstantCompare(inAuthTag, calculatedAuthTag,
- CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0)
- {
- err = MAC_CMP_FAILED_E;
- }
- /* 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(
+ 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;
+}
-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_Init(ChaChaPoly_Aead* aead,
+ const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
+ const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
+ int isEncrypt)
{
- int err;
- Poly1305 poly1305Ctx;
- byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1];
- word32 paddingLen;
- byte little64[8];
+ int ret;
+ byte authKey[CHACHA20_POLY1305_AEAD_KEYSIZE];
- XMEMSET(padding, 0, sizeof(padding));
+ /* check arguments */
+ if (aead == NULL || inKey == NULL || inIV == NULL) {
+ return BAD_FUNC_ARG;
+ }
- /* Initialize Poly1305 */
+ /* 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);
+ }
- err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey,
- CHACHA20_POLY1305_AEAD_KEYSIZE);
- if (err)
- {
- return err;
+ /* Create the Poly1305 key */
+ if (ret == 0) {
+ ret = wc_Chacha_Process(&aead->chacha, authKey, authKey,
+ CHACHA20_POLY1305_AEAD_KEYSIZE);
}
- /* Create the authTag by MAC'ing the following items: */
+ /* Initialize Poly1305 context */
+ if (ret == 0) {
+ ret = wc_Poly1305SetKey(&aead->poly, authKey,
+ CHACHA20_POLY1305_AEAD_KEYSIZE);
+ }
- /* -- AAD */
+ /* advance counter by 1 after creating Poly1305 key */
+ if (ret == 0) {
+ ret = wc_Chacha_SetIV(&aead->chacha, inIV,
+ CHACHA20_POLY1305_AEAD_INITIAL_COUNTER + 1);
+ }
- if (inAAD && inAADLen)
- {
- err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen);
+ if (ret == 0) {
+ aead->state = CHACHA20_POLY1305_STATE_READY;
+ }
- /* -- padding1: pad the AAD to 16 bytes */
+ return ret;
+}
- paddingLen = -inAADLen & (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
- if (paddingLen)
- {
- err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
- }
+/* optional additional authentication data */
+int wc_ChaCha20Poly1305_UpdateAad(ChaChaPoly_Aead* aead,
+ const byte* inAAD, word32 inAADLen)
+{
+ int ret = 0;
- if (err)
- {
- return err;
+ if (aead == NULL || (inAAD == NULL && inAADLen > 0)) {
+ return BAD_FUNC_ARG;
+ }
+ if (aead->state != CHACHA20_POLY1305_STATE_READY &&
+ aead->state != CHACHA20_POLY1305_STATE_AAD) {
+ return BAD_STATE_E;
+ }
+
+ if (inAAD && inAADLen > 0) {
+ ret = wc_Poly1305Update(&aead->poly, inAAD, inAADLen);
+ if (ret == 0) {
+ aead->aadLen += inAADLen;
+ aead->state = CHACHA20_POLY1305_STATE_AAD;
}
}
- /* -- Ciphertext */
+ return ret;
+}
- err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen);
- if (err)
- {
- return err;
+/* inData and outData can be same pointer (inline) */
+int wc_ChaCha20Poly1305_UpdateData(ChaChaPoly_Aead* aead,
+ const byte* inData, byte* outData, word32 dataLen)
+{
+ 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;
}
- /* -- padding2: pad the ciphertext to 16 bytes */
+ /* Pad the AAD */
+ if (aead->state == CHACHA20_POLY1305_STATE_AAD) {
+ ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen);
+ }
- paddingLen = -inCiphertextLen &
- (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
- if (paddingLen)
- {
- err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
- if (err)
- {
- return err;
+ /* 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;
+}
- /* -- AAD length as a 64-bit little endian integer */
-
- word32ToLittle64(inAADLen, little64);
+int wc_ChaCha20Poly1305_Final(ChaChaPoly_Aead* aead,
+ byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
+{
+ int ret = 0;
- err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
- if (err)
- {
- return err;
+ 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;
}
- /* -- Ciphertext length as a 64-bit little endian integer */
+ /* Pad the AAD - Make sure it is done */
+ if (aead->state == CHACHA20_POLY1305_STATE_AAD) {
+ ret = wc_Poly1305_Pad(&aead->poly, aead->aadLen);
+ }
- word32ToLittle64(inCiphertextLen, little64);
+ /* Pad the ciphertext to 16 bytes */
+ if (ret == 0) {
+ ret = wc_Poly1305_Pad(&aead->poly, aead->dataLen);
+ }
- err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
- if (err)
- {
- return err;
+ /* 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 */
+ if (ret == 0) {
+ ret = wc_Poly1305Final(&aead->poly, outAuthTag);
+ }
- err = wc_Poly1305Final(&poly1305Ctx, outAuthTag);
-
- return err;
-}
-
-
-static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8])
-{
- XMEMSET(outLittle64, 0, 8);
+ /* reset and cleanup sensitive context */
+ ForceZero(aead, sizeof(ChaChaPoly_Aead));
- outLittle64[0] = (inLittle32 & 0x000000FF);
- outLittle64[1] = (inLittle32 & 0x0000FF00) >> 8;
- outLittle64[2] = (inLittle32 & 0x00FF0000) >> 16;
- outLittle64[3] = (inLittle32 & 0xFF000000) >> 24;
+ return ret;
}
-
#endif /* HAVE_CHACHA && HAVE_POLY1305 */