Merge branch 'feature/esp_tls_for_supplicant' into 'master'

wpa_supplicant: Support for mbedtls tls handshake

See merge request espressif/esp-idf!8318
This commit is contained in:
Jiang Jiang Jian 2020-07-01 17:23:31 +08:00
commit 664bf79379
21 changed files with 1410 additions and 352 deletions

View file

@ -18,9 +18,9 @@ set(srcs "port/os_xtensa.c"
"src/crypto/aes-unwrap.c"
"src/crypto/aes-wrap.c"
"src/crypto/aes-omac1.c"
"src/crypto/sha256-tlsprf.c"
"src/crypto/bignum.c"
"src/crypto/ccmp.c"
"src/crypto/crypto_mbedtls.c"
"src/crypto/crypto_mbedtls-bignum.c"
"src/crypto/crypto_mbedtls-ec.c"
"src/crypto/crypto_ops.c"
@ -42,6 +42,10 @@ set(srcs "port/os_xtensa.c"
"src/crypto/sha1.c"
"src/crypto/sha256-internal.c"
"src/crypto/sha256.c"
"src/crypto/sha1-tlsprf.c"
"src/crypto/sha256-tlsprf.c"
"src/crypto/sha384-tlsprf.c"
"src/crypto/sha256-prf.c"
"src/eap_peer/chap.c"
"src/eap_peer/eap.c"
"src/eap_peer/eap_common.c"
@ -61,23 +65,6 @@ set(srcs "port/os_xtensa.c"
"src/rsn_supp/pmksa_cache.c"
"src/rsn_supp/wpa.c"
"src/rsn_supp/wpa_ie.c"
"src/tls/asn1.c"
"src/tls/bignum.c"
"src/tls/pkcs1.c"
"src/tls/pkcs5.c"
"src/tls/pkcs8.c"
"src/tls/rsa.c"
"src/tls/tls_internal.c"
"src/tls/tlsv1_client.c"
"src/tls/tlsv1_client_read.c"
"src/tls/tlsv1_client_write.c"
"src/tls/tlsv1_common.c"
"src/tls/tlsv1_cred.c"
"src/tls/tlsv1_record.c"
"src/tls/tlsv1_server.c"
"src/tls/tlsv1_server_read.c"
"src/tls/tlsv1_server_write.c"
"src/tls/x509v3.c"
"src/utils/base64.c"
"src/utils/common.c"
"src/utils/ext_password.c"
@ -95,7 +82,31 @@ set(srcs "port/os_xtensa.c"
"src/wps/wps_registrar.c"
"src/wps/wps_validate.c")
idf_component_register(SRCS "${srcs}"
if(CONFIG_WPA_MBEDTLS_CRYPTO)
set(tls_src "src/crypto/tls_mbedtls.c")
else()
set(tls_src
"src/tls/asn1.c"
"src/tls/bignum.c"
"src/tls/pkcs1.c"
"src/tls/pkcs5.c"
"src/tls/pkcs8.c"
"src/tls/rsa.c"
"src/tls/tls_internal.c"
"src/tls/tlsv1_client.c"
"src/tls/tlsv1_client_read.c"
"src/tls/tlsv1_client_write.c"
"src/tls/tlsv1_common.c"
"src/tls/tlsv1_cred.c"
"src/tls/tlsv1_record.c"
"src/tls/tlsv1_server.c"
"src/tls/tlsv1_server_read.c"
"src/tls/tlsv1_server_write.c"
"src/tls/x509v3.c"
)
endif()
idf_component_register(SRCS "${srcs}" "${tls_src}"
INCLUDE_DIRS include port/include include/esp_supplicant
PRIV_INCLUDE_DIRS src
PRIV_REQUIRES mbedtls esp_timer)

View file

@ -23,12 +23,6 @@ menu "Supplicant"
help
Select this to enable unity test for DPP.
config WPA_TLS_V12
bool "Enable TLS v1.2"
default n
help
Select this to enable TLS v1.2 for WPA2-Enterprise Authentication.
config WPA_WPS_WARS
bool "Add WPS Inter operatability Fixes"
default n

View file

@ -1,5 +1,29 @@
COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
# supplicant make file
COMPONENT_PRIV_INCLUDEDIRS := src
COMPONENT_SRCDIRS := port src/ap src/common src/crypto src/eap_peer src/rsn_supp src/tls src/utils src/esp_supplicant src/wps
COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
ifeq ($(CONFIG_WPA_MBEDTLS_CRYPTO), y)
COMPONENT_OBJEXCLUDE := src/tls/asn1.o \
src/tls/bignum.o \
src/tls/pkcs1.o \
src/tls/pkcs5.o \
src/tls/pkcs8.o \
src/tls/rsa.o \
src/tls/tls_internal.o \
src/tls/tlsv1_client.o \
src/tls/tlsv1_client_read.o \
src/tls/tlsv1_client_write.o \
src/tls/tlsv1_common.o \
src/tls/tlsv1_cred.o \
src/tls/tlsv1_record.o \
src/tls/tlsv1_server.o \
src/tls/tlsv1_server_read.o \
src/tls/tlsv1_server_write.o \
src/tls/x509v3.o
else
COMPONENT_OBJEXCLUDE := src/crypto/tls_mbedtls.o
endif
CFLAGS += -DCONFIG_DPP -DCONFIG_WPA3_SAE -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing

View file

@ -278,6 +278,9 @@ char * ets_strdup(const char *s);
#ifndef os_strstr
#define os_strstr(h, n) strstr((h), (n))
#endif
#ifndef os_strlcpy
#define os_strlcpy(d, s, n) strlcpy((d), (s), (n))
#endif
#ifndef os_snprintf
#ifdef _MSC_VER
@ -291,16 +294,4 @@ static inline int os_snprintf_error(size_t size, int res)
{
return res < 0 || (unsigned int) res >= size;
}
/**
* os_strlcpy - Copy a string with size bound and NUL-termination
* @dest: Destination
* @src: Source
* @siz: Size of the target buffer
* Returns: Total length of the target string (length of src) (not including
* NUL-termination)
*
* This function matches in behavior with the strlcpy(3) function in OpenBSD.
*/
size_t os_strlcpy(char *dest, const char *src, size_t siz);
#endif /* OS_H */

View file

@ -19,14 +19,13 @@
#if CONFIG_WPA_MBEDTLS_CRYPTO
#define USE_MBEDTLS_CRYPTO 1
#else
#define CONFIG_TLS_INTERNAL_CLIENT
#define CONFIG_TLSV12
#endif
#if CONFIG_WPA_DEBUG_PRINT
#define DEBUG_PRINT
#endif
#if CONFIG_WPA_TLS_V12
#define CONFIG_TLSV12
#endif
#endif /* _SUPPLICANT_OPT_H */

View file

@ -0,0 +1,72 @@
/**
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef ESP_PLATFORM
#include "esp_system.h"
#endif
#include "utils/includes.h"
#include "utils/common.h"
#include "crypto.h"
#include "random.h"
#include "sha256.h"
#include "mbedtls/ecp.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/md.h"
int mbedtls_hmac_vector(mbedtls_md_type_t md_type, const u8 *key, size_t key_len,
size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
{
size_t i;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
int ret;
mbedtls_md_init(&md_ctx);
if((md_info = mbedtls_md_info_from_type(md_type)) == NULL )
return -1;
if ((ret = mbedtls_md_setup( &md_ctx, md_info, 1)) != 0)
return(ret);
mbedtls_md_hmac_starts(&md_ctx, key, key_len);
for( i = 0; i < num_elem; i++)
mbedtls_md_hmac_update(&md_ctx, addr[i], len[i]);
mbedtls_md_hmac_finish(&md_ctx, mac);
mbedtls_md_free(&md_ctx);
return 0;
}
int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
return mbedtls_hmac_vector(MBEDTLS_MD_SHA384, key, key_len, num_elem, addr,
len, mac);
}
int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac)
{
return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac);
}

View file

@ -0,0 +1,101 @@
/*
* TLS PRF (SHA1 + MD5)
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "sha1.h"
#include "md5.h"
/**
* tls_prf_sha1_md5 - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
* @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.
*/
int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
{
size_t L_S1, L_S2, i;
const u8 *S1, *S2;
u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN];
u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN];
int MD5_pos, SHA1_pos;
const u8 *MD5_addr[3];
size_t MD5_len[3];
const unsigned char *SHA1_addr[3];
size_t SHA1_len[3];
MD5_addr[0] = A_MD5;
MD5_len[0] = MD5_MAC_LEN;
MD5_addr[1] = (unsigned char *) label;
MD5_len[1] = os_strlen(label);
MD5_addr[2] = seed;
MD5_len[2] = seed_len;
SHA1_addr[0] = A_SHA1;
SHA1_len[0] = SHA1_MAC_LEN;
SHA1_addr[1] = (unsigned char *) label;
SHA1_len[1] = os_strlen(label);
SHA1_addr[2] = seed;
SHA1_len[2] = seed_len;
/* RFC 2246, 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 = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed)
*/
L_S1 = L_S2 = (secret_len + 1) / 2;
S1 = secret;
S2 = secret + L_S1;
if (secret_len & 1) {
/* The last byte of S1 will be shared with S2 */
S2--;
}
hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5);
hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);
MD5_pos = MD5_MAC_LEN;
SHA1_pos = SHA1_MAC_LEN;
for (i = 0; i < outlen; i++) {
if (MD5_pos == MD5_MAC_LEN) {
hmac_md5_vector(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5);
MD5_pos = 0;
hmac_md5(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5);
}
if (SHA1_pos == SHA1_MAC_LEN) {
hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len,
P_SHA1);
SHA1_pos = 0;
hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1);
}
out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos];
MD5_pos++;
SHA1_pos++;
}
os_memset(A_MD5, 0, MD5_MAC_LEN);
os_memset(P_MD5, 0, MD5_MAC_LEN);
os_memset(A_SHA1, 0, SHA1_MAC_LEN);
os_memset(P_SHA1, 0, SHA1_MAC_LEN);
return 0;
}

