17a3f5d11SAllan Jude /*-
27a3f5d11SAllan Jude * Copyright 2005 Colin Percival
31780e407SAllan Jude * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
47a3f5d11SAllan Jude * All rights reserved.
57a3f5d11SAllan Jude *
67a3f5d11SAllan Jude * Redistribution and use in source and binary forms, with or without
77a3f5d11SAllan Jude * modification, are permitted provided that the following conditions
87a3f5d11SAllan Jude * are met:
97a3f5d11SAllan Jude * 1. Redistributions of source code must retain the above copyright
107a3f5d11SAllan Jude * notice, this list of conditions and the following disclaimer.
117a3f5d11SAllan Jude * 2. Redistributions in binary form must reproduce the above copyright
127a3f5d11SAllan Jude * notice, this list of conditions and the following disclaimer in the
137a3f5d11SAllan Jude * documentation and/or other materials provided with the distribution.
147a3f5d11SAllan Jude *
157a3f5d11SAllan Jude * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
167a3f5d11SAllan Jude * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177a3f5d11SAllan Jude * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187a3f5d11SAllan Jude * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197a3f5d11SAllan Jude * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
207a3f5d11SAllan Jude * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217a3f5d11SAllan Jude * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227a3f5d11SAllan Jude * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237a3f5d11SAllan Jude * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247a3f5d11SAllan Jude * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257a3f5d11SAllan Jude * SUCH DAMAGE.
267a3f5d11SAllan Jude */
277a3f5d11SAllan Jude
287a3f5d11SAllan Jude #include <sys/cdefs.h>
297a3f5d11SAllan Jude #include <sys/endian.h>
307a3f5d11SAllan Jude #include <sys/types.h>
317a3f5d11SAllan Jude
327a3f5d11SAllan Jude #ifdef _KERNEL
337a3f5d11SAllan Jude #include <sys/systm.h>
347a3f5d11SAllan Jude #else
357a3f5d11SAllan Jude #include <string.h>
367a3f5d11SAllan Jude #endif
377a3f5d11SAllan Jude
387a3f5d11SAllan Jude #include "sha512.h"
391780e407SAllan Jude #include "sha512t.h"
407a3f5d11SAllan Jude #include "sha384.h"
4171bf1c4cSAndrew Turner #include "sha512c_impl.h"
4271bf1c4cSAndrew Turner
4371bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
4471bf1c4cSAndrew Turner #include <sys/auxv.h>
4571bf1c4cSAndrew Turner #include <machine/ifunc.h>
4671bf1c4cSAndrew Turner #endif
477a3f5d11SAllan Jude
487a3f5d11SAllan Jude #if BYTE_ORDER == BIG_ENDIAN
497a3f5d11SAllan Jude
507a3f5d11SAllan Jude /* Copy a vector of big-endian uint64_t into a vector of bytes */
517a3f5d11SAllan Jude #define be64enc_vect(dst, src, len) \
527a3f5d11SAllan Jude memcpy((void *)dst, (const void *)src, (size_t)len)
537a3f5d11SAllan Jude
547a3f5d11SAllan Jude /* Copy a vector of bytes into a vector of big-endian uint64_t */
557a3f5d11SAllan Jude #define be64dec_vect(dst, src, len) \
567a3f5d11SAllan Jude memcpy((void *)dst, (const void *)src, (size_t)len)
577a3f5d11SAllan Jude
587a3f5d11SAllan Jude #else /* BYTE_ORDER != BIG_ENDIAN */
597a3f5d11SAllan Jude
607a3f5d11SAllan Jude /*
61*6680cfe8SSebastian Huber * Encode a length (len + 7) / 8 vector of (uint64_t) into a length len
62*6680cfe8SSebastian Huber * vector of (unsigned char) in big-endian form. Assumes len is a
63*6680cfe8SSebastian Huber * multiple of 4.
647a3f5d11SAllan Jude */
65*6680cfe8SSebastian Huber static inline void
be64enc_vect(unsigned char * dst,const uint64_t * src,size_t len)667a3f5d11SAllan Jude be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
677a3f5d11SAllan Jude {
687a3f5d11SAllan Jude size_t i;
697a3f5d11SAllan Jude
707a3f5d11SAllan Jude for (i = 0; i < len / 8; i++)
717a3f5d11SAllan Jude be64enc(dst + i * 8, src[i]);
72*6680cfe8SSebastian Huber if (len % 8 == 4)
73*6680cfe8SSebastian Huber be32enc(dst + i * 8, src[i] >> 32);
747a3f5d11SAllan Jude }
757a3f5d11SAllan Jude
767a3f5d11SAllan Jude /*
777a3f5d11SAllan Jude * Decode a big-endian length len vector of (unsigned char) into a length
78*6680cfe8SSebastian Huber * len/8 vector of (uint64_t). Assumes len is a multiple of 8.
797a3f5d11SAllan Jude */
80*6680cfe8SSebastian Huber static inline void
be64dec_vect(uint64_t * dst,const unsigned char * src,size_t len)817a3f5d11SAllan Jude be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
827a3f5d11SAllan Jude {
837a3f5d11SAllan Jude size_t i;
847a3f5d11SAllan Jude
857a3f5d11SAllan Jude for (i = 0; i < len / 8; i++)
867a3f5d11SAllan Jude dst[i] = be64dec(src + i * 8);
877a3f5d11SAllan Jude }
887a3f5d11SAllan Jude
897a3f5d11SAllan Jude #endif /* BYTE_ORDER != BIG_ENDIAN */
907a3f5d11SAllan Jude
91696c3895SColin Percival /* SHA512 round constants. */
92696c3895SColin Percival static const uint64_t K[80] = {
93696c3895SColin Percival 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
94696c3895SColin Percival 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
95696c3895SColin Percival 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
96696c3895SColin Percival 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
97696c3895SColin Percival 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
98696c3895SColin Percival 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
99696c3895SColin Percival 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
100696c3895SColin Percival 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
101696c3895SColin Percival 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
102696c3895SColin Percival 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
103696c3895SColin Percival 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
104696c3895SColin Percival 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
105696c3895SColin Percival 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
106696c3895SColin Percival 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
107696c3895SColin Percival 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
108696c3895SColin Percival 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
109696c3895SColin Percival 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
110696c3895SColin Percival 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
111696c3895SColin Percival 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
112696c3895SColin Percival 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
113696c3895SColin Percival 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
114696c3895SColin Percival 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
115696c3895SColin Percival 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
116696c3895SColin Percival 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
117696c3895SColin Percival 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
118696c3895SColin Percival 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
119696c3895SColin Percival 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
120696c3895SColin Percival 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
121696c3895SColin Percival 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
122696c3895SColin Percival 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
123696c3895SColin Percival 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
124696c3895SColin Percival 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
125696c3895SColin Percival 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
126696c3895SColin Percival 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
127696c3895SColin Percival 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
128696c3895SColin Percival 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
129696c3895SColin Percival 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
130696c3895SColin Percival 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
131696c3895SColin Percival 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
132696c3895SColin Percival 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
133696c3895SColin Percival };
134696c3895SColin Percival
1357a3f5d11SAllan Jude /* Elementary functions used by SHA512 */
1367a3f5d11SAllan Jude #define Ch(x, y, z) ((x & (y ^ z)) ^ z)
1377a3f5d11SAllan Jude #define Maj(x, y, z) ((x & (y | z)) | (y & z))
1387a3f5d11SAllan Jude #define SHR(x, n) (x >> n)
1397a3f5d11SAllan Jude #define ROTR(x, n) ((x >> n) | (x << (64 - n)))
1407a3f5d11SAllan Jude #define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
1417a3f5d11SAllan Jude #define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
1427a3f5d11SAllan Jude #define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
1437a3f5d11SAllan Jude #define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
1447a3f5d11SAllan Jude
1457a3f5d11SAllan Jude /* SHA512 round function */
1467a3f5d11SAllan Jude #define RND(a, b, c, d, e, f, g, h, k) \
147696c3895SColin Percival h += S1(e) + Ch(e, f, g) + k; \
148696c3895SColin Percival d += h; \
149696c3895SColin Percival h += S0(a) + Maj(a, b, c);
1507a3f5d11SAllan Jude
1517a3f5d11SAllan Jude /* Adjusted round function for rotating state */
152696c3895SColin Percival #define RNDr(S, W, i, ii) \
1537a3f5d11SAllan Jude RND(S[(80 - i) % 8], S[(81 - i) % 8], \
1547a3f5d11SAllan Jude S[(82 - i) % 8], S[(83 - i) % 8], \
1557a3f5d11SAllan Jude S[(84 - i) % 8], S[(85 - i) % 8], \
1567a3f5d11SAllan Jude S[(86 - i) % 8], S[(87 - i) % 8], \
157696c3895SColin Percival W[i + ii] + K[i + ii])
158696c3895SColin Percival
159696c3895SColin Percival /* Message schedule computation */
160696c3895SColin Percival #define MSCH(W, ii, i) \
161696c3895SColin Percival W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
1627a3f5d11SAllan Jude
1637a3f5d11SAllan Jude /*
1647a3f5d11SAllan Jude * SHA512 block compression function. The 512-bit state is transformed via
1657a3f5d11SAllan Jude * the 512-bit input block to produce a new state.
1667a3f5d11SAllan Jude */
1677a3f5d11SAllan Jude static void
16871bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
SHA512_Transform_c(uint64_t * state,const unsigned char block[SHA512_BLOCK_LENGTH])16971bf1c4cSAndrew Turner SHA512_Transform_c(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH])
17071bf1c4cSAndrew Turner #else
1717a3f5d11SAllan Jude SHA512_Transform(uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH])
17271bf1c4cSAndrew Turner #endif
1737a3f5d11SAllan Jude {
1747a3f5d11SAllan Jude uint64_t W[80];
1757a3f5d11SAllan Jude uint64_t S[8];
1767a3f5d11SAllan Jude int i;
1777a3f5d11SAllan Jude
178696c3895SColin Percival /* 1. Prepare the first part of the message schedule W. */
1797a3f5d11SAllan Jude be64dec_vect(W, block, SHA512_BLOCK_LENGTH);
1807a3f5d11SAllan Jude
1817a3f5d11SAllan Jude /* 2. Initialize working variables. */
1827a3f5d11SAllan Jude memcpy(S, state, SHA512_DIGEST_LENGTH);
1837a3f5d11SAllan Jude
1847a3f5d11SAllan Jude /* 3. Mix. */
185696c3895SColin Percival for (i = 0; i < 80; i += 16) {
186696c3895SColin Percival RNDr(S, W, 0, i);
187696c3895SColin Percival RNDr(S, W, 1, i);
188696c3895SColin Percival RNDr(S, W, 2, i);
189696c3895SColin Percival RNDr(S, W, 3, i);
190696c3895SColin Percival RNDr(S, W, 4, i);
191696c3895SColin Percival RNDr(S, W, 5, i);
192696c3895SColin Percival RNDr(S, W, 6, i);
193696c3895SColin Percival RNDr(S, W, 7, i);
194696c3895SColin Percival RNDr(S, W, 8, i);
195696c3895SColin Percival RNDr(S, W, 9, i);
196696c3895SColin Percival RNDr(S, W, 10, i);
197696c3895SColin Percival RNDr(S, W, 11, i);
198696c3895SColin Percival RNDr(S, W, 12, i);
199696c3895SColin Percival RNDr(S, W, 13, i);
200696c3895SColin Percival RNDr(S, W, 14, i);
201696c3895SColin Percival RNDr(S, W, 15, i);
202696c3895SColin Percival
203696c3895SColin Percival if (i == 64)
204696c3895SColin Percival break;
205696c3895SColin Percival MSCH(W, 0, i);
206696c3895SColin Percival MSCH(W, 1, i);
207696c3895SColin Percival MSCH(W, 2, i);
208696c3895SColin Percival MSCH(W, 3, i);
209696c3895SColin Percival MSCH(W, 4, i);
210696c3895SColin Percival MSCH(W, 5, i);
211696c3895SColin Percival MSCH(W, 6, i);
212696c3895SColin Percival MSCH(W, 7, i);
213696c3895SColin Percival MSCH(W, 8, i);
214696c3895SColin Percival MSCH(W, 9, i);
215696c3895SColin Percival MSCH(W, 10, i);
216696c3895SColin Percival MSCH(W, 11, i);
217696c3895SColin Percival MSCH(W, 12, i);
218696c3895SColin Percival MSCH(W, 13, i);
219696c3895SColin Percival MSCH(W, 14, i);
220696c3895SColin Percival MSCH(W, 15, i);
221696c3895SColin Percival }
2227a3f5d11SAllan Jude
2237a3f5d11SAllan Jude /* 4. Mix local working variables into global state */
2247a3f5d11SAllan Jude for (i = 0; i < 8; i++)
2257a3f5d11SAllan Jude state[i] += S[i];
2267a3f5d11SAllan Jude }
2277a3f5d11SAllan Jude
22871bf1c4cSAndrew Turner #if defined(ARM64_SHA512)
22971bf1c4cSAndrew Turner static void
SHA512_Transform_arm64(uint64_t * state,const unsigned char block[SHA512_BLOCK_LENGTH])23071bf1c4cSAndrew Turner SHA512_Transform_arm64(uint64_t * state,
23171bf1c4cSAndrew Turner const unsigned char block[SHA512_BLOCK_LENGTH])
23271bf1c4cSAndrew Turner {
23371bf1c4cSAndrew Turner SHA512_Transform_arm64_impl(state, block, K);
23471bf1c4cSAndrew Turner }
23571bf1c4cSAndrew Turner
23671bf1c4cSAndrew Turner DEFINE_UIFUNC(static, void, SHA512_Transform,
23771bf1c4cSAndrew Turner (uint64_t * state, const unsigned char block[SHA512_BLOCK_LENGTH]))
23871bf1c4cSAndrew Turner {
23971bf1c4cSAndrew Turner u_long hwcap;
24071bf1c4cSAndrew Turner
24171bf1c4cSAndrew Turner if (elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)) == 0) {
24271bf1c4cSAndrew Turner if ((hwcap & HWCAP_SHA512) != 0) {
24371bf1c4cSAndrew Turner return (SHA512_Transform_arm64);
24471bf1c4cSAndrew Turner }
24571bf1c4cSAndrew Turner }
24671bf1c4cSAndrew Turner
24771bf1c4cSAndrew Turner return (SHA512_Transform_c);
24871bf1c4cSAndrew Turner }
24971bf1c4cSAndrew Turner #endif
25071bf1c4cSAndrew Turner
2517a3f5d11SAllan Jude static unsigned char PAD[SHA512_BLOCK_LENGTH] = {
2527a3f5d11SAllan Jude 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2537a3f5d11SAllan Jude 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2547a3f5d11SAllan Jude 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2557a3f5d11SAllan Jude 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2567a3f5d11SAllan Jude 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2577a3f5d11SAllan Jude 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2587a3f5d11SAllan Jude 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2597a3f5d11SAllan Jude 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2607a3f5d11SAllan Jude };
2617a3f5d11SAllan Jude
2627a3f5d11SAllan Jude /* Add padding and terminating bit-count. */
2637a3f5d11SAllan Jude static void
SHA512_Pad(SHA512_CTX * ctx)2647a3f5d11SAllan Jude SHA512_Pad(SHA512_CTX * ctx)
2657a3f5d11SAllan Jude {
266696c3895SColin Percival size_t r;
2677a3f5d11SAllan Jude
268696c3895SColin Percival /* Figure out how many bytes we have buffered. */
2697a3f5d11SAllan Jude r = (ctx->count[1] >> 3) & 0x7f;
2707a3f5d11SAllan Jude
271696c3895SColin Percival /* Pad to 112 mod 128, transforming if we finish a block en route. */
272696c3895SColin Percival if (r < 112) {
273696c3895SColin Percival /* Pad to 112 mod 128. */
274696c3895SColin Percival memcpy(&ctx->buf[r], PAD, 112 - r);
275696c3895SColin Percival } else {
276696c3895SColin Percival /* Finish the current block and mix. */
277696c3895SColin Percival memcpy(&ctx->buf[r], PAD, 128 - r);
278696c3895SColin Percival SHA512_Transform(ctx->state, ctx->buf);
279696c3895SColin Percival
280696c3895SColin Percival /* The start of the final block is all zeroes. */
281696c3895SColin Percival memset(&ctx->buf[0], 0, 112);
282696c3895SColin Percival }
283696c3895SColin Percival
284696c3895SColin Percival /* Add the terminating bit-count. */
285696c3895SColin Percival be64enc_vect(&ctx->buf[112], ctx->count, 16);
286696c3895SColin Percival
287696c3895SColin Percival /* Mix in the final block. */
288696c3895SColin Percival SHA512_Transform(ctx->state, ctx->buf);
2897a3f5d11SAllan Jude }
2907a3f5d11SAllan Jude
2917a3f5d11SAllan Jude /* SHA-512 initialization. Begins a SHA-512 operation. */
2927a3f5d11SAllan Jude void
SHA512_Init(SHA512_CTX * ctx)2937a3f5d11SAllan Jude SHA512_Init(SHA512_CTX * ctx)
2947a3f5d11SAllan Jude {
2957a3f5d11SAllan Jude
2967a3f5d11SAllan Jude /* Zero bits processed so far */
2977a3f5d11SAllan Jude ctx->count[0] = ctx->count[1] = 0;
2987a3f5d11SAllan Jude
2997a3f5d11SAllan Jude /* Magic initialization constants */
3007a3f5d11SAllan Jude ctx->state[0] = 0x6a09e667f3bcc908ULL;
3017a3f5d11SAllan Jude ctx->state[1] = 0xbb67ae8584caa73bULL;
3027a3f5d11SAllan Jude ctx->state[2] = 0x3c6ef372fe94f82bULL;
3037a3f5d11SAllan Jude ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
3047a3f5d11SAllan Jude ctx->state[4] = 0x510e527fade682d1ULL;
3057a3f5d11SAllan Jude ctx->state[5] = 0x9b05688c2b3e6c1fULL;
3067a3f5d11SAllan Jude ctx->state[6] = 0x1f83d9abfb41bd6bULL;
3077a3f5d11SAllan Jude ctx->state[7] = 0x5be0cd19137e2179ULL;
3087a3f5d11SAllan Jude }
3097a3f5d11SAllan Jude
3107a3f5d11SAllan Jude /* Add bytes into the hash */
3117a3f5d11SAllan Jude void
SHA512_Update(SHA512_CTX * ctx,const void * in,size_t len)3127a3f5d11SAllan Jude SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
3137a3f5d11SAllan Jude {
3147a3f5d11SAllan Jude uint64_t bitlen[2];
3157a3f5d11SAllan Jude uint64_t r;
3167a3f5d11SAllan Jude const unsigned char *src = in;
3177a3f5d11SAllan Jude
3187a3f5d11SAllan Jude /* Number of bytes left in the buffer from previous updates */
3197a3f5d11SAllan Jude r = (ctx->count[1] >> 3) & 0x7f;
3207a3f5d11SAllan Jude
3217a3f5d11SAllan Jude /* Convert the length into a number of bits */
3227a3f5d11SAllan Jude bitlen[1] = ((uint64_t)len) << 3;
3237a3f5d11SAllan Jude bitlen[0] = ((uint64_t)len) >> 61;
3247a3f5d11SAllan Jude
3257a3f5d11SAllan Jude /* Update number of bits */
3267a3f5d11SAllan Jude if ((ctx->count[1] += bitlen[1]) < bitlen[1])
3277a3f5d11SAllan Jude ctx->count[0]++;
3287a3f5d11SAllan Jude ctx->count[0] += bitlen[0];
3297a3f5d11SAllan Jude
3307a3f5d11SAllan Jude /* Handle the case where we don't need to perform any transforms */
3317a3f5d11SAllan Jude if (len < SHA512_BLOCK_LENGTH - r) {
3327a3f5d11SAllan Jude memcpy(&ctx->buf[r], src, len);
3337a3f5d11SAllan Jude return;
3347a3f5d11SAllan Jude }
3357a3f5d11SAllan Jude
3367a3f5d11SAllan Jude /* Finish the current block */
3377a3f5d11SAllan Jude memcpy(&ctx->buf[r], src, SHA512_BLOCK_LENGTH - r);
3387a3f5d11SAllan Jude SHA512_Transform(ctx->state, ctx->buf);
3397a3f5d11SAllan Jude src += SHA512_BLOCK_LENGTH - r;
3407a3f5d11SAllan Jude len -= SHA512_BLOCK_LENGTH - r;
3417a3f5d11SAllan Jude
3427a3f5d11SAllan Jude /* Perform complete blocks */
3437a3f5d11SAllan Jude while (len >= SHA512_BLOCK_LENGTH) {
3447a3f5d11SAllan Jude SHA512_Transform(ctx->state, src);
3457a3f5d11SAllan Jude src += SHA512_BLOCK_LENGTH;
3467a3f5d11SAllan Jude len -= SHA512_BLOCK_LENGTH;
3477a3f5d11SAllan Jude }
3487a3f5d11SAllan Jude
3497a3f5d11SAllan Jude /* Copy left over data into buffer */
3507a3f5d11SAllan Jude memcpy(ctx->buf, src, len);
3517a3f5d11SAllan Jude }
3527a3f5d11SAllan Jude
3537a3f5d11SAllan Jude /*
3547a3f5d11SAllan Jude * SHA-512 finalization. Pads the input data, exports the hash value,
3557a3f5d11SAllan Jude * and clears the context state.
3567a3f5d11SAllan Jude */
3577a3f5d11SAllan Jude void
SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH],SHA512_CTX * ctx)358571ebf76SConrad Meyer SHA512_Final(unsigned char digest[static SHA512_DIGEST_LENGTH], SHA512_CTX *ctx)
3597a3f5d11SAllan Jude {
3607a3f5d11SAllan Jude
3617a3f5d11SAllan Jude /* Add padding */
3627a3f5d11SAllan Jude SHA512_Pad(ctx);
3637a3f5d11SAllan Jude
3647a3f5d11SAllan Jude /* Write the hash */
3657a3f5d11SAllan Jude be64enc_vect(digest, ctx->state, SHA512_DIGEST_LENGTH);
3667a3f5d11SAllan Jude
3677a3f5d11SAllan Jude /* Clear the context state */
36866bdf50fSXin LI explicit_bzero(ctx, sizeof(*ctx));
3697a3f5d11SAllan Jude }
3707a3f5d11SAllan Jude
3711780e407SAllan Jude /*** SHA-512t: *********************************************************/
3721780e407SAllan Jude /*
3731780e407SAllan Jude * the SHA512t transforms are identical to SHA512 so reuse the existing function
3741780e407SAllan Jude */
3751780e407SAllan Jude void
SHA512_224_Init(SHA512_CTX * ctx)3761780e407SAllan Jude SHA512_224_Init(SHA512_CTX * ctx)
3771780e407SAllan Jude {
3781780e407SAllan Jude
3791780e407SAllan Jude /* Zero bits processed so far */
3801780e407SAllan Jude ctx->count[0] = ctx->count[1] = 0;
3811780e407SAllan Jude
3821780e407SAllan Jude /* Magic initialization constants */
3831780e407SAllan Jude ctx->state[0] = 0x8c3d37c819544da2ULL;
3841780e407SAllan Jude ctx->state[1] = 0x73e1996689dcd4d6ULL;
3851780e407SAllan Jude ctx->state[2] = 0x1dfab7ae32ff9c82ULL;
3861780e407SAllan Jude ctx->state[3] = 0x679dd514582f9fcfULL;
3871780e407SAllan Jude ctx->state[4] = 0x0f6d2b697bd44da8ULL;
3881780e407SAllan Jude ctx->state[5] = 0x77e36f7304c48942ULL;
3891780e407SAllan Jude ctx->state[6] = 0x3f9d85a86a1d36c8ULL;
3901780e407SAllan Jude ctx->state[7] = 0x1112e6ad91d692a1ULL;
3911780e407SAllan Jude }
3921780e407SAllan Jude
3931780e407SAllan Jude void
SHA512_224_Update(SHA512_CTX * ctx,const void * in,size_t len)3941780e407SAllan Jude SHA512_224_Update(SHA512_CTX * ctx, const void *in, size_t len)
3951780e407SAllan Jude {
3961780e407SAllan Jude
3971780e407SAllan Jude SHA512_Update(ctx, in, len);
3981780e407SAllan Jude }
3991780e407SAllan Jude
4001780e407SAllan Jude void
SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH],SHA512_CTX * ctx)4011780e407SAllan Jude SHA512_224_Final(unsigned char digest[static SHA512_224_DIGEST_LENGTH], SHA512_CTX * ctx)
4021780e407SAllan Jude {
4031780e407SAllan Jude
4041780e407SAllan Jude /* Add padding */
4051780e407SAllan Jude SHA512_Pad(ctx);
4061780e407SAllan Jude
4071780e407SAllan Jude /* Write the hash */
4081780e407SAllan Jude be64enc_vect(digest, ctx->state, SHA512_224_DIGEST_LENGTH);
4091780e407SAllan Jude
4101780e407SAllan Jude /* Clear the context state */
41166bdf50fSXin LI explicit_bzero(ctx, sizeof(*ctx));
4121780e407SAllan Jude }
4131780e407SAllan Jude
4141780e407SAllan Jude void
SHA512_256_Init(SHA512_CTX * ctx)4151780e407SAllan Jude SHA512_256_Init(SHA512_CTX * ctx)
4161780e407SAllan Jude {
4171780e407SAllan Jude
4181780e407SAllan Jude /* Zero bits processed so far */
4191780e407SAllan Jude ctx->count[0] = ctx->count[1] = 0;
4201780e407SAllan Jude
4211780e407SAllan Jude /* Magic initialization constants */
4221780e407SAllan Jude ctx->state[0] = 0x22312194fc2bf72cULL;
4231780e407SAllan Jude ctx->state[1] = 0x9f555fa3c84c64c2ULL;
4241780e407SAllan Jude ctx->state[2] = 0x2393b86b6f53b151ULL;
4251780e407SAllan Jude ctx->state[3] = 0x963877195940eabdULL;
4261780e407SAllan Jude ctx->state[4] = 0x96283ee2a88effe3ULL;
4271780e407SAllan Jude ctx->state[5] = 0xbe5e1e2553863992ULL;
4281780e407SAllan Jude ctx->state[6] = 0x2b0199fc2c85b8aaULL;
4291780e407SAllan Jude ctx->state[7] = 0x0eb72ddc81c52ca2ULL;
4301780e407SAllan Jude }
4311780e407SAllan Jude
4321780e407SAllan Jude void
SHA512_256_Update(SHA512_CTX * ctx,const void * in,size_t len)4331780e407SAllan Jude SHA512_256_Update(SHA512_CTX * ctx, const void *in, size_t len)
4341780e407SAllan Jude {
4351780e407SAllan Jude
4361780e407SAllan Jude SHA512_Update(ctx, in, len);
4371780e407SAllan Jude }
4381780e407SAllan Jude
4391780e407SAllan Jude void
SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH],SHA512_CTX * ctx)4401780e407SAllan Jude SHA512_256_Final(unsigned char digest[static SHA512_256_DIGEST_LENGTH], SHA512_CTX * ctx)
4411780e407SAllan Jude {
4421780e407SAllan Jude
4431780e407SAllan Jude /* Add padding */
4441780e407SAllan Jude SHA512_Pad(ctx);
4451780e407SAllan Jude
4461780e407SAllan Jude /* Write the hash */
4471780e407SAllan Jude be64enc_vect(digest, ctx->state, SHA512_256_DIGEST_LENGTH);
4481780e407SAllan Jude
4491780e407SAllan Jude /* Clear the context state */
45066bdf50fSXin LI explicit_bzero(ctx, sizeof(*ctx));
4511780e407SAllan Jude }
4521780e407SAllan Jude
4537a3f5d11SAllan Jude /*** SHA-384: *********************************************************/
4547a3f5d11SAllan Jude /*
4557a3f5d11SAllan Jude * the SHA384 and SHA512 transforms are identical, so SHA384 is skipped
4567a3f5d11SAllan Jude */
4577a3f5d11SAllan Jude
4587a3f5d11SAllan Jude /* SHA-384 initialization. Begins a SHA-384 operation. */
4597a3f5d11SAllan Jude void
SHA384_Init(SHA384_CTX * ctx)4607a3f5d11SAllan Jude SHA384_Init(SHA384_CTX * ctx)
4617a3f5d11SAllan Jude {
4627a3f5d11SAllan Jude
4637a3f5d11SAllan Jude /* Zero bits processed so far */
4647a3f5d11SAllan Jude ctx->count[0] = ctx->count[1] = 0;
4657a3f5d11SAllan Jude
4667a3f5d11SAllan Jude /* Magic initialization constants */
4677a3f5d11SAllan Jude ctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
4687a3f5d11SAllan Jude ctx->state[1] = 0x629a292a367cd507ULL;
4697a3f5d11SAllan Jude ctx->state[2] = 0x9159015a3070dd17ULL;
4707a3f5d11SAllan Jude ctx->state[3] = 0x152fecd8f70e5939ULL;
4717a3f5d11SAllan Jude ctx->state[4] = 0x67332667ffc00b31ULL;
4727a3f5d11SAllan Jude ctx->state[5] = 0x8eb44a8768581511ULL;
4737a3f5d11SAllan Jude ctx->state[6] = 0xdb0c2e0d64f98fa7ULL;
4747a3f5d11SAllan Jude ctx->state[7] = 0x47b5481dbefa4fa4ULL;
4757a3f5d11SAllan Jude }
4767a3f5d11SAllan Jude
4777a3f5d11SAllan Jude /* Add bytes into the SHA-384 hash */
4787a3f5d11SAllan Jude void
SHA384_Update(SHA384_CTX * ctx,const void * in,size_t len)4797a3f5d11SAllan Jude SHA384_Update(SHA384_CTX * ctx, const void *in, size_t len)
4807a3f5d11SAllan Jude {
4817a3f5d11SAllan Jude
4827a3f5d11SAllan Jude SHA512_Update((SHA512_CTX *)ctx, in, len);
4837a3f5d11SAllan Jude }
4847a3f5d11SAllan Jude
4857a3f5d11SAllan Jude /*
4867a3f5d11SAllan Jude * SHA-384 finalization. Pads the input data, exports the hash value,
4877a3f5d11SAllan Jude * and clears the context state.
4887a3f5d11SAllan Jude */
4897a3f5d11SAllan Jude void
SHA384_Final(unsigned char digest[static SHA384_DIGEST_LENGTH],SHA384_CTX * ctx)490571ebf76SConrad Meyer SHA384_Final(unsigned char digest[static SHA384_DIGEST_LENGTH], SHA384_CTX *ctx)
4917a3f5d11SAllan Jude {
4927a3f5d11SAllan Jude
4937a3f5d11SAllan Jude /* Add padding */
4947a3f5d11SAllan Jude SHA512_Pad((SHA512_CTX *)ctx);
4957a3f5d11SAllan Jude
4967a3f5d11SAllan Jude /* Write the hash */
4977a3f5d11SAllan Jude be64enc_vect(digest, ctx->state, SHA384_DIGEST_LENGTH);
4987a3f5d11SAllan Jude
4997a3f5d11SAllan Jude /* Clear the context state */
50066bdf50fSXin LI explicit_bzero(ctx, sizeof(*ctx));
5017a3f5d11SAllan Jude }
5027a3f5d11SAllan Jude
5037a3f5d11SAllan Jude #ifdef WEAK_REFS
5047a3f5d11SAllan Jude /* When building libmd, provide weak references. Note: this is not
5057a3f5d11SAllan Jude activated in the context of compiling these sources for internal
5067a3f5d11SAllan Jude use in libcrypt.
5077a3f5d11SAllan Jude */
5087a3f5d11SAllan Jude #undef SHA512_Init
5097a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Init, SHA512_Init);
5107a3f5d11SAllan Jude #undef SHA512_Update
5117a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Update, SHA512_Update);
5127a3f5d11SAllan Jude #undef SHA512_Final
5137a3f5d11SAllan Jude __weak_reference(_libmd_SHA512_Final, SHA512_Final);
5147a3f5d11SAllan Jude
5151780e407SAllan Jude #undef SHA512_224_Init
5161780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Init, SHA512_224_Init);
5171780e407SAllan Jude #undef SHA512_224_Update
5181780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Update, SHA512_224_Update);
5191780e407SAllan Jude #undef SHA512_224_Final
5201780e407SAllan Jude __weak_reference(_libmd_SHA512_224_Final, SHA512_224_Final);
5211780e407SAllan Jude
5221780e407SAllan Jude #undef SHA512_256_Init
5231780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Init, SHA512_256_Init);
5241780e407SAllan Jude #undef SHA512_256_Update
5251780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Update, SHA512_256_Update);
5261780e407SAllan Jude #undef SHA512_256_Final
5271780e407SAllan Jude __weak_reference(_libmd_SHA512_256_Final, SHA512_256_Final);
5281780e407SAllan Jude
5297a3f5d11SAllan Jude #undef SHA384_Init
5307a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Init, SHA384_Init);
5317a3f5d11SAllan Jude #undef SHA384_Update
5327a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Update, SHA384_Update);
5337a3f5d11SAllan Jude #undef SHA384_Final
5347a3f5d11SAllan Jude __weak_reference(_libmd_SHA384_Final, SHA384_Final);
5357a3f5d11SAllan Jude #endif
536