Dependents: HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL
chacha.c
00001 /* chacha.c 00002 * 00003 * Copyright (C) 2006-2014 wolfSSL Inc. 00004 * 00005 * This file is part of CyaSSL. 00006 * 00007 * CyaSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * CyaSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 00020 * 00021 * based from 00022 * chacha-ref.c version 20080118 00023 * D. J. Bernstein 00024 * Public domain. 00025 */ 00026 00027 00028 #ifdef HAVE_CONFIG_H 00029 #include <config.h> 00030 #endif 00031 00032 #include <cyassl/ctaocrypt/settings.h> 00033 00034 #ifdef HAVE_CHACHA 00035 00036 #include <cyassl/ctaocrypt/chacha.h> 00037 #include <cyassl/ctaocrypt/error-crypt.h> 00038 #include <cyassl/ctaocrypt/logging.h> 00039 #ifdef NO_INLINE 00040 #include <cyassl/ctaocrypt/misc.h> 00041 #else 00042 #include <ctaocrypt/src/misc.c> 00043 #endif 00044 00045 #ifdef CHACHA_AEAD_TEST 00046 #include <stdio.h> 00047 #endif 00048 00049 #ifdef BIG_ENDIAN_ORDER 00050 #define LITTLE32(x) ByteReverseWord32(x) 00051 #else 00052 #define LITTLE32(x) (x) 00053 #endif 00054 00055 /* Number of rounds */ 00056 #define ROUNDS 20 00057 00058 #define U32C(v) (v##U) 00059 #define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF)) 00060 #define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0]) 00061 00062 #define ROTATE(v,c) rotlFixed(v, c) 00063 #define XOR(v,w) ((v) ^ (w)) 00064 #define PLUS(v,w) (U32V((v) + (w))) 00065 #define PLUSONE(v) (PLUS((v),1)) 00066 00067 #define QUARTERROUND(a,b,c,d) \ 00068 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ 00069 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ 00070 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ 00071 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); 00072 00073 00074 /** 00075 * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version 00076 * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB. 00077 */ 00078 int Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) 00079 { 00080 word32 temp[3]; /* used for alignment of memory */ 00081 XMEMSET(temp, 0, 12); 00082 00083 if (ctx == NULL) 00084 return BAD_FUNC_ARG; 00085 00086 #ifdef CHACHA_AEAD_TEST 00087 word32 i; 00088 printf("NONCE : "); 00089 for (i = 0; i < 12; i++) { 00090 printf("%02x", inIv[i]); 00091 } 00092 printf("\n\n"); 00093 #endif 00094 00095 XMEMCPY(temp, inIv, 12); 00096 00097 ctx->X[12] = counter; /* block counter */ 00098 ctx->X[13] = temp[0]; /* fixed variable from nonce */ 00099 ctx->X[14] = temp[1]; /* counter from nonce */ 00100 ctx->X[15] = temp[2]; /* counter from nonce */ 00101 00102 return 0; 00103 } 00104 00105 /* "expand 32-byte k" as unsigned 32 byte */ 00106 static const word32 sigma[4] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574}; 00107 /* "expand 16-byte k" as unsigned 16 byte */ 00108 static const word32 tau[4] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574}; 00109 00110 /** 00111 * Key setup. 8 word iv (nonce) 00112 */ 00113 int Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) 00114 { 00115 const word32* constants; 00116 const byte* k; 00117 00118 if (ctx == NULL) 00119 return BAD_FUNC_ARG; 00120 00121 #ifdef XSTREAM_ALIGN 00122 word32 alignKey[keySz / 4]; 00123 if ((cyassl_word)key % 4) { 00124 CYASSL_MSG("ChachaSetKey unaligned key"); 00125 XMEMCPY(alignKey, key, sizeof(alignKey)); 00126 k = (byte*)alignKey; 00127 } 00128 else { 00129 k = key; 00130 } 00131 #else 00132 k = key; 00133 #endif /* XSTREAM_ALIGN */ 00134 00135 #ifdef CHACHA_AEAD_TEST 00136 word32 i; 00137 printf("ChaCha key used :\n"); 00138 for (i = 0; i < keySz; i++) { 00139 printf("%02x", key[i]); 00140 if ((i + 1) % 8 == 0) 00141 printf("\n"); 00142 } 00143 printf("\n\n"); 00144 #endif 00145 00146 ctx->X[4] = U8TO32_LITTLE(k + 0); 00147 ctx->X[5] = U8TO32_LITTLE(k + 4); 00148 ctx->X[6] = U8TO32_LITTLE(k + 8); 00149 ctx->X[7] = U8TO32_LITTLE(k + 12); 00150 if (keySz == 32) { 00151 k += 16; 00152 constants = sigma; 00153 } 00154 else { 00155 /* key size of 128 */ 00156 if (keySz != 16) 00157 return BAD_FUNC_ARG; 00158 00159 constants = tau; 00160 } 00161 ctx->X[ 8] = U8TO32_LITTLE(k + 0); 00162 ctx->X[ 9] = U8TO32_LITTLE(k + 4); 00163 ctx->X[10] = U8TO32_LITTLE(k + 8); 00164 ctx->X[11] = U8TO32_LITTLE(k + 12); 00165 ctx->X[ 0] = U8TO32_LITTLE(constants + 0); 00166 ctx->X[ 1] = U8TO32_LITTLE(constants + 1); 00167 ctx->X[ 2] = U8TO32_LITTLE(constants + 2); 00168 ctx->X[ 3] = U8TO32_LITTLE(constants + 3); 00169 00170 return 0; 00171 } 00172 00173 /** 00174 * Converts word into bytes with rotations having been done. 00175 */ 00176 static INLINE void Chacha_wordtobyte(word32 output[16], const word32 input[16]) 00177 { 00178 word32 x[16]; 00179 word32 i; 00180 00181 for (i = 0; i < 16; i++) { 00182 x[i] = input[i]; 00183 } 00184 00185 for (i = (ROUNDS); i > 0; i -= 2) { 00186 QUARTERROUND(0, 4, 8, 12) 00187 QUARTERROUND(1, 5, 9, 13) 00188 QUARTERROUND(2, 6, 10, 14) 00189 QUARTERROUND(3, 7, 11, 15) 00190 QUARTERROUND(0, 5, 10, 15) 00191 QUARTERROUND(1, 6, 11, 12) 00192 QUARTERROUND(2, 7, 8, 13) 00193 QUARTERROUND(3, 4, 9, 14) 00194 } 00195 00196 for (i = 0; i < 16; i++) { 00197 x[i] = PLUS(x[i], input[i]); 00198 } 00199 00200 for (i = 0; i < 16; i++) { 00201 output[i] = LITTLE32(x[i]); 00202 } 00203 } 00204 00205 /** 00206 * Encrypt a stream of bytes 00207 */ 00208 static void Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, 00209 word32 bytes) 00210 { 00211 byte* output; 00212 word32 temp[16]; /* used to make sure aligned */ 00213 word32 i; 00214 00215 output = (byte*)temp; 00216 00217 if (!bytes) return; 00218 for (;;) { 00219 Chacha_wordtobyte(temp, ctx->X); 00220 ctx->X[12] = PLUSONE(ctx->X[12]); 00221 if (bytes <= 64) { 00222 for (i = 0; i < bytes; ++i) { 00223 c[i] = m[i] ^ output[i]; 00224 } 00225 return; 00226 } 00227 for (i = 0; i < 64; ++i) { 00228 c[i] = m[i] ^ output[i]; 00229 } 00230 bytes -= 64; 00231 c += 64; 00232 m += 64; 00233 } 00234 } 00235 00236 /** 00237 * API to encrypt/decrypt a message of any size. 00238 */ 00239 int Chacha_Process(ChaCha* ctx, byte* output, const byte* input, word32 msglen) 00240 { 00241 if (ctx == NULL) 00242 return BAD_FUNC_ARG; 00243 00244 Chacha_encrypt_bytes(ctx, input, output, msglen); 00245 00246 return 0; 00247 } 00248 00249 #endif /* HAVE_CHACHA*/ 00250
Generated on Wed Jul 13 2022 02:33:55 by
