00001
00009 #include "dkcSHA512.h"
00010 #include "dkcStdio.h"
00011
00012 #define SHA512_BUFFER_SIZE (SHA512_BLOCK * 8)
00013
00014
00015
00016
00017 const static QWORD c_qwInitH[SHA512_HASH] = {
00018 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
00019 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
00020 };
00021
00022 const static QWORD c_qwK[SHA512_WORK] = {
00023 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
00024 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
00025 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
00026 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
00027 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
00028 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
00029 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
00030 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
00031 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
00032 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
00033 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
00034 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
00035 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
00036 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
00037 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
00038 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
00039 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
00040 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
00041 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
00042 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
00043 };
00044
00045
00046
00047 #define cpuid __asm __emit 0fh __asm __emit 0a2h
00048
00049 static DKC_INLINE BOOL CheckMMX(void)
00050 {
00051 return dkcIsMMX();
00052 }
00053
00054
00055 static DKC_INLINE DWORD ReverseEndianDWORD(DWORD x) {
00056 return dkcReverseEndian32(x);
00057 }
00058 static DKC_INLINE QWORD ReverseEndianQWORD(QWORD x) {
00059 return dkcReverseEndian64(x);
00060 }
00061 static DKC_INLINE QWORD Rotate(QWORD x, DWORD n) {return (x >> n) | (x << (64 - n));}
00062 static DKC_INLINE QWORD Ch(QWORD x, QWORD y, QWORD z) {return (x & (y ^ z)) ^ z;}
00063 static DKC_INLINE QWORD Maj(QWORD x, QWORD y, QWORD z) {return (x & (y | z)) | (y & z);}
00064 static DKC_INLINE QWORD S0(QWORD x) {return Rotate(x, 28) ^ Rotate(x, 34) ^ Rotate(x, 39);}
00065 static DKC_INLINE QWORD S1(QWORD x) {return Rotate(x, 14) ^ Rotate(x, 18) ^ Rotate(x, 41);}
00066 static DKC_INLINE QWORD s0(QWORD x) {return Rotate(x, 1) ^ Rotate(x, 8) ^ (x >> 7);}
00067 static DKC_INLINE QWORD s1(QWORD x) {return Rotate(x, 19) ^ Rotate(x, 61) ^ (x >> 6);}
00068
00069
00070 static DKC_INLINE void Generate(DKC_SHA512 *);
00071 static DKC_INLINE void MMX_Generate(DKC_SHA512 *);
00072
00073 static DKC_INLINE void Default_Generate(DKC_SHA512 *p){
00074 int i;
00075 QWORD W[SHA512_WORK];
00076 QWORD Hash[SHA512_WORK + SHA512_HASH];
00077 QWORD *pHash = &Hash[SHA512_WORK];
00078 QWORD qwT1, qwT2;
00079 for(i = 0; i < SHA512_HASH; i++) Hash[SHA512_WORK + i] = p->m_qwH[i];
00080 for(i = 0; i < SHA512_BLOCK; i++) W[i] = ReverseEndianQWORD(p->m_aBlock[i]);
00081 for(i = SHA512_BLOCK; i < SHA512_WORK; i++) W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
00082 for(i = 0; i < SHA512_WORK; i++){
00083 pHash--;
00084 qwT1 = pHash[8] + S1(pHash[5]) + Ch(pHash[5], pHash[6], pHash[7]) + c_qwK[i] + W[i];
00085 qwT2 = S0(pHash[1]) + Maj(pHash[1], pHash[2], pHash[3]);
00086 pHash[4] += qwT1;
00087 pHash[0] = qwT1 + qwT2;
00088 }
00089 for(i = 0; i < SHA512_HASH; i++) p->m_qwH[i] += Hash[i];
00090 }
00091
00092 #ifdef _MSC_VER
00093
00094 static DKC_INLINE void MMX_Generate(DKC_SHA512 *p)
00095 {
00096 int i;
00097 QWORD W[SHA512_WORK];
00098 QWORD Hash[SHA512_WORK + SHA512_HASH];
00099 QWORD *pBlock;
00100 for(i = 0; i < SHA512_HASH; i++) Hash[SHA512_WORK + i] = p->m_qwH[i];
00101
00102 pBlock = &(p->m_aBlock[0]);
00103
00104 __asm{
00106
00108 mov esi, pBlock
00109 add esi, SHA512_BLOCK*8
00110 lea edi, W
00111 add edi, SHA512_BLOCK*8
00112 mov ecx, -SHA512_BLOCK
00113 loopR:
00114 mov eax, [esi+ecx*8]
00115 mov ebx, [esi+ecx*8+4]
00116 bswap eax
00117 bswap ebx
00118 mov [edi+ecx*8], ebx
00119 mov [edi+ecx*8+4], eax
00120 inc ecx
00121 jnz loopR
00122
00124
00126 lea esi, W
00127 add esi, SHA512_BLOCK*8
00128 add esi, (SHA512_WORK - SHA512_BLOCK)*8
00129 mov ecx, -(SHA512_WORK - SHA512_BLOCK)
00130 loop0:
00132
00134 movq mm0, [esi+ecx*8-7*8]
00135 nop
00136 movq mm1, [esi+ecx*8-16*8]
00137 movq mm2, mm0
00138 movq mm3, mm0
00139 pxor mm2, mm1
00140 pand mm3, mm1
00141 psrld mm2, 1
00142 paddd mm3, mm2
00143 paddd mm0, mm1
00145
00147 movq mm5, [esi+ecx*8-2*8]
00148 psrld mm3, 31
00149 psllq mm3, 32
00150 movq mm4, mm5
00151 paddd mm0, mm3
00152 psllq mm4, 3
00153 movq mm6, mm4
00154 psllq mm4, (45-3)
00155 pxor mm6, mm4
00156 psrlq mm5, 6
00157 pxor mm6, mm5
00158 psrlq mm5, (19-6)
00160
00162 movq mm1, [esi+ecx*8-15*8]
00163 pxor mm6, mm5
00164 psrlq mm5, (61-19)
00165 movq mm4, mm1
00166 pxor mm6, mm5
00167 psllq mm4, 56
00168 movq mm7, mm4
00169 psllq mm4, (63-56)
00170 pxor mm7, mm4
00171 psrlq mm1, 1
00172 pxor mm7, mm1
00174
00176 movq mm2, mm6
00177 movq mm3, mm6
00178 pxor mm2, mm0
00179 pand mm3, mm0
00180 psrld mm2, 1
00181 paddd mm3, mm2
00182 psrlq mm1, (7-1)
00183 pxor mm7, mm1
00184 psrld mm3, 31
00185 paddd mm0, mm6
00186 psrlq mm1, (8-7)
00187 pxor mm7, mm1
00188 psllq mm3, 32
00190
00192 movq mm4, mm7
00193 paddd mm0, mm3
00194 movq mm5, mm7
00195 pxor mm4, mm0
00196 pand mm5, mm0
00197 psrld mm4, 1
00198 paddd mm5, mm4
00199 paddd mm0, mm7
00200 psrld mm5, 31
00201 psllq mm5, 32
00202 paddd mm0, mm5
00203 movq [esi+ecx*8], mm0
00204 inc ecx
00205 jnz loop0
00206
00207
00209
00211 lea ebx, c_qwK
00212 add ebx, SHA512_WORK*8
00213 lea esi, W
00214 add esi, SHA512_WORK*8
00215 lea edi, Hash
00216 add edi, -8
00217 mov ecx, -SHA512_WORK
00218 mov edx, SHA512_WORK
00219 loop1:
00221
00223 movq mm0, [edi+edx*8+8*8]
00224 nop
00225 movq mm1, [ebx+ecx*8]
00226 movq mm2, mm0
00227 movq mm3, mm0
00228 pxor mm2, mm1
00229 pand mm3, mm1
00230 psrld mm2, 1
00231 paddd mm0, mm1
00232 paddd mm3, mm2
00234
00236 movq mm5, [edi+edx*8+5*8]
00237 psrld mm3, 31
00238 movq mm6, [edi+edx*8+6*8]
00239 psllq mm3, 32
00240 movq mm7, [edi+edx*8+7*8]
00241 paddd mm0, mm3
00243
00245 movq mm1, [esi+ecx*8]
00246 pxor mm6, mm7
00247 movq mm2, mm1
00248 pand mm6, mm5
00249 movq mm3, mm1
00250 pxor mm2, mm0
00251 pand mm3, mm0
00252 psrld mm2, 1
00253 paddd mm0, mm1
00254 paddd mm3, mm2
00255 psrld mm3, 31
00256 pxor mm7, mm6
00257 psllq mm3, 32
00259
00261 movq mm4, mm5
00262 psllq mm4, 23
00263 paddd mm0, mm3
00264 movq mm6, mm4
00265 psllq mm4, (46-23)
00266 pxor mm6, mm4
00267 psllq mm4, (50-46)
00268 pxor mm6, mm4
00269 psrlq mm5, 14
00270 pxor mm6, mm5
00271 psrlq mm5, (18-14)
00272 pxor mm6, mm5
00273 psrlq mm5, (41-18)
00274 pxor mm6, mm5
00276
00278 movq mm2, mm7
00279 movq mm3, mm7
00280 pxor mm2, mm0
00281 pand mm3, mm0
00282 psrld mm2, 1
00284
00286 movq mm4, [edi+edx*8+1*8]
00287 paddd mm0, mm7
00288 movq mm1, [edi+edx*8+2*8]
00289 paddd mm3, mm2
00290 movq mm5, [edi+edx*8+3*8]
00291 psrld mm3, 31
00292 movq mm7, mm5
00293 psllq mm3, 32
00294 por mm7, mm1
00295 paddd mm0, mm3
00297
00299 movq mm2, mm6
00300 movq mm3, mm6
00301 pxor mm2, mm0
00302 pand mm3, mm0
00303 psrld mm2, 1
00304 paddd mm0, mm6
00305 paddd mm3, mm2
00306 pand mm1, mm5
00307 psrld mm3, 31
00308 pand mm7, mm4
00309 psllq mm3, 32
00310 por mm7, mm1
00312
00314 movq mm5, mm4
00315 paddd mm0, mm3
00316 psllq mm4, 25
00317 movq mm1, mm0
00318 movq mm6, mm4
00319 psllq mm4, (30-25)
00320 pxor mm6, mm4
00321 psllq mm4, (36-30)
00322 pxor mm6, mm4
00323 psrlq mm5, 28
00324 pxor mm6, mm5
00325 psrlq mm5, (34-28)
00326 pxor mm6, mm5
00327 psrlq mm5, (39-34)
00328 pxor mm6, mm5
00330
00332 movq mm2, mm7
00333 movq mm3, mm7
00334 pxor mm2, mm0
00335 pand mm3, mm0
00336 psrld mm2, 1
00337 paddd mm0, mm7
00338 paddd mm3, mm2
00340
00342 movq mm7, [edi+edx*8+4*8]
00343 psrld mm3, 31
00344 movq mm4, mm7
00345 psllq mm3, 32
00346 paddd mm0, mm3
00347 movq mm5, mm7
00348 pxor mm4, mm1
00349 pand mm5, mm1
00350 paddd mm1, mm7
00351 psrld mm4, 1
00353
00355 movq mm2, mm6
00356 movq mm3, mm6
00357 pxor mm2, mm0
00358 pand mm3, mm0
00359 paddd mm5, mm4
00360 psrld mm2, 1
00361 psrld mm5, 31
00362 paddd mm3, mm2
00363 psllq mm5, 32
00364 paddd mm0, mm6
00365 psrld mm3, 31
00366 paddd mm1, mm5
00367 psllq mm3, 32
00368 dec edx
00369 paddd mm0, mm3
00370 inc ecx
00371 movq [edi+edx*8+4*8+8], mm1
00372 nop
00373 movq [edi+edx*8+8], mm0
00374 jnz loop1
00375 emms
00376 }
00377 for(i = 0; i < SHA512_HASH; i++) p->m_qwH[i] += Hash[i];
00378 }
00379
00380 #else
00381
00382 static DKC_INLINE void MMX_Generate(DKC_SHA512 *p){
00383 Default_Generate(p);
00384 }
00385
00386 #endif
00387
00388 static DKC_INLINE void Generate(DKC_SHA512 *p)
00389 {
00390 if(p->m_bMMX){
00391 MMX_Generate(p);
00392 return;
00393 }
00394 Default_Generate(p);
00395 }
00396
00397 DKC_SHA512 *WINAPI dkcAllocSHA512(){
00398 DKC_SHA512 *p = dkcAllocate(sizeof(DKC_SHA512));
00399 if(NULL==p){
00400 return NULL;
00401 }
00402 p->m_bMMX = CheckMMX();
00403 dkcSHA512Init(p);
00404 return p;
00405 }
00406
00407 void WINAPI dkcSHA512Init(DKC_SHA512 *p){
00408 int i;
00409 for(i = 0; i < SHA512_HASH; i++){
00410 p->m_qwH[i] = c_qwInitH[i];
00411 }
00412 p->m_qwLNumBits = 0;
00413 p->m_qwHNumBits = 0;
00414 p->m_nNumChr = 0;
00415 p->mFinalized = FALSE;
00416 }
00417
00418 void WINAPI dkcSHA512Load(DKC_SHA512 *p,const BYTE *pBuffer,DWORD dwSize){
00419 QWORD qwSize;
00420 QWORD qwLNumBits;
00421 BYTE *pBlock;
00422 DWORD dwReadSize;
00423
00424 if(dwSize == 0) return;
00425 if(p->mFinalized){
00426 return;
00427 }
00428
00429 qwSize = dwSize;
00430 qwLNumBits = (p->m_qwLNumBits + (qwSize << 3));
00431 if(qwLNumBits < p->m_qwLNumBits) p->m_qwHNumBits++;
00432
00433 p->m_qwLNumBits = qwLNumBits;
00434
00435 pBlock = (BYTE *)p->m_aBlock;
00436 while(dwSize){
00437
00438 dwReadSize = (dwSize < SHA512_BUFFER_SIZE - (DWORD)p->m_nNumChr) ?
00439 dwSize :
00440 (SHA512_BUFFER_SIZE - p->m_nNumChr);
00441
00442 memcpy(pBlock + p->m_nNumChr, pBuffer, dwReadSize);
00443
00444 p->m_nNumChr += dwReadSize;
00445 pBuffer += dwReadSize;
00446 dwSize -= dwReadSize;
00447
00448 if(p->m_nNumChr == SHA512_BUFFER_SIZE){
00449 Generate(p);
00450 p->m_nNumChr = 0;
00451 }
00452 }
00453 }
00454
00455 void WINAPI dkcSHA512Final(DKC_SHA512 *p){
00456
00457 BYTE cZero = 0x00;
00458 BYTE cOne = 0x80;
00459 QWORD qwHNumBits;
00460 QWORD qwLNumBits;
00461 if(p->mFinalized){
00462 return;
00463 }
00464 qwHNumBits = ReverseEndianQWORD(p->m_qwHNumBits);
00465 qwLNumBits = ReverseEndianQWORD(p->m_qwLNumBits);
00466
00467 dkcSHA512Load(p,&cOne, 1);
00468 while(p->m_nNumChr != SHA512_BUFFER_SIZE - 16) dkcSHA512Load(p,&cZero, 1);
00469
00470 dkcSHA512Load(p,(BYTE *)&qwHNumBits, 8);
00471 dkcSHA512Load(p,(BYTE *)&qwLNumBits, 8);
00472
00473 p->mFinalized = TRUE;
00474 }
00475
00476 int WINAPI dkcSHA512DigestStr(DKC_SHA512 *p,char *buff,size_t size){
00477
00478 char s[ SHA512_STR_BUFFER_SIZE ];
00479 int i;
00480
00481 s[SHA512_HASH * 16 ] = '\0';
00482
00483 if(SHA512_STR_BUFFER_SIZE > size){
00484 return edk_BufferOverFlow;
00485 }
00486 if(FALSE==p->mFinalized){
00487
00488 return edk_LogicError;
00489 }
00490
00491 for(i = 0; i < SHA512_HASH; i++){
00492 sprintf(s + i * 16, "%08x", (DWORD)(p->m_qwH[i] >> 32));
00493 sprintf(s + i * 16 + 8, "%08x", (DWORD)(p->m_qwH[i] & 0x00000000ffffffff));
00494 }
00495
00496
00497 return dkc_strcpy(buff,size,s,strlen(s));
00498 }
00499
00500
00501 int WINAPI dkcSHA512FinalDigestStr(DKC_SHA512 *p,char *buff,size_t size){
00502 dkcSHA512Final(p);
00503 return dkcSHA512DigestStr(p,buff,size);
00504 }
00505
00506
00507
00508 int WINAPI dkcSHA512Digest(DKC_SHA512 *p,BYTE *buff,size_t size){
00509
00510 size_t i;
00511 if(SHA512_BIN_BUFFER_SIZE > size){
00512 return edk_BufferOverFlow;
00513 }
00514 if(FALSE==p->mFinalized){
00515
00516 return edk_LogicError;
00517 }
00518 for(i = 0; i < SHA512_BIN_BUFFER_SIZE; ++i){
00519 buff[i] = (BYTE)(p->m_qwH[i >> 3] >> (8 * (~i & 7)));
00520 }
00521 return edk_SUCCEEDED;
00522
00523 }
00524
00525
00526 int WINAPI dkcSHA512FinalDigest(DKC_SHA512 *p,BYTE *buff,size_t size){
00527 dkcSHA512Final(p);
00528 return dkcSHA512Digest(p,buff,size);
00529 }
00530
00531
00532 int WINAPI dkcFreeSHA512(DKC_SHA512 **p){
00533 if(NULL==p){
00534 return edk_FAILED;
00535 }
00536 return dkcFree(p);
00537 }
00538
00539 #undef cpuid