00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00055 #include <string.h>
00056
00057 #include "ipsec/md5.h"
00058 #include "ipsec/debug.h"
00059
00060 unsigned char *MD5(const unsigned char *d, unsigned long n, unsigned char *md)
00061 {
00062 MD5_CTX c;
00063 static unsigned char m[MD5_DIGEST_LENGTH];
00064
00065 if (md == NULL) md=m;
00066 MD5_Init(&c);
00067 MD5_Update(&c,d,n);
00068 MD5_Final(md,&c);
00069 memset(&c,0,sizeof(c));
00070 return(md);
00071 }
00072
00073
00074 #define INIT_DATA_A (unsigned long)0x67452301L
00075 #define INIT_DATA_B (unsigned long)0xefcdab89L
00076 #define INIT_DATA_C (unsigned long)0x98badcfeL
00077 #define INIT_DATA_D (unsigned long)0x10325476L
00078
00079 void MD5_Init(MD5_CTX *c)
00080 {
00081 c->A=INIT_DATA_A;
00082 c->B=INIT_DATA_B;
00083 c->C=INIT_DATA_C;
00084 c->D=INIT_DATA_D;
00085 c->Nl=0;
00086 c->Nh=0;
00087 c->num=0;
00088 }
00089
00090
00091 void md5_block_host_order (MD5_CTX *c, const void *p,int num);
00092 void md5_block_data_order (MD5_CTX *c, const void *p,int num);
00093
00094
00095
00096
00097
00098 #undef ROTATE
00099
00100
00101 #ifdef __C166__
00102 #include <intrins.h>
00103 #define ROTATE(a,n) _lrol_(a,n)
00104 #endif
00105
00106
00107 #ifdef ROTATE
00108
00109 #define REVERSE_FETCH32(a,l) ( \
00110 l=*(const MD5_LONG *)(a), \
00111 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24))) \
00112 )
00113 #endif
00114
00115
00116 #define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
00117 l|=(((unsigned long)(*((c)++)))<< 8), \
00118 l|=(((unsigned long)(*((c)++)))<<16), \
00119 l|=(((unsigned long)(*((c)++)))<<24), \
00120 l)
00121 #define HOST_p_c2l(c,l,n) { \
00122 switch (n) { \
00123 case 0: l =((unsigned long)(*((c)++))); \
00124 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
00125 case 2: l|=((unsigned long)(*((c)++)))<<16; \
00126 case 3: l|=((unsigned long)(*((c)++)))<<24; \
00127 } }
00128 #define HOST_p_c2l_p(c,l,sc,len) { \
00129 switch (sc) { \
00130 case 0: l =((unsigned long)(*((c)++))); \
00131 if (--len == 0) break; \
00132 case 1: l|=((unsigned long)(*((c)++)))<< 8; \
00133 if (--len == 0) break; \
00134 case 2: l|=((unsigned long)(*((c)++)))<<16; \
00135 } }
00136
00137 #define HOST_c2l_p(c,l,n) { \
00138 l=0; (c)+=n; \
00139 switch (n) { \
00140 case 3: l =((unsigned long)(*(--(c))))<<16; \
00141 case 2: l|=((unsigned long)(*(--(c))))<< 8; \
00142 case 1: l|=((unsigned long)(*(--(c)))); \
00143 } }
00144 #define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
00145 *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
00146 *((c)++)=(unsigned char)(((l)>>16)&0xff), \
00147 *((c)++)=(unsigned char)(((l)>>24)&0xff), \
00148 l)
00149
00150
00151
00152
00153
00154
00155 void MD5_Update (MD5_CTX *c, const void *data_, unsigned long len)
00156 {
00157 const unsigned char *data=data_;
00158 MD5_LONG * p;
00159 unsigned long l;
00160 int sw,sc,ew,ec;
00161
00162 if (len==0) return;
00163
00164 l=(c->Nl+(len<<3))&0xffffffffL;
00165
00166
00167 if (l < c->Nl)
00168 c->Nh++;
00169 c->Nh+=(len>>29);
00170 c->Nl=l;
00171
00172 if (c->num != 0)
00173 {
00174 p=c->data;
00175 sw=c->num>>2;
00176 sc=c->num&0x03;
00177
00178 if ((c->num+len) >= MD5_CBLOCK)
00179 {
00180 l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
00181 for (; sw<MD5_LBLOCK; sw++)
00182 {
00183 HOST_c2l(data,l); p[sw]=l;
00184 }
00185 md5_block_host_order (c,p,1);
00186 len-=(MD5_CBLOCK-c->num);
00187 c->num=0;
00188
00189 }
00190 else
00191 {
00192 c->num+=len;
00193 if ((sc+len) < 4)
00194 {
00195 l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
00196 }
00197 else
00198 {
00199 ew=(c->num>>2);
00200 ec=(c->num&0x03);
00201 l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
00202 for (; sw < ew; sw++)
00203 {
00204 HOST_c2l(data,l); p[sw]=l;
00205 }
00206 if (ec)
00207 {
00208 HOST_c2l_p(data,l,ec); p[sw]=l;
00209 }
00210 }
00211 return;
00212 }
00213 }
00214
00215 sw=(int) (len/MD5_CBLOCK);
00216 if (sw > 0)
00217 {
00218 if ((((unsigned long)data)%4) == 0)
00219 {
00220
00221 md5_block_host_order (c,(MD5_LONG *)data,sw);
00222 sw*=MD5_CBLOCK;
00223 data+=sw;
00224 len-=sw;
00225 }
00226 else
00227 {
00228 md5_block_data_order(c,data,sw);
00229 sw*=MD5_CBLOCK;
00230 data+=sw;
00231 len-=sw;
00232 }
00233 }
00234
00235 if (len!=0)
00236 {
00237 p = c->data;
00238 c->num = (int) len;
00239 ew=(int) (len>>2);
00240 ec=(int) (len&0x03);
00241 for (; ew; ew--,p++)
00242 {
00243 HOST_c2l(data,l); *p=l;
00244 }
00245 HOST_c2l_p(data,l,ec);
00246 *p=l;
00247 }
00248 }
00249
00250
00251 void MD5_Transform (MD5_CTX *c, const unsigned char *data)
00252 {
00253 if ((((unsigned long)data)%4) == 0)
00254
00255 md5_block_host_order (c,(MD5_LONG *)data,1);
00256 else
00257 md5_block_data_order (c,data,1);
00258 }
00259
00260
00261 void MD5_Final (unsigned char *md, MD5_CTX *c)
00262 {
00263 MD5_LONG *p;
00264 unsigned long l;
00265 int i,j;
00266 static const unsigned char end[4]={0x80,0x00,0x00,0x00};
00267 const unsigned char *cp=end;
00268
00269
00270 p=c->data;
00271 i=c->num>>2;
00272 j=c->num&0x03;
00273
00274 l = (j==0) ? 0 : p[i];
00275
00276 HOST_p_c2l(cp,l,j); p[i++]=l;
00277
00278 if (i>(MD5_LBLOCK-2))
00279 {
00280 if (i<MD5_LBLOCK) p[i]=0;
00281 md5_block_host_order (c,p,1);
00282 i=0;
00283 }
00284 for (; i<(MD5_LBLOCK-2); i++)
00285 p[i]=0;
00286
00287 p[MD5_LBLOCK-2]=c->Nl;
00288 p[MD5_LBLOCK-1]=c->Nh;
00289 md5_block_host_order (c,p,1);
00290
00291
00292
00293 do {
00294 unsigned long ll;
00295 ll=(c)->A; HOST_l2c(ll,(md));
00296 ll=(c)->B; HOST_l2c(ll,(md));
00297 ll=(c)->C; HOST_l2c(ll,(md));
00298 ll=(c)->D; HOST_l2c(ll,(md));
00299 } while (0);
00300
00301
00302 c->num=0;
00303
00304
00305
00306
00307 }
00308
00309
00310 #define F(b,c,d) ((((c) ^ (d)) & (b)) ^ (d))
00311 #define G(b,c,d) ((((b) ^ (c)) & (d)) ^ (c))
00312 #define H(b,c,d) ((b) ^ (c) ^ (d))
00313 #define I(b,c,d) (((~(d)) | (b)) ^ (c))
00314
00315 #define R0(a,b,c,d,k,s,t) { \
00316 a+=((k)+(t)+F((b),(c),(d))); \
00317 a=ROTATE(a,s); \
00318 a+=b; };\
00319
00320 #define R1(a,b,c,d,k,s,t) { \
00321 a+=((k)+(t)+G((b),(c),(d))); \
00322 a=ROTATE(a,s); \
00323 a+=b; };
00324
00325 #define R2(a,b,c,d,k,s,t) { \
00326 a+=((k)+(t)+H((b),(c),(d))); \
00327 a=ROTATE(a,s); \
00328 a+=b; };
00329
00330 #define R3(a,b,c,d,k,s,t) { \
00331 a+=((k)+(t)+I((b),(c),(d))); \
00332 a=ROTATE(a,s); \
00333 a+=b; };
00334
00335
00336
00337 void md5_block_host_order (MD5_CTX *c, const void *data, int num)
00338 {
00339 const MD5_LONG *X=data;
00340 unsigned long A,B,C,D;
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 A=c->A;
00357 B=c->B;
00358 C=c->C;
00359 D=c->D;
00360
00361 for (;num--;X+=MD5_LBLOCK)
00362 {
00363
00364 R0(A,B,C,D,X[ 0], 7,0xd76aa478L);
00365 R0(D,A,B,C,X[ 1],12,0xe8c7b756L);
00366 R0(C,D,A,B,X[ 2],17,0x242070dbL);
00367 R0(B,C,D,A,X[ 3],22,0xc1bdceeeL);
00368 R0(A,B,C,D,X[ 4], 7,0xf57c0fafL);
00369 R0(D,A,B,C,X[ 5],12,0x4787c62aL);
00370 R0(C,D,A,B,X[ 6],17,0xa8304613L);
00371 R0(B,C,D,A,X[ 7],22,0xfd469501L);
00372 R0(A,B,C,D,X[ 8], 7,0x698098d8L);
00373 R0(D,A,B,C,X[ 9],12,0x8b44f7afL);
00374 R0(C,D,A,B,X[10],17,0xffff5bb1L);
00375 R0(B,C,D,A,X[11],22,0x895cd7beL);
00376 R0(A,B,C,D,X[12], 7,0x6b901122L);
00377 R0(D,A,B,C,X[13],12,0xfd987193L);
00378 R0(C,D,A,B,X[14],17,0xa679438eL);
00379 R0(B,C,D,A,X[15],22,0x49b40821L);
00380
00381 R1(A,B,C,D,X[ 1], 5,0xf61e2562L);
00382 R1(D,A,B,C,X[ 6], 9,0xc040b340L);
00383 R1(C,D,A,B,X[11],14,0x265e5a51L);
00384 R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL);
00385 R1(A,B,C,D,X[ 5], 5,0xd62f105dL);
00386 R1(D,A,B,C,X[10], 9,0x02441453L);
00387 R1(C,D,A,B,X[15],14,0xd8a1e681L);
00388 R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L);
00389 R1(A,B,C,D,X[ 9], 5,0x21e1cde6L);
00390 R1(D,A,B,C,X[14], 9,0xc33707d6L);
00391 R1(C,D,A,B,X[ 3],14,0xf4d50d87L);
00392 R1(B,C,D,A,X[ 8],20,0x455a14edL);
00393 R1(A,B,C,D,X[13], 5,0xa9e3e905L);
00394 R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L);
00395 R1(C,D,A,B,X[ 7],14,0x676f02d9L);
00396 R1(B,C,D,A,X[12],20,0x8d2a4c8aL);
00397
00398 R2(A,B,C,D,X[ 5], 4,0xfffa3942L);
00399 R2(D,A,B,C,X[ 8],11,0x8771f681L);
00400 R2(C,D,A,B,X[11],16,0x6d9d6122L);
00401 R2(B,C,D,A,X[14],23,0xfde5380cL);
00402 R2(A,B,C,D,X[ 1], 4,0xa4beea44L);
00403 R2(D,A,B,C,X[ 4],11,0x4bdecfa9L);
00404 R2(C,D,A,B,X[ 7],16,0xf6bb4b60L);
00405 R2(B,C,D,A,X[10],23,0xbebfbc70L);
00406 R2(A,B,C,D,X[13], 4,0x289b7ec6L);
00407 R2(D,A,B,C,X[ 0],11,0xeaa127faL);
00408 R2(C,D,A,B,X[ 3],16,0xd4ef3085L);
00409 R2(B,C,D,A,X[ 6],23,0x04881d05L);
00410 R2(A,B,C,D,X[ 9], 4,0xd9d4d039L);
00411 R2(D,A,B,C,X[12],11,0xe6db99e5L);
00412 R2(C,D,A,B,X[15],16,0x1fa27cf8L);
00413 R2(B,C,D,A,X[ 2],23,0xc4ac5665L);
00414
00415 R3(A,B,C,D,X[ 0], 6,0xf4292244L);
00416 R3(D,A,B,C,X[ 7],10,0x432aff97L);
00417 R3(C,D,A,B,X[14],15,0xab9423a7L);
00418 R3(B,C,D,A,X[ 5],21,0xfc93a039L);
00419 R3(A,B,C,D,X[12], 6,0x655b59c3L);
00420 R3(D,A,B,C,X[ 3],10,0x8f0ccc92L);
00421 R3(C,D,A,B,X[10],15,0xffeff47dL);
00422 R3(B,C,D,A,X[ 1],21,0x85845dd1L);
00423 R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL);
00424 R3(D,A,B,C,X[15],10,0xfe2ce6e0L);
00425 R3(C,D,A,B,X[ 6],15,0xa3014314L);
00426 R3(B,C,D,A,X[13],21,0x4e0811a1L);
00427 R3(A,B,C,D,X[ 4], 6,0xf7537e82L);
00428 R3(D,A,B,C,X[11],10,0xbd3af235L);
00429 R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL);
00430 R3(B,C,D,A,X[ 9],21,0xeb86d391L);
00431
00432 A = c->A += A;
00433 B = c->B += B;
00434 C = c->C += C;
00435 D = c->D += D;
00436 }
00437 }
00438
00439
00440 void md5_block_data_order (MD5_CTX *c, const void *data_, int num)
00441 {
00442 const unsigned char *data=data_;
00443 unsigned long A,B,C,D,l;
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 unsigned long XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
00459 XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
00460 #define X(i) XX##i
00461
00462 A=c->A;
00463 B=c->B;
00464 C=c->C;
00465 D=c->D;
00466
00467 for (;num--;)
00468 {
00469 HOST_c2l(data,l); X( 0)=l; HOST_c2l(data,l); X( 1)=l;
00470
00471 R0(A,B,C,D,X( 0), 7,0xd76aa478L); HOST_c2l(data,l); X( 2)=l;
00472 R0(D,A,B,C,X( 1),12,0xe8c7b756L); HOST_c2l(data,l); X( 3)=l;
00473 R0(C,D,A,B,X( 2),17,0x242070dbL); HOST_c2l(data,l); X( 4)=l;
00474 R0(B,C,D,A,X( 3),22,0xc1bdceeeL); HOST_c2l(data,l); X( 5)=l;
00475 R0(A,B,C,D,X( 4), 7,0xf57c0fafL); HOST_c2l(data,l); X( 6)=l;
00476 R0(D,A,B,C,X( 5),12,0x4787c62aL); HOST_c2l(data,l); X( 7)=l;
00477 R0(C,D,A,B,X( 6),17,0xa8304613L); HOST_c2l(data,l); X( 8)=l;
00478 R0(B,C,D,A,X( 7),22,0xfd469501L); HOST_c2l(data,l); X( 9)=l;
00479 R0(A,B,C,D,X( 8), 7,0x698098d8L); HOST_c2l(data,l); X(10)=l;
00480 R0(D,A,B,C,X( 9),12,0x8b44f7afL); HOST_c2l(data,l); X(11)=l;
00481 R0(C,D,A,B,X(10),17,0xffff5bb1L); HOST_c2l(data,l); X(12)=l;
00482 R0(B,C,D,A,X(11),22,0x895cd7beL); HOST_c2l(data,l); X(13)=l;
00483 R0(A,B,C,D,X(12), 7,0x6b901122L); HOST_c2l(data,l); X(14)=l;
00484 R0(D,A,B,C,X(13),12,0xfd987193L); HOST_c2l(data,l); X(15)=l;
00485 R0(C,D,A,B,X(14),17,0xa679438eL);
00486 R0(B,C,D,A,X(15),22,0x49b40821L);
00487
00488 R1(A,B,C,D,X( 1), 5,0xf61e2562L);
00489 R1(D,A,B,C,X( 6), 9,0xc040b340L);
00490 R1(C,D,A,B,X(11),14,0x265e5a51L);
00491 R1(B,C,D,A,X( 0),20,0xe9b6c7aaL);
00492 R1(A,B,C,D,X( 5), 5,0xd62f105dL);
00493 R1(D,A,B,C,X(10), 9,0x02441453L);
00494 R1(C,D,A,B,X(15),14,0xd8a1e681L);
00495 R1(B,C,D,A,X( 4),20,0xe7d3fbc8L);
00496 R1(A,B,C,D,X( 9), 5,0x21e1cde6L);
00497 R1(D,A,B,C,X(14), 9,0xc33707d6L);
00498 R1(C,D,A,B,X( 3),14,0xf4d50d87L);
00499 R1(B,C,D,A,X( 8),20,0x455a14edL);
00500 R1(A,B,C,D,X(13), 5,0xa9e3e905L);
00501 R1(D,A,B,C,X( 2), 9,0xfcefa3f8L);
00502 R1(C,D,A,B,X( 7),14,0x676f02d9L);
00503 R1(B,C,D,A,X(12),20,0x8d2a4c8aL);
00504
00505 R2(A,B,C,D,X( 5), 4,0xfffa3942L);
00506 R2(D,A,B,C,X( 8),11,0x8771f681L);
00507 R2(C,D,A,B,X(11),16,0x6d9d6122L);
00508 R2(B,C,D,A,X(14),23,0xfde5380cL);
00509 R2(A,B,C,D,X( 1), 4,0xa4beea44L);
00510 R2(D,A,B,C,X( 4),11,0x4bdecfa9L);
00511 R2(C,D,A,B,X( 7),16,0xf6bb4b60L);
00512 R2(B,C,D,A,X(10),23,0xbebfbc70L);
00513 R2(A,B,C,D,X(13), 4,0x289b7ec6L);
00514 R2(D,A,B,C,X( 0),11,0xeaa127faL);
00515 R2(C,D,A,B,X( 3),16,0xd4ef3085L);
00516 R2(B,C,D,A,X( 6),23,0x04881d05L);
00517 R2(A,B,C,D,X( 9), 4,0xd9d4d039L);
00518 R2(D,A,B,C,X(12),11,0xe6db99e5L);
00519 R2(C,D,A,B,X(15),16,0x1fa27cf8L);
00520 R2(B,C,D,A,X( 2),23,0xc4ac5665L);
00521
00522 R3(A,B,C,D,X( 0), 6,0xf4292244L);
00523 R3(D,A,B,C,X( 7),10,0x432aff97L);
00524 R3(C,D,A,B,X(14),15,0xab9423a7L);
00525 R3(B,C,D,A,X( 5),21,0xfc93a039L);
00526 R3(A,B,C,D,X(12), 6,0x655b59c3L);
00527 R3(D,A,B,C,X( 3),10,0x8f0ccc92L);
00528 R3(C,D,A,B,X(10),15,0xffeff47dL);
00529 R3(B,C,D,A,X( 1),21,0x85845dd1L);
00530 R3(A,B,C,D,X( 8), 6,0x6fa87e4fL);
00531 R3(D,A,B,C,X(15),10,0xfe2ce6e0L);
00532 R3(C,D,A,B,X( 6),15,0xa3014314L);
00533 R3(B,C,D,A,X(13),21,0x4e0811a1L);
00534 R3(A,B,C,D,X( 4), 6,0xf7537e82L);
00535 R3(D,A,B,C,X(11),10,0xbd3af235L);
00536 R3(C,D,A,B,X( 2),15,0x2ad7d2bbL);
00537 R3(B,C,D,A,X( 9),21,0xeb86d391L);
00538
00539 A = c->A += A;
00540 B = c->B += B;
00541 C = c->C += C;
00542 D = c->D += D;
00543 }
00544 }
00545
00546
00547
00559 void hmac_md5(unsigned char* text, int text_len, unsigned char* key, int key_len, unsigned char* digest)
00560 {
00561 MD5_CTX context;
00562 unsigned char k_ipad[65];
00563 unsigned char k_opad[65];
00564 unsigned char tk[16];
00565 int i;
00566
00567 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00568 "hmac_md5",
00569 ("text=%p, text_len=%d, key=%p, key_len=%d, digest=%p",
00570 (void *)text, text_len, (void *)key, key_len, (void *)digest)
00571 );
00572
00573
00574
00575 if (key_len > 64) {
00576
00577 MD5_CTX tctx;
00578
00579 MD5_Init(&tctx);
00580 MD5_Update(&tctx, key, key_len);
00581 MD5_Final(tk, &tctx);
00582
00583 key = tk;
00584 key_len = 16;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 memset(k_ipad, '\0', sizeof(k_ipad));
00600 memset(k_opad, '\0', sizeof(k_opad));
00601 memcpy(k_ipad, key, key_len);
00602 memcpy(k_opad, key, key_len);
00603
00604
00605
00606 for (i=0; i<64; i++) {
00607 k_ipad[i] ^= 0x36;
00608 k_opad[i] ^= 0x5c;
00609 }
00610
00611
00612
00613 MD5_Init(&context);
00614
00615 MD5_Update(&context, k_ipad, 64);
00616 MD5_Update(&context, text, text_len);
00617 MD5_Final(digest, &context);
00618
00619
00620
00621 MD5_Init(&context);
00622
00623 MD5_Update(&context, k_opad, 64);
00624 MD5_Update(&context, digest, 16);
00625
00626 MD5_Final(digest, &context);
00627
00628 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "hmac_md5", ("void") );
00629 }
00630