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

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

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 * based from
wolfSSL 7:481bce714567 22 * chacha-ref.c version 20080118
wolfSSL 7:481bce714567 23 * D. J. Bernstein
wolfSSL 7:481bce714567 24 * Public domain.
wolfSSL 7:481bce714567 25 */
wolfSSL 7:481bce714567 26
wolfSSL 7:481bce714567 27
wolfSSL 7:481bce714567 28
wolfSSL 7:481bce714567 29 #ifdef HAVE_CONFIG_H
wolfSSL 7:481bce714567 30 #include <config.h>
wolfSSL 7:481bce714567 31 #endif
wolfSSL 7:481bce714567 32
wolfSSL 7:481bce714567 33 #include <wolfssl/wolfcrypt/settings.h>
wolfSSL 7:481bce714567 34
wolfSSL 7:481bce714567 35 #ifdef HAVE_CHACHA
wolfSSL 7:481bce714567 36
wolfSSL 7:481bce714567 37 #include <wolfssl/wolfcrypt/chacha.h>
wolfSSL 7:481bce714567 38 #include <wolfssl/wolfcrypt/error-crypt.h>
wolfSSL 7:481bce714567 39 #include <wolfssl/wolfcrypt/logging.h>
wolfSSL 7:481bce714567 40 #ifdef NO_INLINE
wolfSSL 7:481bce714567 41 #include <wolfssl/wolfcrypt/misc.h>
wolfSSL 7:481bce714567 42 #else
wolfSSL 7:481bce714567 43 #define WOLFSSL_MISC_INCLUDED
wolfSSL 7:481bce714567 44 #include <wolfcrypt/src/misc.c>
wolfSSL 7:481bce714567 45 #endif
wolfSSL 7:481bce714567 46
wolfSSL 7:481bce714567 47 #ifdef CHACHA_AEAD_TEST
wolfSSL 7:481bce714567 48 #include <stdio.h>
wolfSSL 7:481bce714567 49 #endif
wolfSSL 7:481bce714567 50
wolfSSL 7:481bce714567 51 #ifdef BIG_ENDIAN_ORDER
wolfSSL 7:481bce714567 52 #define LITTLE32(x) ByteReverseWord32(x)
wolfSSL 7:481bce714567 53 #else
wolfSSL 7:481bce714567 54 #define LITTLE32(x) (x)
wolfSSL 7:481bce714567 55 #endif
wolfSSL 7:481bce714567 56
wolfSSL 7:481bce714567 57 /* Number of rounds */
wolfSSL 7:481bce714567 58 #define ROUNDS 20
wolfSSL 7:481bce714567 59
wolfSSL 7:481bce714567 60 #define U32C(v) (v##U)
wolfSSL 7:481bce714567 61 #define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF))
wolfSSL 7:481bce714567 62 #define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0])
wolfSSL 7:481bce714567 63
wolfSSL 7:481bce714567 64 #define ROTATE(v,c) rotlFixed(v, c)
wolfSSL 7:481bce714567 65 #define XOR(v,w) ((v) ^ (w))
wolfSSL 7:481bce714567 66 #define PLUS(v,w) (U32V((v) + (w)))
wolfSSL 7:481bce714567 67 #define PLUSONE(v) (PLUS((v),1))
wolfSSL 7:481bce714567 68
wolfSSL 7:481bce714567 69 #define QUARTERROUND(a,b,c,d) \
wolfSSL 7:481bce714567 70 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
wolfSSL 7:481bce714567 71 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
wolfSSL 7:481bce714567 72 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
wolfSSL 7:481bce714567 73 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
wolfSSL 7:481bce714567 74
wolfSSL 7:481bce714567 75
wolfSSL 7:481bce714567 76 /**
wolfSSL 7:481bce714567 77 * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version
wolfSSL 7:481bce714567 78 * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB.
wolfSSL 7:481bce714567 79 */
wolfSSL 7:481bce714567 80 int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter)
wolfSSL 7:481bce714567 81 {
wolfSSL 7:481bce714567 82 word32 temp[CHACHA_IV_WORDS];/* used for alignment of memory */
wolfSSL 7:481bce714567 83
wolfSSL 7:481bce714567 84 #ifdef CHACHA_AEAD_TEST
wolfSSL 7:481bce714567 85 word32 i;
wolfSSL 7:481bce714567 86 printf("NONCE : ");
wolfSSL 7:481bce714567 87 for (i = 0; i < CHACHA_IV_BYTES; i++) {
wolfSSL 7:481bce714567 88 printf("%02x", inIv[i]);
wolfSSL 7:481bce714567 89 }
wolfSSL 7:481bce714567 90 printf("\n\n");
wolfSSL 7:481bce714567 91 #endif
wolfSSL 7:481bce714567 92
wolfSSL 7:481bce714567 93 if (ctx == NULL)
wolfSSL 7:481bce714567 94 return BAD_FUNC_ARG;
wolfSSL 7:481bce714567 95
wolfSSL 7:481bce714567 96 XMEMCPY(temp, inIv, CHACHA_IV_BYTES);
wolfSSL 7:481bce714567 97
wolfSSL 7:481bce714567 98 ctx->X[CHACHA_IV_BYTES+0] = counter; /* block counter */
wolfSSL 7:481bce714567 99 ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */
wolfSSL 7:481bce714567 100 ctx->X[CHACHA_IV_BYTES+2] = LITTLE32(temp[1]); /* counter from nonce */
wolfSSL 7:481bce714567 101 ctx->X[CHACHA_IV_BYTES+3] = LITTLE32(temp[2]); /* counter from nonce */
wolfSSL 7:481bce714567 102
wolfSSL 7:481bce714567 103 return 0;
wolfSSL 7:481bce714567 104 }
wolfSSL 7:481bce714567 105
wolfSSL 7:481bce714567 106 /* "expand 32-byte k" as unsigned 32 byte */
wolfSSL 7:481bce714567 107 static const word32 sigma[4] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574};
wolfSSL 7:481bce714567 108 /* "expand 16-byte k" as unsigned 16 byte */
wolfSSL 7:481bce714567 109 static const word32 tau[4] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574};
wolfSSL 7:481bce714567 110
wolfSSL 7:481bce714567 111 /**
wolfSSL 7:481bce714567 112 * Key setup. 8 word iv (nonce)
wolfSSL 7:481bce714567 113 */
wolfSSL 7:481bce714567 114 int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz)
wolfSSL 7:481bce714567 115 {
wolfSSL 7:481bce714567 116 const word32* constants;
wolfSSL 7:481bce714567 117 const byte* k;
wolfSSL 7:481bce714567 118
wolfSSL 7:481bce714567 119 #ifdef XSTREAM_ALIGN
wolfSSL 7:481bce714567 120 word32 alignKey[8];
wolfSSL 7:481bce714567 121 #endif
wolfSSL 7:481bce714567 122
wolfSSL 7:481bce714567 123 if (ctx == NULL)
wolfSSL 7:481bce714567 124 return BAD_FUNC_ARG;
wolfSSL 7:481bce714567 125
wolfSSL 7:481bce714567 126 if (keySz != 16 && keySz != 32)
wolfSSL 7:481bce714567 127 return BAD_FUNC_ARG;
wolfSSL 7:481bce714567 128
wolfSSL 7:481bce714567 129 #ifdef XSTREAM_ALIGN
wolfSSL 7:481bce714567 130 if ((wolfssl_word)key % 4) {
wolfSSL 7:481bce714567 131 WOLFSSL_MSG("wc_ChachaSetKey unaligned key");
wolfSSL 7:481bce714567 132 XMEMCPY(alignKey, key, keySz);
wolfSSL 7:481bce714567 133 k = (byte*)alignKey;
wolfSSL 7:481bce714567 134 }
wolfSSL 7:481bce714567 135 else {
wolfSSL 7:481bce714567 136 k = key;
wolfSSL 7:481bce714567 137 }
wolfSSL 7:481bce714567 138 #else
wolfSSL 7:481bce714567 139 k = key;
wolfSSL 7:481bce714567 140 #endif /* XSTREAM_ALIGN */
wolfSSL 7:481bce714567 141
wolfSSL 7:481bce714567 142 #ifdef CHACHA_AEAD_TEST
wolfSSL 7:481bce714567 143 word32 i;
wolfSSL 7:481bce714567 144 printf("ChaCha key used :\n");
wolfSSL 7:481bce714567 145 for (i = 0; i < keySz; i++) {
wolfSSL 7:481bce714567 146 printf("%02x", key[i]);
wolfSSL 7:481bce714567 147 if ((i + 1) % 8 == 0)
wolfSSL 7:481bce714567 148 printf("\n");
wolfSSL 7:481bce714567 149 }
wolfSSL 7:481bce714567 150 printf("\n\n");
wolfSSL 7:481bce714567 151 #endif
wolfSSL 7:481bce714567 152
wolfSSL 7:481bce714567 153 ctx->X[4] = U8TO32_LITTLE(k + 0);
wolfSSL 7:481bce714567 154 ctx->X[5] = U8TO32_LITTLE(k + 4);
wolfSSL 7:481bce714567 155 ctx->X[6] = U8TO32_LITTLE(k + 8);
wolfSSL 7:481bce714567 156 ctx->X[7] = U8TO32_LITTLE(k + 12);
wolfSSL 7:481bce714567 157 if (keySz == 32) {
wolfSSL 7:481bce714567 158 k += 16;
wolfSSL 7:481bce714567 159 constants = sigma;
wolfSSL 7:481bce714567 160 }
wolfSSL 7:481bce714567 161 else {
wolfSSL 7:481bce714567 162 constants = tau;
wolfSSL 7:481bce714567 163 }
wolfSSL 7:481bce714567 164 ctx->X[ 8] = U8TO32_LITTLE(k + 0);
wolfSSL 7:481bce714567 165 ctx->X[ 9] = U8TO32_LITTLE(k + 4);
wolfSSL 7:481bce714567 166 ctx->X[10] = U8TO32_LITTLE(k + 8);
wolfSSL 7:481bce714567 167 ctx->X[11] = U8TO32_LITTLE(k + 12);
wolfSSL 7:481bce714567 168 ctx->X[ 0] = constants[0];
wolfSSL 7:481bce714567 169 ctx->X[ 1] = constants[1];
wolfSSL 7:481bce714567 170 ctx->X[ 2] = constants[2];
wolfSSL 7:481bce714567 171 ctx->X[ 3] = constants[3];
wolfSSL 7:481bce714567 172
wolfSSL 7:481bce714567 173 return 0;
wolfSSL 7:481bce714567 174 }
wolfSSL 7:481bce714567 175
wolfSSL 7:481bce714567 176 /**
wolfSSL 7:481bce714567 177 * Converts word into bytes with rotations having been done.
wolfSSL 7:481bce714567 178 */
wolfSSL 7:481bce714567 179 static INLINE void wc_Chacha_wordtobyte(word32 output[CHACHA_CHUNK_WORDS],
wolfSSL 7:481bce714567 180 const word32 input[CHACHA_CHUNK_WORDS])
wolfSSL 7:481bce714567 181 {
wolfSSL 7:481bce714567 182 word32 x[CHACHA_CHUNK_WORDS];
wolfSSL 7:481bce714567 183 word32 i;
wolfSSL 7:481bce714567 184
wolfSSL 7:481bce714567 185 for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
wolfSSL 7:481bce714567 186 x[i] = input[i];
wolfSSL 7:481bce714567 187 }
wolfSSL 7:481bce714567 188
wolfSSL 7:481bce714567 189 for (i = (ROUNDS); i > 0; i -= 2) {
wolfSSL 7:481bce714567 190 QUARTERROUND(0, 4, 8, 12)
wolfSSL 7:481bce714567 191 QUARTERROUND(1, 5, 9, 13)
wolfSSL 7:481bce714567 192 QUARTERROUND(2, 6, 10, 14)
wolfSSL 7:481bce714567 193 QUARTERROUND(3, 7, 11, 15)
wolfSSL 7:481bce714567 194 QUARTERROUND(0, 5, 10, 15)
wolfSSL 7:481bce714567 195 QUARTERROUND(1, 6, 11, 12)
wolfSSL 7:481bce714567 196 QUARTERROUND(2, 7, 8, 13)
wolfSSL 7:481bce714567 197 QUARTERROUND(3, 4, 9, 14)
wolfSSL 7:481bce714567 198 }
wolfSSL 7:481bce714567 199
wolfSSL 7:481bce714567 200 for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
wolfSSL 7:481bce714567 201 x[i] = PLUS(x[i], input[i]);
wolfSSL 7:481bce714567 202 }
wolfSSL 7:481bce714567 203
wolfSSL 7:481bce714567 204 for (i = 0; i < CHACHA_CHUNK_WORDS; i++) {
wolfSSL 7:481bce714567 205 output[i] = LITTLE32(x[i]);
wolfSSL 7:481bce714567 206 }
wolfSSL 7:481bce714567 207 }
wolfSSL 7:481bce714567 208
wolfSSL 7:481bce714567 209 /**
wolfSSL 7:481bce714567 210 * Encrypt a stream of bytes
wolfSSL 7:481bce714567 211 */
wolfSSL 7:481bce714567 212 static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c,
wolfSSL 7:481bce714567 213 word32 bytes)
wolfSSL 7:481bce714567 214 {
wolfSSL 7:481bce714567 215 byte* output;
wolfSSL 7:481bce714567 216 word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */
wolfSSL 7:481bce714567 217 word32 i;
wolfSSL 7:481bce714567 218
wolfSSL 7:481bce714567 219 output = (byte*)temp;
wolfSSL 7:481bce714567 220
wolfSSL 7:481bce714567 221 if (!bytes) return;
wolfSSL 7:481bce714567 222 for (;;) {
wolfSSL 7:481bce714567 223 wc_Chacha_wordtobyte(temp, ctx->X);
wolfSSL 7:481bce714567 224 ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]);
wolfSSL 7:481bce714567 225 if (bytes <= CHACHA_CHUNK_BYTES) {
wolfSSL 7:481bce714567 226 for (i = 0; i < bytes; ++i) {
wolfSSL 7:481bce714567 227 c[i] = m[i] ^ output[i];
wolfSSL 7:481bce714567 228 }
wolfSSL 7:481bce714567 229 return;
wolfSSL 7:481bce714567 230 }
wolfSSL 7:481bce714567 231 for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) {
wolfSSL 7:481bce714567 232 c[i] = m[i] ^ output[i];
wolfSSL 7:481bce714567 233 }
wolfSSL 7:481bce714567 234 bytes -= CHACHA_CHUNK_BYTES;
wolfSSL 7:481bce714567 235 c += CHACHA_CHUNK_BYTES;
wolfSSL 7:481bce714567 236 m += CHACHA_CHUNK_BYTES;
wolfSSL 7:481bce714567 237 }
wolfSSL 7:481bce714567 238 }
wolfSSL 7:481bce714567 239
wolfSSL 7:481bce714567 240 /**
wolfSSL 7:481bce714567 241 * API to encrypt/decrypt a message of any size.
wolfSSL 7:481bce714567 242 */
wolfSSL 7:481bce714567 243 int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, word32 msglen)
wolfSSL 7:481bce714567 244 {
wolfSSL 7:481bce714567 245 if (ctx == NULL)
wolfSSL 7:481bce714567 246 return BAD_FUNC_ARG;
wolfSSL 7:481bce714567 247
wolfSSL 7:481bce714567 248 wc_Chacha_encrypt_bytes(ctx, input, output, msglen);
wolfSSL 7:481bce714567 249
wolfSSL 7:481bce714567 250 return 0;
wolfSSL 7:481bce714567 251 }
wolfSSL 7:481bce714567 252
wolfSSL 7:481bce714567 253 #endif /* HAVE_CHACHA*/
wolfSSL 7:481bce714567 254
wolfSSL 7:481bce714567 255