1214501Srpaulo/*
2214501Srpaulo * SHA-256 hash implementation and interface functions
3252726Srpaulo * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
4214501Srpaulo *
5252726Srpaulo * This software may be distributed under the terms of the BSD license.
6252726Srpaulo * See README for more details.
7214501Srpaulo */
8214501Srpaulo
9214501Srpaulo#include "includes.h"
10214501Srpaulo
11214501Srpaulo#include "common.h"
12214501Srpaulo#include "sha256.h"
13252726Srpaulo#include "sha256_i.h"
14214501Srpaulo#include "crypto.h"
15214501Srpaulo
16214501Srpaulo
17214501Srpaulo/**
18214501Srpaulo * sha256_vector - SHA256 hash for data vector
19214501Srpaulo * @num_elem: Number of elements in the data vector
20214501Srpaulo * @addr: Pointers to the data areas
21214501Srpaulo * @len: Lengths of the data blocks
22214501Srpaulo * @mac: Buffer for the hash
23214501Srpaulo * Returns: 0 on success, -1 of failure
24214501Srpaulo */
25214501Srpauloint sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
26214501Srpaulo		  u8 *mac)
27214501Srpaulo{
28214501Srpaulo	struct sha256_state ctx;
29214501Srpaulo	size_t i;
30214501Srpaulo
31214501Srpaulo	sha256_init(&ctx);
32214501Srpaulo	for (i = 0; i < num_elem; i++)
33214501Srpaulo		if (sha256_process(&ctx, addr[i], len[i]))
34214501Srpaulo			return -1;
35214501Srpaulo	if (sha256_done(&ctx, mac))
36214501Srpaulo		return -1;
37214501Srpaulo	return 0;
38214501Srpaulo}
39214501Srpaulo
40214501Srpaulo
41214501Srpaulo/* ===== start - public domain SHA256 implementation ===== */
42214501Srpaulo
43214501Srpaulo/* This is based on SHA256 implementation in LibTomCrypt that was released into
44214501Srpaulo * public domain by Tom St Denis. */
45214501Srpaulo
46214501Srpaulo/* the K array */
47214501Srpaulostatic const unsigned long K[64] = {
48214501Srpaulo	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
49214501Srpaulo	0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
50214501Srpaulo	0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
51214501Srpaulo	0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
52214501Srpaulo	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
53214501Srpaulo	0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
54214501Srpaulo	0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
55214501Srpaulo	0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
56214501Srpaulo	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
57214501Srpaulo	0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
58214501Srpaulo	0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
59214501Srpaulo	0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
60214501Srpaulo	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
61214501Srpaulo};
62214501Srpaulo
63214501Srpaulo
64214501Srpaulo/* Various logical functions */
65214501Srpaulo#define RORc(x, y) \
66214501Srpaulo( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
67214501Srpaulo   ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
68214501Srpaulo#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
69214501Srpaulo#define Maj(x,y,z)      (((x | y) & z) | (x & y))
70214501Srpaulo#define S(x, n)         RORc((x), (n))
71214501Srpaulo#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
72214501Srpaulo#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
73214501Srpaulo#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
74214501Srpaulo#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
75214501Srpaulo#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
76214501Srpaulo#ifndef MIN
77214501Srpaulo#define MIN(x, y) (((x) < (y)) ? (x) : (y))
78214501Srpaulo#endif
79214501Srpaulo
80214501Srpaulo/* compress 512-bits */
81214501Srpaulostatic int sha256_compress(struct sha256_state *md, unsigned char *buf)
82214501Srpaulo{
83214501Srpaulo	u32 S[8], W[64], t0, t1;
84214501Srpaulo	u32 t;
85214501Srpaulo	int i;
86214501Srpaulo
87214501Srpaulo	/* copy state into S */
88214501Srpaulo	for (i = 0; i < 8; i++) {
89214501Srpaulo		S[i] = md->state[i];
90214501Srpaulo	}
91214501Srpaulo
92214501Srpaulo	/* copy the state into 512-bits into W[0..15] */
93214501Srpaulo	for (i = 0; i < 16; i++)
94214501Srpaulo		W[i] = WPA_GET_BE32(buf + (4 * i));
95214501Srpaulo
96214501Srpaulo	/* fill W[16..63] */
97214501Srpaulo	for (i = 16; i < 64; i++) {
98214501Srpaulo		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
99214501Srpaulo			W[i - 16];
100214501Srpaulo	}
101214501Srpaulo
102214501Srpaulo	/* Compress */
103214501Srpaulo#define RND(a,b,c,d,e,f,g,h,i)                          \
104214501Srpaulo	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	\
105214501Srpaulo	t1 = Sigma0(a) + Maj(a, b, c);			\
106214501Srpaulo	d += t0;					\
107214501Srpaulo	h  = t0 + t1;
108214501Srpaulo
109214501Srpaulo	for (i = 0; i < 64; ++i) {
110214501Srpaulo		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
111214501Srpaulo		t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
112214501Srpaulo		S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
113214501Srpaulo	}
114214501Srpaulo
115214501Srpaulo	/* feedback */
116214501Srpaulo	for (i = 0; i < 8; i++) {
117214501Srpaulo		md->state[i] = md->state[i] + S[i];
118214501Srpaulo	}
119214501Srpaulo	return 0;
120214501Srpaulo}
121214501Srpaulo
122214501Srpaulo
123214501Srpaulo/* Initialize the hash state */
124252726Srpaulovoid sha256_init(struct sha256_state *md)
125214501Srpaulo{
126214501Srpaulo	md->curlen = 0;
127214501Srpaulo	md->length = 0;
128214501Srpaulo	md->state[0] = 0x6A09E667UL;
129214501Srpaulo	md->state[1] = 0xBB67AE85UL;
130214501Srpaulo	md->state[2] = 0x3C6EF372UL;
131214501Srpaulo	md->state[3] = 0xA54FF53AUL;
132214501Srpaulo	md->state[4] = 0x510E527FUL;
133214501Srpaulo	md->state[5] = 0x9B05688CUL;
134214501Srpaulo	md->state[6] = 0x1F83D9ABUL;
135214501Srpaulo	md->state[7] = 0x5BE0CD19UL;
136214501Srpaulo}
137214501Srpaulo
138214501Srpaulo/**
139214501Srpaulo   Process a block of memory though the hash
140214501Srpaulo   @param md     The hash state
141214501Srpaulo   @param in     The data to hash
142214501Srpaulo   @param inlen  The length of the data (octets)
143214501Srpaulo   @return CRYPT_OK if successful
144214501Srpaulo*/
145252726Srpauloint sha256_process(struct sha256_state *md, const unsigned char *in,
146252726Srpaulo		   unsigned long inlen)
147214501Srpaulo{
148214501Srpaulo	unsigned long n;
149214501Srpaulo
150252726Srpaulo	if (md->curlen >= sizeof(md->buf))
151214501Srpaulo		return -1;
152214501Srpaulo
153214501Srpaulo	while (inlen > 0) {
154252726Srpaulo		if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
155214501Srpaulo			if (sha256_compress(md, (unsigned char *) in) < 0)
156214501Srpaulo				return -1;
157252726Srpaulo			md->length += SHA256_BLOCK_SIZE * 8;
158252726Srpaulo			in += SHA256_BLOCK_SIZE;
159252726Srpaulo			inlen -= SHA256_BLOCK_SIZE;
160214501Srpaulo		} else {
161252726Srpaulo			n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
162214501Srpaulo			os_memcpy(md->buf + md->curlen, in, n);
163214501Srpaulo			md->curlen += n;
164214501Srpaulo			in += n;
165214501Srpaulo			inlen -= n;
166252726Srpaulo			if (md->curlen == SHA256_BLOCK_SIZE) {
167214501Srpaulo				if (sha256_compress(md, md->buf) < 0)
168214501Srpaulo					return -1;
169252726Srpaulo				md->length += 8 * SHA256_BLOCK_SIZE;
170214501Srpaulo				md->curlen = 0;
171214501Srpaulo			}
172214501Srpaulo		}
173214501Srpaulo	}
174214501Srpaulo
175214501Srpaulo	return 0;
176214501Srpaulo}
177214501Srpaulo
178214501Srpaulo
179214501Srpaulo/**
180214501Srpaulo   Terminate the hash to get the digest
181214501Srpaulo   @param md  The hash state
182214501Srpaulo   @param out [out] The destination of the hash (32 bytes)
183214501Srpaulo   @return CRYPT_OK if successful
184214501Srpaulo*/
185252726Srpauloint sha256_done(struct sha256_state *md, unsigned char *out)
186214501Srpaulo{
187214501Srpaulo	int i;
188214501Srpaulo
189214501Srpaulo	if (md->curlen >= sizeof(md->buf))
190214501Srpaulo		return -1;
191214501Srpaulo
192214501Srpaulo	/* increase the length of the message */
193214501Srpaulo	md->length += md->curlen * 8;
194214501Srpaulo
195214501Srpaulo	/* append the '1' bit */
196214501Srpaulo	md->buf[md->curlen++] = (unsigned char) 0x80;
197214501Srpaulo
198214501Srpaulo	/* if the length is currently above 56 bytes we append zeros
199214501Srpaulo	 * then compress.  Then we can fall back to padding zeros and length
200214501Srpaulo	 * encoding like normal.
201214501Srpaulo	 */
202214501Srpaulo	if (md->curlen > 56) {
203252726Srpaulo		while (md->curlen < SHA256_BLOCK_SIZE) {
204214501Srpaulo			md->buf[md->curlen++] = (unsigned char) 0;
205214501Srpaulo		}
206214501Srpaulo		sha256_compress(md, md->buf);
207214501Srpaulo		md->curlen = 0;
208214501Srpaulo	}
209214501Srpaulo
210252726Srpaulo	/* pad up to 56 bytes of zeroes */
211214501Srpaulo	while (md->curlen < 56) {
212214501Srpaulo		md->buf[md->curlen++] = (unsigned char) 0;
213214501Srpaulo	}
214214501Srpaulo
215214501Srpaulo	/* store length */
216214501Srpaulo	WPA_PUT_BE64(md->buf + 56, md->length);
217214501Srpaulo	sha256_compress(md, md->buf);
218214501Srpaulo
219214501Srpaulo	/* copy output */
220214501Srpaulo	for (i = 0; i < 8; i++)
221214501Srpaulo		WPA_PUT_BE32(out + (4 * i), md->state[i]);
222214501Srpaulo
223214501Srpaulo	return 0;
224214501Srpaulo}
225214501Srpaulo
226214501Srpaulo/* ===== end - public domain SHA256 implementation ===== */
227