Dependents: HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL
sha512.c
00001 /* sha512.c 00002 * 00003 * Copyright (C) 2006-2014 wolfSSL Inc. 00004 * 00005 * This file is part of CyaSSL. 00006 * 00007 * CyaSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * CyaSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 00026 #include <cyassl/ctaocrypt/settings.h> 00027 00028 #ifdef CYASSL_SHA512 00029 00030 #ifdef HAVE_FIPS 00031 /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ 00032 #define FIPS_NO_WRAPPERS 00033 #endif 00034 00035 #include <cyassl/ctaocrypt/sha512.h> 00036 #include <cyassl/ctaocrypt/logging.h> 00037 #include <cyassl/ctaocrypt/error-crypt.h> 00038 00039 #ifdef NO_INLINE 00040 #include <cyassl/ctaocrypt/misc.h> 00041 #else 00042 #include <ctaocrypt/src/misc.c> 00043 #endif 00044 00045 00046 #ifndef min 00047 00048 static INLINE word32 min(word32 a, word32 b) 00049 { 00050 return a > b ? b : a; 00051 } 00052 00053 #endif /* min */ 00054 00055 00056 int InitSha512(Sha512* sha512) 00057 { 00058 sha512->digest[0] = W64LIT(0x6a09e667f3bcc908); 00059 sha512->digest[1] = W64LIT(0xbb67ae8584caa73b); 00060 sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b); 00061 sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1); 00062 sha512->digest[4] = W64LIT(0x510e527fade682d1); 00063 sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f); 00064 sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b); 00065 sha512->digest[7] = W64LIT(0x5be0cd19137e2179); 00066 00067 sha512->buffLen = 0; 00068 sha512->loLen = 0; 00069 sha512->hiLen = 0; 00070 00071 return 0; 00072 } 00073 00074 00075 static const word64 K512[80] = { 00076 W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), 00077 W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), 00078 W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), 00079 W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), 00080 W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), 00081 W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), 00082 W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), 00083 W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), 00084 W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), 00085 W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), 00086 W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), 00087 W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), 00088 W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), 00089 W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), 00090 W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), 00091 W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), 00092 W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), 00093 W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), 00094 W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), 00095 W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), 00096 W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), 00097 W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), 00098 W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), 00099 W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), 00100 W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), 00101 W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), 00102 W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), 00103 W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), 00104 W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), 00105 W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), 00106 W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), 00107 W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), 00108 W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), 00109 W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), 00110 W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), 00111 W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), 00112 W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), 00113 W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), 00114 W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), 00115 W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) 00116 }; 00117 00118 00119 #define blk0(i) (W[i] = sha512->buffer[i]) 00120 #define blk2(i) (W[i&15] += s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])+0) 00121 00122 #define Ch(x,y,z) (z^(x&(y^z))) 00123 #define Maj(x,y,z) ((x&y)|(z&(x|y))) 00124 00125 #define a(i) T[(0-i)&7] 00126 #define b(i) T[(1-i)&7] 00127 #define c(i) T[(2-i)&7] 00128 #define d(i) T[(3-i)&7] 00129 #define e(i) T[(4-i)&7] 00130 #define f(i) T[(5-i)&7] 00131 #define g(i) T[(6-i)&7] 00132 #define h(i) T[(7-i)&7] 00133 00134 #define S0(x) (rotrFixed64(x,28)^rotrFixed64(x,34)^rotrFixed64(x,39)) 00135 #define S1(x) (rotrFixed64(x,14)^rotrFixed64(x,18)^rotrFixed64(x,41)) 00136 #define s0(x) (rotrFixed64(x,1)^rotrFixed64(x,8)^(x>>7)) 00137 #define s1(x) (rotrFixed64(x,19)^rotrFixed64(x,61)^(x>>6)) 00138 00139 #define R(i) (j?blk2(i):blk0(i));\ 00140 h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+W[i&15];\ 00141 d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) 00142 00143 #define blk384(i) (W[i] = sha384->buffer[i]) 00144 00145 #define R2(i) (j?blk2(i):blk384(i));\ 00146 h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+W[i&15];\ 00147 d(i)+=h(i);\ 00148 h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) 00149 00150 00151 static int Transform(Sha512* sha512) 00152 { 00153 const word64* K = K512; 00154 00155 word32 j; 00156 word64 T[8]; 00157 00158 #ifdef CYASSL_SMALL_STACK 00159 word64* W; 00160 00161 W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00162 if (W == NULL) 00163 return MEMORY_E; 00164 #else 00165 word64 W[16]; 00166 #endif 00167 00168 /* Copy digest to working vars */ 00169 XMEMCPY(T, sha512->digest, sizeof(T)); 00170 00171 #ifdef USE_SLOW_SHA2 00172 /* over twice as small, but 50% slower */ 00173 /* 80 operations, not unrolled */ 00174 for (j = 0; j < 80; j += 16) { 00175 int m; 00176 for (m = 0; m < 16; m++) { /* braces needed here for macros {} */ 00177 R(m); 00178 } 00179 } 00180 #else 00181 /* 80 operations, partially loop unrolled */ 00182 for (j = 0; j < 80; j += 16) { 00183 R( 0); R( 1); R( 2); R( 3); 00184 R( 4); R( 5); R( 6); R( 7); 00185 R( 8); R( 9); R(10); R(11); 00186 R(12); R(13); R(14); R(15); 00187 } 00188 #endif /* USE_SLOW_SHA2 */ 00189 00190 /* Add the working vars back into digest */ 00191 00192 sha512->digest[0] += a(0); 00193 sha512->digest[1] += b(0); 00194 sha512->digest[2] += c(0); 00195 sha512->digest[3] += d(0); 00196 sha512->digest[4] += e(0); 00197 sha512->digest[5] += f(0); 00198 sha512->digest[6] += g(0); 00199 sha512->digest[7] += h(0); 00200 00201 /* Wipe variables */ 00202 XMEMSET(W, 0, sizeof(word64) * 16); 00203 XMEMSET(T, 0, sizeof(T)); 00204 00205 #ifdef CYASSL_SMALL_STACK 00206 XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00207 #endif 00208 00209 return 0; 00210 } 00211 00212 00213 static INLINE void AddLength(Sha512* sha512, word32 len) 00214 { 00215 word32 tmp = sha512->loLen; 00216 if ( (sha512->loLen += len) < tmp) 00217 sha512->hiLen++; /* carry low to high */ 00218 } 00219 00220 00221 int Sha512Update(Sha512* sha512, const byte* data, word32 len) 00222 { 00223 /* do block size increments */ 00224 byte* local = (byte*)sha512->buffer; 00225 00226 while (len) { 00227 word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen); 00228 XMEMCPY(&local[sha512->buffLen], data, add); 00229 00230 sha512->buffLen += add; 00231 data += add; 00232 len -= add; 00233 00234 if (sha512->buffLen == SHA512_BLOCK_SIZE) { 00235 int ret; 00236 00237 #ifdef LITTLE_ENDIAN_ORDER 00238 ByteReverseWords64(sha512->buffer, sha512->buffer, 00239 SHA512_BLOCK_SIZE); 00240 #endif 00241 ret = Transform(sha512); 00242 if (ret != 0) 00243 return ret; 00244 00245 AddLength(sha512, SHA512_BLOCK_SIZE); 00246 sha512->buffLen = 0; 00247 } 00248 } 00249 return 0; 00250 } 00251 00252 00253 int Sha512Final(Sha512* sha512, byte* hash) 00254 { 00255 byte* local = (byte*)sha512->buffer; 00256 int ret; 00257 00258 AddLength(sha512, sha512->buffLen); /* before adding pads */ 00259 00260 local[sha512->buffLen++] = 0x80; /* add 1 */ 00261 00262 /* pad with zeros */ 00263 if (sha512->buffLen > SHA512_PAD_SIZE) { 00264 XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen); 00265 sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen; 00266 00267 #ifdef LITTLE_ENDIAN_ORDER 00268 ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE); 00269 #endif 00270 ret = Transform(sha512); 00271 if (ret != 0) 00272 return ret; 00273 00274 sha512->buffLen = 0; 00275 } 00276 XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen); 00277 00278 /* put lengths in bits */ 00279 sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) + 00280 (sha512->hiLen << 3); 00281 sha512->loLen = sha512->loLen << 3; 00282 00283 /* store lengths */ 00284 #ifdef LITTLE_ENDIAN_ORDER 00285 ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE); 00286 #endif 00287 /* ! length ordering dependent on digest endian type ! */ 00288 sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; 00289 sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; 00290 00291 ret = Transform(sha512); 00292 if (ret != 0) 00293 return ret; 00294 00295 #ifdef LITTLE_ENDIAN_ORDER 00296 ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE); 00297 #endif 00298 XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE); 00299 00300 return InitSha512(sha512); /* reset state */ 00301 } 00302 00303 00304 int Sha512Hash(const byte* data, word32 len, byte* hash) 00305 { 00306 int ret = 0; 00307 #ifdef CYASSL_SMALL_STACK 00308 Sha512* sha512; 00309 #else 00310 Sha512 sha512[1]; 00311 #endif 00312 00313 #ifdef CYASSL_SMALL_STACK 00314 sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER); 00315 if (sha512 == NULL) 00316 return MEMORY_E; 00317 #endif 00318 00319 if ((ret = InitSha512(sha512)) != 0) { 00320 CYASSL_MSG("InitSha512 failed"); 00321 } 00322 else if ((ret = Sha512Update(sha512, data, len)) != 0) { 00323 CYASSL_MSG("Sha512Update failed"); 00324 } 00325 else if ((ret = Sha512Final(sha512, hash)) != 0) { 00326 CYASSL_MSG("Sha512Final failed"); 00327 } 00328 00329 #ifdef CYASSL_SMALL_STACK 00330 XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00331 #endif 00332 00333 return ret; 00334 } 00335 00336 00337 #ifdef CYASSL_SHA384 00338 00339 int InitSha384(Sha384* sha384) 00340 { 00341 sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8); 00342 sha384->digest[1] = W64LIT(0x629a292a367cd507); 00343 sha384->digest[2] = W64LIT(0x9159015a3070dd17); 00344 sha384->digest[3] = W64LIT(0x152fecd8f70e5939); 00345 sha384->digest[4] = W64LIT(0x67332667ffc00b31); 00346 sha384->digest[5] = W64LIT(0x8eb44a8768581511); 00347 sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7); 00348 sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4); 00349 00350 sha384->buffLen = 0; 00351 sha384->loLen = 0; 00352 sha384->hiLen = 0; 00353 00354 return 0; 00355 } 00356 00357 00358 static int Transform384(Sha384* sha384) 00359 { 00360 const word64* K = K512; 00361 00362 word32 j; 00363 word64 T[8]; 00364 00365 #ifdef CYASSL_SMALL_STACK 00366 word64* W; 00367 00368 W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00369 if (W == NULL) 00370 return MEMORY_E; 00371 #else 00372 word64 W[16]; 00373 #endif 00374 00375 /* Copy digest to working vars */ 00376 XMEMCPY(T, sha384->digest, sizeof(T)); 00377 00378 #ifdef USE_SLOW_SHA2 00379 /* over twice as small, but 50% slower */ 00380 /* 80 operations, not unrolled */ 00381 for (j = 0; j < 80; j += 16) { 00382 int m; 00383 for (m = 0; m < 16; m++) { /* braces needed for macros {} */ 00384 R2(m); 00385 } 00386 } 00387 #else 00388 /* 80 operations, partially loop unrolled */ 00389 for (j = 0; j < 80; j += 16) { 00390 R2( 0); R2( 1); R2( 2); R2( 3); 00391 R2( 4); R2( 5); R2( 6); R2( 7); 00392 R2( 8); R2( 9); R2(10); R2(11); 00393 R2(12); R2(13); R2(14); R2(15); 00394 } 00395 #endif /* USE_SLOW_SHA2 */ 00396 00397 /* Add the working vars back into digest */ 00398 00399 sha384->digest[0] += a(0); 00400 sha384->digest[1] += b(0); 00401 sha384->digest[2] += c(0); 00402 sha384->digest[3] += d(0); 00403 sha384->digest[4] += e(0); 00404 sha384->digest[5] += f(0); 00405 sha384->digest[6] += g(0); 00406 sha384->digest[7] += h(0); 00407 00408 /* Wipe variables */ 00409 XMEMSET(W, 0, sizeof(word64) * 16); 00410 XMEMSET(T, 0, sizeof(T)); 00411 00412 #ifdef CYASSL_SMALL_STACK 00413 XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00414 #endif 00415 00416 return 0; 00417 } 00418 00419 00420 static INLINE void AddLength384(Sha384* sha384, word32 len) 00421 { 00422 word32 tmp = sha384->loLen; 00423 if ( (sha384->loLen += len) < tmp) 00424 sha384->hiLen++; /* carry low to high */ 00425 } 00426 00427 00428 int Sha384Update(Sha384* sha384, const byte* data, word32 len) 00429 { 00430 /* do block size increments */ 00431 byte* local = (byte*)sha384->buffer; 00432 00433 while (len) { 00434 word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen); 00435 XMEMCPY(&local[sha384->buffLen], data, add); 00436 00437 sha384->buffLen += add; 00438 data += add; 00439 len -= add; 00440 00441 if (sha384->buffLen == SHA384_BLOCK_SIZE) { 00442 int ret; 00443 00444 #ifdef LITTLE_ENDIAN_ORDER 00445 ByteReverseWords64(sha384->buffer, sha384->buffer, 00446 SHA384_BLOCK_SIZE); 00447 #endif 00448 ret = Transform384(sha384); 00449 if (ret != 0) 00450 return ret; 00451 00452 AddLength384(sha384, SHA384_BLOCK_SIZE); 00453 sha384->buffLen = 0; 00454 } 00455 } 00456 return 0; 00457 } 00458 00459 00460 int Sha384Final(Sha384* sha384, byte* hash) 00461 { 00462 byte* local = (byte*)sha384->buffer; 00463 int ret; 00464 00465 AddLength384(sha384, sha384->buffLen); /* before adding pads */ 00466 00467 local[sha384->buffLen++] = 0x80; /* add 1 */ 00468 00469 /* pad with zeros */ 00470 if (sha384->buffLen > SHA384_PAD_SIZE) { 00471 XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen); 00472 sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen; 00473 00474 #ifdef LITTLE_ENDIAN_ORDER 00475 ByteReverseWords64(sha384->buffer,sha384->buffer,SHA384_BLOCK_SIZE); 00476 #endif 00477 ret = Transform384(sha384); 00478 if (ret != 0) 00479 return ret; 00480 00481 sha384->buffLen = 0; 00482 } 00483 XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen); 00484 00485 /* put lengths in bits */ 00486 sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) + 00487 (sha384->hiLen << 3); 00488 sha384->loLen = sha384->loLen << 3; 00489 00490 /* store lengths */ 00491 #ifdef LITTLE_ENDIAN_ORDER 00492 ByteReverseWords64(sha384->buffer, sha384->buffer, SHA384_PAD_SIZE); 00493 #endif 00494 /* ! length ordering dependent on digest endian type ! */ 00495 sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen; 00496 sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen; 00497 00498 ret = Transform384(sha384); 00499 if (ret != 0) 00500 return ret; 00501 00502 #ifdef LITTLE_ENDIAN_ORDER 00503 ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE); 00504 #endif 00505 XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE); 00506 00507 return InitSha384(sha384); /* reset state */ 00508 } 00509 00510 00511 int Sha384Hash(const byte* data, word32 len, byte* hash) 00512 { 00513 int ret = 0; 00514 #ifdef CYASSL_SMALL_STACK 00515 Sha384* sha384; 00516 #else 00517 Sha384 sha384[1]; 00518 #endif 00519 00520 #ifdef CYASSL_SMALL_STACK 00521 sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); 00522 if (sha384 == NULL) 00523 return MEMORY_E; 00524 #endif 00525 00526 if ((ret = InitSha384(sha384)) != 0) { 00527 CYASSL_MSG("InitSha384 failed"); 00528 } 00529 else if ((ret = Sha384Update(sha384, data, len)) != 0) { 00530 CYASSL_MSG("Sha384Update failed"); 00531 } 00532 else if ((ret = Sha384Final(sha384, hash)) != 0) { 00533 CYASSL_MSG("Sha384Final failed"); 00534 } 00535 00536 #ifdef CYASSL_SMALL_STACK 00537 XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00538 #endif 00539 00540 return ret; 00541 } 00542 00543 #endif /* CYASSL_SHA384 */ 00544 00545 #endif /* CYASSL_SHA512 */
Generated on Wed Jul 13 2022 02:33:57 by
