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