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
rabbit.c
00001 /* rabbit.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 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #ifndef NO_RABBIT 00030 00031 #include <wolfssl/wolfcrypt/rabbit.h> 00032 #include <wolfssl/wolfcrypt/error-crypt.h> 00033 #include <wolfssl/wolfcrypt/logging.h> 00034 #ifdef NO_INLINE 00035 #include <wolfssl/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 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 #ifdef XSTREAM_ALIGN 00222 /* default heap to NULL or heap test value */ 00223 #ifdef WOLFSSL_HEAP_TEST 00224 ctx->heap = (void*)WOLFSSL_HEAP_TEST; 00225 #else 00226 ctx->heap = NULL; 00227 #endif /* WOLFSSL_HEAP_TEST */ 00228 00229 if ((wolfssl_word)key % 4) { 00230 int alignKey[4]; 00231 00232 /* iv aligned in SetIV */ 00233 WOLFSSL_MSG("wc_RabbitSetKey unaligned key"); 00234 00235 XMEMCPY(alignKey, key, sizeof(alignKey)); 00236 00237 return DoKey(ctx, (const byte*)alignKey, iv); 00238 } 00239 #endif /* XSTREAM_ALIGN */ 00240 00241 return DoKey(ctx, key, iv); 00242 } 00243 00244 00245 /* Encrypt/decrypt a message of any size */ 00246 static INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input, 00247 word32 msglen) 00248 { 00249 /* Encrypt/decrypt all full blocks */ 00250 while (msglen >= 16) { 00251 /* Iterate the system */ 00252 RABBIT_next_state(&(ctx->workCtx)); 00253 00254 /* Encrypt/decrypt 16 bytes of data */ 00255 *(word32*)(output+ 0) = *(word32*)(input+ 0) ^ 00256 LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^ 00257 U32V(ctx->workCtx.x[3]<<16)); 00258 *(word32*)(output+ 4) = *(word32*)(input+ 4) ^ 00259 LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^ 00260 U32V(ctx->workCtx.x[5]<<16)); 00261 *(word32*)(output+ 8) = *(word32*)(input+ 8) ^ 00262 LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^ 00263 U32V(ctx->workCtx.x[7]<<16)); 00264 *(word32*)(output+12) = *(word32*)(input+12) ^ 00265 LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^ 00266 U32V(ctx->workCtx.x[1]<<16)); 00267 00268 /* Increment pointers and decrement length */ 00269 input += 16; 00270 output += 16; 00271 msglen -= 16; 00272 } 00273 00274 /* Encrypt/decrypt remaining data */ 00275 if (msglen) { 00276 00277 word32 i; 00278 word32 tmp[4]; 00279 byte* buffer = (byte*)tmp; 00280 00281 XMEMSET(tmp, 0, sizeof(tmp)); /* help static analysis */ 00282 00283 /* Iterate the system */ 00284 RABBIT_next_state(&(ctx->workCtx)); 00285 00286 /* Generate 16 bytes of pseudo-random data */ 00287 tmp[0] = LITTLE32(ctx->workCtx.x[0] ^ 00288 (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16)); 00289 tmp[1] = LITTLE32(ctx->workCtx.x[2] ^ 00290 (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16)); 00291 tmp[2] = LITTLE32(ctx->workCtx.x[4] ^ 00292 (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16)); 00293 tmp[3] = LITTLE32(ctx->workCtx.x[6] ^ 00294 (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16)); 00295 00296 /* Encrypt/decrypt the data */ 00297 for (i=0; i<msglen; i++) 00298 output[i] = input[i] ^ buffer[i]; 00299 } 00300 00301 return 0; 00302 } 00303 00304 00305 /* Encrypt/decrypt a message of any size */ 00306 int wc_RabbitProcess(Rabbit* ctx, byte* output, const byte* input, word32 msglen) 00307 { 00308 #ifdef XSTREAM_ALIGN 00309 if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) { 00310 #ifndef NO_WOLFSSL_ALLOC_ALIGN 00311 byte* tmp; 00312 WOLFSSL_MSG("wc_RabbitProcess unaligned"); 00313 00314 tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00315 if (tmp == NULL) return MEMORY_E; 00316 00317 XMEMCPY(tmp, input, msglen); 00318 DoProcess(ctx, tmp, tmp, msglen); 00319 XMEMCPY(output, tmp, msglen); 00320 00321 XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00322 00323 return 0; 00324 #else 00325 return BAD_ALIGN_E; 00326 #endif 00327 } 00328 #endif /* XSTREAM_ALIGN */ 00329 00330 return DoProcess(ctx, output, input, msglen); 00331 } 00332 00333 00334 #endif /* NO_RABBIT */ 00335
Generated on Tue Jul 12 2022 23:30:59 by
1.7.2
