00001
00023 #include "dkcHC256.h"
00024
00025 #include <stdlib.h>
00026
00027
00028
00029
00030
00031
00032 #ifndef _MSC_VER
00033 #define rotr(x,n) (((x)>>(n))|((x)<<(32-(n))))
00034 #else
00035 #define rotr(x,n) _lrotr(x,n)
00036 #endif
00037
00038
00039 static DKC_INLINE uint32 h1(uint32 *Q,uint32 x){
00040 DKC_4BYTE_UNION_LITTLE_ENDIAN_BASE a;
00041 a.dword = x;
00042 return Q[a.w.byte0] +
00043 Q[256+a.w.byte1] +
00044 Q[512+a.w.byte2] +
00045 Q[768+a.w.byte3];
00046 }
00047
00048 static DKC_INLINE uint32 h2(uint32 *P,uint32 x){
00049 DKC_4BYTE_UNION_LITTLE_ENDIAN_BASE a;
00050 a.dword = x;
00051 return P[a.w.byte0] +
00052 P[256+a.w.byte1] +
00053 P[512+a.w.byte2] +
00054 P[768+a.w.byte3];
00055 }
00056
00057 static DKC_INLINE uint32 g1(uint32 *Q,uint32 x,uint32 y){
00058 uint32 a,b,c;
00059 a = rotr((x),10);
00060 b = rotr((y),23);
00061 c = ((x)^(y))&0x3ff;
00062 return (a^b) + Q[c];
00063 }
00064 static DKC_INLINE uint32 g2(uint32 *P,uint32 x,uint32 y){
00065 uint32 a,b,c;
00066 a = rotr((x),10);
00067 b = rotr((y),23);
00068 c = ((x)^(y))&0x3ff;
00069 return (a^b) + P[c];
00070 }
00071
00072 #define feedback_1(u,v,b,c) { \
00073 uint32 tem0,tem1,tem2; \
00074 tem0 = rotr((v),23); \
00075 tem1 = rotr((c),10); \
00076 tem2 = ((v) ^ (c)) & 0x3ff; \
00077 (u) += (b)+(tem0^tem1)+Q[tem2]; \
00078 }
00079
00080 #define feedback_2(u,v,b,c) { \
00081 uint32 tem0,tem1,tem2; \
00082 tem0 = rotr((v),23); \
00083 tem1 = rotr((c),10); \
00084 tem2 = ((v) ^ (c)) & 0x3ff; \
00085 (u) += (b)+(tem0^tem1)+P[tem2]; \
00086 }
00087 static DKC_INLINE uint32 fb1(uint32 *Q,uint32 u,uint32 v,uint32 b,uint32 c){
00088 uint32 tem0,tem1,tem2;
00089 tem0 = rotr((v),23);
00090 tem1 = rotr((c),10);
00091 tem2 = ((v) ^ (c)) & 0x3ff;
00092 (u) += (b)+(tem0^tem1)+Q[tem2];
00093 return u;
00094 }
00095 static DKC_INLINE uint32 fb2(uint32 *P,uint32 u,uint32 v,uint32 b,uint32 c){
00096 uint32 tem0,tem1,tem2;
00097 tem0 = rotr((v),23);
00098 tem1 = rotr((c),10);
00099 tem2 = ((v) ^ (c)) & 0x3ff;
00100 (u) += (b)+(tem0^tem1)+P[tem2];
00101 return u;
00102 }
00103 static DKC_INLINE void fb1_(uint32 *Q,uint32 *u,uint32 v,uint32 b,uint32 c){
00104 uint32 tem0,tem1,tem2;
00105 tem0 = rotr((v),23);
00106 tem1 = rotr((c),10);
00107 tem2 = ((v) ^ (c)) & 0x3ff;
00108 (*u) += (b)+(tem0^tem1)+Q[tem2];
00109 }
00110 static DKC_INLINE void fb2_(uint32 *P,uint32 *u,uint32 v,uint32 b,uint32 c){
00111 uint32 tem0,tem1,tem2;
00112 tem0 = rotr((v),23);
00113 tem1 = rotr((c),10);
00114 tem2 = ((v) ^ (c)) & 0x3ff;
00115 (*u) += (b)+(tem0^tem1)+P[tem2];
00116 }
00117 #define f1(x) (rotr((x),7) ^ rotr((x),18) ^ ((x) >> 3))
00118 #define f2(x) (rotr((x),17) ^ rotr((x),19) ^ ((x) >> 10))
00119 #define f(a,b,c,d) (f2((a)) + b + f1((c)) + d)
00120
00121 void initialization(DKC_HC256 *p,uint32 key[], uint32 iv[])
00122 {
00123 uint32 i,j;
00124 uint32 *P = p->P;
00125 uint32 *Q = p->Q;
00126
00127
00128 for (i = 0; i < 8; i++) P[i] = key[i];
00129 for (i = 8; i < 16; i++) P[i] = iv[i-8];
00130
00131 for (i = 16; i < 528; i++)
00132 P[i] = f(P[i-2],P[i-7],P[i-15],P[i-16])+i;
00133 for (i = 0; i < 16; i++)
00134 P[i] = P[i+512];
00135 for (i = 16; i < 1024; i++)
00136 P[i] = f(P[i-2],P[i-7],P[i-15],P[i-16])+512+i;
00137
00138 for (i = 0; i < 16; i++)
00139 Q[i] = P[1024-16+i];
00140 for (i = 16; i < 32; i++)
00141 Q[i] = f(Q[i-2],Q[i-7],Q[i-15],Q[i-16])+1520+i;
00142 for (i = 0; i < 16; i++)
00143 Q[i] = Q[i+16];
00144 for (i = 16; i < 1024;i++)
00145 Q[i] = f(Q[i-2],Q[i-7],Q[i-15],Q[i-16])+1536+i;
00146
00147
00148 for (i = 0; i < 2; i++) {
00149 #if 1
00150 for (j = 0; j < 10; j++)
00151 fb1_(Q,&P[j],P[j+1],P[(j-10)&0x3ff],P[(j-3)&0x3ff]);
00152 for (j = 10; j < 1023; j++)
00153 fb1_(Q,&P[j],P[j+1],P[j-10],P[j-3]);
00154 fb1_(Q,&P[1023],P[0],P[1013],P[1020]);
00155 for (j = 0; j < 10; j++)
00156 fb2_(P,&Q[j],Q[j+1],Q[(j-10)&0x3ff],Q[(j-3)&0x3ff]);
00157 for (j = 10; j < 1023; j++)
00158 fb2_(P,&Q[j],Q[j+1],Q[j-10],Q[j-3]);
00159 fb2_(P,&Q[1023],Q[0],Q[1013],Q[1020]);
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 #else
00173 for (j = 0; j < 10; j++)
00174 feedback_1(P[j],P[j+1],P[(j-10)&0x3ff],P[(j-3)&0x3ff]);
00175 for (j = 10; j < 1023; j++)
00176 feedback_1(P[j],P[j+1],P[j-10],P[j-3]);
00177 feedback_1(P[1023],P[0],P[1013],P[1020]);
00178 for (j = 0; j < 10; j++)
00179 feedback_2(Q[j],Q[j+1],Q[(j-10)&0x3ff],Q[(j-3)&0x3ff]);
00180 for (j = 10; j < 1023; j++)
00181 feedback_2(Q[j],Q[j+1],Q[j-10],Q[j-3]);
00182 feedback_2(Q[1023],Q[0],Q[1013],Q[1020]);
00183 #endif
00184 }
00185
00186
00187 p->counter2048 = 0;
00188 for (i = 0; i < 16; i++) p->X[i] = P[1008+i];
00189 for (i = 0; i < 16; i++) p->Y[i] = Q[1008+i];
00190 }
00191
00192
00193
00194 DKC_INLINE uint32 dkcHC256Process32(DKC_HC256 *p,uint32 u)
00195 {
00196 unsigned long i,i3, i10, i12, i1023;
00197 unsigned long output;
00198
00199 i = p->counter2048 & 0x3ff;
00200 i3 = (i - 3) & 0x3ff;
00201 i10 = (i - 10) & 0x3ff;
00202 i12 = (i - 12) & 0x3ff;
00203 i1023 = (i - 1023) & 0x3ff;
00204
00205 if (p->counter2048 < 1024) {
00206 p->P[i] = p->P[i] + p->P[i10] + g1(p->Q,p->P[i3],p->P[i1023]);
00207 output = h1(p->Q,p->P[i12]) ^ p->P[i];
00208 }
00209 else {
00210 p->Q[i] = p->Q[i] + p->Q[i10] + g2(p->P,p->Q[i3],p->Q[i1023]);
00211 output = h2(p->P,p->Q[i12]) ^ p->Q[i];
00212
00213 }
00214 p->counter2048 = (p->counter2048+1) & 0x7ff;
00215 return (output);
00216 }
00217
00218
00219 static DKC_INLINE void step_A(DKC_HC256 *p,uint32 u,uint32 v,
00220 uint32 a,uint32 b,uint32 c,uint32 d,uint32 *m)
00221 {
00222 uint32 tem0,tem1,tem2,tem3;
00223 tem0 = rotr((v),23);
00224 tem1 = rotr((c),10);
00225 tem2 = ((v) ^ (c)) & 0x3ff;
00226 (u) += (b)+(tem0^tem1) + p->Q[tem2];
00227 (a) = (u);
00228 tem3 = h1(p->P,d);
00229
00230
00231 *m = tem3 ^ (u) ;
00232 }
00233 static DKC_INLINE void step_B(DKC_HC256 *p,uint32 u,uint32 v,
00234 uint32 a,uint32 b,uint32 c,uint32 d,uint32 *m){
00235 uint32 tem0,tem1,tem2,tem3;
00236 tem0 = rotr((v),23);
00237 tem1 = rotr((c),10);
00238 tem2 = ((v) ^ (c)) & 0x3ff;
00239 (u) += (b)+(tem0^tem1)+p->P[tem2];
00240 (a) = (u);
00241 tem3 = h2(p->P,d);
00242
00243
00244 *m = tem3 ^ (u) ;
00245 }
00246
00247
00248 static DKC_INLINE void get_encrypt_array(DKC_HC256 *p,uint32 data[])
00249 {
00250 uint32 cc,dd,counter2048 = p->counter2048;
00251 uint32 *P = p->P,*Q = p->Q,*X =p->X, *Y = p->Y;
00252
00253 cc = counter2048 & 0x3ff;
00254 dd = (cc+16) & 0x3ff;
00255
00256 if (counter2048 < 1024)
00257 {
00258 counter2048 = (counter2048 + 16) & 0x7ff;
00259 step_A(p,P[cc+0], P[cc+1], X[0], X[6], X[13],X[4], &data[0]);
00260 step_A(p,P[cc+1], P[cc+2], X[1], X[7], X[14],X[5], &data[1]);
00261 step_A(p,P[cc+2], P[cc+3], X[2], X[8], X[15],X[6], &data[2]);
00262 step_A(p,P[cc+3], P[cc+4], X[3], X[9], X[0], X[7], &data[3]);
00263 step_A(p,P[cc+4], P[cc+5], X[4], X[10],X[1], X[8], &data[4]);
00264 step_A(p,P[cc+5], P[cc+6], X[5], X[11],X[2], X[9], &data[5]);
00265 step_A(p,P[cc+6], P[cc+7], X[6], X[12],X[3], X[10],&data[6]);
00266 step_A(p,P[cc+7], P[cc+8], X[7], X[13],X[4], X[11],&data[7]);
00267 step_A(p,P[cc+8], P[cc+9], X[8], X[14],X[5], X[12],&data[8]);
00268 step_A(p,P[cc+9], P[cc+10],X[9], X[15],X[6], X[13],&data[9]);
00269 step_A(p,P[cc+10],P[cc+11],X[10],X[0], X[7], X[14],&data[10]);
00270 step_A(p,P[cc+11],P[cc+12],X[11],X[1], X[8], X[15],&data[11]);
00271 step_A(p,P[cc+12],P[cc+13],X[12],X[2], X[9], X[0], &data[12]);
00272 step_A(p,P[cc+13],P[cc+14],X[13],X[3], X[10],X[1], &data[13]);
00273 step_A(p,P[cc+14],P[cc+15],X[14],X[4], X[11],X[2], &data[14]);
00274 step_A(p,P[cc+15],P[dd+0], X[15],X[5], X[12],X[3], &data[15]);
00275 }
00276 else
00277 {
00278 counter2048 = (counter2048 + 16) & 0x7ff;
00279 step_B(p,Q[cc+0], Q[cc+1], Y[0], Y[6], Y[13],Y[4], &data[0]);
00280 step_B(p,Q[cc+1], Q[cc+2], Y[1], Y[7], Y[14],Y[5], &data[1]);
00281 step_B(p,Q[cc+2], Q[cc+3], Y[2], Y[8], Y[15],Y[6], &data[2]);
00282 step_B(p,Q[cc+3], Q[cc+4], Y[3], Y[9], Y[0], Y[7], &data[3]);
00283 step_B(p,Q[cc+4], Q[cc+5], Y[4], Y[10],Y[1], Y[8], &data[4]);
00284 step_B(p,Q[cc+5], Q[cc+6], Y[5], Y[11],Y[2], Y[9], &data[5]);
00285 step_B(p,Q[cc+6], Q[cc+7], Y[6], Y[12],Y[3], Y[10],&data[6]);
00286 step_B(p,Q[cc+7], Q[cc+8], Y[7], Y[13],Y[4], Y[11],&data[7]);
00287 step_B(p,Q[cc+8], Q[cc+9], Y[8], Y[14],Y[5], Y[12],&data[8]);
00288 step_B(p,Q[cc+9], Q[cc+10],Y[9], Y[15],Y[6], Y[13],&data[9]);
00289 step_B(p,Q[cc+10],Q[cc+11],Y[10],Y[0], Y[7], Y[14],&data[10]);
00290 step_B(p,Q[cc+11],Q[cc+12],Y[11],Y[1], Y[8], Y[15],&data[11]);
00291 step_B(p,Q[cc+12],Q[cc+13],Y[12],Y[2], Y[9], Y[0], &data[12]);
00292 step_B(p,Q[cc+13],Q[cc+14],Y[13],Y[3], Y[10],Y[1], &data[13]);
00293 step_B(p,Q[cc+14],Q[cc+15],Y[14],Y[4], Y[11],Y[2], &data[14]);
00294 step_B(p,Q[cc+15],Q[dd+0], Y[15],Y[5], Y[12],Y[3], &data[15]);
00295 }
00296
00297 p->counter2048 = counter2048;
00298 }
00299
00300 static DKC_INLINE int store(DKC_HC256 *p){
00301
00302 dkcmNOT_ASSERT(0 != p->store_size);
00303 if(0 != p->store_size) return edk_LogicError;
00304 get_encrypt_array(p,p->u_store.a32);
00305 p->store_size = 64;
00306 return edk_SUCCEEDED;
00307 }
00308
00309 DKC_INLINE DKC_HC256 *WINAPI dkcAllocHC256(BYTE *key,size_t size,uint32 *iv,size_t ivsize){
00310 DKC_HC256 *p;
00311
00312
00313
00314 if(size != dkcdHC256_KEY_SIZE || ivsize != dkcdHC256_IV_SIZE){
00315 return NULL;
00316 }
00317
00318 p = dkcAllocate(sizeof(DKC_HC256));
00319 if(NULL==p){
00320 return NULL;
00321 }
00322
00323 initialization(p,(uint32 *)key,iv);
00324 store(p);
00325
00326 return p;
00327 }
00328
00329 DKC_INLINE DKC_HC256 *dkcAllocHC256Const(const uint8 *key,size_t size,const uint32 *iv,size_t ivsize)
00330 {
00331 DKC_HC256 *p=NULL;
00332 uint32 *piv = malloc(ivsize);
00333 uint8 *pt;
00334 if(!piv) return NULL;
00335 pt = malloc(size);
00336 if(pt){
00337 memcpy(pt,key,size);
00338 memcpy(piv,iv,ivsize);
00339 p = dkcAllocHC256(pt,size,piv,ivsize);
00340 free(pt);
00341 free(piv);
00342 }
00343 return p;
00344 }
00345
00346 DKC_INLINE int WINAPI dkcFreeHC256(DKC_HC256 **p){
00347 return dkcFree(p);
00348 }
00349
00350
00351 #define get_offset(p) (64 - p->store_size)
00352
00353 static DKC_INLINE uint8 hc256_byte(DKC_HC256 *p){
00354
00355 size_t offset;
00356
00357 dkcmNOT_ASSERT(0==p->store_size);
00358
00359 offset = get_offset(p);
00360 p->store_size--;
00361 return p->u_store.a8[offset];
00362
00363 }
00364
00365 DKC_INLINE uint8 WINAPI dkcHC256Process(DKC_HC256 *p){
00366 int r = 0;
00367
00368 if(p->store_size <= 0){
00369 r = store(p);
00370 dkcmNOT_ASSERT(DKUTIL_FAILED(r));
00371 }
00372 return hc256_byte(p);
00373
00374 }
00375
00376 int WINAPI dkcHC256EncryptDOE(DKC_HC256 *p,uint8 *dest,size_t dsize,const uint8 *src,size_t ssize)
00377 {
00378 if(ssize > dsize){
00379 return edk_ArgumentException;
00380 }
00381 if(dest != src){
00382 memcpy(dest,src,ssize);
00383 }
00384 return dkcHC256EncryptNoDestDOE(p,dest,ssize);
00385
00386 }
00387 static DKC_INLINE int encode_byte(DKC_HC256 *p,uint8 *inout,size_t size,size_t *nextoffset)
00388 {
00389 size_t i=0;
00390 int r;
00391 if(size <= 0){
00392 r = edk_SUCCEEDED;
00393 goto End;
00394 }
00395 if((size > 64) && ( p->store_size == 0 || 64==p->store_size)){
00396
00397 r = edk_NoValueToProcess;
00398 goto End;
00399 }
00400 if(p->store_size ==0){
00401 r = store(p);
00402 dkcmNOT_ASSERT(DKUTIL_FAILED(r));
00403 }
00404 for(i=0;i<size;i++){
00405 inout[i] ^= hc256_byte(p);
00406 if(p->store_size ==0){
00407
00408 if(size - i > 64){
00409 r = edk_NoValueToProcess;
00410 i++;
00411 goto End;
00412 }
00413 r = store(p);
00414 dkcmNOT_ASSERT(DKUTIL_FAILED(r));
00415 }
00416 }
00417 r = edk_SUCCEEDED;
00418 End:
00419 *nextoffset = i;
00420 return r;
00421 }
00422
00423
00425 int WINAPI dkcHC256EncryptNoDestDOE(DKC_HC256 *p,uint8 *inout,size_t size)
00426 {
00427
00428 size_t i = 0;
00429 int r = edk_FAILED;
00430 size_t count,rest;
00431 uint64 *io64 = NULL;
00432
00433 r = encode_byte(p,inout,size,&rest);
00434 switch(r){
00435 case edk_SUCCEEDED:
00436 return r;
00437 case edk_NoValueToProcess:
00438 break;
00439 default:
00440 dkcmNOT_ASSERT(DKUTIL_FAILED(r));
00441 }
00442 size = size - rest;
00443 inout += rest;
00444 if(rest == size) return edk_SUCCEEDED;
00445
00446
00447 count = size / 64;
00448 rest = size % 64;
00449
00450 if(64!=p->store_size){
00451 dkcmASSERT(p->store_size ==0);
00452 r = store(p);
00453 dkcmNOT_ASSERT(DKUTIL_FAILED(r));
00454 }
00455 io64 = (uint64 *)inout;
00456 for(i=0;i<count;i++){
00457
00458 io64[0] ^= p->u_store.a64[0];
00459 io64[1] ^= p->u_store.a64[1];
00460 io64[2] ^= p->u_store.a64[2];
00461 io64[3] ^= p->u_store.a64[3];
00462 io64[4] ^= p->u_store.a64[4];
00463 io64[5] ^= p->u_store.a64[5];
00464 io64[6] ^= p->u_store.a64[6];
00465 io64[7] ^= p->u_store.a64[7];
00466
00467 io64+=8;
00468 p->store_size = 0;
00469 store(p);
00470 }
00471 inout =(uint8*)io64;
00472 return dkcHC256EncryptNoDestDOE(p,inout,rest);
00473
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590