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