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

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

Committer:
wolfSSL
Date:
Fri Jun 26 00:39:20 2015 +0000
Revision:
0:d92f9d21154c
wolfSSL 3.6.0

Who changed what in which revision?

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