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 DKC_INLINE DKC_HC256 *WINAPI dkcAllocHC256(BYTE *key,size_t size){
00193 DKC_HC256 *p;
00194 uint32 iv[8];
00195 if(size != sizeof(uint32) * 8){
00196 return NULL;
00197 }
00198
00199 p = dkcAllocate(sizeof(DKC_HC256));
00200 if(NULL==p){
00201 return NULL;
00202 }
00203 DKUTIL_MEMZERO(iv,sizeof(iv));
00204 initialization(p,(uint32 *)key,iv);
00205 return p;
00206 }
00207
00208
00209
00210 DKC_INLINE int WINAPI dkcFreeHC256(DKC_HC256 **p){
00211 return dkcFree(p);
00212 }
00213
00214
00215
00216 DKC_INLINE uint32 dkcHC256Process(DKC_HC256 *p,uint32 u)
00217 {
00218 unsigned long i,i3, i10, i12, i1023;
00219 unsigned long output;
00220
00221 i = p->counter2048 & 0x3ff;
00222 i3 = (i - 3) & 0x3ff;
00223 i10 = (i - 10) & 0x3ff;
00224 i12 = (i - 12) & 0x3ff;
00225 i1023 = (i - 1023) & 0x3ff;
00226
00227 if (p->counter2048 < 1024) {
00228 p->P[i] = p->P[i] + p->P[i10] + g1(p->Q,p->P[i3],p->P[i1023]);
00229 output = h1(p->Q,p->P[i12]) ^ p->P[i];
00230 }
00231 else {
00232 p->Q[i] = p->Q[i] + p->Q[i10] + g2(p->P,p->Q[i3],p->Q[i1023]);
00233 output = h2(p->P,p->Q[i12]) ^ p->Q[i];
00234
00235 }
00236 p->counter2048 = (p->counter2048+1) & 0x7ff;
00237 return (output);
00238 }
00239
00240
00241 static DKC_INLINE void step_A(DKC_HC256 *p,uint32 u,uint32 v,
00242 uint32 a,uint32 b,uint32 c,uint32 d,uint32 *m)
00243 {
00244 uint32 tem0,tem1,tem2,tem3;
00245 tem0 = rotr((v),23);
00246 tem1 = rotr((c),10);
00247 tem2 = ((v) ^ (c)) & 0x3ff;
00248 (u) += (b)+(tem0^tem1) + p->Q[tem2];
00249 (a) = (u);
00250 tem3 = h1(p->P,d);
00251
00252 (*m) ^= tem3 ^ (u) ;
00253 }
00254 static DKC_INLINE step_B(DKC_HC256 *p,uint32 u,uint32 v,
00255 uint32 a,uint32 b,uint32 c,uint32 d,uint32 *m){
00256 uint32 tem0,tem1,tem2,tem3;
00257 tem0 = rotr((v),23);
00258 tem1 = rotr((c),10);
00259 tem2 = ((v) ^ (c)) & 0x3ff;
00260 (u) += (b)+(tem0^tem1)+p->P[tem2];
00261 (a) = (u);
00262 tem3 = h2(p->P,d);
00263
00264 (*m) ^= tem3 ^ (u) ;
00265 }
00266
00267
00268 static void encrypt(DKC_HC256 *p,uint32 data[])
00269 {
00270 uint32 cc,dd,counter2048 = p->counter2048;
00271 uint32 *P = p->P,*Q = p->Q,*X =p->X, *Y = p->Y;
00272
00273 cc = counter2048 & 0x3ff;
00274 dd = (cc+16) & 0x3ff;
00275
00276 if (counter2048 < 1024)
00277 {
00278 counter2048 = (counter2048 + 16) & 0x7ff;
00279 step_A(p,P[cc+0], P[cc+1], X[0], X[6], X[13],X[4], &data[0]);
00280 step_A(p,P[cc+1], P[cc+2], X[1], X[7], X[14],X[5], &data[1]);
00281 step_A(p,P[cc+2], P[cc+3], X[2], X[8], X[15],X[6], &data[2]);
00282 step_A(p,P[cc+3], P[cc+4], X[3], X[9], X[0], X[7], &data[3]);
00283 step_A(p,P[cc+4], P[cc+5], X[4], X[10],X[1], X[8], &data[4]);
00284 step_A(p,P[cc+5], P[cc+6], X[5], X[11],X[2], X[9], &data[5]);
00285 step_A(p,P[cc+6], P[cc+7], X[6], X[12],X[3], X[10],&data[6]);
00286 step_A(p,P[cc+7], P[cc+8], X[7], X[13],X[4], X[11],&data[7]);
00287 step_A(p,P[cc+8], P[cc+9], X[8], X[14],X[5], X[12],&data[8]);
00288 step_A(p,P[cc+9], P[cc+10],X[9], X[15],X[6], X[13],&data[9]);
00289 step_A(p,P[cc+10],P[cc+11],X[10],X[0], X[7], X[14],&data[10]);
00290 step_A(p,P[cc+11],P[cc+12],X[11],X[1], X[8], X[15],&data[11]);
00291 step_A(p,P[cc+12],P[cc+13],X[12],X[2], X[9], X[0], &data[12]);
00292 step_A(p,P[cc+13],P[cc+14],X[13],X[3], X[10],X[1], &data[13]);
00293 step_A(p,P[cc+14],P[cc+15],X[14],X[4], X[11],X[2], &data[14]);
00294 step_A(p,P[cc+15],P[dd+0], X[15],X[5], X[12],X[3], &data[15]);
00295 }
00296 else
00297 {
00298 counter2048 = (counter2048 + 16) & 0x7ff;
00299 step_B(p,Q[cc+0], Q[cc+1], Y[0], Y[6], Y[13],Y[4], &data[0]);
00300 step_B(p,Q[cc+1], Q[cc+2], Y[1], Y[7], Y[14],Y[5], &data[1]);
00301 step_B(p,Q[cc+2], Q[cc+3], Y[2], Y[8], Y[15],Y[6], &data[2]);
00302 step_B(p,Q[cc+3], Q[cc+4], Y[3], Y[9], Y[0], Y[7], &data[3]);
00303 step_B(p,Q[cc+4], Q[cc+5], Y[4], Y[10],Y[1], Y[8], &data[4]);
00304 step_B(p,Q[cc+5], Q[cc+6], Y[5], Y[11],Y[2], Y[9], &data[5]);
00305 step_B(p,Q[cc+6], Q[cc+7], Y[6], Y[12],Y[3], Y[10],&data[6]);
00306 step_B(p,Q[cc+7], Q[cc+8], Y[7], Y[13],Y[4], Y[11],&data[7]);
00307 step_B(p,Q[cc+8], Q[cc+9], Y[8], Y[14],Y[5], Y[12],&data[8]);
00308 step_B(p,Q[cc+9], Q[cc+10],Y[9], Y[15],Y[6], Y[13],&data[9]);
00309 step_B(p,Q[cc+10],Q[cc+11],Y[10],Y[0], Y[7], Y[14],&data[10]);
00310 step_B(p,Q[cc+11],Q[cc+12],Y[11],Y[1], Y[8], Y[15],&data[11]);
00311 step_B(p,Q[cc+12],Q[cc+13],Y[12],Y[2], Y[9], Y[0], &data[12]);
00312 step_B(p,Q[cc+13],Q[cc+14],Y[13],Y[3], Y[10],Y[1], &data[13]);
00313 step_B(p,Q[cc+14],Q[cc+15],Y[14],Y[4], Y[11],Y[2], &data[14]);
00314 step_B(p,Q[cc+15],Q[dd+0], Y[15],Y[5], Y[12],Y[3], &data[15]);
00315 }
00316
00317 p->counter2048 = counter2048;
00318 }
00319
00320 DKC_INLINE int WINAPI dkcHC256EncryptBlock512NoDestDOE(DKC_HC256 *p,BYTE *dest,size_t size){
00321 dkcmNOT_ASSERT(NULL==p || NULL==dest);
00322 if(size != 512){
00323 return edk_ArgumentException;
00324 }
00325 encrypt(p,(uint32 *)dest);
00326 return edk_SUCCEEDED;
00327 }
00328
00329 DKC_INLINE int WINAPI dkcHC256EncryptBlock512DOE(DKC_HC256 *p,BYTE *dest,size_t dsize,const BYTE *src,size_t ssize)
00330 {
00331 dkcmNOT_ASSERT(NULL==p || NULL==dest || NULL==src);
00332 if(ssize != 512 || dsize < 512){
00333 return edk_ArgumentException;
00334 }
00335 memcpy(dest,src,ssize);
00336 return dkcHC256EncryptBlock512NoDestDOE(p,dest,ssize);
00337 }
00338
00339
00340