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