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
hc128.c
00001 /* hc128.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 #ifdef HAVE_HC128 00030 00031 #include <wolfssl/wolfcrypt/hc128.h> 00032 #include <wolfssl/wolfcrypt/error-crypt.h> 00033 #include <wolfssl/wolfcrypt/logging.h> 00034 #ifdef NO_INLINE 00035 #include <wolfssl/wolfcrypt/hc128.h> 00036 #include <wolfssl/wolfcrypt/misc.h> 00037 #else 00038 #define WOLFSSL_MISC_INCLUDED 00039 #include <wolfcrypt/src/misc.c> 00040 #endif 00041 00042 00043 #ifdef BIG_ENDIAN_ORDER 00044 #define LITTLE32(x) ByteReverseWord32(x) 00045 #else 00046 #define LITTLE32(x) (x) 00047 #endif 00048 00049 00050 /*h1 function*/ 00051 #define h1(ctx, x, y) { \ 00052 byte a,c; \ 00053 a = (byte) (x); \ 00054 c = (byte) ((x) >> 16); \ 00055 y = (ctx->T[512+a])+(ctx->T[512+256+c]); \ 00056 } 00057 00058 /*h2 function*/ 00059 #define h2(ctx, x, y) { \ 00060 byte a,c; \ 00061 a = (byte) (x); \ 00062 c = (byte) ((x) >> 16); \ 00063 y = (ctx->T[a])+(ctx->T[256+c]); \ 00064 } 00065 00066 /*one step of HC-128, update P and generate 32 bits keystream*/ 00067 #define step_P(ctx,u,v,a,b,c,d,n){ \ 00068 word32 tem0,tem1,tem2,tem3; \ 00069 h1((ctx),(ctx->X[(d)]),tem3); \ 00070 tem0 = rotrFixed((ctx->T[(v)]),23); \ 00071 tem1 = rotrFixed((ctx->X[(c)]),10); \ 00072 tem2 = rotrFixed((ctx->X[(b)]),8); \ 00073 (ctx->T[(u)]) += tem2+(tem0 ^ tem1); \ 00074 (ctx->X[(a)]) = (ctx->T[(u)]); \ 00075 (n) = tem3 ^ (ctx->T[(u)]) ; \ 00076 } 00077 00078 /*one step of HC-128, update Q and generate 32 bits keystream*/ 00079 #define step_Q(ctx,u,v,a,b,c,d,n){ \ 00080 word32 tem0,tem1,tem2,tem3; \ 00081 h2((ctx),(ctx->Y[(d)]),tem3); \ 00082 tem0 = rotrFixed((ctx->T[(v)]),(32-23)); \ 00083 tem1 = rotrFixed((ctx->Y[(c)]),(32-10)); \ 00084 tem2 = rotrFixed((ctx->Y[(b)]),(32-8)); \ 00085 (ctx->T[(u)]) += tem2 + (tem0 ^ tem1); \ 00086 (ctx->Y[(a)]) = (ctx->T[(u)]); \ 00087 (n) = tem3 ^ (ctx->T[(u)]) ; \ 00088 } 00089 00090 /*16 steps of HC-128, generate 512 bits keystream*/ 00091 static void generate_keystream(HC128* ctx, word32* keystream) 00092 { 00093 word32 cc,dd; 00094 cc = ctx->counter1024 & 0x1ff; 00095 dd = (cc+16)&0x1ff; 00096 00097 if (ctx->counter1024 < 512) 00098 { 00099 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; 00100 step_P(ctx, cc+0, cc+1, 0, 6, 13,4, keystream[0]); 00101 step_P(ctx, cc+1, cc+2, 1, 7, 14,5, keystream[1]); 00102 step_P(ctx, cc+2, cc+3, 2, 8, 15,6, keystream[2]); 00103 step_P(ctx, cc+3, cc+4, 3, 9, 0, 7, keystream[3]); 00104 step_P(ctx, cc+4, cc+5, 4, 10,1, 8, keystream[4]); 00105 step_P(ctx, cc+5, cc+6, 5, 11,2, 9, keystream[5]); 00106 step_P(ctx, cc+6, cc+7, 6, 12,3, 10,keystream[6]); 00107 step_P(ctx, cc+7, cc+8, 7, 13,4, 11,keystream[7]); 00108 step_P(ctx, cc+8, cc+9, 8, 14,5, 12,keystream[8]); 00109 step_P(ctx, cc+9, cc+10,9, 15,6, 13,keystream[9]); 00110 step_P(ctx, cc+10,cc+11,10,0, 7, 14,keystream[10]); 00111 step_P(ctx, cc+11,cc+12,11,1, 8, 15,keystream[11]); 00112 step_P(ctx, cc+12,cc+13,12,2, 9, 0, keystream[12]); 00113 step_P(ctx, cc+13,cc+14,13,3, 10,1, keystream[13]); 00114 step_P(ctx, cc+14,cc+15,14,4, 11,2, keystream[14]); 00115 step_P(ctx, cc+15,dd+0, 15,5, 12,3, keystream[15]); 00116 } 00117 else 00118 { 00119 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; 00120 step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]); 00121 step_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]); 00122 step_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]); 00123 step_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]); 00124 step_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]); 00125 step_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]); 00126 step_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]); 00127 step_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]); 00128 step_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]); 00129 step_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]); 00130 step_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]); 00131 step_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]); 00132 step_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]); 00133 step_Q(ctx, 512+cc+13,512+cc+14,13,3, 10,1, keystream[13]); 00134 step_Q(ctx, 512+cc+14,512+cc+15,14,4, 11,2, keystream[14]); 00135 step_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]); 00136 } 00137 } 00138 00139 00140 /* The following defines the initialization functions */ 00141 #define f1(x) (rotrFixed((x),7) ^ rotrFixed((x),18) ^ ((x) >> 3)) 00142 #define f2(x) (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10)) 00143 00144 /*update table P*/ 00145 #define update_P(ctx,u,v,a,b,c,d){ \ 00146 word32 tem0,tem1,tem2,tem3; \ 00147 tem0 = rotrFixed((ctx->T[(v)]),23); \ 00148 tem1 = rotrFixed((ctx->X[(c)]),10); \ 00149 tem2 = rotrFixed((ctx->X[(b)]),8); \ 00150 h1((ctx),(ctx->X[(d)]),tem3); \ 00151 (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ 00152 (ctx->X[(a)]) = (ctx->T[(u)]); \ 00153 } 00154 00155 /*update table Q*/ 00156 #define update_Q(ctx,u,v,a,b,c,d){ \ 00157 word32 tem0,tem1,tem2,tem3; \ 00158 tem0 = rotrFixed((ctx->T[(v)]),(32-23)); \ 00159 tem1 = rotrFixed((ctx->Y[(c)]),(32-10)); \ 00160 tem2 = rotrFixed((ctx->Y[(b)]),(32-8)); \ 00161 h2((ctx),(ctx->Y[(d)]),tem3); \ 00162 (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ 00163 (ctx->Y[(a)]) = (ctx->T[(u)]); \ 00164 } 00165 00166 /*16 steps of HC-128, without generating keystream, */ 00167 /*but use the outputs to update P and Q*/ 00168 static void setup_update(HC128* ctx) /*each time 16 steps*/ 00169 { 00170 word32 cc,dd; 00171 cc = ctx->counter1024 & 0x1ff; 00172 dd = (cc+16)&0x1ff; 00173 00174 if (ctx->counter1024 < 512) 00175 { 00176 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; 00177 update_P(ctx, cc+0, cc+1, 0, 6, 13, 4); 00178 update_P(ctx, cc+1, cc+2, 1, 7, 14, 5); 00179 update_P(ctx, cc+2, cc+3, 2, 8, 15, 6); 00180 update_P(ctx, cc+3, cc+4, 3, 9, 0, 7); 00181 update_P(ctx, cc+4, cc+5, 4, 10,1, 8); 00182 update_P(ctx, cc+5, cc+6, 5, 11,2, 9); 00183 update_P(ctx, cc+6, cc+7, 6, 12,3, 10); 00184 update_P(ctx, cc+7, cc+8, 7, 13,4, 11); 00185 update_P(ctx, cc+8, cc+9, 8, 14,5, 12); 00186 update_P(ctx, cc+9, cc+10,9, 15,6, 13); 00187 update_P(ctx, cc+10,cc+11,10,0, 7, 14); 00188 update_P(ctx, cc+11,cc+12,11,1, 8, 15); 00189 update_P(ctx, cc+12,cc+13,12,2, 9, 0); 00190 update_P(ctx, cc+13,cc+14,13,3, 10, 1); 00191 update_P(ctx, cc+14,cc+15,14,4, 11, 2); 00192 update_P(ctx, cc+15,dd+0, 15,5, 12, 3); 00193 } 00194 else 00195 { 00196 ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; 00197 update_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13, 4); 00198 update_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14, 5); 00199 update_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15, 6); 00200 update_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7); 00201 update_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8); 00202 update_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9); 00203 update_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10); 00204 update_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11); 00205 update_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12); 00206 update_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13); 00207 update_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14); 00208 update_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15); 00209 update_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0); 00210 update_Q(ctx, 512+cc+13,512+cc+14,13,3, 10, 1); 00211 update_Q(ctx, 512+cc+14,512+cc+15,14,4, 11, 2); 00212 update_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12, 3); 00213 } 00214 } 00215 00216 00217 /* for the 128-bit key: key[0]...key[15] 00218 * key[0] is the least significant byte of ctx->key[0] (K_0); 00219 * key[3] is the most significant byte of ctx->key[0] (K_0); 00220 * ... 00221 * key[12] is the least significant byte of ctx->key[3] (K_3) 00222 * key[15] is the most significant byte of ctx->key[3] (K_3) 00223 * 00224 * for the 128-bit iv: iv[0]...iv[15] 00225 * iv[0] is the least significant byte of ctx->iv[0] (IV_0); 00226 * iv[3] is the most significant byte of ctx->iv[0] (IV_0); 00227 * ... 00228 * iv[12] is the least significant byte of ctx->iv[3] (IV_3) 00229 * iv[15] is the most significant byte of ctx->iv[3] (IV_3) 00230 */ 00231 00232 00233 00234 static void Hc128_SetIV(HC128* ctx, const byte* inIv) 00235 { 00236 word32 i; 00237 word32 iv[4]; 00238 00239 if (inIv) 00240 XMEMCPY(iv, inIv, sizeof(iv)); 00241 else 00242 XMEMSET(iv, 0, sizeof(iv)); 00243 00244 for (i = 0; i < (128 >> 5); i++) 00245 ctx->iv[i] = LITTLE32(iv[i]); 00246 00247 for (; i < 8; i++) ctx->iv[i] = ctx->iv[i-4]; 00248 00249 /* expand the key and IV into the table T */ 00250 /* (expand the key and IV into the table P and Q) */ 00251 00252 for (i = 0; i < 8; i++) ctx->T[i] = ctx->key[i]; 00253 for (i = 8; i < 16; i++) ctx->T[i] = ctx->iv[i-8]; 00254 00255 for (i = 16; i < (256+16); i++) 00256 ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + 00257 ctx->T[i-16]+i; 00258 00259 for (i = 0; i < 16; i++) ctx->T[i] = ctx->T[256+i]; 00260 00261 for (i = 16; i < 1024; i++) 00262 ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + 00263 ctx->T[i-16]+256+i; 00264 00265 /* initialize counter1024, X and Y */ 00266 ctx->counter1024 = 0; 00267 for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i]; 00268 for (i = 0; i < 16; i++) ctx->Y[i] = ctx->T[512+512-16+i]; 00269 00270 /* run the cipher 1024 steps before generating the output */ 00271 for (i = 0; i < 64; i++) setup_update(ctx); 00272 } 00273 00274 00275 static INLINE int DoKey(HC128* ctx, const byte* key, const byte* iv) 00276 { 00277 word32 i; 00278 00279 /* Key size in bits 128 */ 00280 for (i = 0; i < (128 >> 5); i++) 00281 ctx->key[i] = LITTLE32(((word32*)key)[i]); 00282 00283 for ( ; i < 8 ; i++) ctx->key[i] = ctx->key[i-4]; 00284 00285 Hc128_SetIV(ctx, iv); 00286 00287 return 0; 00288 } 00289 00290 00291 int wc_Hc128_SetHeap(HC128* ctx, void* heap) 00292 { 00293 if (ctx == NULL) { 00294 return BAD_FUNC_ARG; 00295 } 00296 00297 #ifdef XSTREAM_ALIGN 00298 ctx->heap = heap; 00299 #endif 00300 00301 (void)heap; 00302 return 0; 00303 } 00304 00305 /* Key setup */ 00306 int wc_Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv) 00307 { 00308 #ifdef XSTREAM_ALIGN 00309 /* default heap to NULL or heap test value */ 00310 #ifdef WOLFSSL_HEAP_TEST 00311 ctx->heap = (void*)WOLFSSL_HEAP_TEST; 00312 #else 00313 ctx->heap = NULL; 00314 #endif /* WOLFSSL_HEAP_TEST */ 00315 00316 if ((wolfssl_word)key % 4) { 00317 int alignKey[4]; 00318 00319 /* iv gets aligned in SetIV */ 00320 WOLFSSL_MSG("Hc128SetKey unaligned key"); 00321 00322 XMEMCPY(alignKey, key, sizeof(alignKey)); 00323 00324 return DoKey(ctx, (const byte*)alignKey, iv); 00325 } 00326 #endif /* XSTREAM_ALIGN */ 00327 00328 return DoKey(ctx, key, iv); 00329 } 00330 00331 00332 00333 /* The following defines the encryption of data stream */ 00334 static INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, 00335 word32 msglen) 00336 { 00337 word32 i, keystream[16]; 00338 00339 for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64) 00340 { 00341 generate_keystream(ctx, keystream); 00342 00343 /* unroll loop */ 00344 ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]); 00345 ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]); 00346 ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]); 00347 ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]); 00348 ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]); 00349 ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]); 00350 ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]); 00351 ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]); 00352 ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]); 00353 ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]); 00354 ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]); 00355 ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]); 00356 ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]); 00357 ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]); 00358 ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]); 00359 ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]); 00360 } 00361 00362 if (msglen > 0) 00363 { 00364 XMEMSET(keystream, 0, sizeof(keystream)); /* hush the static analysis */ 00365 generate_keystream(ctx, keystream); 00366 00367 #ifdef BIG_ENDIAN_ORDER 00368 { 00369 word32 wordsLeft = msglen / sizeof(word32); 00370 if (msglen % sizeof(word32)) wordsLeft++; 00371 00372 ByteReverseWords(keystream, keystream, wordsLeft * sizeof(word32)); 00373 } 00374 #endif 00375 00376 for (i = 0; i < msglen; i++) 00377 output[i] = input[i] ^ ((byte*)keystream)[i]; 00378 } 00379 00380 return 0; 00381 } 00382 00383 00384 /* Encrypt/decrypt a message of any size */ 00385 int wc_Hc128_Process(HC128* ctx, byte* output, const byte* input, word32 msglen) 00386 { 00387 #ifdef XSTREAM_ALIGN 00388 if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) { 00389 #ifndef NO_WOLFSSL_ALLOC_ALIGN 00390 byte* tmp; 00391 WOLFSSL_MSG("Hc128Process unaligned"); 00392 00393 tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00394 if (tmp == NULL) return MEMORY_E; 00395 00396 XMEMCPY(tmp, input, msglen); 00397 DoProcess(ctx, tmp, tmp, msglen); 00398 XMEMCPY(output, tmp, msglen); 00399 00400 XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00401 00402 return 0; 00403 #else 00404 return BAD_ALIGN_E; 00405 #endif 00406 } 00407 #endif /* XSTREAM_ALIGN */ 00408 00409 return DoProcess(ctx, output, input, msglen); 00410 } 00411 00412 00413 #else /* HAVE_HC128 */ 00414 00415 00416 #ifdef _MSC_VER 00417 /* 4206 warning for blank file */ 00418 #pragma warning(disable: 4206) 00419 #endif 00420 00421 00422 #endif /* HAVE_HC128 */ 00423
Generated on Tue Jul 12 2022 23:30:55 by
1.7.2