View file

@ -0,0 +1,108 @@
/*
* 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 "utils/includes.h"
#include "utils/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;
}
os_memset(hash, 0, sizeof(hash));
return 0;
}

View file

@ -26,8 +26,8 @@
* 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)
int 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];
@ -50,12 +50,15 @@ void tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label,
* PRF(secret, label, seed) = P_SHA256(secret, label + seed)
*/
hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A);
if (hmac_sha256_vector(secret, secret_len, 2, &addr[1], &len[1], A) < 0)
return -1;
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);
if (hmac_sha256_vector(secret, secret_len, 3, addr, len, P) <
0 ||
hmac_sha256(secret, secret_len, A, SHA256_MAC_LEN, A) < 0)
return -1;
clen = outlen - pos;
if (clen > SHA256_MAC_LEN)
@ -63,4 +66,6 @@ void tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label,
os_memcpy(out + pos, P, clen);
pos += clen;
}
return 0;
}

View file

@ -49,8 +49,8 @@ int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
{
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
unsigned char tk[32];
const u8 *_addr[6];
size_t _len[6], i;
const u8 *_addr[11];
size_t _len[11], i;
if (num_elem > 5) {
/*
@ -114,104 +114,11 @@ int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
* @key_len: Length of the key in bytes
* @data: Pointers to the data area
* @data_len: Length of the data area
* @mac: Buffer for the hash (20 bytes)
*/
int
hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac)
{
return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
}
/**
* 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
* @mac: Buffer for the hash (32 bytes)
* 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)
int hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac)
{
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;
}
os_memset(hash, 0, sizeof(hash));
return 0;
return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
}

View file

@ -26,7 +26,7 @@ int sha256_prf(const u8 *key, size_t key_len, const char *label,
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);
void tls_prf_sha256(const u8 *secret, size_t secret_len,
int 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);

View file

@ -0,0 +1,71 @@
/*
* TLS PRF P_SHA384
* Copyright (c) 2011-2019, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "sha384.h"
/**
* tls_prf_sha384 - Pseudo-Random Function for TLS v1.2 (P_SHA384, 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 5246, Chapter 5.
*/
int tls_prf_sha384(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[SHA384_MAC_LEN];
u8 P[SHA384_MAC_LEN];
size_t pos;
const unsigned char *addr[3];
size_t len[3];
addr[0] = A;
len[0] = SHA384_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_SHA384(secret, label + seed)
*/
if (hmac_sha384_vector(secret, secret_len, 2, &addr[1], &len[1], A) < 0)
return -1;
pos = 0;
while (pos < outlen) {
if (hmac_sha384_vector(secret, secret_len, 3, addr, len, P) <
0 ||
hmac_sha384(secret, secret_len, A, SHA384_MAC_LEN, A) < 0)
return -1;
clen = outlen - pos;
if (clen > SHA384_MAC_LEN)
clen = SHA384_MAC_LEN;
os_memcpy(out + pos, P, clen);
pos += clen;
}
return 0;
}

View file

@ -0,0 +1,30 @@
/*
* SHA384 hash implementation and interface functions
* Copyright (c) 2015-2017, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#ifndef SHA384_H
#define SHA384_H
#define SHA384_MAC_LEN 48
int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac);
int hmac_sha384(const u8 *key, size_t key_len, const u8 *data,
size_t data_len, u8 *mac);
int sha384_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
int sha384_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);
int tls_prf_sha384(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen);
int hmac_sha384_kdf(const u8 *secret, size_t secret_len,
const char *label, const u8 *seed, size_t seed_len,
u8 *out, size_t outlen);
#endif /* SHA384_H */

View file

@ -0,0 +1,879 @@
/**
* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utils/includes.h"
#include "utils/common.h"
#include "tls/tls.h"
#include "crypto/sha1.h"
#include "crypto/md5.h"
#include "crypto/sha256.h"
#include "crypto/sha384.h"
#include "mbedtls/ssl_internal.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/entropy.h"
#include "mbedtls/debug.h"
#ifdef ESPRESSIF_USE
#include "mbedtls/esp_debug.h"
#include "mbedtls/esp_config.h"
#else
#include "mbedtls/config.h"
#endif
#define TLS_RANDOM_LEN 32
#define TLS_MASTER_SECRET_LEN 48
#define MAX_CIPHERSUITE 32
/* Throw a compilation error if basic requirements in mbedtls are not enabled */
#if !defined(MBEDTLS_SSL_TLS_C)
#error "TLS not enabled in mbedtls config"
#endif
#if !defined(MBEDTLS_SHA256_C)
#error "SHA256 is disabled in mbedtls config"
#endif
#if !defined(MBEDTLS_AES_C)
#error "AES support is disabled in mbedtls config"
#endif
uint32_t tls_instance_count;
struct tls_data {
/* Data for mbedlts */
struct wpabuf *in_data;
/* Data from mbedtls */
struct wpabuf *out_data;
};
typedef struct tls_context {
mbedtls_ssl_context ssl; /*!< TLS/SSL context */
mbedtls_entropy_context entropy; /*!< mbedTLS entropy context structure */
mbedtls_ctr_drbg_context ctr_drbg; /*!< mbedTLS ctr drbg context structure */
mbedtls_ssl_config conf; /*!< TLS/SSL config to be shared structures */
mbedtls_x509_crt cacert; /*!< Container for X.509 CA certificate */
mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */
mbedtls_x509_crt clientcert; /*!< Container for X.509 client certificate */
mbedtls_pk_context clientkey; /*!< Private key of client certificate */
int ciphersuite[MAX_CIPHERSUITE];
} tls_context_t;
struct tls_connection {
tls_context_t *tls;
struct tls_data tls_io_data;
unsigned char randbytes[2 * TLS_RANDOM_LEN];
};
static void tls_mbedtls_cleanup(tls_context_t *tls)
{
if (!tls) {
return;
}
tls->cacert_ptr = NULL;
mbedtls_x509_crt_free(&tls->cacert);
mbedtls_x509_crt_free(&tls->clientcert);
mbedtls_pk_free(&tls->clientkey);
mbedtls_entropy_free(&tls->entropy);
mbedtls_ssl_config_free(&tls->conf);
mbedtls_ctr_drbg_free(&tls->ctr_drbg);
mbedtls_ssl_free(&tls->ssl);
}
static void tls_mbedtls_conn_delete(tls_context_t *tls)
{
if (tls != NULL) {
tls_mbedtls_cleanup(tls);
}
}
static int tls_mbedtls_write(void *ctx, const unsigned char *buf, size_t len)
{
struct tls_connection *conn = (struct tls_connection *)ctx;
struct tls_data *data = &conn->tls_io_data;
if (data->out_data) {
wpabuf_resize(&data->out_data, len);
} else {
data->out_data = wpabuf_alloc(len);
}
wpabuf_put_data(data->out_data, buf, len);
return len;
}
static int tls_mbedtls_read(void *ctx, unsigned char *buf, size_t len)
{
struct tls_connection *conn = (struct tls_connection *)ctx;
struct tls_data *data = &conn->tls_io_data;
struct wpabuf *local_buf;
size_t data_len = len;
if (len > wpabuf_len(data->in_data)) {
wpa_printf(MSG_ERROR, "don't have suffient data\n");
data_len = wpabuf_len(data->in_data);
}
os_memcpy(buf, wpabuf_head(data->in_data), data_len);
/* adjust buffer */
if (len < wpabuf_len(data->in_data)) {
local_buf = wpabuf_alloc_copy(wpabuf_head(data->in_data) + len,
wpabuf_len(data->in_data) - len);
wpabuf_free(data->in_data);
data->in_data = local_buf;
} else {
wpabuf_free(data->in_data);
data->in_data = NULL;
}
return data_len;
}
static int set_pki_context(tls_context_t *tls, const struct tls_connection_params *cfg)
{
int ret;
if (cfg->client_cert_blob == NULL || cfg->private_key_blob == NULL) {
wpa_printf(MSG_ERROR, "%s: config not correct", __func__);
return -1;
}
mbedtls_x509_crt_init(&tls->clientcert);
mbedtls_pk_init(&tls->clientkey);
ret = mbedtls_x509_crt_parse(&tls->clientcert,
cfg->client_cert_blob, cfg->client_cert_blob_len);
if (ret < 0) {
wpa_printf(MSG_ERROR, "mbedtls_x509_crt_parse returned -0x%x", -ret);
return ret;
}
ret = mbedtls_pk_parse_key(&tls->clientkey, cfg->private_key_blob, cfg->private_key_blob_len,
(const unsigned char *)cfg->private_key_passwd,
cfg->private_key_passwd ? os_strlen(cfg->private_key_passwd) : 0);
if (ret < 0) {
wpa_printf(MSG_ERROR, "mbedtls_pk_parse_keyfile returned -0x%x", -ret);
return ret;
}
ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey);
if (ret < 0) {
wpa_printf(MSG_ERROR, "mbedtls_ssl_conf_own_cert returned -0x%x", -ret);
return ret;
}
return 0;
}
static int set_ca_cert(tls_context_t *tls, const unsigned char *cacert, size_t cacert_len)
{
tls->cacert_ptr = &tls->cacert;
mbedtls_x509_crt_init(tls->cacert_ptr);
int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len);
if (ret < 0) {
wpa_printf(MSG_ERROR, "mbedtls_x509_crt_parse returned -0x%x", -ret);
return ret;
}
mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL);
return 0;
}
static int tls_sig_hashes_for_eap[] = {
#if defined(MBEDTLS_SHA512_C)
MBEDTLS_MD_SHA512,
MBEDTLS_MD_SHA384,
#endif
#if defined(MBEDTLS_SHA256_C)
MBEDTLS_MD_SHA256,
MBEDTLS_MD_SHA224,
#endif
#if defined(MBEDTLS_SHA1_C)
MBEDTLS_MD_SHA1,
#endif
MBEDTLS_MD_NONE
};
const mbedtls_x509_crt_profile eap_mbedtls_x509_crt_profile =
{
#if defined(MBEDTLS_SHA1_C)
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
#endif
#if defined(MBEDTLS_SHA256_C)
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
#endif
#if defined(MBEDTLS_SHA512_C)
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) |
MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ) |
#endif
0,
0xFFFFFFF, /* Any PK alg */
0xFFFFFFF, /* Any curve */
1024,
};
static void tls_enable_sha1_config(tls_context_t *tls)
{
const mbedtls_x509_crt_profile *crt_profile = &eap_mbedtls_x509_crt_profile;
mbedtls_ssl_conf_cert_profile(&tls->conf, crt_profile);
mbedtls_ssl_conf_sig_hashes(&tls->conf, tls_sig_hashes_for_eap);
}
static const int eap_ciphersuite_preference[] =
{
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
#endif
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
#endif
#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
#endif
/* The PSK suites */
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
#endif
#if defined(MBEDTLS_GCM_C)
MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
#endif
#if defined(MBEDTLS_CCM_C)
MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
#endif
#endif
#if defined(MBEDTLS_DES_C)
/* 3DES suites */
MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
#endif
#if defined(MBEDTLS_ARC4_C)
/* RC4 suites */
MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA,
MBEDTLS_TLS_RSA_WITH_RC4_128_SHA,
MBEDTLS_TLS_RSA_WITH_RC4_128_MD5,
MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA,
MBEDTLS_TLS_PSK_WITH_RC4_128_SHA,
#endif
};
static void tls_set_ciphersuite(tls_context_t *tls)
{
/* Only set ciphersuite if cert's key length is high or ciphersuites are set by user */
if (tls->ciphersuite[0]) {
mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite);
} else if (mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 ||
mbedtls_pk_get_bitlen(&tls->cacert_ptr->pk) > 2048) {
mbedtls_ssl_conf_ciphersuites(&tls->conf, eap_ciphersuite_preference);
}
}
static int set_client_config(const struct tls_connection_params *cfg, tls_context_t *tls)
{
int ret;
assert(cfg != NULL);
assert(tls != NULL);
ret = mbedtls_ssl_config_defaults(&tls->conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0) {
wpa_printf(MSG_ERROR, "mbedtls_ssl_config_defaults returned -0x%x", -ret);
return ret;
}
/* Enable SHA1 support since it's not enabled by default in mbedtls */
tls_enable_sha1_config(tls);
if (cfg->ca_cert_blob != NULL) {
ret = set_ca_cert(tls, cfg->ca_cert_blob, cfg->ca_cert_blob_len);
if (ret != 0) {
return ret;
}
mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL);
} else {
mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE);
}
if (cfg->client_cert_blob != NULL && cfg->private_key_blob != NULL) {
ret = set_pki_context(tls, cfg);
if (ret != 0) {
wpa_printf(MSG_ERROR, "Failed to set client pki context");
return ret;
}
}
/* Usages of default ciphersuites can take a lot of time on low end device
* and can cause watchdog. Enabling the ciphers which are secured enough
* but doesn't take that much processing power */
tls_set_ciphersuite(tls);
return 0;
}
static int tls_create_mbedtls_handle(const struct tls_connection_params *params,
tls_context_t *tls)
{
int ret;
assert(params != NULL);
assert(tls != NULL);
mbedtls_ssl_init(&tls->ssl);
mbedtls_ctr_drbg_init(&tls->ctr_drbg);
mbedtls_ssl_config_init(&tls->conf);
mbedtls_entropy_init(&tls->entropy);
ret = set_client_config(params, tls);
if (ret != 0) {
wpa_printf(MSG_ERROR, "Failed to set client configurations");
goto exit;
}
ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, mbedtls_entropy_func,
&tls->entropy, NULL, 0);
if (ret != 0) {
wpa_printf(MSG_ERROR, "mbedtls_ctr_drbg_seed returned -0x%x", -ret);
goto exit;
}
mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg);
ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf);
if (ret != 0) {
wpa_printf(MSG_ERROR, "mbedtls_ssl_setup returned -0x%x", -ret);
goto exit;
}
/* Enable debug prints in case supplicant's prints are enabled */
#if defined(DEBUG_PRINT) && defined(CONFIG_MBEDTLS_DEBUG) && defined(ESPRESSIF_USE)
mbedtls_esp_enable_debug_log(&tls->conf, 2);
#endif
return 0;
exit:
tls_mbedtls_cleanup(tls);
return ret;
}
void *tls_init()
{
tls_instance_count++;
return &tls_instance_count;
}
void tls_deinit(void *tls_ctx)
{
tls_instance_count--;
}
struct tls_connection * tls_connection_init(void *tls_ctx)
{
struct tls_connection *conn = os_zalloc(sizeof(*conn));
if (!conn) {
wpa_printf(MSG_ERROR, "TLS: Failed to allocate connection memory");
return NULL;
}
return conn;
}
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
{
/* Free ssl ctx and data */
tls_mbedtls_conn_delete((tls_context_t *) conn->tls);
conn->tls = NULL;
/* Data in in ssl ctx, free connection */
os_free(conn);
}
int tls_get_errors(void *tls_ctx)
{
return 0;
}
int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
{
mbedtls_ssl_context *ssl = &conn->tls->ssl;
if (ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) {
return 1;
}
return 0;
}
int tls_global_set_verify(void *tls_ctx, int check_crl)
{
wpa_printf(MSG_INFO, "TLS: global settings are not supported");
return -1;
}
int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
int verify_peer)
{
wpa_printf(MSG_INFO, "TLS: tls_connection_set_verify not supported");
return -1;
}
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
tls_context_t *tls = conn->tls;
int ret = 0;
/* data freed by sender */
conn->tls_io_data.out_data = NULL;
if (wpabuf_len(in_data)) {
conn->tls_io_data.in_data = wpabuf_dup(in_data);
}
ret = mbedtls_ssl_handshake_step(&tls->ssl);
if (ret < 0) {
wpa_printf(MSG_ERROR, "%s:%d", __func__, __LINE__);
goto end;
}
/* Multiple reads */
while (conn->tls_io_data.in_data) {
ret = mbedtls_ssl_handshake_step(&tls->ssl);
if (ret < 0)
break;
}
/* State machine just started, get client hello */
if (tls->ssl.state == MBEDTLS_SSL_CLIENT_HELLO) {
ret = mbedtls_ssl_handshake_step(&tls->ssl);
}
if (ret < 0) {
wpa_printf(MSG_ERROR, "%s:%d", __func__, __LINE__);
goto end;
}
/* Already read sever data till hello done */
if (tls->ssl.state == MBEDTLS_SSL_CLIENT_CERTIFICATE) {
/* Read random data before session completes, not present after handshake */
if (tls->ssl.handshake) {
os_memcpy(conn->randbytes, tls->ssl.handshake->randbytes,
TLS_RANDOM_LEN * 2);
}
/* trigger state machine multiple times to reach till finish */
while (tls->ssl.state <= MBEDTLS_SSL_CLIENT_FINISHED) {
ret = mbedtls_ssl_handshake_step(&tls->ssl);
if (ret < 0) {
break;
}
}
}
/* Trigger state machine till handshake is complete or error occures */
if (tls->ssl.state == MBEDTLS_SSL_FLUSH_BUFFERS) {
while (tls->ssl.state <= MBEDTLS_SSL_HANDSHAKE_OVER) {
ret = mbedtls_ssl_handshake_step(&tls->ssl);
if (ret < 0) {
break;
}
}
}
if (!conn->tls_io_data.out_data) {
wpa_printf(MSG_INFO, "application data is null, adding one byte for ack");
u8 *dummy = os_zalloc(1);
conn->tls_io_data.out_data = wpabuf_alloc_ext_data(dummy, 0);
}
end:
return conn->tls_io_data.out_data;
}
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data,
struct wpabuf **appl_data)
{
wpa_printf(MSG_ERROR, "%s: not supported %d", __func__, __LINE__);
return NULL;
}
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
/* Reset dangling pointer */
conn->tls_io_data.out_data = NULL;
ssize_t ret = mbedtls_ssl_write(&conn->tls->ssl,
(unsigned char*) wpabuf_head(in_data), wpabuf_len(in_data));
if (ret < wpabuf_len(in_data)) {
wpa_printf(MSG_ERROR, "%s:%d, not able to write whole data",
__func__, __LINE__);
}
return conn->tls_io_data.out_data;
}
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
struct tls_connection *conn,
const struct wpabuf *in_data)
{
unsigned char buf[1200];
int ret;
conn->tls_io_data.in_data = wpabuf_dup(in_data);
ret = mbedtls_ssl_read(&conn->tls->ssl, buf, 1200);
if (ret < 0) {
wpa_printf(MSG_ERROR, "%s:%d, not able to write whole data",
__func__, __LINE__);
return NULL;
}
struct wpabuf *out = wpabuf_alloc_copy(buf, ret);
return out;
}
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
{
if (conn && conn->tls && conn->tls->ssl.handshake) {
return conn->tls->ssl.handshake->resume;
}
return 0;
}
/* cipher array should contain cipher number in mbedtls num as per IANA
* Please see cipherlist is u8, therefore only initial ones are supported */
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
u8 *ciphers)
{
int i = 0;
while (*ciphers != 0 && i < MAX_CIPHERSUITE) {
conn->tls->ciphersuite[i] = ciphers[i];
i++;
}
return 0;
}
int tls_get_version(void *tls_ctx, struct tls_connection *conn,
char *buf, size_t buflen)
{
const char *name;
if (conn == NULL) {
return -1;
}
name = mbedtls_ssl_get_version(&conn->tls->ssl);
if (name == NULL) {
return -1;
}
os_strlcpy(buf, name, buflen);
return 0;
}
int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
char *buf, size_t buflen)
{
const char *name;
if (conn == NULL) {
return -1;
}
name = mbedtls_ssl_get_ciphersuite(&conn->tls->ssl);
if (name == NULL) {
return -1;
}
os_strlcpy(buf, name, buflen);
return 0;
}
int tls_connection_enable_workaround(void *tls_ctx,
struct tls_connection *conn)
{
wpa_printf(MSG_ERROR, "%s: not supported %d", __func__, __LINE__);
return -1;
}
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
{
return 0;
}
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
{
wpa_printf(MSG_ERROR, "%s: not supported %d", __func__, __LINE__);
return 0;
}
int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn)
{
wpa_printf(MSG_ERROR, "%s: not supported %d", __func__, __LINE__);
return 0;
}
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
const struct tls_connection_params *params)
{
int ret = 0;
tls_context_t *tls = (tls_context_t *)os_zalloc(sizeof(tls_context_t));
if (!tls) {
wpa_printf(MSG_ERROR, "failed to allocate tls context");
return -1;
}
if (!params) {
wpa_printf(MSG_ERROR, "configuration is null");
ret = -1;
goto err;
}
ret = tls_create_mbedtls_handle(params, tls);
if (ret < 0) {
wpa_printf(MSG_ERROR, "failed to create ssl handle");
goto err;
}
mbedtls_ssl_set_bio(&tls->ssl, conn, tls_mbedtls_write, tls_mbedtls_read, NULL);
conn->tls = (tls_context_t *)tls;
return ret;
err:
os_free(tls);
return ret;
}
int tls_global_set_params(void *tls_ctx,
const struct tls_connection_params *params)
{
wpa_printf(MSG_INFO, "TLS: Global parameters not supported");
return -1;
}
int tls_connection_set_session_ticket_cb(void *tls_ctx,
struct tls_connection *conn,
tls_session_ticket_cb cb,
void *ctx)
{
wpa_printf(MSG_ERROR, "TLS: %s not supported", __func__);
return -1;
}
static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
u8 *out, size_t out_len)
{
int ret;
u8 seed[2 * TLS_RANDOM_LEN];
mbedtls_ssl_context *ssl = &conn->tls->ssl;
mbedtls_ssl_transform *transform = ssl->transform;
if (!ssl || !transform) {
wpa_printf(MSG_ERROR, "TLS: %s, session ingo is null", __func__);
return -1;
}
if (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
wpa_printf(MSG_ERROR, "TLS: %s, incorrect tls state=%d", __func__, ssl->state);
return -1;
}
if (server_random_first) {
os_memcpy(seed, conn->randbytes + TLS_RANDOM_LEN, TLS_RANDOM_LEN);
os_memcpy(seed + TLS_RANDOM_LEN, conn->randbytes, TLS_RANDOM_LEN);
} else {
os_memcpy(seed, conn->randbytes, 2 * TLS_RANDOM_LEN);
}
wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN);
wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->session->master, TLS_MASTER_SECRET_LEN);
if (transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
ret = tls_prf_sha384(ssl->session->master, TLS_MASTER_SECRET_LEN,
label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
} else if (transform->ciphersuite_info->mac == MBEDTLS_MD_SHA256) {
ret = tls_prf_sha256(ssl->session->master, TLS_MASTER_SECRET_LEN,
label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
} else {
ret = tls_prf_sha1_md5(ssl->session->master, TLS_MASTER_SECRET_LEN,
label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
}
if (ret < 0) {
wpa_printf(MSG_ERROR, "prf failed, ret=%d\n", ret);
}
wpa_hexdump_key(MSG_MSGDUMP, "key", out, out_len);
return ret;
}
int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
const char *label, u8 *out, size_t out_len)
{
return tls_connection_prf(tls_ctx, conn, label, 0, out, out_len);
}
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
{
if (conn->tls_io_data.in_data) {
wpabuf_free(conn->tls_io_data.in_data);
}
conn->tls_io_data.in_data = NULL;
/* outdata may have dangling pointer */
conn->tls_io_data.out_data = NULL;
return mbedtls_ssl_session_reset(&conn->tls->ssl);
}
int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
struct tls_random *data)
{
mbedtls_ssl_context *ssl = &conn->tls->ssl;
os_memset(data, 0, sizeof(*data));
if (ssl->state == MBEDTLS_SSL_CLIENT_HELLO) {
return -1;
}
data->client_random = conn->randbytes;
data->client_random_len = TLS_RANDOM_LEN;
if (ssl->state != MBEDTLS_SSL_SERVER_HELLO) {
data->server_random = conn->randbytes + TLS_RANDOM_LEN;
data->server_random_len = TLS_RANDOM_LEN;
}
return 0;
}

