Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of CyaSSL by
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/error-crypt.h> 00037 #ifdef NO_INLINE 00038 #include <cyassl/ctaocrypt/misc.h> 00039 #else 00040 #include <ctaocrypt/src/misc.c> 00041 #endif 00042 00043 00044 #ifndef min 00045 00046 static INLINE word32 min(word32 a, word32 b) 00047 { 00048 return a > b ? b : a; 00049 } 00050 00051 #endif /* min */ 00052 00053 00054 int InitSha512(Sha512* sha512) 00055 { 00056 sha512->digest[0] = W64LIT(0x6a09e667f3bcc908); 00057 sha512->digest[1] = W64LIT(0xbb67ae8584caa73b); 00058 sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b); 00059 sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1); 00060 sha512->digest[4] = W64LIT(0x510e527fade682d1); 00061 sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f); 00062 sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b); 00063 sha512->digest[7] = W64LIT(0x5be0cd19137e2179); 00064 00065 sha512->buffLen = 0; 00066 sha512->loLen = 0; 00067 sha512->hiLen = 0; 00068 00069 return 0; 00070 } 00071 00072 00073 static const word64 K512[80] = { 00074 W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), 00075 W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), 00076 W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), 00077 W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), 00078 W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), 00079 W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), 00080 W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), 00081 W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), 00082 W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), 00083 W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), 00084 W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), 00085 W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), 00086 W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), 00087 W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), 00088 W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), 00089 W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), 00090 W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), 00091 W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), 00092 W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), 00093 W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), 00094 W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), 00095 W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), 00096 W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), 00097 W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), 00098 W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), 00099 W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), 00100 W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), 00101 W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), 00102 W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), 00103 W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), 00104 W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), 00105 W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), 00106 W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), 00107 W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), 00108 W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), 00109 W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), 00110 W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), 00111 W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), 00112 W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), 00113 W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) 00114 }; 00115 00116 00117 #define blk0(i) (W[i] = sha512->buffer[i]) 00118 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) 00119 00120 #define Ch(x,y,z) (z^(x&(y^z))) 00121 #define Maj(x,y,z) ((x&y)|(z&(x|y))) 00122 00123 #define a(i) T[(0-i)&7] 00124 #define b(i) T[(1-i)&7] 00125 #define c(i) T[(2-i)&7] 00126 #define d(i) T[(3-i)&7] 00127 #define e(i) T[(4-i)&7] 00128 #define f(i) T[(5-i)&7] 00129 #define g(i) T[(6-i)&7] 00130 #define h(i) T[(7-i)&7] 00131 00132 #define S0(x) (rotrFixed64(x,28)^rotrFixed64(x,34)^rotrFixed64(x,39)) 00133 #define S1(x) (rotrFixed64(x,14)^rotrFixed64(x,18)^rotrFixed64(x,41)) 00134 #define s0(x) (rotrFixed64(x,1)^rotrFixed64(x,8)^(x>>7)) 00135 #define s1(x) (rotrFixed64(x,19)^rotrFixed64(x,61)^(x>>6)) 00136 00137 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\ 00138 d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) 00139 00140 #define blk384(i) (W[i] = sha384->buffer[i]) 00141 00142 #define R2(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk384(i));\ 00143 d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i)) 00144 00145 00146 static int Transform(Sha512* sha512) 00147 { 00148 const word64* K = K512; 00149 00150 word32 j; 00151 word64 T[8]; 00152 00153 #ifdef CYASSL_SMALL_STACK 00154 word64* W; 00155 00156 W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00157 if (W == NULL) 00158 return MEMORY_E; 00159 #else 00160 word64 W[16]; 00161 #endif 00162 00163 /* Copy digest to working vars */ 00164 XMEMCPY(T, sha512->digest, sizeof(T)); 00165 00166 #ifdef USE_SLOW_SHA2 00167 /* over twice as small, but 50% slower */ 00168 /* 80 operations, not unrolled */ 00169 for (j = 0; j < 80; j += 16) { 00170 int m; 00171 for (m = 0; m < 16; m++) { /* braces needed here for macros {} */ 00172 R(m); 00173 } 00174 } 00175 #else 00176 /* 80 operations, partially loop unrolled */ 00177 for (j = 0; j < 80; j += 16) { 00178 R( 0); R( 1); R( 2); R( 3); 00179 R( 4); R( 5); R( 6); R( 7); 00180 R( 8); R( 9); R(10); R(11); 00181 R(12); R(13); R(14); R(15); 00182 } 00183 #endif /* USE_SLOW_SHA2 */ 00184 00185 /* Add the working vars back into digest */ 00186 00187 sha512->digest[0] += a(0); 00188 sha512->digest[1] += b(0); 00189 sha512->digest[2] += c(0); 00190 sha512->digest[3] += d(0); 00191 sha512->digest[4] += e(0); 00192 sha512->digest[5] += f(0); 00193 sha512->digest[6] += g(0); 00194 sha512->digest[7] += h(0); 00195 00196 /* Wipe variables */ 00197 XMEMSET(W, 0, sizeof(word64) * 16); 00198 XMEMSET(T, 0, sizeof(T)); 00199 00200 #ifdef CYASSL_SMALL_STACK 00201 XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00202 #endif 00203 00204 return 0; 00205 } 00206 00207 00208 static INLINE void AddLength(Sha512* sha512, word32 len) 00209 { 00210 word32 tmp = sha512->loLen; 00211 if ( (sha512->loLen += len) < tmp) 00212 sha512->hiLen++; /* carry low to high */ 00213 } 00214 00215 00216 int Sha512Update(Sha512* sha512, const byte* data, word32 len) 00217 { 00218 /* do block size increments */ 00219 byte* local = (byte*)sha512->buffer; 00220 00221 while (len) { 00222 word32 add = min(len, SHA512_BLOCK_SIZE - sha512->buffLen); 00223 XMEMCPY(&local[sha512->buffLen], data, add); 00224 00225 sha512->buffLen += add; 00226 data += add; 00227 len -= add; 00228 00229 if (sha512->buffLen == SHA512_BLOCK_SIZE) { 00230 int ret; 00231 00232 #ifdef LITTLE_ENDIAN_ORDER 00233 ByteReverseWords64(sha512->buffer, sha512->buffer, 00234 SHA512_BLOCK_SIZE); 00235 #endif 00236 ret = Transform(sha512); 00237 if (ret != 0) 00238 return ret; 00239 00240 AddLength(sha512, SHA512_BLOCK_SIZE); 00241 sha512->buffLen = 0; 00242 } 00243 } 00244 return 0; 00245 } 00246 00247 00248 int Sha512Final(Sha512* sha512, byte* hash) 00249 { 00250 byte* local = (byte*)sha512->buffer; 00251 int ret; 00252 00253 AddLength(sha512, sha512->buffLen); /* before adding pads */ 00254 00255 local[sha512->buffLen++] = 0x80; /* add 1 */ 00256 00257 /* pad with zeros */ 00258 if (sha512->buffLen > SHA512_PAD_SIZE) { 00259 XMEMSET(&local[sha512->buffLen], 0, SHA512_BLOCK_SIZE -sha512->buffLen); 00260 sha512->buffLen += SHA512_BLOCK_SIZE - sha512->buffLen; 00261 00262 #ifdef LITTLE_ENDIAN_ORDER 00263 ByteReverseWords64(sha512->buffer,sha512->buffer,SHA512_BLOCK_SIZE); 00264 #endif 00265 ret = Transform(sha512); 00266 if (ret != 0) 00267 return ret; 00268 00269 sha512->buffLen = 0; 00270 } 00271 XMEMSET(&local[sha512->buffLen], 0, SHA512_PAD_SIZE - sha512->buffLen); 00272 00273 /* put lengths in bits */ 00274 sha512->hiLen = (sha512->loLen >> (8*sizeof(sha512->loLen) - 3)) + 00275 (sha512->hiLen << 3); 00276 sha512->loLen = sha512->loLen << 3; 00277 00278 /* store lengths */ 00279 #ifdef LITTLE_ENDIAN_ORDER 00280 ByteReverseWords64(sha512->buffer, sha512->buffer, SHA512_PAD_SIZE); 00281 #endif 00282 /* ! length ordering dependent on digest endian type ! */ 00283 sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; 00284 sha512->buffer[SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; 00285 00286 ret = Transform(sha512); 00287 if (ret != 0) 00288 return ret; 00289 00290 #ifdef LITTLE_ENDIAN_ORDER 00291 ByteReverseWords64(sha512->digest, sha512->digest, SHA512_DIGEST_SIZE); 00292 #endif 00293 XMEMCPY(hash, sha512->digest, SHA512_DIGEST_SIZE); 00294 00295 return InitSha512(sha512); /* reset state */ 00296 } 00297 00298 00299 00300 #ifdef CYASSL_SHA384 00301 00302 int InitSha384(Sha384* sha384) 00303 { 00304 sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8); 00305 sha384->digest[1] = W64LIT(0x629a292a367cd507); 00306 sha384->digest[2] = W64LIT(0x9159015a3070dd17); 00307 sha384->digest[3] = W64LIT(0x152fecd8f70e5939); 00308 sha384->digest[4] = W64LIT(0x67332667ffc00b31); 00309 sha384->digest[5] = W64LIT(0x8eb44a8768581511); 00310 sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7); 00311 sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4); 00312 00313 sha384->buffLen = 0; 00314 sha384->loLen = 0; 00315 sha384->hiLen = 0; 00316 00317 return 0; 00318 } 00319 00320 00321 static int Transform384(Sha384* sha384) 00322 { 00323 const word64* K = K512; 00324 00325 word32 j; 00326 word64 T[8]; 00327 00328 #ifdef CYASSL_SMALL_STACK 00329 word64* W; 00330 00331 W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00332 if (W == NULL) 00333 return MEMORY_E; 00334 #else 00335 word64 W[16]; 00336 #endif 00337 00338 /* Copy digest to working vars */ 00339 XMEMCPY(T, sha384->digest, sizeof(T)); 00340 00341 #ifdef USE_SLOW_SHA2 00342 /* over twice as small, but 50% slower */ 00343 /* 80 operations, not unrolled */ 00344 for (j = 0; j < 80; j += 16) { 00345 int m; 00346 for (m = 0; m < 16; m++) { /* braces needed for macros {} */ 00347 R2(m); 00348 } 00349 } 00350 #else 00351 /* 80 operations, partially loop unrolled */ 00352 for (j = 0; j < 80; j += 16) { 00353 R2( 0); R2( 1); R2( 2); R2( 3); 00354 R2( 4); R2( 5); R2( 6); R2( 7); 00355 R2( 8); R2( 9); R2(10); R2(11); 00356 R2(12); R2(13); R2(14); R2(15); 00357 } 00358 #endif /* USE_SLOW_SHA2 */ 00359 00360 /* Add the working vars back into digest */ 00361 00362 sha384->digest[0] += a(0); 00363 sha384->digest[1] += b(0); 00364 sha384->digest[2] += c(0); 00365 sha384->digest[3] += d(0); 00366 sha384->digest[4] += e(0); 00367 sha384->digest[5] += f(0); 00368 sha384->digest[6] += g(0); 00369 sha384->digest[7] += h(0); 00370 00371 /* Wipe variables */ 00372 XMEMSET(W, 0, sizeof(word64) * 16); 00373 XMEMSET(T, 0, sizeof(T)); 00374 00375 #ifdef CYASSL_SMALL_STACK 00376 XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00377 #endif 00378 00379 return 0; 00380 } 00381 00382 00383 static INLINE void AddLength384(Sha384* sha384, word32 len) 00384 { 00385 word32 tmp = sha384->loLen; 00386 if ( (sha384->loLen += len) < tmp) 00387 sha384->hiLen++; /* carry low to high */ 00388 } 00389 00390 00391 int Sha384Update(Sha384* sha384, const byte* data, word32 len) 00392 { 00393 /* do block size increments */ 00394 byte* local = (byte*)sha384->buffer; 00395 00396 while (len) { 00397 word32 add = min(len, SHA384_BLOCK_SIZE - sha384->buffLen); 00398 XMEMCPY(&local[sha384->buffLen], data, add); 00399 00400 sha384->buffLen += add; 00401 data += add; 00402 len -= add; 00403 00404 if (sha384->buffLen == SHA384_BLOCK_SIZE) { 00405 int ret; 00406 00407 #ifdef LITTLE_ENDIAN_ORDER 00408 ByteReverseWords64(sha384->buffer, sha384->buffer, 00409 SHA384_BLOCK_SIZE); 00410 #endif 00411 ret = Transform384(sha384); 00412 if (ret != 0) 00413 return ret; 00414 00415 AddLength384(sha384, SHA384_BLOCK_SIZE); 00416 sha384->buffLen = 0; 00417 } 00418 } 00419 return 0; 00420 } 00421 00422 00423 int Sha384Final(Sha384* sha384, byte* hash) 00424 { 00425 byte* local = (byte*)sha384->buffer; 00426 int ret; 00427 00428 AddLength384(sha384, sha384->buffLen); /* before adding pads */ 00429 00430 local[sha384->buffLen++] = 0x80; /* add 1 */ 00431 00432 /* pad with zeros */ 00433 if (sha384->buffLen > SHA384_PAD_SIZE) { 00434 XMEMSET(&local[sha384->buffLen], 0, SHA384_BLOCK_SIZE -sha384->buffLen); 00435 sha384->buffLen += SHA384_BLOCK_SIZE - sha384->buffLen; 00436 00437 #ifdef LITTLE_ENDIAN_ORDER 00438 ByteReverseWords64(sha384->buffer,sha384->buffer,SHA384_BLOCK_SIZE); 00439 #endif 00440 ret = Transform384(sha384); 00441 if (ret != 0) 00442 return ret; 00443 00444 sha384->buffLen = 0; 00445 } 00446 XMEMSET(&local[sha384->buffLen], 0, SHA384_PAD_SIZE - sha384->buffLen); 00447 00448 /* put lengths in bits */ 00449 sha384->hiLen = (sha384->loLen >> (8*sizeof(sha384->loLen) - 3)) + 00450 (sha384->hiLen << 3); 00451 sha384->loLen = sha384->loLen << 3; 00452 00453 /* store lengths */ 00454 #ifdef LITTLE_ENDIAN_ORDER 00455 ByteReverseWords64(sha384->buffer, sha384->buffer, SHA384_PAD_SIZE); 00456 #endif 00457 /* ! length ordering dependent on digest endian type ! */ 00458 sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 2] = sha384->hiLen; 00459 sha384->buffer[SHA384_BLOCK_SIZE / sizeof(word64) - 1] = sha384->loLen; 00460 00461 ret = Transform384(sha384); 00462 if (ret != 0) 00463 return ret; 00464 00465 #ifdef LITTLE_ENDIAN_ORDER 00466 ByteReverseWords64(sha384->digest, sha384->digest, SHA384_DIGEST_SIZE); 00467 #endif 00468 XMEMCPY(hash, sha384->digest, SHA384_DIGEST_SIZE); 00469 00470 return InitSha384(sha384); /* reset state */ 00471 } 00472 00473 #endif /* CYASSL_SHA384 */ 00474 00475 #endif /* CYASSL_SHA512 */ 00476
Generated on Tue Jul 12 2022 21:40:05 by
1.7.2
