wolfSSL 3.11.1 for TLS1.3 beta

Fork of wolfSSL by wolf SSL

Committer:
wolfSSL
Date:
Tue May 02 08:44:47 2017 +0000
Revision:
7:481bce714567
wolfSSL3.10.2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wolfSSL 7:481bce714567 1 /* chacha.c
wolfSSL 7:481bce714567 2 *
wolfSSL 7:481bce714567 3 * Copyright (C) 2006-2016 wolfSSL Inc.
wolfSSL 7:481bce714567 4 *
wolfSSL 7:481bce714567 5 * This file is part of wolfSSL.
wolfSSL 7:481bce714567 6 *
wolfSSL 7:481bce714567 7 * wolfSSL is free software; you can redistribute it and/or modify
wolfSSL 7:481bce714567 8 * it under the terms of the GNU General Public License as published by
wolfSSL 7:481bce714567 9 * the Free Software Foundation; either version 2 of the License, or
wolfSSL 7:481bce714567 10 * (at your option) any later version.
wolfSSL 7:481bce714567 11 *
wolfSSL 7:481bce714567 12 * wolfSSL is distributed in the hope that it will be useful,
wolfSSL 7:481bce714567 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
wolfSSL 7:481bce714567 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wolfSSL 7:481bce714567 15 * GNU General Public License for more details.
wolfSSL 7:481bce714567 16 *
wolfSSL 7:481bce714567 17 * You should have received a copy of the GNU General Public License
wolfSSL 7:481bce714567 18 * along with this program; if not, write to the Free Software
wolfSSL 7:481bce714567 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
wolfSSL 7:481bce714567 20 */
wolfSSL 7:481bce714567 21
wolfSSL 7:481bce714567 22
wolfSSL 7:481bce714567 23
wolfSSL 7:481bce714567 24 #ifdef HAVE_CONFIG_H
wolfSSL 7:481bce714567 25 #include <config.h>
wolfSSL 7:481bce714567 26 #endif
wolfSSL 7:481bce714567 27
wolfSSL 7:481bce714567 28 #include <wolfssl/wolfcrypt/settings.h>
wolfSSL 7:481bce714567 29
wolfSSL 7:481bce714567 30 #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
wolfSSL 7:481bce714567 31
wolfSSL 7:481bce714567 32 #include <wolfssl/wolfcrypt/chacha20_poly1305.h>
wolfSSL 7:481bce714567 33 #include <wolfssl/wolfcrypt/error-crypt.h>
wolfSSL 7:481bce714567 34 #include <wolfssl/wolfcrypt/logging.h>
wolfSSL 7:481bce714567 35 #include <wolfssl/wolfcrypt/chacha.h>
wolfSSL 7:481bce714567 36 #include <wolfssl/wolfcrypt/poly1305.h>
wolfSSL 7:481bce714567 37
wolfSSL 7:481bce714567 38 #ifdef NO_INLINE
wolfSSL 7:481bce714567 39 #include <wolfssl/wolfcrypt/misc.h>
wolfSSL 7:481bce714567 40 #else
wolfSSL 7:481bce714567 41 #define WOLFSSL_MISC_INCLUDED
wolfSSL 7:481bce714567 42 #include <wolfcrypt/src/misc.c>
wolfSSL 7:481bce714567 43 #endif
wolfSSL 7:481bce714567 44
wolfSSL 7:481bce714567 45 #ifdef CHACHA_AEAD_TEST
wolfSSL 7:481bce714567 46 #include <stdio.h>
wolfSSL 7:481bce714567 47 #endif
wolfSSL 7:481bce714567 48
wolfSSL 7:481bce714567 49 #define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0
wolfSSL 7:481bce714567 50 #define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16
wolfSSL 7:481bce714567 51
wolfSSL 7:481bce714567 52 static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]);
wolfSSL 7:481bce714567 53 static int calculateAuthTag(
wolfSSL 7:481bce714567 54 const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
wolfSSL 7:481bce714567 55 const byte* inAAD, const word32 inAADLen,
wolfSSL 7:481bce714567 56 const byte *inCiphertext, const word32 inCiphertextLen,
wolfSSL 7:481bce714567 57 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]);
wolfSSL 7:481bce714567 58
wolfSSL 7:481bce714567 59 int wc_ChaCha20Poly1305_Encrypt(
wolfSSL 7:481bce714567 60 const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
wolfSSL 7:481bce714567 61 const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
wolfSSL 7:481bce714567 62 const byte* inAAD, const word32 inAADLen,
wolfSSL 7:481bce714567 63 const byte* inPlaintext, const word32 inPlaintextLen,
wolfSSL 7:481bce714567 64 byte* outCiphertext,
wolfSSL 7:481bce714567 65 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
wolfSSL 7:481bce714567 66 {
wolfSSL 7:481bce714567 67 int err;
wolfSSL 7:481bce714567 68 byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
wolfSSL 7:481bce714567 69 ChaCha chaChaCtx;
wolfSSL 7:481bce714567 70
wolfSSL 7:481bce714567 71 /* Validate function arguments */
wolfSSL 7:481bce714567 72
wolfSSL 7:481bce714567 73 if (!inKey || !inIV ||
wolfSSL 7:481bce714567 74 !inPlaintext || !inPlaintextLen ||
wolfSSL 7:481bce714567 75 !outCiphertext ||
wolfSSL 7:481bce714567 76 !outAuthTag)
wolfSSL 7:481bce714567 77 {
wolfSSL 7:481bce714567 78 return BAD_FUNC_ARG;
wolfSSL 7:481bce714567 79 }
wolfSSL 7:481bce714567 80
wolfSSL 7:481bce714567 81 XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
wolfSSL 7:481bce714567 82
wolfSSL 7:481bce714567 83 /* Create the Poly1305 key */
wolfSSL 7:481bce714567 84 err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
wolfSSL 7:481bce714567 85 if (err != 0) return err;
wolfSSL 7:481bce714567 86
wolfSSL 7:481bce714567 87 err = wc_Chacha_SetIV(&chaChaCtx, inIV,
wolfSSL 7:481bce714567 88 CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
wolfSSL 7:481bce714567 89 if (err != 0) return err;
wolfSSL 7:481bce714567 90
wolfSSL 7:481bce714567 91 err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key,
wolfSSL 7:481bce714567 92 CHACHA20_POLY1305_AEAD_KEYSIZE);
wolfSSL 7:481bce714567 93 if (err != 0) return err;
wolfSSL 7:481bce714567 94
wolfSSL 7:481bce714567 95 /* Encrypt the plaintext using ChaCha20 */
wolfSSL 7:481bce714567 96 err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext,
wolfSSL 7:481bce714567 97 inPlaintextLen);
wolfSSL 7:481bce714567 98 /* Calculate the Poly1305 auth tag */
wolfSSL 7:481bce714567 99 if (err == 0)
wolfSSL 7:481bce714567 100 err = calculateAuthTag(poly1305Key,
wolfSSL 7:481bce714567 101 inAAD, inAADLen,
wolfSSL 7:481bce714567 102 outCiphertext, inPlaintextLen,
wolfSSL 7:481bce714567 103 outAuthTag);
wolfSSL 7:481bce714567 104 ForceZero(poly1305Key, sizeof(poly1305Key));
wolfSSL 7:481bce714567 105
wolfSSL 7:481bce714567 106 return err;
wolfSSL 7:481bce714567 107 }
wolfSSL 7:481bce714567 108
wolfSSL 7:481bce714567 109
wolfSSL 7:481bce714567 110 int wc_ChaCha20Poly1305_Decrypt(
wolfSSL 7:481bce714567 111 const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
wolfSSL 7:481bce714567 112 const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE],
wolfSSL 7:481bce714567 113 const byte* inAAD, const word32 inAADLen,
wolfSSL 7:481bce714567 114 const byte* inCiphertext, const word32 inCiphertextLen,
wolfSSL 7:481bce714567 115 const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE],
wolfSSL 7:481bce714567 116 byte* outPlaintext)
wolfSSL 7:481bce714567 117 {
wolfSSL 7:481bce714567 118 int err;
wolfSSL 7:481bce714567 119 byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE];
wolfSSL 7:481bce714567 120 ChaCha chaChaCtx;
wolfSSL 7:481bce714567 121 byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE];
wolfSSL 7:481bce714567 122
wolfSSL 7:481bce714567 123 /* Validate function arguments */
wolfSSL 7:481bce714567 124
wolfSSL 7:481bce714567 125 if (!inKey || !inIV ||
wolfSSL 7:481bce714567 126 !inCiphertext || !inCiphertextLen ||
wolfSSL 7:481bce714567 127 !inAuthTag ||
wolfSSL 7:481bce714567 128 !outPlaintext)
wolfSSL 7:481bce714567 129 {
wolfSSL 7:481bce714567 130 return BAD_FUNC_ARG;
wolfSSL 7:481bce714567 131 }
wolfSSL 7:481bce714567 132
wolfSSL 7:481bce714567 133 XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag));
wolfSSL 7:481bce714567 134 XMEMSET(poly1305Key, 0, sizeof(poly1305Key));
wolfSSL 7:481bce714567 135
wolfSSL 7:481bce714567 136 /* Create the Poly1305 key */
wolfSSL 7:481bce714567 137 err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE);
wolfSSL 7:481bce714567 138 if (err != 0) return err;
wolfSSL 7:481bce714567 139
wolfSSL 7:481bce714567 140 err = wc_Chacha_SetIV(&chaChaCtx, inIV,
wolfSSL 7:481bce714567 141 CHACHA20_POLY1305_AEAD_INITIAL_COUNTER);
wolfSSL 7:481bce714567 142 if (err != 0) return err;
wolfSSL 7:481bce714567 143
wolfSSL 7:481bce714567 144 err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key,
wolfSSL 7:481bce714567 145 CHACHA20_POLY1305_AEAD_KEYSIZE);
wolfSSL 7:481bce714567 146 if (err != 0) return err;
wolfSSL 7:481bce714567 147
wolfSSL 7:481bce714567 148 /* Calculate the Poly1305 auth tag */
wolfSSL 7:481bce714567 149 err = calculateAuthTag(poly1305Key,
wolfSSL 7:481bce714567 150 inAAD, inAADLen,
wolfSSL 7:481bce714567 151 inCiphertext, inCiphertextLen,
wolfSSL 7:481bce714567 152 calculatedAuthTag);
wolfSSL 7:481bce714567 153
wolfSSL 7:481bce714567 154 /* Compare the calculated auth tag with the received one */
wolfSSL 7:481bce714567 155 if (err == 0 && ConstantCompare(inAuthTag, calculatedAuthTag,
wolfSSL 7:481bce714567 156 CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0)
wolfSSL 7:481bce714567 157 {
wolfSSL 7:481bce714567 158 err = MAC_CMP_FAILED_E;
wolfSSL 7:481bce714567 159 }
wolfSSL 7:481bce714567 160
wolfSSL 7:481bce714567 161 /* Decrypt the received ciphertext */
wolfSSL 7:481bce714567 162 if (err == 0)
wolfSSL 7:481bce714567 163 err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext,
wolfSSL 7:481bce714567 164 inCiphertextLen);
wolfSSL 7:481bce714567 165 ForceZero(poly1305Key, sizeof(poly1305Key));
wolfSSL 7:481bce714567 166
wolfSSL 7:481bce714567 167 return err;
wolfSSL 7:481bce714567 168 }
wolfSSL 7:481bce714567 169
wolfSSL 7:481bce714567 170
wolfSSL 7:481bce714567 171 static int calculateAuthTag(
wolfSSL 7:481bce714567 172 const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE],
wolfSSL 7:481bce714567 173 const byte *inAAD, const word32 inAADLen,
wolfSSL 7:481bce714567 174 const byte *inCiphertext, const word32 inCiphertextLen,
wolfSSL 7:481bce714567 175 byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE])
wolfSSL 7:481bce714567 176 {
wolfSSL 7:481bce714567 177 int err;
wolfSSL 7:481bce714567 178 Poly1305 poly1305Ctx;
wolfSSL 7:481bce714567 179 byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1];
wolfSSL 7:481bce714567 180 word32 paddingLen;
wolfSSL 7:481bce714567 181 byte little64[8];
wolfSSL 7:481bce714567 182
wolfSSL 7:481bce714567 183 XMEMSET(padding, 0, sizeof(padding));
wolfSSL 7:481bce714567 184
wolfSSL 7:481bce714567 185 /* Initialize Poly1305 */
wolfSSL 7:481bce714567 186
wolfSSL 7:481bce714567 187 err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey,
wolfSSL 7:481bce714567 188 CHACHA20_POLY1305_AEAD_KEYSIZE);
wolfSSL 7:481bce714567 189 if (err)
wolfSSL 7:481bce714567 190 {
wolfSSL 7:481bce714567 191 return err;
wolfSSL 7:481bce714567 192 }
wolfSSL 7:481bce714567 193
wolfSSL 7:481bce714567 194 /* Create the authTag by MAC'ing the following items: */
wolfSSL 7:481bce714567 195
wolfSSL 7:481bce714567 196 /* -- AAD */
wolfSSL 7:481bce714567 197
wolfSSL 7:481bce714567 198 if (inAAD && inAADLen)
wolfSSL 7:481bce714567 199 {
wolfSSL 7:481bce714567 200 err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen);
wolfSSL 7:481bce714567 201
wolfSSL 7:481bce714567 202 /* -- padding1: pad the AAD to 16 bytes */
wolfSSL 7:481bce714567 203
wolfSSL 7:481bce714567 204 paddingLen = -(int)inAADLen & (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
wolfSSL 7:481bce714567 205 if (paddingLen)
wolfSSL 7:481bce714567 206 {
wolfSSL 7:481bce714567 207 err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
wolfSSL 7:481bce714567 208 }
wolfSSL 7:481bce714567 209
wolfSSL 7:481bce714567 210 if (err)
wolfSSL 7:481bce714567 211 {
wolfSSL 7:481bce714567 212 return err;
wolfSSL 7:481bce714567 213 }
wolfSSL 7:481bce714567 214 }
wolfSSL 7:481bce714567 215
wolfSSL 7:481bce714567 216 /* -- Ciphertext */
wolfSSL 7:481bce714567 217
wolfSSL 7:481bce714567 218 err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen);
wolfSSL 7:481bce714567 219 if (err)
wolfSSL 7:481bce714567 220 {
wolfSSL 7:481bce714567 221 return err;
wolfSSL 7:481bce714567 222 }
wolfSSL 7:481bce714567 223
wolfSSL 7:481bce714567 224 /* -- padding2: pad the ciphertext to 16 bytes */
wolfSSL 7:481bce714567 225
wolfSSL 7:481bce714567 226 paddingLen = -(int)inCiphertextLen &
wolfSSL 7:481bce714567 227 (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1);
wolfSSL 7:481bce714567 228 if (paddingLen)
wolfSSL 7:481bce714567 229 {
wolfSSL 7:481bce714567 230 err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen);
wolfSSL 7:481bce714567 231 if (err)
wolfSSL 7:481bce714567 232 {
wolfSSL 7:481bce714567 233 return err;
wolfSSL 7:481bce714567 234 }
wolfSSL 7:481bce714567 235 }
wolfSSL 7:481bce714567 236
wolfSSL 7:481bce714567 237 /* -- AAD length as a 64-bit little endian integer */
wolfSSL 7:481bce714567 238
wolfSSL 7:481bce714567 239 word32ToLittle64(inAADLen, little64);
wolfSSL 7:481bce714567 240
wolfSSL 7:481bce714567 241 err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
wolfSSL 7:481bce714567 242 if (err)
wolfSSL 7:481bce714567 243 {
wolfSSL 7:481bce714567 244 return err;
wolfSSL 7:481bce714567 245 }
wolfSSL 7:481bce714567 246
wolfSSL 7:481bce714567 247 /* -- Ciphertext length as a 64-bit little endian integer */
wolfSSL 7:481bce714567 248
wolfSSL 7:481bce714567 249 word32ToLittle64(inCiphertextLen, little64);
wolfSSL 7:481bce714567 250
wolfSSL 7:481bce714567 251 err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64));
wolfSSL 7:481bce714567 252 if (err)
wolfSSL 7:481bce714567 253 {
wolfSSL 7:481bce714567 254 return err;
wolfSSL 7:481bce714567 255 }
wolfSSL 7:481bce714567 256
wolfSSL 7:481bce714567 257 /* Finalize the auth tag */
wolfSSL 7:481bce714567 258
wolfSSL 7:481bce714567 259 err = wc_Poly1305Final(&poly1305Ctx, outAuthTag);
wolfSSL 7:481bce714567 260
wolfSSL 7:481bce714567 261 return err;
wolfSSL 7:481bce714567 262 }
wolfSSL 7:481bce714567 263
wolfSSL 7:481bce714567 264
wolfSSL 7:481bce714567 265 static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8])
wolfSSL 7:481bce714567 266 {
wolfSSL 7:481bce714567 267 XMEMSET(outLittle64, 0, 8);
wolfSSL 7:481bce714567 268
wolfSSL 7:481bce714567 269 outLittle64[0] = (byte)(inLittle32 & 0x000000FF);
wolfSSL 7:481bce714567 270 outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8);
wolfSSL 7:481bce714567 271 outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16);
wolfSSL 7:481bce714567 272 outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24);
wolfSSL 7:481bce714567 273 }
wolfSSL 7:481bce714567 274
wolfSSL 7:481bce714567 275
wolfSSL 7:481bce714567 276 #endif /* HAVE_CHACHA && HAVE_POLY1305 */
wolfSSL 7:481bce714567 277