View file

@ -248,53 +248,21 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len)
{
struct tls_keys keys;
u8 *rnd = NULL, *out;
u8 *out;
out = os_malloc(len);
if (out == NULL)
return NULL;
/* First, try to use TLS library function for PRF, if available. */
if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len)
== 0)
return out;
/*
* TLS library did not support key generation, so get the needed TLS
* session parameters and use an internal implementation of TLS PRF to
* derive the key.
*/
if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys))
goto fail;
if (keys.client_random == NULL || keys.server_random == NULL ||
keys.master_key == NULL)
goto fail;
rnd = os_malloc(keys.client_random_len + keys.server_random_len);
if (rnd == NULL)
goto fail;
os_memcpy(rnd, keys.client_random, keys.client_random_len);
os_memcpy(rnd + keys.client_random_len, keys.server_random,
keys.server_random_len);
if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len,
label, rnd, keys.client_random_len +
keys.server_random_len, out, len)) {
goto fail;
if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out,
len)) {
os_free(out);
return NULL;
}
os_free(rnd);
return out;
fail:
os_free(out);
os_free(rnd);
return NULL;
}
/**
* eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
@ -312,18 +280,17 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
struct eap_ssl_data *data, u8 eap_type,
size_t *len)
{
struct tls_keys keys;
struct tls_random keys;
u8 *out;
/*
* TLS library did not support session ID generation,
* so get the needed TLS session parameters
*/
if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
if (tls_connection_get_random(sm->ssl_ctx, data->conn, &keys))
return NULL;
if (keys.client_random == NULL || keys.server_random == NULL ||
keys.master_key == NULL)
if (keys.client_random == NULL || keys.server_random == NULL)
return NULL;
*len = 1 + keys.client_random_len + keys.server_random_len;

