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

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

Committer:
wolfSSL
Date:
Thu Apr 28 00:57:21 2016 +0000
Revision:
4:1b0d80432c79
wolfSSL 3.9.0

Who changed what in which revision?

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