xref: /freebsd/contrib/wpa/src/crypto/sha1-tprf.c (revision c5c3ba6b43cac20dc9432eac15758d41cb2b8b1f)
1e28a4053SRui Paulo /*
2e28a4053SRui Paulo  * SHA1 T-PRF for EAP-FAST
3e28a4053SRui Paulo  * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
4e28a4053SRui Paulo  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
7e28a4053SRui Paulo  */
8e28a4053SRui Paulo 
9e28a4053SRui Paulo #include "includes.h"
10e28a4053SRui Paulo 
11e28a4053SRui Paulo #include "common.h"
12e28a4053SRui Paulo #include "sha1.h"
13e28a4053SRui Paulo #include "crypto.h"
14e28a4053SRui Paulo 
15e28a4053SRui Paulo /**
16e28a4053SRui Paulo  * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF)
17e28a4053SRui Paulo  * @key: Key for PRF
18e28a4053SRui Paulo  * @key_len: Length of the key in bytes
19e28a4053SRui Paulo  * @label: A unique label for each purpose of the PRF
20e28a4053SRui Paulo  * @seed: Seed value to bind into the key
21e28a4053SRui Paulo  * @seed_len: Length of the seed
22e28a4053SRui Paulo  * @buf: Buffer for the generated pseudo-random key
23e28a4053SRui Paulo  * @buf_len: Number of bytes of key to generate
24e28a4053SRui Paulo  * Returns: 0 on success, -1 of failure
25e28a4053SRui Paulo  *
26e28a4053SRui Paulo  * This function is used to derive new, cryptographically separate keys from a
27e28a4053SRui Paulo  * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5.
28e28a4053SRui Paulo  */
sha1_t_prf(const u8 * key,size_t key_len,const char * label,const u8 * seed,size_t seed_len,u8 * buf,size_t buf_len)29e28a4053SRui Paulo int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
30e28a4053SRui Paulo 	       const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
31e28a4053SRui Paulo {
32e28a4053SRui Paulo 	unsigned char counter = 0;
33e28a4053SRui Paulo 	size_t pos, plen;
34e28a4053SRui Paulo 	u8 hash[SHA1_MAC_LEN];
35e28a4053SRui Paulo 	size_t label_len = os_strlen(label);
36e28a4053SRui Paulo 	u8 output_len[2];
37e28a4053SRui Paulo 	const unsigned char *addr[5];
38e28a4053SRui Paulo 	size_t len[5];
39e28a4053SRui Paulo 
40e28a4053SRui Paulo 	addr[0] = hash;
41e28a4053SRui Paulo 	len[0] = 0;
42e28a4053SRui Paulo 	addr[1] = (unsigned char *) label;
43e28a4053SRui Paulo 	len[1] = label_len + 1;
44e28a4053SRui Paulo 	addr[2] = seed;
45e28a4053SRui Paulo 	len[2] = seed_len;
46e28a4053SRui Paulo 	addr[3] = output_len;
47e28a4053SRui Paulo 	len[3] = 2;
48e28a4053SRui Paulo 	addr[4] = &counter;
49e28a4053SRui Paulo 	len[4] = 1;
50e28a4053SRui Paulo 
51e28a4053SRui Paulo 	output_len[0] = (buf_len >> 8) & 0xff;
52e28a4053SRui Paulo 	output_len[1] = buf_len & 0xff;
53e28a4053SRui Paulo 	pos = 0;
54e28a4053SRui Paulo 	while (pos < buf_len) {
55e28a4053SRui Paulo 		counter++;
56e28a4053SRui Paulo 		plen = buf_len - pos;
57e28a4053SRui Paulo 		if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
58e28a4053SRui Paulo 			return -1;
59e28a4053SRui Paulo 		if (plen >= SHA1_MAC_LEN) {
60e28a4053SRui Paulo 			os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
61e28a4053SRui Paulo 			pos += SHA1_MAC_LEN;
62e28a4053SRui Paulo 		} else {
63e28a4053SRui Paulo 			os_memcpy(&buf[pos], hash, plen);
64e28a4053SRui Paulo 			break;
65e28a4053SRui Paulo 		}
66e28a4053SRui Paulo 		len[0] = SHA1_MAC_LEN;
67e28a4053SRui Paulo 	}
68e28a4053SRui Paulo 
69*206b73d0SCy Schubert 	forced_memzero(hash, SHA1_MAC_LEN);
70325151a3SRui Paulo 
71e28a4053SRui Paulo 	return 0;
72e28a4053SRui Paulo }
73