View file

@ -11,9 +11,7 @@
struct tls_connection;
struct tls_keys {
const u8 *master_key; /* TLS master secret */
size_t master_key_len;
struct tls_random {
const u8 *client_random;
size_t client_random_len;
const u8 *server_random;
@ -287,41 +285,31 @@ int __must_check tls_connection_set_verify(void *tls_ctx,
int verify_peer);
/**
* tls_connection_get_keys - Get master key and random data from TLS connection
* tls_connection_get_random - Get random data from TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @keys: Structure of key/random data (filled on success)
* Returns: 0 on success, -1 on failure
*/
int __must_check tls_connection_get_keys(void *tls_ctx,
int __must_check tls_connection_get_random(void *tls_ctx,
struct tls_connection *conn,
struct tls_keys *keys);
struct tls_random *data);
/**
* tls_connection_prf - Use TLS-PRF to derive keying material
* tls_connection_export_key - Derive keying material from a TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* @label: Label (e.g., description of the key) for PRF
* @server_random_first: seed is 0 = client_random|server_random,
* 1 = server_random|client_random
* @out: Buffer for output data from TLS-PRF
* @out_len: Length of the output buffer
* Returns: 0 on success, -1 on failure
*
* This function is optional to implement if tls_connection_get_keys() provides
* access to master secret and server/client random values. If these values are
* not exported from the TLS library, tls_connection_prf() is required so that
* further keying material can be derived from the master secret. If not
* implemented, the function will still need to be defined, but it can just
* return -1. Example implementation of this function is in tls_prf_sha1_md5()
* when it is called with seed set to client_random|server_random (or
* server_random|client_random).
* Exports keying material using the mechanism described in RFC 5705.
*/
int __must_check tls_connection_prf(void *tls_ctx,
struct tls_connection *conn,
const char *label,
int server_random_first,
u8 *out, size_t out_len);
int __must_check tls_connection_export_key(void *tls_ctx,
struct tls_connection *conn,
const char *label,
u8 *out, size_t out_len);
/**
* tls_connection_handshake - Process TLS handshake (client side)
@ -506,16 +494,6 @@ int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn);
int tls_connection_get_write_alerts(void *tls_ctx,
struct tls_connection *conn);
/**
* tls_connection_get_keyblock_size - Get TLS key_block size
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
* Returns: Size of the key_block for the negotiated cipher suite or -1 on
* failure
*/
int tls_connection_get_keyblock_size(void *tls_ctx,
struct tls_connection *conn);
/**
* tls_capabilities - Get supported TLS capabilities
* @tls_ctx: TLS context data from tls_init()

View file

@ -18,10 +18,6 @@
#include "tls/tlsv1_client.h"
#include "tls/tlsv1_server.h"
#ifndef CONFIG_TLS_INTERNAL_CLIENT
#define CONFIG_TLS_INTERNAL_CLIENT
#endif
static int tls_ref_count = 0;
struct tls_global {
@ -280,43 +276,76 @@ int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
return -1;
}
int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn,
struct tls_keys *keys)
int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
struct tls_random *data)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client)
return tlsv1_client_get_keys(conn->client, keys);
return tlsv1_client_get_random(conn->client, data);
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server)
return tlsv1_server_get_keys(conn->server, keys);
return tlsv1_server_get_random(conn->server, data);
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
}
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
u8 *out, size_t out_len)
static int tls_get_keyblock_size(struct tls_connection *conn)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client)
return tlsv1_client_get_keyblock_size(conn->client);
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server)
return tlsv1_server_get_keyblock_size(conn->server);
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
}
static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
const char *label, int server_random_first,
int skip_keyblock, u8 *out, size_t out_len)
{
int ret = -1, skip = 0;
u8 *tmp_out = NULL;
u8 *_out = out;
if (skip_keyblock) {
skip = tls_get_keyblock_size(conn);
if (skip < 0)
return -1;
tmp_out = os_malloc(skip + out_len);
if (!tmp_out)
return -1;
_out = tmp_out;
}
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client) {
return tlsv1_client_prf(conn->client, label,
ret = tlsv1_client_prf(conn->client, label,
server_random_first,
out, out_len);
}
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server) {
return tlsv1_server_prf(conn->server, label,
ret = tlsv1_server_prf(conn->server, label,
server_random_first,
out, out_len);
}
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
if (ret == 0 && skip_keyblock)
os_memcpy(out, _out + skip, out_len);
wpa_bin_clear_free(tmp_out, skip);
return ret;
}
int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
const char *label, u8 *out, size_t out_len)
{
return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
}
struct wpabuf * tls_connection_handshake(void *tls_ctx,
struct tls_connection *conn,
@ -585,28 +614,11 @@ int tls_connection_get_write_alerts(void *tls_ctx,
return 0;
}
int tls_connection_get_keyblock_size(void *tls_ctx,
struct tls_connection *conn)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
if (conn->client)
return tlsv1_client_get_keyblock_size(conn->client);
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
#ifdef CONFIG_TLS_INTERNAL_SERVER
if (conn->server)
return tlsv1_server_get_keyblock_size(conn->server);
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
}
unsigned int tls_capabilities(void *tls_ctx)
{
return 0;
}
int tls_connection_set_session_ticket_cb(void *tls_ctx,
struct tls_connection *conn,
tls_session_ticket_cb cb,
@ -626,90 +638,3 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
#endif /* CONFIG_TLS_INTERNAL_SERVER */
return -1;
}
/**
* tls_prf_sha1_md5 - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246)
* @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.
*/
int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
{
size_t L_S1, L_S2, i;
const u8 *S1, *S2;
u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN];
u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN];
int MD5_pos, SHA1_pos;
const u8 *MD5_addr[3];
size_t MD5_len[3];
const unsigned char *SHA1_addr[3];
size_t SHA1_len[3];
if (secret_len & 1)
return -1;
MD5_addr[0] = A_MD5;
MD5_len[0] = MD5_MAC_LEN;
MD5_addr[1] = (unsigned char *) label;
MD5_len[1] = os_strlen(label);
MD5_addr[2] = seed;
MD5_len[2] = seed_len;
SHA1_addr[0] = A_SHA1;
SHA1_len[0] = SHA1_MAC_LEN;
SHA1_addr[1] = (unsigned char *) label;
SHA1_len[1] = os_strlen(label);
SHA1_addr[2] = seed;
SHA1_len[2] = seed_len;
/* RFC 2246, 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 = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed)
*/
L_S1 = L_S2 = (secret_len + 1) / 2;
S1 = secret;
S2 = secret + L_S1;
if (secret_len & 1) {
/* The last byte of S1 will be shared with S2 */
S2--;
}
hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5);
hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);
MD5_pos = MD5_MAC_LEN;
SHA1_pos = SHA1_MAC_LEN;
for (i = 0; i < outlen; i++) {
if (MD5_pos == MD5_MAC_LEN) {
hmac_md5_vector(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5);
MD5_pos = 0;
hmac_md5(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5);
}
if (SHA1_pos == SHA1_MAC_LEN) {
hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len,
P_SHA1);
SHA1_pos = 0;
hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1);
}
out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos];
MD5_pos++;
SHA1_pos++;
}
return 0;
}

