197447ea4SJohn-Mark Gurney /*-
297447ea4SJohn-Mark Gurney * Copyright 2005 Colin Percival
397447ea4SJohn-Mark Gurney * All rights reserved.
497447ea4SJohn-Mark Gurney *
597447ea4SJohn-Mark Gurney * Redistribution and use in source and binary forms, with or without
697447ea4SJohn-Mark Gurney * modification, are permitted provided that the following conditions
797447ea4SJohn-Mark Gurney * are met:
897447ea4SJohn-Mark Gurney * 1. Redistributions of source code must retain the above copyright
997447ea4SJohn-Mark Gurney * notice, this list of conditions and the following disclaimer.
1097447ea4SJohn-Mark Gurney * 2. Redistributions in binary form must reproduce the above copyright
1197447ea4SJohn-Mark Gurney * notice, this list of conditions and the following disclaimer in the
1297447ea4SJohn-Mark Gurney * documentation and/or other materials provided with the distribution.
1397447ea4SJohn-Mark Gurney *
1497447ea4SJohn-Mark Gurney * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1597447ea4SJohn-Mark Gurney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1697447ea4SJohn-Mark Gurney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1797447ea4SJohn-Mark Gurney * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1897447ea4SJohn-Mark Gurney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1997447ea4SJohn-Mark Gurney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2097447ea4SJohn-Mark Gurney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2197447ea4SJohn-Mark Gurney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2297447ea4SJohn-Mark Gurney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2397447ea4SJohn-Mark Gurney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2497447ea4SJohn-Mark Gurney * SUCH DAMAGE.
2597447ea4SJohn-Mark Gurney */
2697447ea4SJohn-Mark Gurney
2797447ea4SJohn-Mark Gurney #include <sys/cdefs.h>
2897447ea4SJohn-Mark Gurney #include <sys/endian.h>
2997447ea4SJohn-Mark Gurney #include <sys/types.h>
3097447ea4SJohn-Mark Gurney
318083f14fSJohn-Mark Gurney #ifdef _KERNEL
328083f14fSJohn-Mark Gurney #include <sys/systm.h>
338083f14fSJohn-Mark Gurney #else
3497447ea4SJohn-Mark Gurney #include <string.h>
358083f14fSJohn-Mark Gurney #endif
3697447ea4SJohn-Mark Gurney
371245c6d1SConrad Meyer #include "sha224.h"
3897447ea4SJohn-Mark Gurney #include "sha256.h"
3969d8dc20SAndrew Turner #include "sha256c_impl.h"
4069d8dc20SAndrew Turner
4169d8dc20SAndrew Turner #if defined(ARM64_SHA2)
4269d8dc20SAndrew Turner #include <sys/auxv.h>
4369d8dc20SAndrew Turner #include <machine/ifunc.h>
4469d8dc20SAndrew Turner #endif
4597447ea4SJohn-Mark Gurney
4697447ea4SJohn-Mark Gurney #if BYTE_ORDER == BIG_ENDIAN
4797447ea4SJohn-Mark Gurney
4897447ea4SJohn-Mark Gurney /* Copy a vector of big-endian uint32_t into a vector of bytes */
4997447ea4SJohn-Mark Gurney #define be32enc_vect(dst, src, len) \
5097447ea4SJohn-Mark Gurney memcpy((void *)dst, (const void *)src, (size_t)len)
5197447ea4SJohn-Mark Gurney
5297447ea4SJohn-Mark Gurney /* Copy a vector of bytes into a vector of big-endian uint32_t */
5397447ea4SJohn-Mark Gurney #define be32dec_vect(dst, src, len) \
5497447ea4SJohn-Mark Gurney memcpy((void *)dst, (const void *)src, (size_t)len)
5597447ea4SJohn-Mark Gurney
5697447ea4SJohn-Mark Gurney #else /* BYTE_ORDER != BIG_ENDIAN */
5797447ea4SJohn-Mark Gurney
5897447ea4SJohn-Mark Gurney /*
5997447ea4SJohn-Mark Gurney * Encode a length len/4 vector of (uint32_t) into a length len vector of
6097447ea4SJohn-Mark Gurney * (unsigned char) in big-endian form. Assumes len is a multiple of 4.
6197447ea4SJohn-Mark Gurney */
6297447ea4SJohn-Mark Gurney static void
be32enc_vect(unsigned char * dst,const uint32_t * src,size_t len)6397447ea4SJohn-Mark Gurney be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
6497447ea4SJohn-Mark Gurney {
6597447ea4SJohn-Mark Gurney size_t i;
6697447ea4SJohn-Mark Gurney
6797447ea4SJohn-Mark Gurney for (i = 0; i < len / 4; i++)
6897447ea4SJohn-Mark Gurney be32enc(dst + i * 4, src[i]);
6997447ea4SJohn-Mark Gurney }
7097447ea4SJohn-Mark Gurney
7197447ea4SJohn-Mark Gurney /*
7297447ea4SJohn-Mark Gurney * Decode a big-endian length len vector of (unsigned char) into a length
7397447ea4SJohn-Mark Gurney * len/4 vector of (uint32_t). Assumes len is a multiple of 4.
7497447ea4SJohn-Mark Gurney */
7597447ea4SJohn-Mark Gurney static void
be32dec_vect(uint32_t * dst,const unsigned char * src,size_t len)7697447ea4SJohn-Mark Gurney be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
7797447ea4SJohn-Mark Gurney {
7897447ea4SJohn-Mark Gurney size_t i;
7997447ea4SJohn-Mark Gurney
8097447ea4SJohn-Mark Gurney for (i = 0; i < len / 4; i++)
8197447ea4SJohn-Mark Gurney dst[i] = be32dec(src + i * 4);
8297447ea4SJohn-Mark Gurney }
8397447ea4SJohn-Mark Gurney
8497447ea4SJohn-Mark Gurney #endif /* BYTE_ORDER != BIG_ENDIAN */
8597447ea4SJohn-Mark Gurney
86696c3895SColin Percival /* SHA256 round constants. */
87696c3895SColin Percival static const uint32_t K[64] = {
88696c3895SColin Percival 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
89696c3895SColin Percival 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
90696c3895SColin Percival 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
91696c3895SColin Percival 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
92696c3895SColin Percival 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
93696c3895SColin Percival 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
94696c3895SColin Percival 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
95696c3895SColin Percival 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
96696c3895SColin Percival 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
97696c3895SColin Percival 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
98696c3895SColin Percival 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
99696c3895SColin Percival 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
100696c3895SColin Percival 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
101696c3895SColin Percival 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
102696c3895SColin Percival 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
103696c3895SColin Percival 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
104696c3895SColin Percival };
105696c3895SColin Percival
10697447ea4SJohn-Mark Gurney /* Elementary functions used by SHA256 */
10797447ea4SJohn-Mark Gurney #define Ch(x, y, z) ((x & (y ^ z)) ^ z)
10897447ea4SJohn-Mark Gurney #define Maj(x, y, z) ((x & (y | z)) | (y & z))
10997447ea4SJohn-Mark Gurney #define SHR(x, n) (x >> n)
11097447ea4SJohn-Mark Gurney #define ROTR(x, n) ((x >> n) | (x << (32 - n)))
11197447ea4SJohn-Mark Gurney #define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
11297447ea4SJohn-Mark Gurney #define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
11397447ea4SJohn-Mark Gurney #define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
11497447ea4SJohn-Mark Gurney #define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
11597447ea4SJohn-Mark Gurney
11697447ea4SJohn-Mark Gurney /* SHA256 round function */
11797447ea4SJohn-Mark Gurney #define RND(a, b, c, d, e, f, g, h, k) \
118696c3895SColin Percival h += S1(e) + Ch(e, f, g) + k; \
119696c3895SColin Percival d += h; \
120696c3895SColin Percival h += S0(a) + Maj(a, b, c);
12197447ea4SJohn-Mark Gurney
12297447ea4SJohn-Mark Gurney /* Adjusted round function for rotating state */
123696c3895SColin Percival #define RNDr(S, W, i, ii) \
12497447ea4SJohn-Mark Gurney RND(S[(64 - i) % 8], S[(65 - i) % 8], \
12597447ea4SJohn-Mark Gurney S[(66 - i) % 8], S[(67 - i) % 8], \
12697447ea4SJohn-Mark Gurney S[(68 - i) % 8], S[(69 - i) % 8], \
12797447ea4SJohn-Mark Gurney S[(70 - i) % 8], S[(71 - i) % 8], \
128696c3895SColin Percival W[i + ii] + K[i + ii])
129696c3895SColin Percival
130696c3895SColin Percival /* Message schedule computation */
131696c3895SColin Percival #define MSCH(W, ii, i) \
132696c3895SColin Percival W[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]
13397447ea4SJohn-Mark Gurney
13497447ea4SJohn-Mark Gurney /*
13597447ea4SJohn-Mark Gurney * SHA256 block compression function. The 256-bit state is transformed via
13697447ea4SJohn-Mark Gurney * the 512-bit input block to produce a new state.
13797447ea4SJohn-Mark Gurney */
13897447ea4SJohn-Mark Gurney static void
139*a6765c4bSJohn Baldwin #if defined(ARM64_SHA2)
SHA256_Transform_c(uint32_t * state,const unsigned char block[64])14069d8dc20SAndrew Turner SHA256_Transform_c(uint32_t * state, const unsigned char block[64])
141*a6765c4bSJohn Baldwin #else
142*a6765c4bSJohn Baldwin SHA256_Transform(uint32_t * state, const unsigned char block[64])
143*a6765c4bSJohn Baldwin #endif
14497447ea4SJohn-Mark Gurney {
14597447ea4SJohn-Mark Gurney uint32_t W[64];
14697447ea4SJohn-Mark Gurney uint32_t S[8];
14797447ea4SJohn-Mark Gurney int i;
14897447ea4SJohn-Mark Gurney
149696c3895SColin Percival /* 1. Prepare the first part of the message schedule W. */
15097447ea4SJohn-Mark Gurney be32dec_vect(W, block, 64);
15197447ea4SJohn-Mark Gurney
15297447ea4SJohn-Mark Gurney /* 2. Initialize working variables. */
15397447ea4SJohn-Mark Gurney memcpy(S, state, 32);
15497447ea4SJohn-Mark Gurney
15597447ea4SJohn-Mark Gurney /* 3. Mix. */
156696c3895SColin Percival for (i = 0; i < 64; i += 16) {
157696c3895SColin Percival RNDr(S, W, 0, i);
158696c3895SColin Percival RNDr(S, W, 1, i);
159696c3895SColin Percival RNDr(S, W, 2, i);
160696c3895SColin Percival RNDr(S, W, 3, i);
161696c3895SColin Percival RNDr(S, W, 4, i);
162696c3895SColin Percival RNDr(S, W, 5, i);
163696c3895SColin Percival RNDr(S, W, 6, i);
164696c3895SColin Percival RNDr(S, W, 7, i);
165696c3895SColin Percival RNDr(S, W, 8, i);
166696c3895SColin Percival RNDr(S, W, 9, i);
167696c3895SColin Percival RNDr(S, W, 10, i);
168696c3895SColin Percival RNDr(S, W, 11, i);
169696c3895SColin Percival RNDr(S, W, 12, i);
170696c3895SColin Percival RNDr(S, W, 13, i);
171696c3895SColin Percival RNDr(S, W, 14, i);
172696c3895SColin Percival RNDr(S, W, 15, i);
173696c3895SColin Percival
174696c3895SColin Percival if (i == 48)
175696c3895SColin Percival break;
176696c3895SColin Percival MSCH(W, 0, i);
177696c3895SColin Percival MSCH(W, 1, i);
178696c3895SColin Percival MSCH(W, 2, i);
179696c3895SColin Percival MSCH(W, 3, i);
180696c3895SColin Percival MSCH(W, 4, i);
181696c3895SColin Percival MSCH(W, 5, i);
182696c3895SColin Percival MSCH(W, 6, i);
183696c3895SColin Percival MSCH(W, 7, i);
184696c3895SColin Percival MSCH(W, 8, i);
185696c3895SColin Percival MSCH(W, 9, i);
186696c3895SColin Percival MSCH(W, 10, i);
187696c3895SColin Percival MSCH(W, 11, i);
188696c3895SColin Percival MSCH(W, 12, i);
189696c3895SColin Percival MSCH(W, 13, i);
190696c3895SColin Percival MSCH(W, 14, i);
191696c3895SColin Percival MSCH(W, 15, i);
192696c3895SColin Percival }
19397447ea4SJohn-Mark Gurney
19497447ea4SJohn-Mark Gurney /* 4. Mix local working variables into global state */
19597447ea4SJohn-Mark Gurney for (i = 0; i < 8; i++)
19697447ea4SJohn-Mark Gurney state[i] += S[i];
19797447ea4SJohn-Mark Gurney }
19897447ea4SJohn-Mark Gurney
19969d8dc20SAndrew Turner #if defined(ARM64_SHA2)
20069d8dc20SAndrew Turner static void
SHA256_Transform_arm64(uint32_t * state,const unsigned char block[64])20169d8dc20SAndrew Turner SHA256_Transform_arm64(uint32_t * state, const unsigned char block[64])
20269d8dc20SAndrew Turner {
20369d8dc20SAndrew Turner SHA256_Transform_arm64_impl(state, block, K);
20469d8dc20SAndrew Turner }
20569d8dc20SAndrew Turner
20669d8dc20SAndrew Turner DEFINE_UIFUNC(static, void, SHA256_Transform,
20769d8dc20SAndrew Turner (uint32_t * state, const unsigned char block[64]))
20869d8dc20SAndrew Turner {
20969d8dc20SAndrew Turner u_long hwcap;
21069d8dc20SAndrew Turner
21169d8dc20SAndrew Turner if (elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)) == 0) {
21269d8dc20SAndrew Turner if ((hwcap & HWCAP_SHA2) != 0)
21369d8dc20SAndrew Turner return (SHA256_Transform_arm64);
21469d8dc20SAndrew Turner }
21569d8dc20SAndrew Turner
21669d8dc20SAndrew Turner return (SHA256_Transform_c);
21769d8dc20SAndrew Turner }
21869d8dc20SAndrew Turner #endif
21969d8dc20SAndrew Turner
22097447ea4SJohn-Mark Gurney static unsigned char PAD[64] = {
22197447ea4SJohn-Mark Gurney 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22297447ea4SJohn-Mark Gurney 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22397447ea4SJohn-Mark Gurney 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22497447ea4SJohn-Mark Gurney 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
22597447ea4SJohn-Mark Gurney };
22697447ea4SJohn-Mark Gurney
22797447ea4SJohn-Mark Gurney /* Add padding and terminating bit-count. */
22897447ea4SJohn-Mark Gurney static void
SHA256_Pad(SHA256_CTX * ctx)22997447ea4SJohn-Mark Gurney SHA256_Pad(SHA256_CTX * ctx)
23097447ea4SJohn-Mark Gurney {
231696c3895SColin Percival size_t r;
23297447ea4SJohn-Mark Gurney
233696c3895SColin Percival /* Figure out how many bytes we have buffered. */
23497447ea4SJohn-Mark Gurney r = (ctx->count >> 3) & 0x3f;
23597447ea4SJohn-Mark Gurney
236696c3895SColin Percival /* Pad to 56 mod 64, transforming if we finish a block en route. */
237696c3895SColin Percival if (r < 56) {
238696c3895SColin Percival /* Pad to 56 mod 64. */
239696c3895SColin Percival memcpy(&ctx->buf[r], PAD, 56 - r);
240696c3895SColin Percival } else {
241696c3895SColin Percival /* Finish the current block and mix. */
242696c3895SColin Percival memcpy(&ctx->buf[r], PAD, 64 - r);
243696c3895SColin Percival SHA256_Transform(ctx->state, ctx->buf);
244696c3895SColin Percival
245696c3895SColin Percival /* The start of the final block is all zeroes. */
246696c3895SColin Percival memset(&ctx->buf[0], 0, 56);
247696c3895SColin Percival }
248696c3895SColin Percival
249696c3895SColin Percival /* Add the terminating bit-count. */
250696c3895SColin Percival be64enc(&ctx->buf[56], ctx->count);
251696c3895SColin Percival
252696c3895SColin Percival /* Mix in the final block. */
253696c3895SColin Percival SHA256_Transform(ctx->state, ctx->buf);
25497447ea4SJohn-Mark Gurney }
25597447ea4SJohn-Mark Gurney
25697447ea4SJohn-Mark Gurney /* SHA-256 initialization. Begins a SHA-256 operation. */
25797447ea4SJohn-Mark Gurney void
SHA256_Init(SHA256_CTX * ctx)25897447ea4SJohn-Mark Gurney SHA256_Init(SHA256_CTX * ctx)
25997447ea4SJohn-Mark Gurney {
26097447ea4SJohn-Mark Gurney
26197447ea4SJohn-Mark Gurney /* Zero bits processed so far */
26297447ea4SJohn-Mark Gurney ctx->count = 0;
26397447ea4SJohn-Mark Gurney
26497447ea4SJohn-Mark Gurney /* Magic initialization constants */
26597447ea4SJohn-Mark Gurney ctx->state[0] = 0x6A09E667;
26697447ea4SJohn-Mark Gurney ctx->state[1] = 0xBB67AE85;
26797447ea4SJohn-Mark Gurney ctx->state[2] = 0x3C6EF372;
26897447ea4SJohn-Mark Gurney ctx->state[3] = 0xA54FF53A;
26997447ea4SJohn-Mark Gurney ctx->state[4] = 0x510E527F;
27097447ea4SJohn-Mark Gurney ctx->state[5] = 0x9B05688C;
27197447ea4SJohn-Mark Gurney ctx->state[6] = 0x1F83D9AB;
27297447ea4SJohn-Mark Gurney ctx->state[7] = 0x5BE0CD19;
27397447ea4SJohn-Mark Gurney }
27497447ea4SJohn-Mark Gurney
27597447ea4SJohn-Mark Gurney /* Add bytes into the hash */
27697447ea4SJohn-Mark Gurney void
SHA256_Update(SHA256_CTX * ctx,const void * in,size_t len)27797447ea4SJohn-Mark Gurney SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len)
27897447ea4SJohn-Mark Gurney {
27997447ea4SJohn-Mark Gurney uint64_t bitlen;
28097447ea4SJohn-Mark Gurney uint32_t r;
28197447ea4SJohn-Mark Gurney const unsigned char *src = in;
28297447ea4SJohn-Mark Gurney
28397447ea4SJohn-Mark Gurney /* Number of bytes left in the buffer from previous updates */
28497447ea4SJohn-Mark Gurney r = (ctx->count >> 3) & 0x3f;
28597447ea4SJohn-Mark Gurney
28697447ea4SJohn-Mark Gurney /* Convert the length into a number of bits */
28797447ea4SJohn-Mark Gurney bitlen = len << 3;
28897447ea4SJohn-Mark Gurney
28997447ea4SJohn-Mark Gurney /* Update number of bits */
29097447ea4SJohn-Mark Gurney ctx->count += bitlen;
29197447ea4SJohn-Mark Gurney
29297447ea4SJohn-Mark Gurney /* Handle the case where we don't need to perform any transforms */
29397447ea4SJohn-Mark Gurney if (len < 64 - r) {
29497447ea4SJohn-Mark Gurney memcpy(&ctx->buf[r], src, len);
29597447ea4SJohn-Mark Gurney return;
29697447ea4SJohn-Mark Gurney }
29797447ea4SJohn-Mark Gurney
29897447ea4SJohn-Mark Gurney /* Finish the current block */
29997447ea4SJohn-Mark Gurney memcpy(&ctx->buf[r], src, 64 - r);
30097447ea4SJohn-Mark Gurney SHA256_Transform(ctx->state, ctx->buf);
30197447ea4SJohn-Mark Gurney src += 64 - r;
30297447ea4SJohn-Mark Gurney len -= 64 - r;
30397447ea4SJohn-Mark Gurney
30497447ea4SJohn-Mark Gurney /* Perform complete blocks */
30597447ea4SJohn-Mark Gurney while (len >= 64) {
30697447ea4SJohn-Mark Gurney SHA256_Transform(ctx->state, src);
30797447ea4SJohn-Mark Gurney src += 64;
30897447ea4SJohn-Mark Gurney len -= 64;
30997447ea4SJohn-Mark Gurney }
31097447ea4SJohn-Mark Gurney
31197447ea4SJohn-Mark Gurney /* Copy left over data into buffer */
31297447ea4SJohn-Mark Gurney memcpy(ctx->buf, src, len);
31397447ea4SJohn-Mark Gurney }
31497447ea4SJohn-Mark Gurney
31597447ea4SJohn-Mark Gurney /*
31697447ea4SJohn-Mark Gurney * SHA-256 finalization. Pads the input data, exports the hash value,
31797447ea4SJohn-Mark Gurney * and clears the context state.
31897447ea4SJohn-Mark Gurney */
31997447ea4SJohn-Mark Gurney void
SHA256_Final(unsigned char digest[static SHA256_DIGEST_LENGTH],SHA256_CTX * ctx)320571ebf76SConrad Meyer SHA256_Final(unsigned char digest[static SHA256_DIGEST_LENGTH], SHA256_CTX *ctx)
32197447ea4SJohn-Mark Gurney {
32297447ea4SJohn-Mark Gurney
32397447ea4SJohn-Mark Gurney /* Add padding */
32497447ea4SJohn-Mark Gurney SHA256_Pad(ctx);
32597447ea4SJohn-Mark Gurney
32697447ea4SJohn-Mark Gurney /* Write the hash */
327571ebf76SConrad Meyer be32enc_vect(digest, ctx->state, SHA256_DIGEST_LENGTH);
32897447ea4SJohn-Mark Gurney
32997447ea4SJohn-Mark Gurney /* Clear the context state */
33066bdf50fSXin LI explicit_bzero(ctx, sizeof(*ctx));
33197447ea4SJohn-Mark Gurney }
3322ff9c4f9SJohn-Mark Gurney
3331245c6d1SConrad Meyer /*** SHA-224: *********************************************************/
3341245c6d1SConrad Meyer /*
3351245c6d1SConrad Meyer * the SHA224 and SHA256 transforms are identical
3361245c6d1SConrad Meyer */
3371245c6d1SConrad Meyer
3381245c6d1SConrad Meyer /* SHA-224 initialization. Begins a SHA-224 operation. */
3391245c6d1SConrad Meyer void
SHA224_Init(SHA224_CTX * ctx)3401245c6d1SConrad Meyer SHA224_Init(SHA224_CTX * ctx)
3411245c6d1SConrad Meyer {
3421245c6d1SConrad Meyer
3431245c6d1SConrad Meyer /* Zero bits processed so far */
3441245c6d1SConrad Meyer ctx->count = 0;
3451245c6d1SConrad Meyer
3461245c6d1SConrad Meyer /* Magic initialization constants */
3471245c6d1SConrad Meyer ctx->state[0] = 0xC1059ED8;
3481245c6d1SConrad Meyer ctx->state[1] = 0x367CD507;
3491245c6d1SConrad Meyer ctx->state[2] = 0x3070DD17;
3501245c6d1SConrad Meyer ctx->state[3] = 0xF70E5939;
3511245c6d1SConrad Meyer ctx->state[4] = 0xFFC00B31;
3521245c6d1SConrad Meyer ctx->state[5] = 0x68581511;
3531245c6d1SConrad Meyer ctx->state[6] = 0x64f98FA7;
3541245c6d1SConrad Meyer ctx->state[7] = 0xBEFA4FA4;
3551245c6d1SConrad Meyer }
3561245c6d1SConrad Meyer
3571245c6d1SConrad Meyer /* Add bytes into the SHA-224 hash */
3581245c6d1SConrad Meyer void
SHA224_Update(SHA224_CTX * ctx,const void * in,size_t len)3591245c6d1SConrad Meyer SHA224_Update(SHA224_CTX * ctx, const void *in, size_t len)
3601245c6d1SConrad Meyer {
3611245c6d1SConrad Meyer
3621245c6d1SConrad Meyer SHA256_Update((SHA256_CTX *)ctx, in, len);
3631245c6d1SConrad Meyer }
3641245c6d1SConrad Meyer
3651245c6d1SConrad Meyer /*
3661245c6d1SConrad Meyer * SHA-224 finalization. Pads the input data, exports the hash value,
3671245c6d1SConrad Meyer * and clears the context state.
3681245c6d1SConrad Meyer */
3691245c6d1SConrad Meyer void
SHA224_Final(unsigned char digest[static SHA224_DIGEST_LENGTH],SHA224_CTX * ctx)3701245c6d1SConrad Meyer SHA224_Final(unsigned char digest[static SHA224_DIGEST_LENGTH], SHA224_CTX *ctx)
3711245c6d1SConrad Meyer {
3721245c6d1SConrad Meyer
3731245c6d1SConrad Meyer /* Add padding */
3741245c6d1SConrad Meyer SHA256_Pad((SHA256_CTX *)ctx);
3751245c6d1SConrad Meyer
3761245c6d1SConrad Meyer /* Write the hash */
3771245c6d1SConrad Meyer be32enc_vect(digest, ctx->state, SHA224_DIGEST_LENGTH);
3781245c6d1SConrad Meyer
3791245c6d1SConrad Meyer /* Clear the context state */
3801245c6d1SConrad Meyer explicit_bzero(ctx, sizeof(*ctx));
3811245c6d1SConrad Meyer }
3821245c6d1SConrad Meyer
3832ff9c4f9SJohn-Mark Gurney #ifdef WEAK_REFS
3842ff9c4f9SJohn-Mark Gurney /* When building libmd, provide weak references. Note: this is not
3852ff9c4f9SJohn-Mark Gurney activated in the context of compiling these sources for internal
3862ff9c4f9SJohn-Mark Gurney use in libcrypt.
3872ff9c4f9SJohn-Mark Gurney */
3882ff9c4f9SJohn-Mark Gurney #undef SHA256_Init
3892ff9c4f9SJohn-Mark Gurney __weak_reference(_libmd_SHA256_Init, SHA256_Init);
3902ff9c4f9SJohn-Mark Gurney #undef SHA256_Update
3912ff9c4f9SJohn-Mark Gurney __weak_reference(_libmd_SHA256_Update, SHA256_Update);
3922ff9c4f9SJohn-Mark Gurney #undef SHA256_Final
3932ff9c4f9SJohn-Mark Gurney __weak_reference(_libmd_SHA256_Final, SHA256_Final);
3941245c6d1SConrad Meyer
3951245c6d1SConrad Meyer #undef SHA224_Init
3961245c6d1SConrad Meyer __weak_reference(_libmd_SHA224_Init, SHA224_Init);
3971245c6d1SConrad Meyer #undef SHA224_Update
3981245c6d1SConrad Meyer __weak_reference(_libmd_SHA224_Update, SHA224_Update);
3991245c6d1SConrad Meyer #undef SHA224_Final
4001245c6d1SConrad Meyer __weak_reference(_libmd_SHA224_Final, SHA224_Final);
4012ff9c4f9SJohn-Mark Gurney #endif
402