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