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