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.
rabbit.c
00001 /* rabbit.c 00002 * 00003 * Copyright (C) 2006-2017 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 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfcrypt/settings.h> 00028 00029 #ifndef NO_RABBIT 00030 00031 #include <wolfcrypt/rabbit.h> 00032 #include <wolfcrypt/error-crypt.h> 00033 #include <wolfcrypt/logging.h> 00034 #ifdef NO_INLINE 00035 #include <wolfcrypt/misc.h> 00036 #else 00037 #define WOLFSSL_MISC_INCLUDED 00038 #include <wolfcrypt/src/misc.c> 00039 #endif 00040 00041 00042 #ifdef BIG_ENDIAN_ORDER 00043 #define LITTLE32(x) ByteReverseWord32(x) 00044 #else 00045 #define LITTLE32(x) (x) 00046 #endif 00047 00048 #define U32V(x) ((word32)(x) & 0xFFFFFFFFU) 00049 00050 00051 /* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ 00052 /* the upper 32 bits XOR the lower 32 bits */ 00053 static word32 RABBIT_g_func(word32 x) 00054 { 00055 /* Temporary variables */ 00056 word32 a, b, h, l; 00057 00058 /* Construct high and low argument for squaring */ 00059 a = x&0xFFFF; 00060 b = x>>16; 00061 00062 /* Calculate high and low result of squaring */ 00063 h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b; 00064 l = x*x; 00065 00066 /* Return high XOR low */ 00067 return U32V(h^l); 00068 } 00069 00070 00071 /* Calculate the next internal state */ 00072 static void RABBIT_next_state(RabbitCtx* ctx) 00073 { 00074 /* Temporary variables */ 00075 word32 g[8], c_old[8], i; 00076 00077 /* Save old counter values */ 00078 for (i=0; i<8; i++) 00079 c_old[i] = ctx->c[i]; 00080 00081 /* Calculate new counter values */ 00082 ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry); 00083 ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0])); 00084 ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1])); 00085 ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2])); 00086 ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3])); 00087 ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4])); 00088 ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5])); 00089 ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6])); 00090 ctx->carry = (ctx->c[7] < c_old[7]); 00091 00092 /* Calculate the g-values */ 00093 for (i=0;i<8;i++) 00094 g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i])); 00095 00096 /* Calculate new state values */ 00097 ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16)); 00098 ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]); 00099 ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16)); 00100 ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]); 00101 ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16)); 00102 ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]); 00103 ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16)); 00104 ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]); 00105 } 00106 00107 00108 /* IV setup */ 00109 static void wc_RabbitSetIV(Rabbit* ctx, const byte* inIv) 00110 { 00111 /* Temporary variables */ 00112 word32 i0, i1, i2, i3, i; 00113 word32 iv[2]; 00114 00115 if (inIv) 00116 XMEMCPY(iv, inIv, sizeof(iv)); 00117 else 00118 XMEMSET(iv, 0, sizeof(iv)); 00119 00120 /* Generate four subvectors */ 00121 i0 = LITTLE32(iv[0]); 00122 i2 = LITTLE32(iv[1]); 00123 i1 = (i0>>16) | (i2&0xFFFF0000); 00124 i3 = (i2<<16) | (i0&0x0000FFFF); 00125 00126 /* Modify counter values */ 00127 ctx->workCtx.c[0] = ctx->masterCtx.c[0] ^ i0; 00128 ctx->workCtx.c[1] = ctx->masterCtx.c[1] ^ i1; 00129 ctx->workCtx.c[2] = ctx->masterCtx.c[2] ^ i2; 00130 ctx->workCtx.c[3] = ctx->masterCtx.c[3] ^ i3; 00131 ctx->workCtx.c[4] = ctx->masterCtx.c[4] ^ i0; 00132 ctx->workCtx.c[5] = ctx->masterCtx.c[5] ^ i1; 00133 ctx->workCtx.c[6] = ctx->masterCtx.c[6] ^ i2; 00134 ctx->workCtx.c[7] = ctx->masterCtx.c[7] ^ i3; 00135 00136 /* Copy state variables */ 00137 for (i=0; i<8; i++) 00138 ctx->workCtx.x[i] = ctx->masterCtx.x[i]; 00139 ctx->workCtx.carry = ctx->masterCtx.carry; 00140 00141 /* Iterate the system four times */ 00142 for (i=0; i<4; i++) 00143 RABBIT_next_state(&(ctx->workCtx)); 00144 } 00145 00146 00147 /* Key setup */ 00148 static WC_INLINE int DoKey(Rabbit* ctx, const byte* key, const byte* iv) 00149 { 00150 /* Temporary variables */ 00151 word32 k0, k1, k2, k3, i; 00152 00153 /* Generate four subkeys */ 00154 k0 = LITTLE32(*(word32*)(key+ 0)); 00155 k1 = LITTLE32(*(word32*)(key+ 4)); 00156 k2 = LITTLE32(*(word32*)(key+ 8)); 00157 k3 = LITTLE32(*(word32*)(key+12)); 00158 00159 /* Generate initial state variables */ 00160 ctx->masterCtx.x[0] = k0; 00161 ctx->masterCtx.x[2] = k1; 00162 ctx->masterCtx.x[4] = k2; 00163 ctx->masterCtx.x[6] = k3; 00164 ctx->masterCtx.x[1] = U32V(k3<<16) | (k2>>16); 00165 ctx->masterCtx.x[3] = U32V(k0<<16) | (k3>>16); 00166 ctx->masterCtx.x[5] = U32V(k1<<16) | (k0>>16); 00167 ctx->masterCtx.x[7] = U32V(k2<<16) | (k1>>16); 00168 00169 /* Generate initial counter values */ 00170 ctx->masterCtx.c[0] = rotlFixed(k2, 16); 00171 ctx->masterCtx.c[2] = rotlFixed(k3, 16); 00172 ctx->masterCtx.c[4] = rotlFixed(k0, 16); 00173 ctx->masterCtx.c[6] = rotlFixed(k1, 16); 00174 ctx->masterCtx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); 00175 ctx->masterCtx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); 00176 ctx->masterCtx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); 00177 ctx->masterCtx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); 00178 00179 /* Clear carry bit */ 00180 ctx->masterCtx.carry = 0; 00181 00182 /* Iterate the system four times */ 00183 for (i=0; i<4; i++) 00184 RABBIT_next_state(&(ctx->masterCtx)); 00185 00186 /* Modify the counters */ 00187 for (i=0; i<8; i++) 00188 ctx->masterCtx.c[i] ^= ctx->masterCtx.x[(i+4)&0x7]; 00189 00190 /* Copy master instance to work instance */ 00191 for (i=0; i<8; i++) { 00192 ctx->workCtx.x[i] = ctx->masterCtx.x[i]; 00193 ctx->workCtx.c[i] = ctx->masterCtx.c[i]; 00194 } 00195 ctx->workCtx.carry = ctx->masterCtx.carry; 00196 00197 wc_RabbitSetIV(ctx, iv); 00198 00199 return 0; 00200 } 00201 00202 00203 int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap) 00204 { 00205 if (ctx == NULL) { 00206 return BAD_FUNC_ARG; 00207 } 00208 00209 #ifdef XSTREAM_ALIGN 00210 ctx->heap = heap; 00211 #endif 00212 00213 (void)heap; 00214 return 0; 00215 } 00216 00217 00218 /* Key setup */ 00219 int wc_RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv) 00220 { 00221 if (ctx == NULL || key == NULL) { 00222 return BAD_FUNC_ARG; 00223 } 00224 00225 #ifdef XSTREAM_ALIGN 00226 /* default heap to NULL or heap test value */ 00227 #ifdef WOLFSSL_HEAP_TEST 00228 ctx->heap = (void*)WOLFSSL_HEAP_TEST; 00229 #else 00230 ctx->heap = NULL; 00231 #endif /* WOLFSSL_HEAP_TEST */ 00232 00233 if ((wolfssl_word)key % 4) { 00234 int alignKey[4]; 00235 00236 /* iv aligned in SetIV */ 00237 WOLFSSL_MSG("wc_RabbitSetKey unaligned key"); 00238 00239 XMEMCPY(alignKey, key, sizeof(alignKey)); 00240 00241 return DoKey(ctx, (const byte*)alignKey, iv); 00242 } 00243 #endif /* XSTREAM_ALIGN */ 00244 00245 return DoKey(ctx, key, iv); 00246 } 00247 00248 00249 /* Encrypt/decrypt a message of any size */ 00250 static WC_INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input, 00251 word32 msglen) 00252 { 00253 /* Encrypt/decrypt all full blocks */ 00254 while (msglen >= 16) { 00255 /* Iterate the system */ 00256 RABBIT_next_state(&(ctx->workCtx)); 00257 00258 /* Encrypt/decrypt 16 bytes of data */ 00259 *(word32*)(output+ 0) = *(word32*)(input+ 0) ^ 00260 LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^ 00261 U32V(ctx->workCtx.x[3]<<16)); 00262 *(word32*)(output+ 4) = *(word32*)(input+ 4) ^ 00263 LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^ 00264 U32V(ctx->workCtx.x[5]<<16)); 00265 *(word32*)(output+ 8) = *(word32*)(input+ 8) ^ 00266 LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^ 00267 U32V(ctx->workCtx.x[7]<<16)); 00268 *(word32*)(output+12) = *(word32*)(input+12) ^ 00269 LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^ 00270 U32V(ctx->workCtx.x[1]<<16)); 00271 00272 /* Increment pointers and decrement length */ 00273 input += 16; 00274 output += 16; 00275 msglen -= 16; 00276 } 00277 00278 /* Encrypt/decrypt remaining data */ 00279 if (msglen) { 00280 00281 word32 i; 00282 word32 tmp[4]; 00283 byte* buffer = (byte*)tmp; 00284 00285 XMEMSET(tmp, 0, sizeof(tmp)); /* help static analysis */ 00286 00287 /* Iterate the system */ 00288 RABBIT_next_state(&(ctx->workCtx)); 00289 00290 /* Generate 16 bytes of pseudo-random data */ 00291 tmp[0] = LITTLE32(ctx->workCtx.x[0] ^ 00292 (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16)); 00293 tmp[1] = LITTLE32(ctx->workCtx.x[2] ^ 00294 (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16)); 00295 tmp[2] = LITTLE32(ctx->workCtx.x[4] ^ 00296 (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16)); 00297 tmp[3] = LITTLE32(ctx->workCtx.x[6] ^ 00298 (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16)); 00299 00300 /* Encrypt/decrypt the data */ 00301 for (i=0; i<msglen; i++) 00302 output[i] = input[i] ^ buffer[i]; 00303 } 00304 00305 return 0; 00306 } 00307 00308 00309 /* Encrypt/decrypt a message of any size */ 00310 int wc_RabbitProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen) 00311 { 00312 if (ctx == NULL || output == NULL || input == NULL) { 00313 return BAD_FUNC_ARG; 00314 } 00315 00316 #ifdef XSTREAM_ALIGN 00317 if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) { 00318 #ifndef NO_WOLFSSL_ALLOC_ALIGN 00319 byte* tmp; 00320 WOLFSSL_MSG("wc_RabbitProcess unaligned"); 00321 00322 tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00323 if (tmp == NULL) return MEMORY_E; 00324 00325 XMEMCPY(tmp, input, msglen); 00326 DoProcess(ctx, tmp, tmp, msglen); 00327 XMEMCPY(output, tmp, msglen); 00328 00329 XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00330 00331 return 0; 00332 #else 00333 return BAD_ALIGN_E; 00334 #endif 00335 } 00336 #endif /* XSTREAM_ALIGN */ 00337 00338 return DoProcess(ctx, output, input, msglen); 00339 } 00340 00341 00342 #endif /* NO_RABBIT */ 00343
Generated on Tue Jul 12 2022 16:58:06 by
1.7.2