11573Srgrimes/* 21573Srgrimes * SHA256-based PRF (IEEE 802.11r) 31573Srgrimes * Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi> 41573Srgrimes * 51573Srgrimes * This software may be distributed under the terms of the BSD license. 61573Srgrimes * See README for more details. 71573Srgrimes */ 81573Srgrimes 91573Srgrimes#include "includes.h" 101573Srgrimes 111573Srgrimes#include "common.h" 121573Srgrimes#include "sha256.h" 131573Srgrimes#include "crypto.h" 141573Srgrimes 151573Srgrimes 161573Srgrimes/** 171573Srgrimes * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) 181573Srgrimes * @key: Key for PRF 191573Srgrimes * @key_len: Length of the key in bytes 201573Srgrimes * @label: A unique label for each purpose of the PRF 211573Srgrimes * @data: Extra data to bind into the key 221573Srgrimes * @data_len: Length of the data 231573Srgrimes * @buf: Buffer for the generated pseudo-random key 241573Srgrimes * @buf_len: Number of bytes of key to generate 251573Srgrimes * Returns: 0 on success, -1 on failure 261573Srgrimes * 271573Srgrimes * This function is used to derive new, cryptographically separate keys from a 281573Srgrimes * given key. 291573Srgrimes */ 301573Srgrimesint sha256_prf(const u8 *key, size_t key_len, const char *label, 311573Srgrimes const u8 *data, size_t data_len, u8 *buf, size_t buf_len) 321573Srgrimes{ 331573Srgrimes return sha256_prf_bits(key, key_len, label, data, data_len, buf, 341573Srgrimes buf_len * 8); 351573Srgrimes} 361573Srgrimes 371573Srgrimes 381573Srgrimes/** 398870Srgrimes * sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function 401573Srgrimes * @key: Key for KDF 411573Srgrimes * @key_len: Length of the key in bytes 421573Srgrimes * @label: A unique label for each purpose of the PRF 431573Srgrimes * @data: Extra data to bind into the key 441573Srgrimes * @data_len: Length of the data 451573Srgrimes * @buf: Buffer for the generated pseudo-random key 461573Srgrimes * @buf_len: Number of bits of key to generate 471573Srgrimes * Returns: 0 on success, -1 on failure 481573Srgrimes * 491573Srgrimes * This function is used to derive new, cryptographically separate keys from a 501573Srgrimes * given key. If the requested buf_len is not divisible by eight, the least 511573Srgrimes * significant 1-7 bits of the last octet in the output are not part of the 521573Srgrimes * requested output. 531573Srgrimes */ 541573Srgrimesint sha256_prf_bits(const u8 *key, size_t key_len, const char *label, 551573Srgrimes const u8 *data, size_t data_len, u8 *buf, 561573Srgrimes size_t buf_len_bits) 571573Srgrimes{ 581573Srgrimes u16 counter = 1; 591573Srgrimes size_t pos, plen; 601573Srgrimes u8 hash[SHA256_MAC_LEN]; 611573Srgrimes const u8 *addr[4]; 621573Srgrimes size_t len[4]; 631573Srgrimes u8 counter_le[2], length_le[2]; 641573Srgrimes size_t buf_len = (buf_len_bits + 7) / 8; 651573Srgrimes 661573Srgrimes addr[0] = counter_le; 671573Srgrimes len[0] = 2; 681573Srgrimes addr[1] = (u8 *) label; 691573Srgrimes len[1] = os_strlen(label); 701573Srgrimes addr[2] = data; 711573Srgrimes len[2] = data_len; 721573Srgrimes addr[3] = length_le; 731573Srgrimes len[3] = sizeof(length_le); 7417141Sjkh 751573Srgrimes WPA_PUT_LE16(length_le, buf_len_bits); 761573Srgrimes pos = 0; 771573Srgrimes while (pos < buf_len) { 781573Srgrimes plen = buf_len - pos; 791573Srgrimes WPA_PUT_LE16(counter_le, counter); 806683Sphk if (plen >= SHA256_MAC_LEN) { 8114523Shsu if (hmac_sha256_vector(key, key_len, 4, addr, len, 821573Srgrimes &buf[pos]) < 0) 8314523Shsu return -1; 841573Srgrimes pos += SHA256_MAC_LEN; 851573Srgrimes } else { 861573Srgrimes if (hmac_sha256_vector(key, key_len, 4, addr, len, 871573Srgrimes hash) < 0) 881573Srgrimes return -1; 891573Srgrimes os_memcpy(&buf[pos], hash, plen); 901573Srgrimes pos += plen; 911573Srgrimes break; 921573Srgrimes } 931573Srgrimes counter++; 941573Srgrimes } 9514523Shsu 961573Srgrimes /* 971573Srgrimes * Mask out unused bits in the last octet if it does not use all the 981573Srgrimes * bits. 991573Srgrimes */ 10014523Shsu if (buf_len_bits % 8) { 1011573Srgrimes u8 mask = 0xff << (8 - buf_len_bits % 8); 1021573Srgrimes buf[pos - 1] &= mask; 1031573Srgrimes } 1041573Srgrimes 1051573Srgrimes forced_memzero(hash, sizeof(hash)); 1061573Srgrimes 1071573Srgrimes return 0; 1081573Srgrimes} 1091573Srgrimes