View file

@ -729,12 +729,12 @@ int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
/**
* tlsv1_client_get_keys - Get master key and random data from TLS connection
* tlsv1_client_get_random - Get random data from TLS connection
* @conn: TLSv1 client connection data from tlsv1_client_init()
* @keys: Structure of key/random data (filled on success)
* @keys: Structure of random data (filled on success)
* Returns: 0 on success, -1 on failure
*/
int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys)
int tlsv1_client_get_random(struct tlsv1_client *conn, struct tls_random *keys)
{
os_memset(keys, 0, sizeof(*keys));
if (conn->state == CLIENT_HELLO)
@ -746,8 +746,6 @@ int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys)
if (conn->state != SERVER_HELLO) {
keys->server_random = conn->server_random;
keys->server_random_len = TLS_RANDOM_LEN;
keys->master_key = conn->master_secret;
keys->master_key_len = TLS_MASTER_SECRET_LEN;
}
return 0;

View file

@ -36,7 +36,7 @@ int tlsv1_client_shutdown(struct tlsv1_client *conn);
int tlsv1_client_resumed(struct tlsv1_client *conn);
int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
const u8 *data, size_t data_len);
int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys);
int tlsv1_client_get_random(struct tlsv1_client *conn, struct tls_random *data);
int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn);
int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers);
int tlsv1_client_set_cred(struct tlsv1_client *conn,

View file

@ -570,12 +570,12 @@ int tlsv1_server_resumed(struct tlsv1_server *conn)
/**
* tlsv1_server_get_keys - Get master key and random data from TLS connection
* tlsv1_server_get_random - Get random data from TLS connection
* @conn: TLSv1 server connection data from tlsv1_server_init()
* @keys: Structure of key/random data (filled on success)
* @keys: Structure of random data (filled on success)
* Returns: 0 on success, -1 on failure
*/
int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys)
int tlsv1_server_get_random(struct tlsv1_server *conn, struct tls_random *keys)
{
os_memset(keys, 0, sizeof(*keys));
if (conn->state == CLIENT_HELLO)
@ -587,8 +587,6 @@ int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys)
if (conn->state != SERVER_HELLO) {
keys->server_random = conn->server_random;
keys->server_random_len = TLS_RANDOM_LEN;
keys->master_key = conn->master_secret;
keys->master_key_len = TLS_MASTER_SECRET_LEN;
}
return 0;

View file

@ -32,7 +32,7 @@ int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf,
size_t buflen);
int tlsv1_server_shutdown(struct tlsv1_server *conn);
int tlsv1_server_resumed(struct tlsv1_server *conn);
int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys);
int tlsv1_server_get_random(struct tlsv1_server *conn, struct tls_random *data);
int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn);
int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers);
int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer);