161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/*
261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * SHA256-based PRF (IEEE 802.11r)
3e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *
561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * See README for more details.
761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */
861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "includes.h"
1061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "common.h"
1261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "sha256.h"
1361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "crypto.h"
1461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/**
1761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
1861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @key: Key for PRF
1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @key_len: Length of the key in bytes
2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @label: A unique label for each purpose of the PRF
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @data: Extra data to bind into the key
2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @data_len: Length of the data
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @buf: Buffer for the generated pseudo-random key
2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * @buf_len: Number of bytes of key to generate
25e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Returns: 0 on success, -1 on failure
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *
2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * This function is used to derive new, cryptographically separate keys from a
2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * given key.
2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */
30e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtint sha256_prf(const u8 *key, size_t key_len, const char *label,
3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
33e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	return sha256_prf_bits(key, key_len, label, data, data_len, buf,
34e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			       buf_len * 8);
35a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
36a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
37a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
38a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
39a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function
40a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @key: Key for KDF
41a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @key_len: Length of the key in bytes
42a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @label: A unique label for each purpose of the PRF
43a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @data: Extra data to bind into the key
44a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @data_len: Length of the data
45a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @buf: Buffer for the generated pseudo-random key
46a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @buf_len: Number of bits of key to generate
47e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt * Returns: 0 on success, -1 on failure
48a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
49a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to derive new, cryptographically separate keys from a
50a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * given key. If the requested buf_len is not divisible by eight, the least
51a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * significant 1-7 bits of the last octet in the output are not part of the
52a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * requested output.
53a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
54e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidtint sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
55e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		    const u8 *data, size_t data_len, u8 *buf,
56e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt		    size_t buf_len_bits)
57a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u16 counter = 1;
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t pos, plen;
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 hash[SHA256_MAC_LEN];
6161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *addr[4];
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len[4];
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 counter_le[2], length_le[2];
64a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	size_t buf_len = (buf_len_bits + 7) / 8;
6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[0] = counter_le;
6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[0] = 2;
6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[1] = (u8 *) label;
6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[1] = os_strlen(label);
7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[2] = data;
7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[2] = data_len;
7261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[3] = length_le;
7361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[3] = sizeof(length_le);
7461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
75a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	WPA_PUT_LE16(length_le, buf_len_bits);
7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = 0;
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (pos < buf_len) {
7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		plen = buf_len - pos;
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		WPA_PUT_LE16(counter_le, counter);
8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (plen >= SHA256_MAC_LEN) {
81e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			if (hmac_sha256_vector(key, key_len, 4, addr, len,
82e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt					       &buf[pos]) < 0)
83e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt				return -1;
8461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			pos += SHA256_MAC_LEN;
8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else {
86e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt			if (hmac_sha256_vector(key, key_len, 4, addr, len,
87e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt					       hash) < 0)
88e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt				return -1;
8961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os_memcpy(&buf[pos], hash, plen);
90a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			pos += plen;
9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		counter++;
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
95a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
96a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	/*
97a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * Mask out unused bits in the last octet if it does not use all the
98a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * bits.
99a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 */
100a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (buf_len_bits % 8) {
101a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		u8 mask = 0xff << (8 - buf_len_bits % 8);
102a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		buf[pos - 1] &= mask;
103a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
104746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt
105746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt	os_memset(hash, 0, sizeof(hash));
106e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt
107e4663044d3a689fb5458247e9bc0f8b58cf72fcaDmitry Shmidt	return 0;
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
109