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