xref: /freebsd/contrib/wpa/src/crypto/sha256.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
139beb93cSSam Leffler /*
239beb93cSSam Leffler  * SHA-256 hash implementation and interface functions
339beb93cSSam Leffler  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
539beb93cSSam Leffler  * This program is free software; you can redistribute it and/or modify
639beb93cSSam Leffler  * it under the terms of the GNU General Public License version 2 as
739beb93cSSam Leffler  * published by the Free Software Foundation.
839beb93cSSam Leffler  *
939beb93cSSam Leffler  * Alternatively, this software may be distributed under the terms of BSD
1039beb93cSSam Leffler  * license.
1139beb93cSSam Leffler  *
1239beb93cSSam Leffler  * See README and COPYING for more details.
1339beb93cSSam Leffler  */
1439beb93cSSam Leffler 
1539beb93cSSam Leffler #include "includes.h"
1639beb93cSSam Leffler 
1739beb93cSSam Leffler #include "common.h"
1839beb93cSSam Leffler #include "sha256.h"
1939beb93cSSam Leffler #include "crypto.h"
2039beb93cSSam Leffler 
2139beb93cSSam Leffler 
2239beb93cSSam Leffler /**
2339beb93cSSam Leffler  * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
2439beb93cSSam Leffler  * @key: Key for HMAC operations
2539beb93cSSam Leffler  * @key_len: Length of the key in bytes
2639beb93cSSam Leffler  * @num_elem: Number of elements in the data vector
2739beb93cSSam Leffler  * @addr: Pointers to the data areas
2839beb93cSSam Leffler  * @len: Lengths of the data blocks
2939beb93cSSam Leffler  * @mac: Buffer for the hash (32 bytes)
3039beb93cSSam Leffler  */
3139beb93cSSam Leffler void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
3239beb93cSSam Leffler 			const u8 *addr[], const size_t *len, u8 *mac)
3339beb93cSSam Leffler {
3439beb93cSSam Leffler 	unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
3539beb93cSSam Leffler 	unsigned char tk[32];
3639beb93cSSam Leffler 	const u8 *_addr[6];
3739beb93cSSam Leffler 	size_t _len[6], i;
3839beb93cSSam Leffler 
3939beb93cSSam Leffler 	if (num_elem > 5) {
4039beb93cSSam Leffler 		/*
4139beb93cSSam Leffler 		 * Fixed limit on the number of fragments to avoid having to
4239beb93cSSam Leffler 		 * allocate memory (which could fail).
4339beb93cSSam Leffler 		 */
4439beb93cSSam Leffler 		return;
4539beb93cSSam Leffler 	}
4639beb93cSSam Leffler 
4739beb93cSSam Leffler         /* if key is longer than 64 bytes reset it to key = SHA256(key) */
4839beb93cSSam Leffler         if (key_len > 64) {
4939beb93cSSam Leffler 		sha256_vector(1, &key, &key_len, tk);
5039beb93cSSam Leffler 		key = tk;
5139beb93cSSam Leffler 		key_len = 32;
5239beb93cSSam Leffler         }
5339beb93cSSam Leffler 
5439beb93cSSam Leffler 	/* the HMAC_SHA256 transform looks like:
5539beb93cSSam Leffler 	 *
5639beb93cSSam Leffler 	 * SHA256(K XOR opad, SHA256(K XOR ipad, text))
5739beb93cSSam Leffler 	 *
5839beb93cSSam Leffler 	 * where K is an n byte key
5939beb93cSSam Leffler 	 * ipad is the byte 0x36 repeated 64 times
6039beb93cSSam Leffler 	 * opad is the byte 0x5c repeated 64 times
6139beb93cSSam Leffler 	 * and text is the data being protected */
6239beb93cSSam Leffler 
6339beb93cSSam Leffler 	/* start out by storing key in ipad */
6439beb93cSSam Leffler 	os_memset(k_pad, 0, sizeof(k_pad));
6539beb93cSSam Leffler 	os_memcpy(k_pad, key, key_len);
6639beb93cSSam Leffler 	/* XOR key with ipad values */
6739beb93cSSam Leffler 	for (i = 0; i < 64; i++)
6839beb93cSSam Leffler 		k_pad[i] ^= 0x36;
6939beb93cSSam Leffler 
7039beb93cSSam Leffler 	/* perform inner SHA256 */
7139beb93cSSam Leffler 	_addr[0] = k_pad;
7239beb93cSSam Leffler 	_len[0] = 64;
7339beb93cSSam Leffler 	for (i = 0; i < num_elem; i++) {
7439beb93cSSam Leffler 		_addr[i + 1] = addr[i];
7539beb93cSSam Leffler 		_len[i + 1] = len[i];
7639beb93cSSam Leffler 	}
7739beb93cSSam Leffler 	sha256_vector(1 + num_elem, _addr, _len, mac);
7839beb93cSSam Leffler 
7939beb93cSSam Leffler 	os_memset(k_pad, 0, sizeof(k_pad));
8039beb93cSSam Leffler 	os_memcpy(k_pad, key, key_len);
8139beb93cSSam Leffler 	/* XOR key with opad values */
8239beb93cSSam Leffler 	for (i = 0; i < 64; i++)
8339beb93cSSam Leffler 		k_pad[i] ^= 0x5c;
8439beb93cSSam Leffler 
8539beb93cSSam Leffler 	/* perform outer SHA256 */
8639beb93cSSam Leffler 	_addr[0] = k_pad;
8739beb93cSSam Leffler 	_len[0] = 64;
8839beb93cSSam Leffler 	_addr[1] = mac;
8939beb93cSSam Leffler 	_len[1] = SHA256_MAC_LEN;
9039beb93cSSam Leffler 	sha256_vector(2, _addr, _len, mac);
9139beb93cSSam Leffler }
9239beb93cSSam Leffler 
9339beb93cSSam Leffler 
9439beb93cSSam Leffler /**
9539beb93cSSam Leffler  * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
9639beb93cSSam Leffler  * @key: Key for HMAC operations
9739beb93cSSam Leffler  * @key_len: Length of the key in bytes
9839beb93cSSam Leffler  * @data: Pointers to the data area
9939beb93cSSam Leffler  * @data_len: Length of the data area
10039beb93cSSam Leffler  * @mac: Buffer for the hash (20 bytes)
10139beb93cSSam Leffler  */
10239beb93cSSam Leffler void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
10339beb93cSSam Leffler 		 size_t data_len, u8 *mac)
10439beb93cSSam Leffler {
10539beb93cSSam Leffler 	hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
10639beb93cSSam Leffler }
10739beb93cSSam Leffler 
10839beb93cSSam Leffler 
10939beb93cSSam Leffler /**
11039beb93cSSam Leffler  * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
11139beb93cSSam Leffler  * @key: Key for PRF
11239beb93cSSam Leffler  * @key_len: Length of the key in bytes
11339beb93cSSam Leffler  * @label: A unique label for each purpose of the PRF
11439beb93cSSam Leffler  * @data: Extra data to bind into the key
11539beb93cSSam Leffler  * @data_len: Length of the data
11639beb93cSSam Leffler  * @buf: Buffer for the generated pseudo-random key
11739beb93cSSam Leffler  * @buf_len: Number of bytes of key to generate
11839beb93cSSam Leffler  *
11939beb93cSSam Leffler  * This function is used to derive new, cryptographically separate keys from a
12039beb93cSSam Leffler  * given key.
12139beb93cSSam Leffler  */
12239beb93cSSam Leffler void sha256_prf(const u8 *key, size_t key_len, const char *label,
12339beb93cSSam Leffler 		const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
12439beb93cSSam Leffler {
12539beb93cSSam Leffler 	u16 counter = 0;
12639beb93cSSam Leffler 	size_t pos, plen;
12739beb93cSSam Leffler 	u8 hash[SHA256_MAC_LEN];
12839beb93cSSam Leffler 	const u8 *addr[4];
12939beb93cSSam Leffler 	size_t len[4];
13039beb93cSSam Leffler 	u8 counter_le[2], length_le[2];
13139beb93cSSam Leffler 
13239beb93cSSam Leffler 	addr[0] = counter_le;
13339beb93cSSam Leffler 	len[0] = 2;
13439beb93cSSam Leffler 	addr[1] = (u8 *) label;
13539beb93cSSam Leffler 	len[1] = os_strlen(label);
13639beb93cSSam Leffler 	addr[2] = data;
13739beb93cSSam Leffler 	len[2] = data_len;
13839beb93cSSam Leffler 	addr[3] = length_le;
13939beb93cSSam Leffler 	len[3] = sizeof(length_le);
14039beb93cSSam Leffler 
14139beb93cSSam Leffler 	WPA_PUT_LE16(length_le, buf_len * 8);
14239beb93cSSam Leffler 	pos = 0;
14339beb93cSSam Leffler 	while (pos < buf_len) {
14439beb93cSSam Leffler 		plen = buf_len - pos;
14539beb93cSSam Leffler 		WPA_PUT_LE16(counter_le, counter);
14639beb93cSSam Leffler 		if (plen >= SHA256_MAC_LEN) {
14739beb93cSSam Leffler 			hmac_sha256_vector(key, key_len, 4, addr, len,
14839beb93cSSam Leffler 					   &buf[pos]);
14939beb93cSSam Leffler 			pos += SHA256_MAC_LEN;
15039beb93cSSam Leffler 		} else {
15139beb93cSSam Leffler 			hmac_sha256_vector(key, key_len, 4, addr, len, hash);
15239beb93cSSam Leffler 			os_memcpy(&buf[pos], hash, plen);
15339beb93cSSam Leffler 			break;
15439beb93cSSam Leffler 		}
15539beb93cSSam Leffler 		counter++;
15639beb93cSSam Leffler 	}
15739beb93cSSam Leffler }
15839beb93cSSam Leffler 
15939beb93cSSam Leffler 
16039beb93cSSam Leffler #ifdef INTERNAL_SHA256
16139beb93cSSam Leffler 
16239beb93cSSam Leffler struct sha256_state {
16339beb93cSSam Leffler 	u64 length;
16439beb93cSSam Leffler 	u32 state[8], curlen;
16539beb93cSSam Leffler 	u8 buf[64];
16639beb93cSSam Leffler };
16739beb93cSSam Leffler 
16839beb93cSSam Leffler static void sha256_init(struct sha256_state *md);
16939beb93cSSam Leffler static int sha256_process(struct sha256_state *md, const unsigned char *in,
17039beb93cSSam Leffler 			  unsigned long inlen);
17139beb93cSSam Leffler static int sha256_done(struct sha256_state *md, unsigned char *out);
17239beb93cSSam Leffler 
17339beb93cSSam Leffler 
17439beb93cSSam Leffler /**
17539beb93cSSam Leffler  * sha256_vector - SHA256 hash for data vector
17639beb93cSSam Leffler  * @num_elem: Number of elements in the data vector
17739beb93cSSam Leffler  * @addr: Pointers to the data areas
17839beb93cSSam Leffler  * @len: Lengths of the data blocks
17939beb93cSSam Leffler  * @mac: Buffer for the hash
18039beb93cSSam Leffler  */
18139beb93cSSam Leffler void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
18239beb93cSSam Leffler 		 u8 *mac)
18339beb93cSSam Leffler {
18439beb93cSSam Leffler 	struct sha256_state ctx;
18539beb93cSSam Leffler 	size_t i;
18639beb93cSSam Leffler 
18739beb93cSSam Leffler 	sha256_init(&ctx);
18839beb93cSSam Leffler 	for (i = 0; i < num_elem; i++)
18939beb93cSSam Leffler 		sha256_process(&ctx, addr[i], len[i]);
19039beb93cSSam Leffler 	sha256_done(&ctx, mac);
19139beb93cSSam Leffler }
19239beb93cSSam Leffler 
19339beb93cSSam Leffler 
19439beb93cSSam Leffler /* ===== start - public domain SHA256 implementation ===== */
19539beb93cSSam Leffler 
19639beb93cSSam Leffler /* This is based on SHA256 implementation in LibTomCrypt that was released into
19739beb93cSSam Leffler  * public domain by Tom St Denis. */
19839beb93cSSam Leffler 
19939beb93cSSam Leffler /* the K array */
20039beb93cSSam Leffler static const unsigned long K[64] = {
20139beb93cSSam Leffler 	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
20239beb93cSSam Leffler 	0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
20339beb93cSSam Leffler 	0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
20439beb93cSSam Leffler 	0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
20539beb93cSSam Leffler 	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
20639beb93cSSam Leffler 	0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
20739beb93cSSam Leffler 	0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
20839beb93cSSam Leffler 	0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
20939beb93cSSam Leffler 	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
21039beb93cSSam Leffler 	0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
21139beb93cSSam Leffler 	0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
21239beb93cSSam Leffler 	0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
21339beb93cSSam Leffler 	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
21439beb93cSSam Leffler };
21539beb93cSSam Leffler 
21639beb93cSSam Leffler 
21739beb93cSSam Leffler /* Various logical functions */
21839beb93cSSam Leffler #define RORc(x, y) \
21939beb93cSSam Leffler ( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
22039beb93cSSam Leffler    ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
22139beb93cSSam Leffler #define Ch(x,y,z)       (z ^ (x & (y ^ z)))
22239beb93cSSam Leffler #define Maj(x,y,z)      (((x | y) & z) | (x & y))
22339beb93cSSam Leffler #define S(x, n)         RORc((x), (n))
22439beb93cSSam Leffler #define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
22539beb93cSSam Leffler #define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
22639beb93cSSam Leffler #define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
22739beb93cSSam Leffler #define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
22839beb93cSSam Leffler #define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
22939beb93cSSam Leffler #ifndef MIN
23039beb93cSSam Leffler #define MIN(x, y) (((x) < (y)) ? (x) : (y))
23139beb93cSSam Leffler #endif
23239beb93cSSam Leffler 
23339beb93cSSam Leffler /* compress 512-bits */
23439beb93cSSam Leffler static int sha256_compress(struct sha256_state *md, unsigned char *buf)
23539beb93cSSam Leffler {
23639beb93cSSam Leffler 	u32 S[8], W[64], t0, t1;
23739beb93cSSam Leffler 	u32 t;
23839beb93cSSam Leffler 	int i;
23939beb93cSSam Leffler 
24039beb93cSSam Leffler 	/* copy state into S */
24139beb93cSSam Leffler 	for (i = 0; i < 8; i++) {
24239beb93cSSam Leffler 		S[i] = md->state[i];
24339beb93cSSam Leffler 	}
24439beb93cSSam Leffler 
24539beb93cSSam Leffler 	/* copy the state into 512-bits into W[0..15] */
24639beb93cSSam Leffler 	for (i = 0; i < 16; i++)
24739beb93cSSam Leffler 		W[i] = WPA_GET_BE32(buf + (4 * i));
24839beb93cSSam Leffler 
24939beb93cSSam Leffler 	/* fill W[16..63] */
25039beb93cSSam Leffler 	for (i = 16; i < 64; i++) {
25139beb93cSSam Leffler 		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
25239beb93cSSam Leffler 			W[i - 16];
25339beb93cSSam Leffler 	}
25439beb93cSSam Leffler 
25539beb93cSSam Leffler 	/* Compress */
25639beb93cSSam Leffler #define RND(a,b,c,d,e,f,g,h,i)                          \
25739beb93cSSam Leffler 	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	\
25839beb93cSSam Leffler 	t1 = Sigma0(a) + Maj(a, b, c);			\
25939beb93cSSam Leffler 	d += t0;					\
26039beb93cSSam Leffler 	h  = t0 + t1;
26139beb93cSSam Leffler 
26239beb93cSSam Leffler 	for (i = 0; i < 64; ++i) {
26339beb93cSSam Leffler 		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
26439beb93cSSam Leffler 		t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
26539beb93cSSam Leffler 		S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
26639beb93cSSam Leffler 	}
26739beb93cSSam Leffler 
26839beb93cSSam Leffler 	/* feedback */
26939beb93cSSam Leffler 	for (i = 0; i < 8; i++) {
27039beb93cSSam Leffler 		md->state[i] = md->state[i] + S[i];
27139beb93cSSam Leffler 	}
27239beb93cSSam Leffler 	return 0;
27339beb93cSSam Leffler }
27439beb93cSSam Leffler 
27539beb93cSSam Leffler 
27639beb93cSSam Leffler /* Initialize the hash state */
27739beb93cSSam Leffler static void sha256_init(struct sha256_state *md)
27839beb93cSSam Leffler {
27939beb93cSSam Leffler 	md->curlen = 0;
28039beb93cSSam Leffler 	md->length = 0;
28139beb93cSSam Leffler 	md->state[0] = 0x6A09E667UL;
28239beb93cSSam Leffler 	md->state[1] = 0xBB67AE85UL;
28339beb93cSSam Leffler 	md->state[2] = 0x3C6EF372UL;
28439beb93cSSam Leffler 	md->state[3] = 0xA54FF53AUL;
28539beb93cSSam Leffler 	md->state[4] = 0x510E527FUL;
28639beb93cSSam Leffler 	md->state[5] = 0x9B05688CUL;
28739beb93cSSam Leffler 	md->state[6] = 0x1F83D9ABUL;
28839beb93cSSam Leffler 	md->state[7] = 0x5BE0CD19UL;
28939beb93cSSam Leffler }
29039beb93cSSam Leffler 
29139beb93cSSam Leffler /**
29239beb93cSSam Leffler    Process a block of memory though the hash
29339beb93cSSam Leffler    @param md     The hash state
29439beb93cSSam Leffler    @param in     The data to hash
29539beb93cSSam Leffler    @param inlen  The length of the data (octets)
29639beb93cSSam Leffler    @return CRYPT_OK if successful
29739beb93cSSam Leffler */
29839beb93cSSam Leffler static int sha256_process(struct sha256_state *md, const unsigned char *in,
29939beb93cSSam Leffler 			  unsigned long inlen)
30039beb93cSSam Leffler {
30139beb93cSSam Leffler 	unsigned long n;
30239beb93cSSam Leffler #define block_size 64
30339beb93cSSam Leffler 
30439beb93cSSam Leffler 	if (md->curlen > sizeof(md->buf))
30539beb93cSSam Leffler 		return -1;
30639beb93cSSam Leffler 
30739beb93cSSam Leffler 	while (inlen > 0) {
30839beb93cSSam Leffler 		if (md->curlen == 0 && inlen >= block_size) {
30939beb93cSSam Leffler 			if (sha256_compress(md, (unsigned char *) in) < 0)
31039beb93cSSam Leffler 				return -1;
31139beb93cSSam Leffler 			md->length += block_size * 8;
31239beb93cSSam Leffler 			in += block_size;
31339beb93cSSam Leffler 			inlen -= block_size;
31439beb93cSSam Leffler 		} else {
31539beb93cSSam Leffler 			n = MIN(inlen, (block_size - md->curlen));
31639beb93cSSam Leffler 			os_memcpy(md->buf + md->curlen, in, n);
31739beb93cSSam Leffler 			md->curlen += n;
31839beb93cSSam Leffler 			in += n;
31939beb93cSSam Leffler 			inlen -= n;
32039beb93cSSam Leffler 			if (md->curlen == block_size) {
32139beb93cSSam Leffler 				if (sha256_compress(md, md->buf) < 0)
32239beb93cSSam Leffler 					return -1;
32339beb93cSSam Leffler 				md->length += 8 * block_size;
32439beb93cSSam Leffler 				md->curlen = 0;
32539beb93cSSam Leffler 			}
32639beb93cSSam Leffler 		}
32739beb93cSSam Leffler 	}
32839beb93cSSam Leffler 
32939beb93cSSam Leffler 	return 0;
33039beb93cSSam Leffler }
33139beb93cSSam Leffler 
33239beb93cSSam Leffler 
33339beb93cSSam Leffler /**
33439beb93cSSam Leffler    Terminate the hash to get the digest
33539beb93cSSam Leffler    @param md  The hash state
33639beb93cSSam Leffler    @param out [out] The destination of the hash (32 bytes)
33739beb93cSSam Leffler    @return CRYPT_OK if successful
33839beb93cSSam Leffler */
33939beb93cSSam Leffler static int sha256_done(struct sha256_state *md, unsigned char *out)
34039beb93cSSam Leffler {
34139beb93cSSam Leffler 	int i;
34239beb93cSSam Leffler 
34339beb93cSSam Leffler 	if (md->curlen >= sizeof(md->buf))
34439beb93cSSam Leffler 		return -1;
34539beb93cSSam Leffler 
34639beb93cSSam Leffler 	/* increase the length of the message */
34739beb93cSSam Leffler 	md->length += md->curlen * 8;
34839beb93cSSam Leffler 
34939beb93cSSam Leffler 	/* append the '1' bit */
35039beb93cSSam Leffler 	md->buf[md->curlen++] = (unsigned char) 0x80;
35139beb93cSSam Leffler 
35239beb93cSSam Leffler 	/* if the length is currently above 56 bytes we append zeros
35339beb93cSSam Leffler 	 * then compress.  Then we can fall back to padding zeros and length
35439beb93cSSam Leffler 	 * encoding like normal.
35539beb93cSSam Leffler 	 */
35639beb93cSSam Leffler 	if (md->curlen > 56) {
35739beb93cSSam Leffler 		while (md->curlen < 64) {
35839beb93cSSam Leffler 			md->buf[md->curlen++] = (unsigned char) 0;
35939beb93cSSam Leffler 		}
36039beb93cSSam Leffler 		sha256_compress(md, md->buf);
36139beb93cSSam Leffler 		md->curlen = 0;
36239beb93cSSam Leffler 	}
36339beb93cSSam Leffler 
36439beb93cSSam Leffler 	/* pad upto 56 bytes of zeroes */
36539beb93cSSam Leffler 	while (md->curlen < 56) {
36639beb93cSSam Leffler 		md->buf[md->curlen++] = (unsigned char) 0;
36739beb93cSSam Leffler 	}
36839beb93cSSam Leffler 
36939beb93cSSam Leffler 	/* store length */
37039beb93cSSam Leffler 	WPA_PUT_BE64(md->buf + 56, md->length);
37139beb93cSSam Leffler 	sha256_compress(md, md->buf);
37239beb93cSSam Leffler 
37339beb93cSSam Leffler 	/* copy output */
37439beb93cSSam Leffler 	for (i = 0; i < 8; i++)
37539beb93cSSam Leffler 		WPA_PUT_BE32(out + (4 * i), md->state[i]);
37639beb93cSSam Leffler 
37739beb93cSSam Leffler 	return 0;
37839beb93cSSam Leffler }
37939beb93cSSam Leffler 
38039beb93cSSam Leffler /* ===== end - public domain SHA256 implementation ===== */
38139beb93cSSam Leffler 
38239beb93cSSam Leffler #endif /* INTERNAL_SHA256 */
383