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.
hc128.c
00001 /* hc128.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 #ifdef HAVE_HC128 00030 00031 #include <wolfcrypt/hc128.h> 00032 #include <wolfcrypt/error-crypt.h> 00033 #include <wolfcrypt/logging.h> 00034 #ifdef NO_INLINE 00035 #include <wolfcrypt/hc128.h> 00036 #include <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 WC_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 if (ctx == NULL || key == NULL) { 00309 return BAD_FUNC_ARG; 00310 } 00311 00312 #ifdef XSTREAM_ALIGN 00313 /* default heap to NULL or heap test value */ 00314 #ifdef WOLFSSL_HEAP_TEST 00315 ctx->heap = (void*)WOLFSSL_HEAP_TEST; 00316 #else 00317 ctx->heap = NULL; 00318 #endif /* WOLFSSL_HEAP_TEST */ 00319 00320 if ((wolfssl_word)key % 4) { 00321 int alignKey[4]; 00322 00323 /* iv gets aligned in SetIV */ 00324 WOLFSSL_MSG("Hc128SetKey unaligned key"); 00325 00326 XMEMCPY(alignKey, key, sizeof(alignKey)); 00327 00328 return DoKey(ctx, (const byte*)alignKey, iv); 00329 } 00330 #endif /* XSTREAM_ALIGN */ 00331 00332 return DoKey(ctx, key, iv); 00333 } 00334 00335 00336 00337 /* The following defines the encryption of data stream */ 00338 static WC_INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, 00339 word32 msglen) 00340 { 00341 word32 i, keystream[16]; 00342 00343 for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64) 00344 { 00345 generate_keystream(ctx, keystream); 00346 00347 /* unroll loop */ 00348 ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]); 00349 ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]); 00350 ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]); 00351 ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]); 00352 ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]); 00353 ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]); 00354 ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]); 00355 ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]); 00356 ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]); 00357 ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]); 00358 ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]); 00359 ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]); 00360 ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]); 00361 ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]); 00362 ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]); 00363 ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]); 00364 } 00365 00366 if (msglen > 0) 00367 { 00368 XMEMSET(keystream, 0, sizeof(keystream)); /* hush the static analysis */ 00369 generate_keystream(ctx, keystream); 00370 00371 #ifdef BIG_ENDIAN_ORDER 00372 { 00373 word32 wordsLeft = msglen / sizeof(word32); 00374 if (msglen % sizeof(word32)) wordsLeft++; 00375 00376 ByteReverseWords(keystream, keystream, wordsLeft * sizeof(word32)); 00377 } 00378 #endif 00379 00380 for (i = 0; i < msglen; i++) 00381 output[i] = input[i] ^ ((byte*)keystream)[i]; 00382 } 00383 00384 return 0; 00385 } 00386 00387 00388 /* Encrypt/decrypt a message of any size */ 00389 int wc_Hc128_Process(HC128* ctx, byte* output, const byte* input, word32 msglen) 00390 { 00391 if (ctx == NULL || output == NULL || input == NULL) { 00392 return BAD_FUNC_ARG; 00393 } 00394 00395 #ifdef XSTREAM_ALIGN 00396 if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) { 00397 #ifndef NO_WOLFSSL_ALLOC_ALIGN 00398 byte* tmp; 00399 WOLFSSL_MSG("Hc128Process unaligned"); 00400 00401 tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00402 if (tmp == NULL) return MEMORY_E; 00403 00404 XMEMCPY(tmp, input, msglen); 00405 DoProcess(ctx, tmp, tmp, msglen); 00406 XMEMCPY(output, tmp, msglen); 00407 00408 XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); 00409 00410 return 0; 00411 #else 00412 return BAD_ALIGN_E; 00413 #endif 00414 } 00415 #endif /* XSTREAM_ALIGN */ 00416 00417 return DoProcess(ctx, output, input, msglen); 00418 } 00419 00420 00421 #else /* HAVE_HC128 */ 00422 00423 00424 #ifdef _MSC_VER 00425 /* 4206 warning for blank file */ 00426 #pragma warning(disable: 4206) 00427 #endif 00428 00429 00430 #endif /* HAVE_HC128 */ 00431
Generated on Tue Jul 12 2022 16:58:06 by
1.7.2