esp-idf/components/wpa_supplicant/src/crypto/sha256-prf.c
kapil.gupta ad7cb5f5c1 wpa_supplicant: Write Crypto API based on mbedtls
This commit add following crypto changes

1. Update current crypto code with upstream supplicant code
2. Add a proper porting layer to use mbedtls APIs for all the crypto
   operations used by supplicant.

Internal crypto will be used when USE_MBEDLTS flag is disabled
in supplicant's menuconfig.

This commit also removes the clutter in crypto files due to partial
porting of some APIs to mbedtls, all the code from those files have
been removed and rewritten in a generic way, this is inspired from
current upstream code.

This also reduces the lib size significantly, supplicant's lib
size reduces around ~567kb after this change(NB: lib size doesn't
indicate reduction in final bin size).
2021-05-04 10:54:57 +00:00

109 lines
2.8 KiB
C

/*
* SHA256-based PRF (IEEE 802.11r)
* Copyright (c) 2003-2016, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "sha256.h"
#include "crypto.h"
/**
* sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
* @key: Key for PRF
* @key_len: Length of the key in bytes
* @label: A unique label for each purpose of the PRF
* @data: Extra data to bind into the key
* @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bytes of key to generate
* Returns: 0 on success, -1 on failure
*
* This function is used to derive new, cryptographically separate keys from a
* given key.
*/
int sha256_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
{
return sha256_prf_bits(key, key_len, label, data, data_len, buf,
buf_len * 8);
}
/**
* sha256_prf_bits - IEEE Std 802.11-2012, 11.6.1.7.2 Key derivation function
* @key: Key for KDF
* @key_len: Length of the key in bytes
* @label: A unique label for each purpose of the PRF
* @data: Extra data to bind into the key
* @data_len: Length of the data
* @buf: Buffer for the generated pseudo-random key
* @buf_len: Number of bits of key to generate
* Returns: 0 on success, -1 on failure
*
* This function is used to derive new, cryptographically separate keys from a
* given key. If the requested buf_len is not divisible by eight, the least
* significant 1-7 bits of the last octet in the output are not part of the
* requested output.
*/
int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf,
size_t buf_len_bits)
{
u16 counter = 1;
size_t pos, plen;
u8 hash[SHA256_MAC_LEN];
const u8 *addr[4];
size_t len[4];
u8 counter_le[2], length_le[2];
size_t buf_len = (buf_len_bits + 7) / 8;
addr[0] = counter_le;
len[0] = 2;
addr[1] = (u8 *) label;
len[1] = os_strlen(label);
addr[2] = data;
len[2] = data_len;
addr[3] = length_le;
len[3] = sizeof(length_le);
WPA_PUT_LE16(length_le, buf_len_bits);
pos = 0;
while (pos < buf_len) {
plen = buf_len - pos;
WPA_PUT_LE16(counter_le, counter);
if (plen >= SHA256_MAC_LEN) {
if (hmac_sha256_vector(key, key_len, 4, addr, len,
&buf[pos]) < 0)
return -1;
pos += SHA256_MAC_LEN;
} else {
if (hmac_sha256_vector(key, key_len, 4, addr, len,
hash) < 0)
return -1;
os_memcpy(&buf[pos], hash, plen);
pos += plen;
break;
}
counter++;
}
/*
* Mask out unused bits in the last octet if it does not use all the
* bits.
*/
if (buf_len_bits % 8) {
u8 mask = 0xff << (8 - buf_len_bits % 8);
buf[pos - 1] &= mask;
}
forced_memzero(hash, sizeof(hash));
return 0;
}