161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/*
261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * SHA256-based PRF (IEEE 802.11r)
3a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * Copyright (c) 2003-2013, 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
2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt *
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * This function is used to derive new, cryptographically separate keys from a
2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * given key.
2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */
2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtvoid sha256_prf(const u8 *key, size_t key_len, const char *label,
3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt{
32a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	sha256_prf_bits(key, key_len, label, data, data_len, buf, buf_len * 8);
33a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt}
34a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
35a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
36a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt/**
37a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function
38a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @key: Key for KDF
39a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @key_len: Length of the key in bytes
40a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @label: A unique label for each purpose of the PRF
41a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @data: Extra data to bind into the key
42a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @data_len: Length of the data
43a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @buf: Buffer for the generated pseudo-random key
44a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * @buf_len: Number of bits of key to generate
45a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt *
46a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * This function is used to derive new, cryptographically separate keys from a
47a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * given key. If the requested buf_len is not divisible by eight, the least
48a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * significant 1-7 bits of the last octet in the output are not part of the
49a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt * requested output.
50a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt */
51a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidtvoid sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
52a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		     const u8 *data, size_t data_len, u8 *buf,
53a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		     size_t buf_len_bits)
54a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt{
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u16 counter = 1;
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t pos, plen;
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 hash[SHA256_MAC_LEN];
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	const u8 *addr[4];
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	size_t len[4];
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 counter_le[2], length_le[2];
61a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	size_t buf_len = (buf_len_bits + 7) / 8;
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[0] = counter_le;
6461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[0] = 2;
6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[1] = (u8 *) label;
6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[1] = os_strlen(label);
6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[2] = data;
6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[2] = data_len;
6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	addr[3] = length_le;
7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	len[3] = sizeof(length_le);
7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
72a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	WPA_PUT_LE16(length_le, buf_len_bits);
7361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	pos = 0;
7461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (pos < buf_len) {
7561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		plen = buf_len - pos;
7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		WPA_PUT_LE16(counter_le, counter);
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (plen >= SHA256_MAC_LEN) {
7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			hmac_sha256_vector(key, key_len, 4, addr, len,
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					   &buf[pos]);
8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			pos += SHA256_MAC_LEN;
8161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		} else {
8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			hmac_sha256_vector(key, key_len, 4, addr, len, hash);
8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os_memcpy(&buf[pos], hash, plen);
84a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt			pos += plen;
8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			break;
8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		counter++;
8861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
89a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt
90a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	/*
91a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * Mask out unused bits in the last octet if it does not use all the
92a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 * bits.
93a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	 */
94a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	if (buf_len_bits % 8) {
95a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		u8 mask = 0xff << (8 - buf_len_bits % 8);
96a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt		buf[pos - 1] &= mask;
97a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt	}
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt}
99