1160814Ssimon/* crypto/sha/sha512.c */ 2160814Ssimon/* ==================================================================== 3160814Ssimon * Copyright (c) 2004 The OpenSSL Project. All rights reserved 4160814Ssimon * according to the OpenSSL license [found in ../../LICENSE]. 5160814Ssimon * ==================================================================== 6160814Ssimon */ 7160814Ssimon#include <openssl/opensslconf.h> 8194206Ssimon#ifdef OPENSSL_FIPS 9296465Sdelphij# include <openssl/fips.h> 10194206Ssimon#endif 11194206Ssimon 12160814Ssimon#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512) 13296465Sdelphij/*- 14160814Ssimon * IMPLEMENTATION NOTES. 15160814Ssimon * 16160814Ssimon * As you might have noticed 32-bit hash algorithms: 17160814Ssimon * 18160814Ssimon * - permit SHA_LONG to be wider than 32-bit (case on CRAY); 19160814Ssimon * - optimized versions implement two transform functions: one operating 20160814Ssimon * on [aligned] data in host byte order and one - on data in input 21160814Ssimon * stream byte order; 22160814Ssimon * - share common byte-order neutral collector and padding function 23160814Ssimon * implementations, ../md32_common.h; 24160814Ssimon * 25160814Ssimon * Neither of the above applies to this SHA-512 implementations. Reasons 26160814Ssimon * [in reverse order] are: 27160814Ssimon * 28160814Ssimon * - it's the only 64-bit hash algorithm for the moment of this writing, 29160814Ssimon * there is no need for common collector/padding implementation [yet]; 30160814Ssimon * - by supporting only one transform function [which operates on 31160814Ssimon * *aligned* data in input stream byte order, big-endian in this case] 32160814Ssimon * we minimize burden of maintenance in two ways: a) collector/padding 33160814Ssimon * function is simpler; b) only one transform function to stare at; 34160814Ssimon * - SHA_LONG64 is required to be exactly 64-bit in order to be able to 35160814Ssimon * apply a number of optimizations to mitigate potential performance 36160814Ssimon * penalties caused by previous design decision; 37160814Ssimon * 38160814Ssimon * Caveat lector. 39160814Ssimon * 40160814Ssimon * Implementation relies on the fact that "long long" is 64-bit on 41160814Ssimon * both 32- and 64-bit platforms. If some compiler vendor comes up 42160814Ssimon * with 128-bit long long, adjustment to sha.h would be required. 43160814Ssimon * As this implementation relies on 64-bit integer type, it's totally 44160814Ssimon * inappropriate for platforms which don't support it, most notably 45160814Ssimon * 16-bit platforms. 46296465Sdelphij * <appro@fy.chalmers.se> 47160814Ssimon */ 48296465Sdelphij# include <stdlib.h> 49296465Sdelphij# include <string.h> 50160814Ssimon 51296465Sdelphij# include <openssl/crypto.h> 52296465Sdelphij# include <openssl/sha.h> 53296465Sdelphij# include <openssl/opensslv.h> 54160814Ssimon 55296465Sdelphij# include "cryptlib.h" 56160814Ssimon 57296465Sdelphijconst char SHA512_version[] = "SHA-512" OPENSSL_VERSION_PTEXT; 58160814Ssimon 59296465Sdelphij# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ 60194206Ssimon defined(__x86_64) || defined(_M_AMD64) || defined(_M_X64) || \ 61194206Ssimon defined(__s390__) || defined(__s390x__) || \ 62194206Ssimon defined(SHA512_ASM) 63296465Sdelphij# define SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA 64296465Sdelphij# endif 65160814Ssimon 66296465Sdelphijint SHA384_Init(SHA512_CTX *c) 67296465Sdelphij{ 68296465Sdelphij# ifdef OPENSSL_FIPS 69296465Sdelphij FIPS_selftest_check(); 70296465Sdelphij# endif 71296465Sdelphij c->h[0] = U64(0xcbbb9d5dc1059ed8); 72296465Sdelphij c->h[1] = U64(0x629a292a367cd507); 73296465Sdelphij c->h[2] = U64(0x9159015a3070dd17); 74296465Sdelphij c->h[3] = U64(0x152fecd8f70e5939); 75296465Sdelphij c->h[4] = U64(0x67332667ffc00b31); 76296465Sdelphij c->h[5] = U64(0x8eb44a8768581511); 77296465Sdelphij c->h[6] = U64(0xdb0c2e0d64f98fa7); 78296465Sdelphij c->h[7] = U64(0x47b5481dbefa4fa4); 79296465Sdelphij c->Nl = 0; 80296465Sdelphij c->Nh = 0; 81296465Sdelphij c->num = 0; 82296465Sdelphij c->md_len = SHA384_DIGEST_LENGTH; 83296465Sdelphij return 1; 84296465Sdelphij} 85160814Ssimon 86296465Sdelphijint SHA512_Init(SHA512_CTX *c) 87296465Sdelphij{ 88296465Sdelphij# ifdef OPENSSL_FIPS 89296465Sdelphij FIPS_selftest_check(); 90296465Sdelphij# endif 91296465Sdelphij c->h[0] = U64(0x6a09e667f3bcc908); 92296465Sdelphij c->h[1] = U64(0xbb67ae8584caa73b); 93296465Sdelphij c->h[2] = U64(0x3c6ef372fe94f82b); 94296465Sdelphij c->h[3] = U64(0xa54ff53a5f1d36f1); 95296465Sdelphij c->h[4] = U64(0x510e527fade682d1); 96296465Sdelphij c->h[5] = U64(0x9b05688c2b3e6c1f); 97296465Sdelphij c->h[6] = U64(0x1f83d9abfb41bd6b); 98296465Sdelphij c->h[7] = U64(0x5be0cd19137e2179); 99296465Sdelphij c->Nl = 0; 100296465Sdelphij c->Nh = 0; 101296465Sdelphij c->num = 0; 102296465Sdelphij c->md_len = SHA512_DIGEST_LENGTH; 103296465Sdelphij return 1; 104296465Sdelphij} 105160814Ssimon 106296465Sdelphij# ifndef SHA512_ASM 107160814Ssimonstatic 108296465Sdelphij# endif 109296465Sdelphijvoid sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num); 110160814Ssimon 111296465Sdelphijint SHA512_Final(unsigned char *md, SHA512_CTX *c) 112296465Sdelphij{ 113296465Sdelphij unsigned char *p = (unsigned char *)c->u.p; 114296465Sdelphij size_t n = c->num; 115160814Ssimon 116296465Sdelphij p[n] = 0x80; /* There always is a room for one */ 117296465Sdelphij n++; 118296465Sdelphij if (n > (sizeof(c->u) - 16)) 119296465Sdelphij memset(p + n, 0, sizeof(c->u) - n), n = 0, 120296465Sdelphij sha512_block_data_order(c, p, 1); 121160814Ssimon 122296465Sdelphij memset(p + n, 0, sizeof(c->u) - 16 - n); 123296465Sdelphij# ifdef B_ENDIAN 124296465Sdelphij c->u.d[SHA_LBLOCK - 2] = c->Nh; 125296465Sdelphij c->u.d[SHA_LBLOCK - 1] = c->Nl; 126296465Sdelphij# else 127296465Sdelphij p[sizeof(c->u) - 1] = (unsigned char)(c->Nl); 128296465Sdelphij p[sizeof(c->u) - 2] = (unsigned char)(c->Nl >> 8); 129296465Sdelphij p[sizeof(c->u) - 3] = (unsigned char)(c->Nl >> 16); 130296465Sdelphij p[sizeof(c->u) - 4] = (unsigned char)(c->Nl >> 24); 131296465Sdelphij p[sizeof(c->u) - 5] = (unsigned char)(c->Nl >> 32); 132296465Sdelphij p[sizeof(c->u) - 6] = (unsigned char)(c->Nl >> 40); 133296465Sdelphij p[sizeof(c->u) - 7] = (unsigned char)(c->Nl >> 48); 134296465Sdelphij p[sizeof(c->u) - 8] = (unsigned char)(c->Nl >> 56); 135296465Sdelphij p[sizeof(c->u) - 9] = (unsigned char)(c->Nh); 136296465Sdelphij p[sizeof(c->u) - 10] = (unsigned char)(c->Nh >> 8); 137296465Sdelphij p[sizeof(c->u) - 11] = (unsigned char)(c->Nh >> 16); 138296465Sdelphij p[sizeof(c->u) - 12] = (unsigned char)(c->Nh >> 24); 139296465Sdelphij p[sizeof(c->u) - 13] = (unsigned char)(c->Nh >> 32); 140296465Sdelphij p[sizeof(c->u) - 14] = (unsigned char)(c->Nh >> 40); 141296465Sdelphij p[sizeof(c->u) - 15] = (unsigned char)(c->Nh >> 48); 142296465Sdelphij p[sizeof(c->u) - 16] = (unsigned char)(c->Nh >> 56); 143296465Sdelphij# endif 144160814Ssimon 145296465Sdelphij sha512_block_data_order(c, p, 1); 146160814Ssimon 147296465Sdelphij if (md == 0) 148296465Sdelphij return 0; 149160814Ssimon 150296465Sdelphij switch (c->md_len) { 151296465Sdelphij /* Let compiler decide if it's appropriate to unroll... */ 152296465Sdelphij case SHA384_DIGEST_LENGTH: 153296465Sdelphij for (n = 0; n < SHA384_DIGEST_LENGTH / 8; n++) { 154296465Sdelphij SHA_LONG64 t = c->h[n]; 155160814Ssimon 156296465Sdelphij *(md++) = (unsigned char)(t >> 56); 157296465Sdelphij *(md++) = (unsigned char)(t >> 48); 158296465Sdelphij *(md++) = (unsigned char)(t >> 40); 159296465Sdelphij *(md++) = (unsigned char)(t >> 32); 160296465Sdelphij *(md++) = (unsigned char)(t >> 24); 161296465Sdelphij *(md++) = (unsigned char)(t >> 16); 162296465Sdelphij *(md++) = (unsigned char)(t >> 8); 163296465Sdelphij *(md++) = (unsigned char)(t); 164296465Sdelphij } 165296465Sdelphij break; 166296465Sdelphij case SHA512_DIGEST_LENGTH: 167296465Sdelphij for (n = 0; n < SHA512_DIGEST_LENGTH / 8; n++) { 168296465Sdelphij SHA_LONG64 t = c->h[n]; 169160814Ssimon 170296465Sdelphij *(md++) = (unsigned char)(t >> 56); 171296465Sdelphij *(md++) = (unsigned char)(t >> 48); 172296465Sdelphij *(md++) = (unsigned char)(t >> 40); 173296465Sdelphij *(md++) = (unsigned char)(t >> 32); 174296465Sdelphij *(md++) = (unsigned char)(t >> 24); 175296465Sdelphij *(md++) = (unsigned char)(t >> 16); 176296465Sdelphij *(md++) = (unsigned char)(t >> 8); 177296465Sdelphij *(md++) = (unsigned char)(t); 178296465Sdelphij } 179296465Sdelphij break; 180296465Sdelphij /* ... as well as make sure md_len is not abused. */ 181296465Sdelphij default: 182296465Sdelphij return 0; 183296465Sdelphij } 184160814Ssimon 185296465Sdelphij return 1; 186296465Sdelphij} 187160814Ssimon 188296465Sdelphijint SHA384_Final(unsigned char *md, SHA512_CTX *c) 189296465Sdelphij{ 190296465Sdelphij return SHA512_Final(md, c); 191296465Sdelphij} 192160814Ssimon 193296465Sdelphijint SHA512_Update(SHA512_CTX *c, const void *_data, size_t len) 194296465Sdelphij{ 195296465Sdelphij SHA_LONG64 l; 196296465Sdelphij unsigned char *p = c->u.p; 197296465Sdelphij const unsigned char *data = (const unsigned char *)_data; 198160814Ssimon 199296465Sdelphij if (len == 0) 200296465Sdelphij return 1; 201160814Ssimon 202296465Sdelphij l = (c->Nl + (((SHA_LONG64) len) << 3)) & U64(0xffffffffffffffff); 203296465Sdelphij if (l < c->Nl) 204296465Sdelphij c->Nh++; 205296465Sdelphij if (sizeof(len) >= 8) 206296465Sdelphij c->Nh += (((SHA_LONG64) len) >> 61); 207296465Sdelphij c->Nl = l; 208160814Ssimon 209296465Sdelphij if (c->num != 0) { 210296465Sdelphij size_t n = sizeof(c->u) - c->num; 211160814Ssimon 212296465Sdelphij if (len < n) { 213296465Sdelphij memcpy(p + c->num, data, len), c->num += len; 214296465Sdelphij return 1; 215296465Sdelphij } else { 216296465Sdelphij memcpy(p + c->num, data, n), c->num = 0; 217296465Sdelphij len -= n, data += n; 218296465Sdelphij sha512_block_data_order(c, p, 1); 219296465Sdelphij } 220296465Sdelphij } 221160814Ssimon 222296465Sdelphij if (len >= sizeof(c->u)) { 223296465Sdelphij# ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA 224296465Sdelphij if ((size_t)data % sizeof(c->u.d[0]) != 0) 225296465Sdelphij while (len >= sizeof(c->u)) 226296465Sdelphij memcpy(p, data, sizeof(c->u)), 227296465Sdelphij sha512_block_data_order(c, p, 1), 228296465Sdelphij len -= sizeof(c->u), data += sizeof(c->u); 229296465Sdelphij else 230296465Sdelphij# endif 231296465Sdelphij sha512_block_data_order(c, data, len / sizeof(c->u)), 232296465Sdelphij data += len, len %= sizeof(c->u), data -= len; 233296465Sdelphij } 234160814Ssimon 235296465Sdelphij if (len != 0) 236296465Sdelphij memcpy(p, data, len), c->num = (int)len; 237160814Ssimon 238296465Sdelphij return 1; 239296465Sdelphij} 240160814Ssimon 241296465Sdelphijint SHA384_Update(SHA512_CTX *c, const void *data, size_t len) 242296465Sdelphij{ 243296465Sdelphij return SHA512_Update(c, data, len); 244296465Sdelphij} 245160814Ssimon 246296465Sdelphijvoid SHA512_Transform(SHA512_CTX *c, const unsigned char *data) 247296465Sdelphij{ 248296465Sdelphij sha512_block_data_order(c, data, 1); 249296465Sdelphij} 250160814Ssimon 251160814Ssimonunsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md) 252296465Sdelphij{ 253296465Sdelphij SHA512_CTX c; 254296465Sdelphij static unsigned char m[SHA384_DIGEST_LENGTH]; 255160814Ssimon 256296465Sdelphij if (md == NULL) 257296465Sdelphij md = m; 258296465Sdelphij SHA384_Init(&c); 259296465Sdelphij SHA512_Update(&c, d, n); 260296465Sdelphij SHA512_Final(md, &c); 261296465Sdelphij OPENSSL_cleanse(&c, sizeof(c)); 262296465Sdelphij return (md); 263296465Sdelphij} 264160814Ssimon 265160814Ssimonunsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md) 266296465Sdelphij{ 267296465Sdelphij SHA512_CTX c; 268296465Sdelphij static unsigned char m[SHA512_DIGEST_LENGTH]; 269160814Ssimon 270296465Sdelphij if (md == NULL) 271296465Sdelphij md = m; 272296465Sdelphij SHA512_Init(&c); 273296465Sdelphij SHA512_Update(&c, d, n); 274296465Sdelphij SHA512_Final(md, &c); 275296465Sdelphij OPENSSL_cleanse(&c, sizeof(c)); 276296465Sdelphij return (md); 277296465Sdelphij} 278160814Ssimon 279296465Sdelphij# ifndef SHA512_ASM 280160814Ssimonstatic const SHA_LONG64 K512[80] = { 281296465Sdelphij U64(0x428a2f98d728ae22), U64(0x7137449123ef65cd), 282296465Sdelphij U64(0xb5c0fbcfec4d3b2f), U64(0xe9b5dba58189dbbc), 283296465Sdelphij U64(0x3956c25bf348b538), U64(0x59f111f1b605d019), 284296465Sdelphij U64(0x923f82a4af194f9b), U64(0xab1c5ed5da6d8118), 285296465Sdelphij U64(0xd807aa98a3030242), U64(0x12835b0145706fbe), 286296465Sdelphij U64(0x243185be4ee4b28c), U64(0x550c7dc3d5ffb4e2), 287296465Sdelphij U64(0x72be5d74f27b896f), U64(0x80deb1fe3b1696b1), 288296465Sdelphij U64(0x9bdc06a725c71235), U64(0xc19bf174cf692694), 289296465Sdelphij U64(0xe49b69c19ef14ad2), U64(0xefbe4786384f25e3), 290296465Sdelphij U64(0x0fc19dc68b8cd5b5), U64(0x240ca1cc77ac9c65), 291296465Sdelphij U64(0x2de92c6f592b0275), U64(0x4a7484aa6ea6e483), 292296465Sdelphij U64(0x5cb0a9dcbd41fbd4), U64(0x76f988da831153b5), 293296465Sdelphij U64(0x983e5152ee66dfab), U64(0xa831c66d2db43210), 294296465Sdelphij U64(0xb00327c898fb213f), U64(0xbf597fc7beef0ee4), 295296465Sdelphij U64(0xc6e00bf33da88fc2), U64(0xd5a79147930aa725), 296296465Sdelphij U64(0x06ca6351e003826f), U64(0x142929670a0e6e70), 297296465Sdelphij U64(0x27b70a8546d22ffc), U64(0x2e1b21385c26c926), 298296465Sdelphij U64(0x4d2c6dfc5ac42aed), U64(0x53380d139d95b3df), 299296465Sdelphij U64(0x650a73548baf63de), U64(0x766a0abb3c77b2a8), 300296465Sdelphij U64(0x81c2c92e47edaee6), U64(0x92722c851482353b), 301296465Sdelphij U64(0xa2bfe8a14cf10364), U64(0xa81a664bbc423001), 302296465Sdelphij U64(0xc24b8b70d0f89791), U64(0xc76c51a30654be30), 303296465Sdelphij U64(0xd192e819d6ef5218), U64(0xd69906245565a910), 304296465Sdelphij U64(0xf40e35855771202a), U64(0x106aa07032bbd1b8), 305296465Sdelphij U64(0x19a4c116b8d2d0c8), U64(0x1e376c085141ab53), 306296465Sdelphij U64(0x2748774cdf8eeb99), U64(0x34b0bcb5e19b48a8), 307296465Sdelphij U64(0x391c0cb3c5c95a63), U64(0x4ed8aa4ae3418acb), 308296465Sdelphij U64(0x5b9cca4f7763e373), U64(0x682e6ff3d6b2b8a3), 309296465Sdelphij U64(0x748f82ee5defb2fc), U64(0x78a5636f43172f60), 310296465Sdelphij U64(0x84c87814a1f0ab72), U64(0x8cc702081a6439ec), 311296465Sdelphij U64(0x90befffa23631e28), U64(0xa4506cebde82bde9), 312296465Sdelphij U64(0xbef9a3f7b2c67915), U64(0xc67178f2e372532b), 313296465Sdelphij U64(0xca273eceea26619c), U64(0xd186b8c721c0c207), 314296465Sdelphij U64(0xeada7dd6cde0eb1e), U64(0xf57d4f7fee6ed178), 315296465Sdelphij U64(0x06f067aa72176fba), U64(0x0a637dc5a2c898a6), 316296465Sdelphij U64(0x113f9804bef90dae), U64(0x1b710b35131c471b), 317296465Sdelphij U64(0x28db77f523047d84), U64(0x32caab7b40c72493), 318296465Sdelphij U64(0x3c9ebe0a15c9bebc), U64(0x431d67c49c100d4c), 319296465Sdelphij U64(0x4cc5d4becb3e42b6), U64(0x597f299cfc657e2a), 320296465Sdelphij U64(0x5fcb6fab3ad6faec), U64(0x6c44198c4a475817) 321296465Sdelphij}; 322160814Ssimon 323296465Sdelphij# ifndef PEDANTIC 324296465Sdelphij# if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) 325296465Sdelphij# if defined(__x86_64) || defined(__x86_64__) 326296465Sdelphij# define ROTR(a,n) ({ unsigned long ret; \ 327296465Sdelphij asm ("rorq %1,%0" \ 328296465Sdelphij : "=r"(ret) \ 329296465Sdelphij : "J"(n),"0"(a) \ 330296465Sdelphij : "cc"); ret; }) 331296465Sdelphij# if !defined(B_ENDIAN) 332296465Sdelphij# define PULL64(x) ({ SHA_LONG64 ret=*((const SHA_LONG64 *)(&(x))); \ 333296465Sdelphij asm ("bswapq %0" \ 334296465Sdelphij : "=r"(ret) \ 335296465Sdelphij : "0"(ret)); ret; }) 336296465Sdelphij# endif 337296465Sdelphij# elif (defined(__i386) || defined(__i386__)) && !defined(B_ENDIAN) 338296465Sdelphij# if defined(I386_ONLY) 339296465Sdelphij# define PULL64(x) ({ const unsigned int *p=(const unsigned int *)(&(x));\ 340296465Sdelphij unsigned int hi=p[0],lo=p[1]; \ 341296465Sdelphij asm("xchgb %%ah,%%al;xchgb %%dh,%%dl;"\ 342296465Sdelphij "roll $16,%%eax; roll $16,%%edx; "\ 343296465Sdelphij "xchgb %%ah,%%al;xchgb %%dh,%%dl;" \ 344296465Sdelphij : "=a"(lo),"=d"(hi) \ 345296465Sdelphij : "0"(lo),"1"(hi) : "cc"); \ 346296465Sdelphij ((SHA_LONG64)hi)<<32|lo; }) 347296465Sdelphij# else 348296465Sdelphij# define PULL64(x) ({ const unsigned int *p=(const unsigned int *)(&(x));\ 349296465Sdelphij unsigned int hi=p[0],lo=p[1]; \ 350296465Sdelphij asm ("bswapl %0; bswapl %1;" \ 351296465Sdelphij : "=r"(lo),"=r"(hi) \ 352296465Sdelphij : "0"(lo),"1"(hi)); \ 353296465Sdelphij ((SHA_LONG64)hi)<<32|lo; }) 354296465Sdelphij# endif 355296465Sdelphij# elif (defined(_ARCH_PPC) && defined(__64BIT__)) || defined(_ARCH_PPC64) 356296465Sdelphij# define ROTR(a,n) ({ unsigned long ret; \ 357296465Sdelphij asm ("rotrdi %0,%1,%2" \ 358296465Sdelphij : "=r"(ret) \ 359296465Sdelphij : "r"(a),"K"(n)); ret; }) 360296465Sdelphij# endif 361296465Sdelphij# elif defined(_MSC_VER) 362296465Sdelphij# if defined(_WIN64) /* applies to both IA-64 and AMD64 */ 363296465Sdelphij# define ROTR(a,n) _rotr64((a),n) 364296465Sdelphij# endif 365296465Sdelphij# if defined(_M_IX86) && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) 366296465Sdelphij# if defined(I386_ONLY) 367296465Sdelphijstatic SHA_LONG64 __fastcall __pull64be(const void *x) 368296465Sdelphij{ 369296465Sdelphij _asm mov edx,[ecx + 0] 370296465Sdelphij _asm mov eax,[ecx + 4] 371296465Sdelphij_asm xchg dh, dl 372296465Sdelphij _asm xchg ah, al 373296465Sdelphij _asm rol edx, 16 _asm rol eax, 16 _asm xchg dh, dl _asm xchg ah, al} 374296465Sdelphij# else 375296465Sdelphijstatic SHA_LONG64 __fastcall __pull64be(const void *x) 376296465Sdelphij{ 377296465Sdelphij _asm mov edx,[ecx + 0] 378296465Sdelphij _asm mov eax,[ecx + 4] 379296465Sdelphij_asm bswap edx _asm bswap eax} 380296465Sdelphij# endif 381296465Sdelphij# define PULL64(x) __pull64be(&(x)) 382296465Sdelphij# if _MSC_VER<=1200 383296465Sdelphij# pragma inline_depth(0) 384296465Sdelphij# endif 385296465Sdelphij# endif 386194206Ssimon# endif 387160814Ssimon# endif 388296465Sdelphij# ifndef PULL64 389296465Sdelphij# define B(x,j) (((SHA_LONG64)(*(((const unsigned char *)(&x))+j)))<<((7-j)*8)) 390296465Sdelphij# define PULL64(x) (B(x,0)|B(x,1)|B(x,2)|B(x,3)|B(x,4)|B(x,5)|B(x,6)|B(x,7)) 391194206Ssimon# endif 392296465Sdelphij# ifndef ROTR 393296465Sdelphij# define ROTR(x,s) (((x)>>s) | (x)<<(64-s)) 394194206Ssimon# endif 395296465Sdelphij# define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) 396296465Sdelphij# define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) 397296465Sdelphij# define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) 398296465Sdelphij# define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) 399296465Sdelphij# define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) 400296465Sdelphij# define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 401296465Sdelphij# if defined(OPENSSL_IA32_SSE2) && !defined(OPENSSL_NO_ASM) && !defined(I386_ONLY) 402296465Sdelphij# define GO_FOR_SSE2(ctx,in,num) do { \ 403296465Sdelphij void sha512_block_sse2(void *,const void *,size_t); \ 404296465Sdelphij if (!(OPENSSL_ia32cap_P & (1<<26))) break; \ 405296465Sdelphij sha512_block_sse2(ctx->h,in,num); return; \ 406296465Sdelphij } while (0) 407296465Sdelphij# endif 408296465Sdelphij# ifdef OPENSSL_SMALL_FOOTPRINT 409296465Sdelphijstatic void sha512_block_data_order(SHA512_CTX *ctx, const void *in, 410296465Sdelphij size_t num) 411296465Sdelphij{ 412296465Sdelphij const SHA_LONG64 *W = in; 413296465Sdelphij SHA_LONG64 a, b, c, d, e, f, g, h, s0, s1, T1, T2; 414296465Sdelphij SHA_LONG64 X[16]; 415296465Sdelphij int i; 416160814Ssimon 417296465Sdelphij# ifdef GO_FOR_SSE2 418296465Sdelphij GO_FOR_SSE2(ctx, in, num); 419296465Sdelphij# endif 420194206Ssimon 421296465Sdelphij while (num--) { 422160814Ssimon 423296465Sdelphij a = ctx->h[0]; 424296465Sdelphij b = ctx->h[1]; 425296465Sdelphij c = ctx->h[2]; 426296465Sdelphij d = ctx->h[3]; 427296465Sdelphij e = ctx->h[4]; 428296465Sdelphij f = ctx->h[5]; 429296465Sdelphij g = ctx->h[6]; 430296465Sdelphij h = ctx->h[7]; 431160814Ssimon 432296465Sdelphij for (i = 0; i < 16; i++) { 433296465Sdelphij# ifdef B_ENDIAN 434296465Sdelphij T1 = X[i] = W[i]; 435296465Sdelphij# else 436296465Sdelphij T1 = X[i] = PULL64(W[i]); 437296465Sdelphij# endif 438296465Sdelphij T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; 439296465Sdelphij T2 = Sigma0(a) + Maj(a, b, c); 440296465Sdelphij h = g; 441296465Sdelphij g = f; 442296465Sdelphij f = e; 443296465Sdelphij e = d + T1; 444296465Sdelphij d = c; 445296465Sdelphij c = b; 446296465Sdelphij b = a; 447296465Sdelphij a = T1 + T2; 448296465Sdelphij } 449160814Ssimon 450296465Sdelphij for (; i < 80; i++) { 451296465Sdelphij s0 = X[(i + 1) & 0x0f]; 452296465Sdelphij s0 = sigma0(s0); 453296465Sdelphij s1 = X[(i + 14) & 0x0f]; 454296465Sdelphij s1 = sigma1(s1); 455160814Ssimon 456296465Sdelphij T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf]; 457296465Sdelphij T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; 458296465Sdelphij T2 = Sigma0(a) + Maj(a, b, c); 459296465Sdelphij h = g; 460296465Sdelphij g = f; 461296465Sdelphij f = e; 462296465Sdelphij e = d + T1; 463296465Sdelphij d = c; 464296465Sdelphij c = b; 465296465Sdelphij b = a; 466296465Sdelphij a = T1 + T2; 467296465Sdelphij } 468160814Ssimon 469296465Sdelphij ctx->h[0] += a; 470296465Sdelphij ctx->h[1] += b; 471296465Sdelphij ctx->h[2] += c; 472296465Sdelphij ctx->h[3] += d; 473296465Sdelphij ctx->h[4] += e; 474296465Sdelphij ctx->h[5] += f; 475296465Sdelphij ctx->h[6] += g; 476296465Sdelphij ctx->h[7] += h; 477160814Ssimon 478296465Sdelphij W += SHA_LBLOCK; 479296465Sdelphij } 480296465Sdelphij} 481160814Ssimon 482296465Sdelphij# else 483296465Sdelphij# define ROUND_00_15(i,a,b,c,d,e,f,g,h) do { \ 484296465Sdelphij T1 += h + Sigma1(e) + Ch(e,f,g) + K512[i]; \ 485296465Sdelphij h = Sigma0(a) + Maj(a,b,c); \ 486296465Sdelphij d += T1; h += T1; } while (0) 487296465Sdelphij# define ROUND_16_80(i,a,b,c,d,e,f,g,h,X) do { \ 488296465Sdelphij s0 = X[(i+1)&0x0f]; s0 = sigma0(s0); \ 489296465Sdelphij s1 = X[(i+14)&0x0f]; s1 = sigma1(s1); \ 490296465Sdelphij T1 = X[(i)&0x0f] += s0 + s1 + X[(i+9)&0x0f]; \ 491296465Sdelphij ROUND_00_15(i,a,b,c,d,e,f,g,h); } while (0) 492296465Sdelphijstatic void sha512_block_data_order(SHA512_CTX *ctx, const void *in, 493296465Sdelphij size_t num) 494296465Sdelphij{ 495296465Sdelphij const SHA_LONG64 *W = in; 496296465Sdelphij SHA_LONG64 a, b, c, d, e, f, g, h, s0, s1, T1; 497296465Sdelphij SHA_LONG64 X[16]; 498296465Sdelphij int i; 499160814Ssimon 500296465Sdelphij# ifdef GO_FOR_SSE2 501296465Sdelphij GO_FOR_SSE2(ctx, in, num); 502296465Sdelphij# endif 503160814Ssimon 504296465Sdelphij while (num--) { 505160814Ssimon 506296465Sdelphij a = ctx->h[0]; 507296465Sdelphij b = ctx->h[1]; 508296465Sdelphij c = ctx->h[2]; 509296465Sdelphij d = ctx->h[3]; 510296465Sdelphij e = ctx->h[4]; 511296465Sdelphij f = ctx->h[5]; 512296465Sdelphij g = ctx->h[6]; 513296465Sdelphij h = ctx->h[7]; 514160814Ssimon 515296465Sdelphij# ifdef B_ENDIAN 516296465Sdelphij T1 = X[0] = W[0]; 517296465Sdelphij ROUND_00_15(0, a, b, c, d, e, f, g, h); 518296465Sdelphij T1 = X[1] = W[1]; 519296465Sdelphij ROUND_00_15(1, h, a, b, c, d, e, f, g); 520296465Sdelphij T1 = X[2] = W[2]; 521296465Sdelphij ROUND_00_15(2, g, h, a, b, c, d, e, f); 522296465Sdelphij T1 = X[3] = W[3]; 523296465Sdelphij ROUND_00_15(3, f, g, h, a, b, c, d, e); 524296465Sdelphij T1 = X[4] = W[4]; 525296465Sdelphij ROUND_00_15(4, e, f, g, h, a, b, c, d); 526296465Sdelphij T1 = X[5] = W[5]; 527296465Sdelphij ROUND_00_15(5, d, e, f, g, h, a, b, c); 528296465Sdelphij T1 = X[6] = W[6]; 529296465Sdelphij ROUND_00_15(6, c, d, e, f, g, h, a, b); 530296465Sdelphij T1 = X[7] = W[7]; 531296465Sdelphij ROUND_00_15(7, b, c, d, e, f, g, h, a); 532296465Sdelphij T1 = X[8] = W[8]; 533296465Sdelphij ROUND_00_15(8, a, b, c, d, e, f, g, h); 534296465Sdelphij T1 = X[9] = W[9]; 535296465Sdelphij ROUND_00_15(9, h, a, b, c, d, e, f, g); 536296465Sdelphij T1 = X[10] = W[10]; 537296465Sdelphij ROUND_00_15(10, g, h, a, b, c, d, e, f); 538296465Sdelphij T1 = X[11] = W[11]; 539296465Sdelphij ROUND_00_15(11, f, g, h, a, b, c, d, e); 540296465Sdelphij T1 = X[12] = W[12]; 541296465Sdelphij ROUND_00_15(12, e, f, g, h, a, b, c, d); 542296465Sdelphij T1 = X[13] = W[13]; 543296465Sdelphij ROUND_00_15(13, d, e, f, g, h, a, b, c); 544296465Sdelphij T1 = X[14] = W[14]; 545296465Sdelphij ROUND_00_15(14, c, d, e, f, g, h, a, b); 546296465Sdelphij T1 = X[15] = W[15]; 547296465Sdelphij ROUND_00_15(15, b, c, d, e, f, g, h, a); 548296465Sdelphij# else 549296465Sdelphij T1 = X[0] = PULL64(W[0]); 550296465Sdelphij ROUND_00_15(0, a, b, c, d, e, f, g, h); 551296465Sdelphij T1 = X[1] = PULL64(W[1]); 552296465Sdelphij ROUND_00_15(1, h, a, b, c, d, e, f, g); 553296465Sdelphij T1 = X[2] = PULL64(W[2]); 554296465Sdelphij ROUND_00_15(2, g, h, a, b, c, d, e, f); 555296465Sdelphij T1 = X[3] = PULL64(W[3]); 556296465Sdelphij ROUND_00_15(3, f, g, h, a, b, c, d, e); 557296465Sdelphij T1 = X[4] = PULL64(W[4]); 558296465Sdelphij ROUND_00_15(4, e, f, g, h, a, b, c, d); 559296465Sdelphij T1 = X[5] = PULL64(W[5]); 560296465Sdelphij ROUND_00_15(5, d, e, f, g, h, a, b, c); 561296465Sdelphij T1 = X[6] = PULL64(W[6]); 562296465Sdelphij ROUND_00_15(6, c, d, e, f, g, h, a, b); 563296465Sdelphij T1 = X[7] = PULL64(W[7]); 564296465Sdelphij ROUND_00_15(7, b, c, d, e, f, g, h, a); 565296465Sdelphij T1 = X[8] = PULL64(W[8]); 566296465Sdelphij ROUND_00_15(8, a, b, c, d, e, f, g, h); 567296465Sdelphij T1 = X[9] = PULL64(W[9]); 568296465Sdelphij ROUND_00_15(9, h, a, b, c, d, e, f, g); 569296465Sdelphij T1 = X[10] = PULL64(W[10]); 570296465Sdelphij ROUND_00_15(10, g, h, a, b, c, d, e, f); 571296465Sdelphij T1 = X[11] = PULL64(W[11]); 572296465Sdelphij ROUND_00_15(11, f, g, h, a, b, c, d, e); 573296465Sdelphij T1 = X[12] = PULL64(W[12]); 574296465Sdelphij ROUND_00_15(12, e, f, g, h, a, b, c, d); 575296465Sdelphij T1 = X[13] = PULL64(W[13]); 576296465Sdelphij ROUND_00_15(13, d, e, f, g, h, a, b, c); 577296465Sdelphij T1 = X[14] = PULL64(W[14]); 578296465Sdelphij ROUND_00_15(14, c, d, e, f, g, h, a, b); 579296465Sdelphij T1 = X[15] = PULL64(W[15]); 580296465Sdelphij ROUND_00_15(15, b, c, d, e, f, g, h, a); 581296465Sdelphij# endif 582160814Ssimon 583296465Sdelphij for (i = 16; i < 80; i += 8) { 584296465Sdelphij ROUND_16_80(i + 0, a, b, c, d, e, f, g, h, X); 585296465Sdelphij ROUND_16_80(i + 1, h, a, b, c, d, e, f, g, X); 586296465Sdelphij ROUND_16_80(i + 2, g, h, a, b, c, d, e, f, X); 587296465Sdelphij ROUND_16_80(i + 3, f, g, h, a, b, c, d, e, X); 588296465Sdelphij ROUND_16_80(i + 4, e, f, g, h, a, b, c, d, X); 589296465Sdelphij ROUND_16_80(i + 5, d, e, f, g, h, a, b, c, X); 590296465Sdelphij ROUND_16_80(i + 6, c, d, e, f, g, h, a, b, X); 591296465Sdelphij ROUND_16_80(i + 7, b, c, d, e, f, g, h, a, X); 592296465Sdelphij } 593160814Ssimon 594296465Sdelphij ctx->h[0] += a; 595296465Sdelphij ctx->h[1] += b; 596296465Sdelphij ctx->h[2] += c; 597296465Sdelphij ctx->h[3] += d; 598296465Sdelphij ctx->h[4] += e; 599296465Sdelphij ctx->h[5] += f; 600296465Sdelphij ctx->h[6] += g; 601296465Sdelphij ctx->h[7] += h; 602160814Ssimon 603296465Sdelphij W += SHA_LBLOCK; 604296465Sdelphij } 605296465Sdelphij} 606160814Ssimon 607296465Sdelphij# endif 608160814Ssimon 609296465Sdelphij# endif /* SHA512_ASM */ 610160814Ssimon 611296465Sdelphij#else /* OPENSSL_NO_SHA512 */ 612160814Ssimon 613296465Sdelphij/* 614296465Sdelphij * Sensitive compilers ("Compaq C V6.4-005 on OpenVMS VAX V7.3", for example) 615296465Sdelphij * dislike a statement-free file, complaining: "%CC-W-EMPTYFILE, Source file 616296465Sdelphij * does not contain any declarations." 617205128Ssimon */ 618205128Ssimon 619205128Ssimonint sha512_dummy(); 620205128Ssimon 621296465Sdelphij#endif /* OPENSSL_NO_SHA512 */ 622