wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more

Revision:
13:f67a6c6013ca
Parent:
11:cee25a834751
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wolfcrypt/src/chacha20_poly1305.c	Tue Aug 22 10:48:22 2017 +0000
@@ -0,0 +1,277 @@
+/* chacha.c
+ *
+ * Copyright (C) 2006-2016 wolfSSL Inc.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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-1335, USA
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+
+#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
+
+#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],
+                const byte* inAAD, const word32 inAADLen,
+                const byte* inPlaintext, const word32 inPlaintextLen,
+                byte* outCiphertext,
+                byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
+{
+    int err;
+    byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
+    ChaCha chaChaCtx;
+
+    /* Validate function arguments */
+
+    if (!inKey || !inIV ||
+        !inPlaintext || !inPlaintextLen ||
+        !outCiphertext ||
+        !outAuthTag)
+    {
+        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;
+}
+
+
+int wc_ChaCha20Poly1305_Decrypt(
+                const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
+                const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
+                const byte* inAAD, const word32 inAADLen,
+                const byte* inCiphertext, const word32 inCiphertextLen,
+                const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
+                byte* outPlaintext)
+{
+    int err;
+    byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
+    ChaCha chaChaCtx;
+    byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
+
+    /* Validate function arguments */
+
+    if (!inKey || !inIV ||
+        !inCiphertext || !inCiphertextLen ||
+        !inAuthTag ||
+        !outPlaintext)
+    {
+        return BAD_FUNC_ARG;
+    }
+
+    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;
+}
+
+
+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 err;
+    Poly1305 poly1305Ctx;
+    byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1];
+    word32 paddingLen;
+    byte little64[8];
+
+    XMEMSET(padding, 0, sizeof(padding));
+
+    /* Initialize Poly1305 */
+
+    err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey,
+                            CHACHA20_POLY1305_AEAD_KEYSIZE);
+    if (err)
+    {
+        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 */
+
+    err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen);
+    if (err)
+    {
+        return err;
+    }
+
+    /* -- 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 */
+
+    word32ToLittle64(inAADLen, little64);
+
+    err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
+    if (err)
+    {
+        return err;
+    }
+
+    /* -- Ciphertext length as a 64-bit little endian integer */
+
+    word32ToLittle64(inCiphertextLen, little64);
+
+    err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
+    if (err)
+    {
+        return err;
+    }
+
+    /* Finalize the auth tag */
+
+    err = wc_Poly1305Final(&poly1305Ctx, outAuthTag);
+
+    return err;
+}
+
+
+static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8])
+{
+    XMEMSET(outLittle64, 0, 8);
+
+    outLittle64[0] = (byte)(inLittle32 & 0x000000FF);
+    outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8);
+    outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16);
+    outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24);
+}
+
+
+#endif /* HAVE_CHACHA && HAVE_POLY1305 */
+