1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * SHA1-based PRF 3e5b75505Sopenharmony_ci * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * 5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 6e5b75505Sopenharmony_ci * See README for more details. 7e5b75505Sopenharmony_ci */ 8e5b75505Sopenharmony_ci 9e5b75505Sopenharmony_ci#include "includes.h" 10e5b75505Sopenharmony_ci 11e5b75505Sopenharmony_ci#include "common.h" 12e5b75505Sopenharmony_ci#include "sha1.h" 13e5b75505Sopenharmony_ci#include "crypto.h" 14e5b75505Sopenharmony_ci 15e5b75505Sopenharmony_ci 16e5b75505Sopenharmony_ci/** 17e5b75505Sopenharmony_ci * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) 18e5b75505Sopenharmony_ci * @key: Key for PRF 19e5b75505Sopenharmony_ci * @key_len: Length of the key in bytes 20e5b75505Sopenharmony_ci * @label: A unique label for each purpose of the PRF 21e5b75505Sopenharmony_ci * @data: Extra data to bind into the key 22e5b75505Sopenharmony_ci * @data_len: Length of the data 23e5b75505Sopenharmony_ci * @buf: Buffer for the generated pseudo-random key 24e5b75505Sopenharmony_ci * @buf_len: Number of bytes of key to generate 25e5b75505Sopenharmony_ci * Returns: 0 on success, -1 of failure 26e5b75505Sopenharmony_ci * 27e5b75505Sopenharmony_ci * This function is used to derive new, cryptographically separate keys from a 28e5b75505Sopenharmony_ci * given key (e.g., PMK in IEEE 802.11i). 29e5b75505Sopenharmony_ci */ 30e5b75505Sopenharmony_ciint sha1_prf(const u8 *key, size_t key_len, const char *label, 31e5b75505Sopenharmony_ci const u8 *data, size_t data_len, u8 *buf, size_t buf_len) 32e5b75505Sopenharmony_ci{ 33e5b75505Sopenharmony_ci u8 counter = 0; 34e5b75505Sopenharmony_ci size_t pos, plen; 35e5b75505Sopenharmony_ci u8 hash[SHA1_MAC_LEN]; 36e5b75505Sopenharmony_ci size_t label_len = os_strlen(label) + 1; 37e5b75505Sopenharmony_ci const unsigned char *addr[3]; 38e5b75505Sopenharmony_ci size_t len[3]; 39e5b75505Sopenharmony_ci 40e5b75505Sopenharmony_ci addr[0] = (u8 *) label; 41e5b75505Sopenharmony_ci len[0] = label_len; 42e5b75505Sopenharmony_ci addr[1] = data; 43e5b75505Sopenharmony_ci len[1] = data_len; 44e5b75505Sopenharmony_ci addr[2] = &counter; 45e5b75505Sopenharmony_ci len[2] = 1; 46e5b75505Sopenharmony_ci 47e5b75505Sopenharmony_ci pos = 0; 48e5b75505Sopenharmony_ci while (pos < buf_len) { 49e5b75505Sopenharmony_ci plen = buf_len - pos; 50e5b75505Sopenharmony_ci if (plen >= SHA1_MAC_LEN) { 51e5b75505Sopenharmony_ci if (hmac_sha1_vector(key, key_len, 3, addr, len, 52e5b75505Sopenharmony_ci &buf[pos])) 53e5b75505Sopenharmony_ci return -1; 54e5b75505Sopenharmony_ci pos += SHA1_MAC_LEN; 55e5b75505Sopenharmony_ci } else { 56e5b75505Sopenharmony_ci if (hmac_sha1_vector(key, key_len, 3, addr, len, 57e5b75505Sopenharmony_ci hash)) 58e5b75505Sopenharmony_ci return -1; 59e5b75505Sopenharmony_ci os_memcpy(&buf[pos], hash, plen); 60e5b75505Sopenharmony_ci break; 61e5b75505Sopenharmony_ci } 62e5b75505Sopenharmony_ci counter++; 63e5b75505Sopenharmony_ci } 64e5b75505Sopenharmony_ci forced_memzero(hash, sizeof(hash)); 65e5b75505Sopenharmony_ci 66e5b75505Sopenharmony_ci return 0; 67e5b75505Sopenharmony_ci} 68