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