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

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

Committer:
wolfSSL
Date:
Tue Aug 22 10:48:22 2017 +0000
Revision:
13:f67a6c6013ca
Parent:
11:cee25a834751
wolfSSL3.12.0 with TLS1.3

Who changed what in which revision?

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