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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "wizard/studio.h"
00042 #include "wizard/exception.h"
00043 #include "wizard/exception-private.h"
00044 #include "wizard/memory_.h"
00045 #include "wizard/md5.h"
00046
00047
00048
00049
00050 #define MD5Blocksize 64
00051 #define MD5Digestsize 16
00052
00053
00054
00055
00056 struct _MD5Info
00057 {
00058 unsigned int
00059 digestsize,
00060 blocksize;
00061
00062 StringInfo
00063 *digest,
00064 *message;
00065
00066 unsigned int
00067 *accumulator,
00068 low_order,
00069 high_order;
00070
00071 time_t
00072 timestamp;
00073
00074 size_t
00075 signature;
00076 };
00077
00078
00079
00080
00081 static void
00082 TransformMD5(MD5Info *,unsigned int *);
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 WizardExport MD5Info *AcquireMD5Info(void)
00103 {
00104 MD5Info
00105 *md5_info;
00106
00107 md5_info=(MD5Info *) AcquireAlignedMemory(1,sizeof(*md5_info));
00108 if (md5_info == (MD5Info *) NULL)
00109 ThrowWizardFatalError(HashDomain,MemoryError);
00110 (void) ResetWizardMemory(md5_info,0,sizeof(*md5_info));
00111 md5_info->digestsize=MD5Digestsize;
00112 md5_info->blocksize=MD5Blocksize;
00113 md5_info->digest=AcquireStringInfo(MD5Digestsize);
00114 md5_info->message=AcquireStringInfo(MD5Blocksize);
00115 md5_info->accumulator=(unsigned int *) AcquireQuantumMemory(4UL,
00116 sizeof(*md5_info->accumulator));
00117 if (md5_info->accumulator == (unsigned int *) NULL)
00118 ThrowWizardFatalError(HashDomain,MemoryError);
00119 md5_info->timestamp=time((time_t *) NULL);
00120 md5_info->signature=WizardSignature;
00121 return(md5_info);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 WizardExport MD5Info *DestroyMD5Info(MD5Info *md5_info)
00147 {
00148 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00149 assert(md5_info != (MD5Info *) NULL);
00150 assert(md5_info->signature == WizardSignature);
00151 if (md5_info->accumulator != (unsigned int *) NULL)
00152 md5_info->accumulator=(unsigned int *)
00153 RelinquishWizardMemory(md5_info->accumulator);
00154 if (md5_info->message != (StringInfo *) NULL)
00155 md5_info->message=DestroyStringInfo(md5_info->message);
00156 if (md5_info->digest != (StringInfo *) NULL)
00157 md5_info->digest=DestroyStringInfo(md5_info->digest);
00158 md5_info->signature=(~WizardSignature);
00159 md5_info=(MD5Info *) RelinquishWizardMemory(md5_info);
00160 return(md5_info);
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 WizardExport void FinalizeMD5(MD5Info *md5_info)
00187 {
00188 ssize_t
00189 number_bytes;
00190
00191 register ssize_t
00192 i;
00193
00194 register unsigned char
00195 *p;
00196
00197 StringInfo
00198 *pad;
00199
00200 unsigned char
00201 *datum;
00202
00203 unsigned int
00204 message[16];
00205
00206
00207
00208
00209 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00210 assert(md5_info != (MD5Info *) NULL);
00211 assert(md5_info->signature == WizardSignature);
00212 message[14]=md5_info->low_order;
00213 message[15]=md5_info->high_order;
00214
00215
00216
00217 number_bytes=(ssize_t) ((md5_info->low_order >> 3) & 0x3F);
00218
00219
00220
00221 pad=AcquireStringInfo((size_t) ((number_bytes < 56) ? (56-number_bytes) :
00222 (120-number_bytes)));
00223 datum=GetStringInfoDatum(pad);
00224 datum[0]=(unsigned char) 0x80;
00225 for (i=1; i < (ssize_t) GetStringInfoLength(pad); i++)
00226 datum[i]=(unsigned char) 0x0;
00227 UpdateMD5(md5_info,pad);
00228 pad=DestroyStringInfo(pad);
00229
00230
00231
00232 p=GetStringInfoDatum(md5_info->message);
00233 for (i=0; i < 14; i++)
00234 {
00235 message[i]=(unsigned int) (*p++);
00236 message[i]|=((unsigned int) (*p++)) << 8;
00237 message[i]|=((unsigned int) (*p++)) << 16;
00238 message[i]|=((unsigned int) (*p++)) << 24;
00239 }
00240 TransformMD5(md5_info,message);
00241
00242
00243
00244 p=GetStringInfoDatum(md5_info->digest);
00245 for (i=0; i < (MD5Digestsize/4); i++)
00246 {
00247 *p++=(unsigned char) (md5_info->accumulator[i] & 0xff);
00248 *p++=(unsigned char) ((md5_info->accumulator[i] >> 8) & 0xff);
00249 *p++=(unsigned char) ((md5_info->accumulator[i] >> 16) & 0xff);
00250 *p++=(unsigned char) ((md5_info->accumulator[i] >> 24) & 0xff);
00251 }
00252
00253
00254
00255 number_bytes=0;
00256 (void) ResetWizardMemory(message,0,sizeof(message));
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 WizardExport unsigned int GetMD5Blocksize(const MD5Info *md5_info)
00282 {
00283 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00284 WizardAssert(CipherDomain,md5_info != (MD5Info *) NULL);
00285 WizardAssert(CipherDomain,md5_info->signature == WizardSignature);
00286 return(md5_info->blocksize);
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 WizardExport const StringInfo *GetMD5Digest(const MD5Info *md5_info)
00312 {
00313 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00314 WizardAssert(HashDomain,md5_info != (MD5Info *) NULL);
00315 WizardAssert(HashDomain,md5_info->signature == WizardSignature);
00316 return(md5_info->digest);
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 WizardExport unsigned int GetMD5Digestsize(const MD5Info *md5_info)
00342 {
00343 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00344 WizardAssert(CipherDomain,md5_info != (MD5Info *) NULL);
00345 WizardAssert(CipherDomain,md5_info->signature == WizardSignature);
00346 return(md5_info->digestsize);
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 WizardExport void InitializeMD5(MD5Info *md5_info)
00373 {
00374 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00375 assert(md5_info != (MD5Info *) NULL);
00376 assert(md5_info->signature == WizardSignature);
00377 md5_info->low_order=(unsigned int) 0;
00378 md5_info->high_order=(unsigned int) 0;
00379
00380
00381
00382 md5_info->accumulator[0]=(unsigned int) 0x67452301;
00383 md5_info->accumulator[1]=(unsigned int) 0xefcdab89;
00384 md5_info->accumulator[2]=(unsigned int) 0x98badcfe;
00385 md5_info->accumulator[3]=(unsigned int) 0x10325476;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 static inline unsigned int F(unsigned int x,unsigned int y,unsigned int z)
00413 {
00414 return((x & y) | (~x & z));
00415 }
00416
00417 static inline unsigned int G(unsigned int x,unsigned int y,unsigned int z)
00418 {
00419 return((x & z) | (y & ~z));
00420 }
00421
00422 static inline unsigned int H(unsigned int x,unsigned int y,unsigned int z)
00423 {
00424 return(x ^ y ^ z);
00425 }
00426
00427 static inline unsigned int I(unsigned int x,unsigned int y,unsigned int z)
00428 {
00429 return(y ^ (x | ~z));
00430 }
00431
00432 static inline unsigned int Trunc32(unsigned int x)
00433 {
00434 return((unsigned int) (x & 0xffffffffUL));
00435 }
00436
00437 static inline unsigned int RotateLeft(unsigned int x,unsigned int n)
00438 {
00439 return(Trunc32((x << n) | (x >> (32-n))));
00440 }
00441
00442 static void TransformMD5(MD5Info *md5_info,unsigned int *message)
00443 {
00444 register ssize_t
00445 i;
00446
00447 register unsigned int
00448 j;
00449
00450 register const unsigned int
00451 *p;
00452
00453 static const unsigned int
00454 K[64]=
00455 {
00456 0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU, 0xf57c0fafU,
00457 0x4787c62aU, 0xa8304613U, 0xfd469501U, 0x698098d8U, 0x8b44f7afU,
00458 0xffff5bb1U, 0x895cd7beU, 0x6b901122U, 0xfd987193U, 0xa679438eU,
00459 0x49b40821U, 0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU,
00460 0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U, 0x21e1cde6U,
00461 0xc33707d6U, 0xf4d50d87U, 0x455a14edU, 0xa9e3e905U, 0xfcefa3f8U,
00462 0x676f02d9U, 0x8d2a4c8aU, 0xfffa3942U, 0x8771f681U, 0x6d9d6122U,
00463 0xfde5380cU, 0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U,
00464 0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U, 0xd9d4d039U,
00465 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U, 0xf4292244U, 0x432aff97U,
00466 0xab9423a7U, 0xfc93a039U, 0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU,
00467 0x85845dd1U, 0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U,
00468 0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U,
00469 };
00470
00471 unsigned int
00472 A,
00473 B,
00474 C,
00475 D;
00476
00477
00478
00479 A=md5_info->accumulator[0];
00480 B=md5_info->accumulator[1];
00481 C=md5_info->accumulator[2];
00482 D=md5_info->accumulator[3];
00483
00484
00485
00486 p=K;
00487 j=0;
00488 for (i=0; i < 4; i++)
00489 {
00490 A+=F(B,C,D)+message[j & 0x0f]+(*p++);
00491 A=RotateLeft(A,7)+B;
00492 j++;
00493 D+=F(A,B,C)+message[j & 0x0f]+(*p++);
00494 D=RotateLeft(D,12)+A;
00495 j++;
00496 C+=F(D,A,B)+message[j & 0x0f]+(*p++);
00497 C=RotateLeft(C,17)+D;
00498 j++;
00499 B+=F(C,D,A)+message[j & 0x0f]+(*p++);
00500 B=RotateLeft(B,22)+C;
00501 j++;
00502 }
00503
00504
00505
00506 j=1;
00507 for (i=0; i < 4; i++)
00508 {
00509 A+=G(B,C,D)+message[j & 0x0f]+(*p++);
00510 A=RotateLeft(A,5)+B;
00511 j+=5;
00512 D+=G(A,B,C)+message[j & 0x0f]+(*p++);
00513 D=RotateLeft(D,9)+A;
00514 j+=5;
00515 C+=G(D,A,B)+message[j & 0x0f]+(*p++);
00516 C=RotateLeft(C,14)+D;
00517 j+=5;
00518 B+=G(C,D,A)+message[j & 0x0f]+(*p++);
00519 B=RotateLeft(B,20)+C;
00520 j+=5;
00521 }
00522
00523
00524
00525 j=5;
00526 for (i=0; i < 4; i++)
00527 {
00528 A+=H(B,C,D)+message[j & 0x0f]+(*p++);
00529 A=RotateLeft(A,4)+B;
00530 j+=3;
00531 D+=H(A,B,C)+message[j & 0x0f]+(*p++);
00532 D=RotateLeft(D,11)+A;
00533 j+=3;
00534 C+=H(D,A,B)+message[j & 0x0f]+(*p++);
00535 C=RotateLeft(C,16)+D;
00536 j+=3;
00537 B+=H(C,D,A)+message[j & 0x0f]+(*p++);
00538 B=RotateLeft(B,23)+C;
00539 j+=3;
00540 }
00541
00542
00543
00544 j=0;
00545 for (i=0; i < 4; i++)
00546 {
00547 A+=I(B,C,D)+message[j & 0x0f]+(*p++);
00548 A=RotateLeft(A,6)+B;
00549 j+=7;
00550 D+=I(A,B,C)+message[j & 0x0f]+(*p++);
00551 D=RotateLeft(D,10)+A;
00552 j+=7;
00553 C+=I(D,A,B)+message[j & 0x0f]+(*p++);
00554 C=RotateLeft(C,15)+D;
00555 j+=7;
00556 B+=I(C,D,A)+message[j & 0x0f]+(*p++);
00557 B=RotateLeft(B,21)+C;
00558 j+=7;
00559 }
00560
00561
00562
00563 md5_info->accumulator[0]=Trunc32(md5_info->accumulator[0]+A);
00564 md5_info->accumulator[1]=Trunc32(md5_info->accumulator[1]+B);
00565 md5_info->accumulator[2]=Trunc32(md5_info->accumulator[2]+C);
00566 md5_info->accumulator[3]=Trunc32(md5_info->accumulator[3]+D);
00567
00568
00569
00570 A=0;
00571 B=0;
00572 C=0;
00573 D=0;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 WizardExport void UpdateMD5(MD5Info *md5_info,const StringInfo *message)
00599 {
00600 register unsigned char
00601 *p;
00602
00603 register ssize_t
00604 i,
00605 j;
00606
00607 unsigned char
00608 *datum;
00609
00610 unsigned int
00611 buffer[16],
00612 number_bits,
00613 number_bytes;
00614
00615
00616
00617
00618 assert(md5_info != (MD5Info *) NULL);
00619 assert(md5_info->signature == WizardSignature);
00620 number_bytes=(unsigned int) ((md5_info->low_order >> 3) & 0x3F);
00621 number_bits=(unsigned int) (md5_info->low_order+(GetStringInfoLength(message)
00622 << 3));
00623 if ((number_bits & 0xffffffff) < md5_info->low_order)
00624 md5_info->high_order++;
00625 md5_info->low_order+=(unsigned int) (GetStringInfoLength(message) << 3);
00626 md5_info->high_order+=(unsigned int) (GetStringInfoLength(message) >> 29);
00627 datum=GetStringInfoDatum(message);
00628 for (i=0; i < (ssize_t) GetStringInfoLength(message); i++)
00629 {
00630 p=GetStringInfoDatum(md5_info->message);
00631 p[number_bytes++]=datum[i];
00632 if (number_bytes != 0x40)
00633 continue;
00634 for (j=0; j < 16; j++)
00635 {
00636 buffer[j]=(unsigned int) (*p++);
00637 buffer[j]|=((unsigned int) (*p++)) << 8;
00638 buffer[j]|=((unsigned int) (*p++)) << 16;
00639 buffer[j]|=((unsigned int) (*p++)) << 24;
00640 }
00641 TransformMD5(md5_info,buffer);
00642 number_bytes=0;
00643 }
00644
00645
00646
00647 number_bits=0;
00648 number_bytes=0;
00649 (void) ResetWizardMemory(buffer,0,sizeof(buffer));
00650 }