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