diff --git a/hostapd/Makefile b/hostapd/Makefile index 75767aee7..2dfb7d611 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -683,6 +683,9 @@ OBJS += ../src/crypto/sha256.o ifdef CONFIG_INTERNAL_SHA256 OBJS += ../src/crypto/sha256-internal.o endif +ifdef NEED_TLS_PRF_SHA256 +OBJS += ../src/crypto/sha256-tlsprf.o +endif endif ifdef NEED_DH_GROUPS diff --git a/src/crypto/Makefile b/src/crypto/Makefile index 290fa677a..b221dd449 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -41,6 +41,7 @@ LIB_OBJS= \ sha1-tlsprf.o \ sha1-tprf.o \ sha256.o \ + sha256-tlsprf.o \ sha256-internal.o LIB_OBJS += crypto_internal.o diff --git a/src/crypto/sha256-tlsprf.c b/src/crypto/sha256-tlsprf.c new file mode 100644 index 000000000..6763c9677 --- /dev/null +++ b/src/crypto/sha256-tlsprf.c @@ -0,0 +1,72 @@ +/* + * TLS PRF P_SHA256 + * Copyright (c) 2011, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha256.h" + + +/** + * tls_prf_sha256 - Pseudo-Random Function for TLS v1.2 (P_SHA256, RFC 5246) + * @secret: Key for PRF + * @secret_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @seed: Seed value to bind into the key + * @seed_len: Length of the seed + * @out: Buffer for the generated pseudo-random key + * @outlen: 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 in TLS. This PRF is defined in RFC 2246, Chapter 5. + */ +void tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label, + const u8 *seed, size_t seed_len, u8 *out, size_t outlen) +{ + size_t clen; + u8 A[SHA256_MAC_LEN]; + u8 P[SHA256_MAC_LEN]; + size_t pos; + const unsigned char *addr[3]; + size_t len[3]; + + addr[0] = A; + len[0] = SHA256_MAC_LEN; + addr[1] = (unsigned char *) label; + len[1] = os_strlen(label); + addr[2] = seed; + len[2] = seed_len; + + /* + * RFC 5246, Chapter 5 + * A(0) = seed, A(i) = HMAC(secret, A(i-1)) + * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. + * PRF(secret, label, seed) = P_SHA256(secret, label + seed) + */ + + hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A); + + pos = 0; + while (pos < outlen) { + hmac_sha256_vector(secret, secret_len, 3, addr, len, P); + hmac_sha256(secret, secret_len, A, SHA256_MAC_LEN, A); + + clen = outlen - pos; + if (clen > SHA256_MAC_LEN) + clen = SHA256_MAC_LEN; + os_memcpy(out + pos, P, clen); + pos += clen; + } +} diff --git a/src/crypto/sha256.h b/src/crypto/sha256.h index dc597f09b..b1ce6afe4 100644 --- a/src/crypto/sha256.h +++ b/src/crypto/sha256.h @@ -1,6 +1,6 @@ /* * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen + * Copyright (c) 2003-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,5 +23,8 @@ void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); void 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); +void tls_prf_sha256(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); #endif /* SHA256_H */ diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 5ec720780..dad156cae 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1094,6 +1094,9 @@ SHA256OBJS += ../src/crypto/sha256.o ifdef CONFIG_INTERNAL_SHA256 SHA256OBJS += ../src/crypto/sha256-internal.o endif +ifdef NEED_TLS_PRF_SHA256 +SHA256OBJS += ../src/crypto/sha256-tlsprf.o +endif OBJS += $(SHA256OBJS) endif