sha256-internal.c revision 1f69aa52ea2e0a73ac502565df8c666ee49cab6a
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SHA-256 hash implementation and interface functions
31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify
68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license.
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details.
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sha256.h"
191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "sha256_i.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * sha256_vector - SHA256 hash for data vector
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @num_elem: Number of elements in the data vector
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @addr: Pointers to the data areas
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Lengths of the data blocks
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mac: Buffer for the hash
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 of failure
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  u8 *mac)
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sha256_state ctx;
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t i;
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sha256_init(&ctx);
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_elem; i++)
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sha256_process(&ctx, addr[i], len[i]))
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sha256_done(&ctx, mac))
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* ===== start - public domain SHA256 implementation ===== */
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* This is based on SHA256 implementation in LibTomCrypt that was released into
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * public domain by Tom St Denis. */
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* the K array */
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const unsigned long K[64] = {
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt};
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Various logical functions */
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RORc(x, y) \
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Maj(x,y,z)      (((x | y) & z) | (x & y))
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define S(x, n)         RORc((x), (n))
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef MIN
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MIN(x, y) (((x) < (y)) ? (x) : (y))
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* compress 512-bits */
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int sha256_compress(struct sha256_state *md, unsigned char *buf)
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 S[8], W[64], t0, t1;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 t;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* copy state into S */
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 8; i++) {
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		S[i] = md->state[i];
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* copy the state into 512-bits into W[0..15] */
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 16; i++)
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		W[i] = WPA_GET_BE32(buf + (4 * i));
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* fill W[16..63] */
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 16; i < 64; i++) {
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			W[i - 16];
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Compress */
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define RND(a,b,c,d,e,f,g,h,i)                          \
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	\
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	t1 = Sigma0(a) + Maj(a, b, c);			\
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	d += t0;					\
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	h  = t0 + t1;
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 64; ++i) {
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* feedback */
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 8; i++) {
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		md->state[i] = md->state[i] + S[i];
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Initialize the hash state */
1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid sha256_init(struct sha256_state *md)
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->curlen = 0;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->length = 0;
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[0] = 0x6A09E667UL;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[1] = 0xBB67AE85UL;
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[2] = 0x3C6EF372UL;
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[3] = 0xA54FF53AUL;
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[4] = 0x510E527FUL;
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[5] = 0x9B05688CUL;
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[6] = 0x1F83D9ABUL;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->state[7] = 0x5BE0CD19UL;
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   Process a block of memory though the hash
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   @param md     The hash state
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   @param in     The data to hash
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   @param inlen  The length of the data (octets)
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   @return CRYPT_OK if successful
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt*/
1511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint sha256_process(struct sha256_state *md, const unsigned char *in,
1521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		   unsigned long inlen)
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned long n;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (md->curlen >= sizeof(md->buf))
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (inlen > 0) {
1601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (sha256_compress(md, (unsigned char *) in) < 0)
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				return -1;
1631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			md->length += SHA256_BLOCK_SIZE * 8;
1641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			in += SHA256_BLOCK_SIZE;
1651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			inlen -= SHA256_BLOCK_SIZE;
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			os_memcpy(md->buf + md->curlen, in, n);
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			md->curlen += n;
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			in += n;
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			inlen -= n;
1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (md->curlen == SHA256_BLOCK_SIZE) {
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				if (sha256_compress(md, md->buf) < 0)
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					return -1;
1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				md->length += 8 * SHA256_BLOCK_SIZE;
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				md->curlen = 0;
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   Terminate the hash to get the digest
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   @param md  The hash state
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   @param out [out] The destination of the hash (32 bytes)
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt   @return CRYPT_OK if successful
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt*/
1911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint sha256_done(struct sha256_state *md, unsigned char *out)
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (md->curlen >= sizeof(md->buf))
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* increase the length of the message */
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->length += md->curlen * 8;
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* append the '1' bit */
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	md->buf[md->curlen++] = (unsigned char) 0x80;
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* if the length is currently above 56 bytes we append zeros
2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * then compress.  Then we can fall back to padding zeros and length
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * encoding like normal.
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (md->curlen > 56) {
2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		while (md->curlen < SHA256_BLOCK_SIZE) {
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			md->buf[md->curlen++] = (unsigned char) 0;
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sha256_compress(md, md->buf);
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		md->curlen = 0;
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	/* pad up to 56 bytes of zeroes */
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (md->curlen < 56) {
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		md->buf[md->curlen++] = (unsigned char) 0;
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* store length */
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	WPA_PUT_BE64(md->buf + 56, md->length);
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sha256_compress(md, md->buf);
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* copy output */
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < 8; i++)
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		WPA_PUT_BE32(out + (4 * i), md->state[i]);
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* ===== end - public domain SHA256 implementation ===== */
233