Xuyi Wang / wolfcrypt

Dependents:   OS

Committer:
sPymbed
Date:
Wed Nov 20 13:28:01 2019 +0000
Revision:
0:1387ff3eed4a
initial version

Who changed what in which revision?

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