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.
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 #include <wolfcrypt/src/misc.c> 00044 #endif 00045 00046 #ifdef CHACHA_AEAD_TEST 00047 #include <stdio.h> 00048 #endif 00049 00050 #ifdef BIG_ENDIAN_ORDER 00051 #define LITTLE32(x) ByteReverseWord32(x) 00052 #else 00053 #define LITTLE32(x) (x) 00054 #endif 00055 00056 /* Number of rounds */ 00057 #define ROUNDS 20 00058 00059 #define U32C(v) (v##U) 00060 #define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF)) 00061 #define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0]) 00062 00063 #define ROTATE(v,c) rotlFixed(v, c) 00064 #define XOR(v,w) ((v) ^ (w)) 00065 #define PLUS(v,w) (U32V((v) + (w))) 00066 #define PLUSONE(v) (PLUS((v),1)) 00067 00068 #define QUARTERROUND(a,b,c,d) \ 00069 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ 00070 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ 00071 x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ 00072 x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); 00073 00074 00075 /** 00076 * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version 00077 * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB. 00078 */ 00079 int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) 00080 { 00081 word32 temp[3]; /* used for alignment of memory */ 00082 00083 #ifdef CHACHA_AEAD_TEST 00084 word32 i; 00085 printf("NONCE : "); 00086 for (i = 0; i < 12; i++) { 00087 printf("%02x", inIv[i]); 00088 } 00089 printf("\n\n"); 00090 #endif 00091 00092 if (ctx == NULL) 00093 return BAD_FUNC_ARG; 00094 00095 XMEMCPY(temp, inIv, 12); 00096 00097 ctx->X[12] = counter; /* block counter */ 00098 ctx->X[13] = LITTLE32(temp[0]); /* fixed variable from nonce */ 00099 ctx->X[14] = LITTLE32(temp[1]); /* counter from nonce */ 00100 ctx->X[15] = LITTLE32(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 wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) 00114 { 00115 const word32* constants; 00116 const byte* k; 00117 00118 #ifdef XSTREAM_ALIGN 00119 word32 alignKey[8]; 00120 #endif 00121 00122 if (ctx == NULL) 00123 return BAD_FUNC_ARG; 00124 00125 if (keySz != 16 && keySz != 32) 00126 return BAD_FUNC_ARG; 00127 00128 #ifdef XSTREAM_ALIGN 00129 if ((wolfssl_word)key % 4) { 00130 WOLFSSL_MSG("wc_ChachaSetKey unaligned key"); 00131 XMEMCPY(alignKey, key, keySz); 00132 k = (byte*)alignKey; 00133 } 00134 else { 00135 k = key; 00136 } 00137 #else 00138 k = key; 00139 #endif /* XSTREAM_ALIGN */ 00140 00141 #ifdef CHACHA_AEAD_TEST 00142 word32 i; 00143 printf("ChaCha key used :\n"); 00144 for (i = 0; i < keySz; i++) { 00145 printf("%02x", key[i]); 00146 if ((i + 1) % 8 == 0) 00147 printf("\n"); 00148 } 00149 printf("\n\n"); 00150 #endif 00151 00152 ctx->X[4] = U8TO32_LITTLE(k + 0); 00153 ctx->X[5] = U8TO32_LITTLE(k + 4); 00154 ctx->X[6] = U8TO32_LITTLE(k + 8); 00155 ctx->X[7] = U8TO32_LITTLE(k + 12); 00156 if (keySz == 32) { 00157 k += 16; 00158 constants = sigma; 00159 } 00160 else { 00161 constants = tau; 00162 } 00163 ctx->X[ 8] = U8TO32_LITTLE(k + 0); 00164 ctx->X[ 9] = U8TO32_LITTLE(k + 4); 00165 ctx->X[10] = U8TO32_LITTLE(k + 8); 00166 ctx->X[11] = U8TO32_LITTLE(k + 12); 00167 ctx->X[ 0] = constants[0]; 00168 ctx->X[ 1] = constants[1]; 00169 ctx->X[ 2] = constants[2]; 00170 ctx->X[ 3] = constants[3]; 00171 00172 return 0; 00173 } 00174 00175 /** 00176 * Converts word into bytes with rotations having been done. 00177 */ 00178 static INLINE void wc_Chacha_wordtobyte(word32 output[16], const word32 input[16]) 00179 { 00180 word32 x[16]; 00181 word32 i; 00182 00183 for (i = 0; i < 16; i++) { 00184 x[i] = input[i]; 00185 } 00186 00187 for (i = (ROUNDS); i > 0; i -= 2) { 00188 QUARTERROUND(0, 4, 8, 12) 00189 QUARTERROUND(1, 5, 9, 13) 00190 QUARTERROUND(2, 6, 10, 14) 00191 QUARTERROUND(3, 7, 11, 15) 00192 QUARTERROUND(0, 5, 10, 15) 00193 QUARTERROUND(1, 6, 11, 12) 00194 QUARTERROUND(2, 7, 8, 13) 00195 QUARTERROUND(3, 4, 9, 14) 00196 } 00197 00198 for (i = 0; i < 16; i++) { 00199 x[i] = PLUS(x[i], input[i]); 00200 } 00201 00202 for (i = 0; i < 16; i++) { 00203 output[i] = LITTLE32(x[i]); 00204 } 00205 } 00206 00207 /** 00208 * Encrypt a stream of bytes 00209 */ 00210 static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, 00211 word32 bytes) 00212 { 00213 byte* output; 00214 word32 temp[16]; /* used to make sure aligned */ 00215 word32 i; 00216 00217 output = (byte*)temp; 00218 00219 if (!bytes) return; 00220 for (;;) { 00221 wc_Chacha_wordtobyte(temp, ctx->X); 00222 ctx->X[12] = PLUSONE(ctx->X[12]); 00223 if (bytes <= 64) { 00224 for (i = 0; i < bytes; ++i) { 00225 c[i] = m[i] ^ output[i]; 00226 } 00227 return; 00228 } 00229 for (i = 0; i < 64; ++i) { 00230 c[i] = m[i] ^ output[i]; 00231 } 00232 bytes -= 64; 00233 c += 64; 00234 m += 64; 00235 } 00236 } 00237 00238 /** 00239 * API to encrypt/decrypt a message of any size. 00240 */ 00241 int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, word32 msglen) 00242 { 00243 if (ctx == NULL) 00244 return BAD_FUNC_ARG; 00245 00246 wc_Chacha_encrypt_bytes(ctx, input, output, msglen); 00247 00248 return 0; 00249 } 00250 00251 #endif /* HAVE_CHACHA*/ 00252 00253
Generated on Tue Jul 12 2022 15:55:18 by
1.7.2