161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/* 261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * SHA1-based PRF 361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Copyright (c) 2003-2005, 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 "sha1.h" 1361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "crypto.h" 1461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 1661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt/** 1761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) 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 * Returns: 0 on success, -1 of failure 2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * 2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * This function is used to derive new, cryptographically separate keys from a 2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * given key (e.g., PMK in IEEE 802.11i). 2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtint sha1_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{ 3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 counter = 0; 3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t pos, plen; 3561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt u8 hash[SHA1_MAC_LEN]; 3661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t label_len = os_strlen(label) + 1; 3761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt const unsigned char *addr[3]; 3861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt size_t len[3]; 3961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 4061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt addr[0] = (u8 *) label; 4161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len[0] = label_len; 4261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt addr[1] = data; 4361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len[1] = data_len; 4461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt addr[2] = &counter; 4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt len[2] = 1; 4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = 0; 4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt while (pos < buf_len) { 4961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt plen = buf_len - pos; 5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (plen >= SHA1_MAC_LEN) { 5161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hmac_sha1_vector(key, key_len, 3, addr, len, 5261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt &buf[pos])) 5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos += SHA1_MAC_LEN; 5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else { 5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (hmac_sha1_vector(key, key_len, 3, addr, len, 5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt hash)) 5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return -1; 5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_memcpy(&buf[pos], hash, plen); 6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt break; 6161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt counter++; 6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 64746bde5f922dfd627d25111da4313395bc4ed6afDmitry Shmidt os_memset(hash, 0, sizeof(hash)); 6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return 0; 6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt} 68