Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of wolfSSL by
chacha.c
00001 /* chacha.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL 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 * wolfSSL 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-1335, USA 00020 * 00021 * based from 00022 * chacha-ref.c version 20080118 00023 * D. J. Bernstein 00024 * Public domain. 00025 */ 00026 00027 00028 00029 #ifdef HAVE_CONFIG_H 00030 #include <config.h> 00031 #endif 00032 00033 #include <wolfssl/wolfcrypt/settings.h> 00034 00035 #ifdef HAVE_CHACHA 00036 00037 #include <wolfssl/wolfcrypt/chacha.h> 00038 #include <wolfssl/wolfcrypt/error-crypt.h> 00039 #include <wolfssl/wolfcrypt/logging.h> 00040 #ifdef NO_INLINE 00041 #include <wolfssl/wolfcrypt/misc.h> 00042 #else 00043 #define WOLFSSL_MISC_INCLUDED 00044 #include <wolfcrypt/src/misc.c> 00045 #endif 00046 00047 #ifdef CHACHA_AEAD_TEST 00048 #include <stdio.h> 00049 #endif 00050 00051 #ifdef BIG_ENDIAN_ORDER 00052 #define LITTLE32(x) ByteReverseWord32(x) 00053 #else 00054 #define LITTLE32(x) (x) 00055 #endif 00056 00057 /* Number of rounds */ 00058 #define ROUNDS 20 00059 00060 #define U32C(v) (v##U) 00061 #define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF)) 00062 #define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0]) 00063 00064 #define ROTATE(v,c) rotlFixed(v, c) 00065 #define XOR(v,w) ((v) ^ (w)) 00066 #define PLUS(v,w) (U32V((v) + (w))) 00067 #define PLUSONE(v) (PLUS((v),1)) 00068 00069 #define QUARTERROUND(a,b,c,d) \ 00070 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ 00071 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ 00072 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ 00073 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); 00074 00075 00076 /** 00077 * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version 00078 * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB. 00079 */ 00080 int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) 00081 { 00082 word32 temp[CHACHA_IV_WORDS];/* used for alignment of memory */ 00083 00084 #ifdef CHACHA_AEAD_TEST 00085 word32 i; 00086 printf("NONCE : "); 00087 for (i = 0; i < CHACHA_IV_BYTES; i++) { 00088 printf("%02x", inIv[i]); 00089 } 00090 printf("\n\n"); 00091 #endif 00092 00093 if (ctx == NULL) 00094 return BAD_FUNC_ARG; 00095 00096 XMEMCPY(temp, inIv, CHACHA_IV_BYTES); 00097 00098 ctx->X[CHACHA_IV_BYTES+0] = counter; /* block counter */ 00099 ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */ 00100 ctx->X[CHACHA_IV_BYTES+2] = LITTLE32(temp[1]); /* counter from nonce */ 00101 ctx->X[CHACHA_IV_BYTES+3] = LITTLE32(temp[2]); /* counter from nonce */ 00102 00103 return 0; 00104 } 00105 00106 /* "expand 32-byte k" as unsigned 32 byte */ 00107 static const word32 sigma[4] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574}; 00108 /* "expand 16-byte k" as unsigned 16 byte */ 00109 static const word32 tau[4] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574}; 00110 00111 /** 00112 * Key setup. 8 word iv (nonce) 00113 */ 00114 int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) 00115 { 00116 const word32* constants; 00117 const byte* k; 00118 00119 #ifdef XSTREAM_ALIGN 00120 word32 alignKey[8]; 00121 #endif 00122 00123 if (ctx == NULL) 00124 return BAD_FUNC_ARG; 00125 00126 if (keySz != 16 && keySz != 32) 00127 return BAD_FUNC_ARG; 00128 00129 #ifdef XSTREAM_ALIGN 00130 if ((wolfssl_word)key % 4) { 00131 WOLFSSL_MSG("wc_ChachaSetKey unaligned key"); 00132 XMEMCPY(alignKey, key, keySz); 00133 k = (byte*)alignKey; 00134 } 00135 else { 00136 k = key; 00137 } 00138 #else 00139 k = key; 00140 #endif /* XSTREAM_ALIGN */ 00141 00142 #ifdef CHACHA_AEAD_TEST 00143 word32 i; 00144 printf("ChaCha key used :\n"); 00145 for (i = 0; i < keySz; i++) { 00146 printf("%02x", key[i]); 00147 if ((i + 1) % 8 == 0) 00148 printf("\n"); 00149 } 00150 printf("\n\n"); 00151 #endif 00152 00153 ctx->X[4] = U8TO32_LITTLE(k + 0); 00154 ctx->X[5] = U8TO32_LITTLE(k + 4); 00155 ctx->X[6] = U8TO32_LITTLE(k + 8); 00156 ctx->X[7] = U8TO32_LITTLE(k + 12); 00157 if (keySz == 32) { 00158 k += 16; 00159 constants = sigma; 00160 } 00161 else { 00162 constants = tau; 00163 } 00164 ctx->X[ 8] = U8TO32_LITTLE(k + 0); 00165 ctx->X[ 9] = U8TO32_LITTLE(k + 4); 00166 ctx->X[10] = U8TO32_LITTLE(k + 8); 00167 ctx->X[11] = U8TO32_LITTLE(k + 12); 00168 ctx->X[ 0] = constants[0]; 00169 ctx->X[ 1] = constants[1]; 00170 ctx->X[ 2] = constants[2]; 00171 ctx->X[ 3] = constants[3]; 00172 00173 return 0; 00174 } 00175 00176 /** 00177 * Converts word into bytes with rotations having been done. 00178 */ 00179 static INLINE void wc_Chacha_wordtobyte(word32 output[CHACHA_CHUNK_WORDS], 00180 const word32 input[CHACHA_CHUNK_WORDS]) 00181 { 00182 word32 x[CHACHA_CHUNK_WORDS]; 00183 word32 i; 00184 00185 for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { 00186 x[i] = input[i]; 00187 } 00188 00189 for (i = (ROUNDS); i > 0; i -= 2) { 00190 QUARTERROUND(0, 4, 8, 12) 00191 QUARTERROUND(1, 5, 9, 13) 00192 QUARTERROUND(2, 6, 10, 14) 00193 QUARTERROUND(3, 7, 11, 15) 00194 QUARTERROUND(0, 5, 10, 15) 00195 QUARTERROUND(1, 6, 11, 12) 00196 QUARTERROUND(2, 7, 8, 13) 00197 QUARTERROUND(3, 4, 9, 14) 00198 } 00199 00200 for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { 00201 x[i] = PLUS(x[i], input[i]); 00202 } 00203 00204 for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { 00205 output[i] = LITTLE32(x[i]); 00206 } 00207 } 00208 00209 /** 00210 * Encrypt a stream of bytes 00211 */ 00212 static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, 00213 word32 bytes) 00214 { 00215 byte* output; 00216 word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ 00217 word32 i; 00218 00219 output = (byte*)temp; 00220 00221 if (!bytes) return; 00222 for (;;) { 00223 wc_Chacha_wordtobyte(temp, ctx->X); 00224 ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); 00225 if (bytes <= CHACHA_CHUNK_BYTES) { 00226 for (i = 0; i < bytes; ++i) { 00227 c[i] = m[i] ^ output[i]; 00228 } 00229 return; 00230 } 00231 for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) { 00232 c[i] = m[i] ^ output[i]; 00233 } 00234 bytes -= CHACHA_CHUNK_BYTES; 00235 c += CHACHA_CHUNK_BYTES; 00236 m += CHACHA_CHUNK_BYTES; 00237 } 00238 } 00239 00240 /** 00241 * API to encrypt/decrypt a message of any size. 00242 */ 00243 int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, word32 msglen) 00244 { 00245 if (ctx == NULL) 00246 return BAD_FUNC_ARG; 00247 00248 wc_Chacha_encrypt_bytes(ctx, input, output, msglen); 00249 00250 return 0; 00251 } 00252 00253 #endif /* HAVE_CHACHA*/ 00254 00255
Generated on Tue Jul 12 2022 23:30:54 by
1.7.2
