Move SHA256-based PRF function into a separate C file
[mech_eap.git] / src / crypto / sha256.c
1 /*
2  * SHA-256 hash implementation and interface functions
3  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "sha256.h"
13 #include "crypto.h"
14
15
16 /**
17  * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
18  * @key: Key for HMAC operations
19  * @key_len: Length of the key in bytes
20  * @num_elem: Number of elements in the data vector
21  * @addr: Pointers to the data areas
22  * @len: Lengths of the data blocks
23  * @mac: Buffer for the hash (32 bytes)
24  */
25 void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
26                         const u8 *addr[], const size_t *len, u8 *mac)
27 {
28         unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
29         unsigned char tk[32];
30         const u8 *_addr[6];
31         size_t _len[6], i;
32
33         if (num_elem > 5) {
34                 /*
35                  * Fixed limit on the number of fragments to avoid having to
36                  * allocate memory (which could fail).
37                  */
38                 return;
39         }
40
41         /* if key is longer than 64 bytes reset it to key = SHA256(key) */
42         if (key_len > 64) {
43                 sha256_vector(1, &key, &key_len, tk);
44                 key = tk;
45                 key_len = 32;
46         }
47
48         /* the HMAC_SHA256 transform looks like:
49          *
50          * SHA256(K XOR opad, SHA256(K XOR ipad, text))
51          *
52          * where K is an n byte key
53          * ipad is the byte 0x36 repeated 64 times
54          * opad is the byte 0x5c repeated 64 times
55          * and text is the data being protected */
56
57         /* start out by storing key in ipad */
58         os_memset(k_pad, 0, sizeof(k_pad));
59         os_memcpy(k_pad, key, key_len);
60         /* XOR key with ipad values */
61         for (i = 0; i < 64; i++)
62                 k_pad[i] ^= 0x36;
63
64         /* perform inner SHA256 */
65         _addr[0] = k_pad;
66         _len[0] = 64;
67         for (i = 0; i < num_elem; i++) {
68                 _addr[i + 1] = addr[i];
69                 _len[i + 1] = len[i];
70         }
71         sha256_vector(1 + num_elem, _addr, _len, mac);
72
73         os_memset(k_pad, 0, sizeof(k_pad));
74         os_memcpy(k_pad, key, key_len);
75         /* XOR key with opad values */
76         for (i = 0; i < 64; i++)
77                 k_pad[i] ^= 0x5c;
78
79         /* perform outer SHA256 */
80         _addr[0] = k_pad;
81         _len[0] = 64;
82         _addr[1] = mac;
83         _len[1] = SHA256_MAC_LEN;
84         sha256_vector(2, _addr, _len, mac);
85 }
86
87
88 /**
89  * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
90  * @key: Key for HMAC operations
91  * @key_len: Length of the key in bytes
92  * @data: Pointers to the data area
93  * @data_len: Length of the data area
94  * @mac: Buffer for the hash (20 bytes)
95  */
96 void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
97                  size_t data_len, u8 *mac)
98 {
99         hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
100 }