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