sha256.c revision 189251
1202878Srdivacky/*
2202878Srdivacky * SHA-256 hash implementation and interface functions
3202878Srdivacky * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
4202878Srdivacky *
5202878Srdivacky * This program is free software; you can redistribute it and/or modify
6202878Srdivacky * it under the terms of the GNU General Public License version 2 as
7202878Srdivacky * published by the Free Software Foundation.
8202878Srdivacky *
9202878Srdivacky * Alternatively, this software may be distributed under the terms of BSD
10202878Srdivacky * license.
11202878Srdivacky *
12202878Srdivacky * See README and COPYING for more details.
13202878Srdivacky */
14202878Srdivacky
15202878Srdivacky#include "includes.h"
16202878Srdivacky
17202878Srdivacky#include "common.h"
18202878Srdivacky#include "sha256.h"
19202878Srdivacky#include "crypto.h"
20203954Srdivacky
21202878Srdivacky
22202878Srdivacky/**
23203954Srdivacky * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
24203954Srdivacky * @key: Key for HMAC operations
25203954Srdivacky * @key_len: Length of the key in bytes
26203954Srdivacky * @num_elem: Number of elements in the data vector
27203954Srdivacky * @addr: Pointers to the data areas
28203954Srdivacky * @len: Lengths of the data blocks
29203954Srdivacky * @mac: Buffer for the hash (32 bytes)
30203954Srdivacky */
31203954Srdivackyvoid hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
32203954Srdivacky			const u8 *addr[], const size_t *len, u8 *mac)
33203954Srdivacky{
34203954Srdivacky	unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
35203954Srdivacky	unsigned char tk[32];
36203954Srdivacky	const u8 *_addr[6];
37203954Srdivacky	size_t _len[6], i;
38203954Srdivacky
39203954Srdivacky	if (num_elem > 5) {
40203954Srdivacky		/*
41203954Srdivacky		 * Fixed limit on the number of fragments to avoid having to
42202878Srdivacky		 * allocate memory (which could fail).
43202878Srdivacky		 */
44202878Srdivacky		return;
45203954Srdivacky	}
46202878Srdivacky
47202878Srdivacky        /* if key is longer than 64 bytes reset it to key = SHA256(key) */
48202878Srdivacky        if (key_len > 64) {
49202878Srdivacky		sha256_vector(1, &key, &key_len, tk);
50202878Srdivacky		key = tk;
51		key_len = 32;
52        }
53
54	/* the HMAC_SHA256 transform looks like:
55	 *
56	 * SHA256(K XOR opad, SHA256(K XOR ipad, text))
57	 *
58	 * where K is an n byte key
59	 * ipad is the byte 0x36 repeated 64 times
60	 * opad is the byte 0x5c repeated 64 times
61	 * and text is the data being protected */
62
63	/* start out by storing key in ipad */
64	os_memset(k_pad, 0, sizeof(k_pad));
65	os_memcpy(k_pad, key, key_len);
66	/* XOR key with ipad values */
67	for (i = 0; i < 64; i++)
68		k_pad[i] ^= 0x36;
69
70	/* perform inner SHA256 */
71	_addr[0] = k_pad;
72	_len[0] = 64;
73	for (i = 0; i < num_elem; i++) {
74		_addr[i + 1] = addr[i];
75		_len[i + 1] = len[i];
76	}
77	sha256_vector(1 + num_elem, _addr, _len, mac);
78
79	os_memset(k_pad, 0, sizeof(k_pad));
80	os_memcpy(k_pad, key, key_len);
81	/* XOR key with opad values */
82	for (i = 0; i < 64; i++)
83		k_pad[i] ^= 0x5c;
84
85	/* perform outer SHA256 */
86	_addr[0] = k_pad;
87	_len[0] = 64;
88	_addr[1] = mac;
89	_len[1] = SHA256_MAC_LEN;
90	sha256_vector(2, _addr, _len, mac);
91}
92
93
94/**
95 * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
96 * @key: Key for HMAC operations
97 * @key_len: Length of the key in bytes
98 * @data: Pointers to the data area
99 * @data_len: Length of the data area
100 * @mac: Buffer for the hash (20 bytes)
101 */
102void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
103		 size_t data_len, u8 *mac)
104{
105	hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
106}
107
108
109/**
110 * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
111 * @key: Key for PRF
112 * @key_len: Length of the key in bytes
113 * @label: A unique label for each purpose of the PRF
114 * @data: Extra data to bind into the key
115 * @data_len: Length of the data
116 * @buf: Buffer for the generated pseudo-random key
117 * @buf_len: Number of bytes of key to generate
118 *
119 * This function is used to derive new, cryptographically separate keys from a
120 * given key.
121 */
122void sha256_prf(const u8 *key, size_t key_len, const char *label,
123		const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
124{
125	u16 counter = 0;
126	size_t pos, plen;
127	u8 hash[SHA256_MAC_LEN];
128	const u8 *addr[4];
129	size_t len[4];
130	u8 counter_le[2], length_le[2];
131
132	addr[0] = counter_le;
133	len[0] = 2;
134	addr[1] = (u8 *) label;
135	len[1] = os_strlen(label);
136	addr[2] = data;
137	len[2] = data_len;
138	addr[3] = length_le;
139	len[3] = sizeof(length_le);
140
141	WPA_PUT_LE16(length_le, buf_len * 8);
142	pos = 0;
143	while (pos < buf_len) {
144		plen = buf_len - pos;
145		WPA_PUT_LE16(counter_le, counter);
146		if (plen >= SHA256_MAC_LEN) {
147			hmac_sha256_vector(key, key_len, 4, addr, len,
148					   &buf[pos]);
149			pos += SHA256_MAC_LEN;
150		} else {
151			hmac_sha256_vector(key, key_len, 4, addr, len, hash);
152			os_memcpy(&buf[pos], hash, plen);
153			break;
154		}
155		counter++;
156	}
157}
158
159
160#ifdef INTERNAL_SHA256
161
162struct sha256_state {
163	u64 length;
164	u32 state[8], curlen;
165	u8 buf[64];
166};
167
168static void sha256_init(struct sha256_state *md);
169static int sha256_process(struct sha256_state *md, const unsigned char *in,
170			  unsigned long inlen);
171static int sha256_done(struct sha256_state *md, unsigned char *out);
172
173
174/**
175 * sha256_vector - SHA256 hash for data vector
176 * @num_elem: Number of elements in the data vector
177 * @addr: Pointers to the data areas
178 * @len: Lengths of the data blocks
179 * @mac: Buffer for the hash
180 */
181void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
182		 u8 *mac)
183{
184	struct sha256_state ctx;
185	size_t i;
186
187	sha256_init(&ctx);
188	for (i = 0; i < num_elem; i++)
189		sha256_process(&ctx, addr[i], len[i]);
190	sha256_done(&ctx, mac);
191}
192
193
194/* ===== start - public domain SHA256 implementation ===== */
195
196/* This is based on SHA256 implementation in LibTomCrypt that was released into
197 * public domain by Tom St Denis. */
198
199/* the K array */
200static const unsigned long K[64] = {
201	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
202	0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
203	0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
204	0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
205	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
206	0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
207	0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
208	0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
209	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
210	0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
211	0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
212	0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
213	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
214};
215
216
217/* Various logical functions */
218#define RORc(x, y) \
219( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
220   ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
221#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
222#define Maj(x,y,z)      (((x | y) & z) | (x & y))
223#define S(x, n)         RORc((x), (n))
224#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
225#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
226#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
227#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
228#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
229#ifndef MIN
230#define MIN(x, y) (((x) < (y)) ? (x) : (y))
231#endif
232
233/* compress 512-bits */
234static int sha256_compress(struct sha256_state *md, unsigned char *buf)
235{
236	u32 S[8], W[64], t0, t1;
237	u32 t;
238	int i;
239
240	/* copy state into S */
241	for (i = 0; i < 8; i++) {
242		S[i] = md->state[i];
243	}
244
245	/* copy the state into 512-bits into W[0..15] */
246	for (i = 0; i < 16; i++)
247		W[i] = WPA_GET_BE32(buf + (4 * i));
248
249	/* fill W[16..63] */
250	for (i = 16; i < 64; i++) {
251		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
252			W[i - 16];
253	}
254
255	/* Compress */
256#define RND(a,b,c,d,e,f,g,h,i)                          \
257	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	\
258	t1 = Sigma0(a) + Maj(a, b, c);			\
259	d += t0;					\
260	h  = t0 + t1;
261
262	for (i = 0; i < 64; ++i) {
263		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
264		t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
265		S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
266	}
267
268	/* feedback */
269	for (i = 0; i < 8; i++) {
270		md->state[i] = md->state[i] + S[i];
271	}
272	return 0;
273}
274
275
276/* Initialize the hash state */
277static void sha256_init(struct sha256_state *md)
278{
279	md->curlen = 0;
280	md->length = 0;
281	md->state[0] = 0x6A09E667UL;
282	md->state[1] = 0xBB67AE85UL;
283	md->state[2] = 0x3C6EF372UL;
284	md->state[3] = 0xA54FF53AUL;
285	md->state[4] = 0x510E527FUL;
286	md->state[5] = 0x9B05688CUL;
287	md->state[6] = 0x1F83D9ABUL;
288	md->state[7] = 0x5BE0CD19UL;
289}
290
291/**
292   Process a block of memory though the hash
293   @param md     The hash state
294   @param in     The data to hash
295   @param inlen  The length of the data (octets)
296   @return CRYPT_OK if successful
297*/
298static int sha256_process(struct sha256_state *md, const unsigned char *in,
299			  unsigned long inlen)
300{
301	unsigned long n;
302#define block_size 64
303
304	if (md->curlen > sizeof(md->buf))
305		return -1;
306
307	while (inlen > 0) {
308		if (md->curlen == 0 && inlen >= block_size) {
309			if (sha256_compress(md, (unsigned char *) in) < 0)
310				return -1;
311			md->length += block_size * 8;
312			in += block_size;
313			inlen -= block_size;
314		} else {
315			n = MIN(inlen, (block_size - md->curlen));
316			os_memcpy(md->buf + md->curlen, in, n);
317			md->curlen += n;
318			in += n;
319			inlen -= n;
320			if (md->curlen == block_size) {
321				if (sha256_compress(md, md->buf) < 0)
322					return -1;
323				md->length += 8 * block_size;
324				md->curlen = 0;
325			}
326		}
327	}
328
329	return 0;
330}
331
332
333/**
334   Terminate the hash to get the digest
335   @param md  The hash state
336   @param out [out] The destination of the hash (32 bytes)
337   @return CRYPT_OK if successful
338*/
339static int sha256_done(struct sha256_state *md, unsigned char *out)
340{
341	int i;
342
343	if (md->curlen >= sizeof(md->buf))
344		return -1;
345
346	/* increase the length of the message */
347	md->length += md->curlen * 8;
348
349	/* append the '1' bit */
350	md->buf[md->curlen++] = (unsigned char) 0x80;
351
352	/* if the length is currently above 56 bytes we append zeros
353	 * then compress.  Then we can fall back to padding zeros and length
354	 * encoding like normal.
355	 */
356	if (md->curlen > 56) {
357		while (md->curlen < 64) {
358			md->buf[md->curlen++] = (unsigned char) 0;
359		}
360		sha256_compress(md, md->buf);
361		md->curlen = 0;
362	}
363
364	/* pad upto 56 bytes of zeroes */
365	while (md->curlen < 56) {
366		md->buf[md->curlen++] = (unsigned char) 0;
367	}
368
369	/* store length */
370	WPA_PUT_BE64(md->buf + 56, md->length);
371	sha256_compress(md, md->buf);
372
373	/* copy output */
374	for (i = 0; i < 8; i++)
375		WPA_PUT_BE32(out + (4 * i), md->state[i]);
376
377	return 0;
378}
379
380/* ===== end - public domain SHA256 implementation ===== */
381
382#endif /* INTERNAL_SHA256 */
383