mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
Merge branch 'feature/eap_tls_v1.3_support' into 'master'
wpa_supplicant: Add TLS v1.3 support in WiFi Enterprise Authentication Closes WIFI-6135 See merge request espressif/esp-idf!24975
This commit is contained in:
@@ -493,6 +493,20 @@ menu "Wi-Fi"
|
||||
TLS-v1.0, TLS-v1.1 versions. Incase your server is using one of these version,
|
||||
it is advisable to update your server.
|
||||
Please disable this option for compatibilty with older TLS versions.
|
||||
|
||||
config ESP_WIFI_EAP_TLS1_3
|
||||
bool "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection"
|
||||
default n
|
||||
select MBEDTLS_SSL_PROTO_TLS1_3
|
||||
depends on ESP_WIFI_MBEDTLS_TLS_CLIENT && IDF_EXPERIMENTAL_FEATURES
|
||||
help
|
||||
Select this option to support EAP with TLS v1.3.
|
||||
This configuration still supports compatibility with EAP-TLS v1.2.
|
||||
Please note that enabling this configuration will cause every application which
|
||||
uses TLS go for TLS1.3 if server supports that. TLS1.3 is still in development in mbedtls
|
||||
and there may be interoperability issues with this. Please modify your application to set
|
||||
max version as TLS1.2 if you want to enable TLS1.3 only for WiFi connection.
|
||||
|
||||
endif
|
||||
|
||||
config ESP_WIFI_WAPI_PSK
|
||||
@@ -629,6 +643,11 @@ menu "Wi-Fi"
|
||||
disabling this will reduce binary size.
|
||||
disabling this will disable the use of any esp_wifi_sta_wpa2_ent_* (as APIs will be meaningless)
|
||||
|
||||
Note that when using bigger certificates on low-power chips without crypto
|
||||
hardware acceleration, it is recommended to adjust the task watchdog timer (TWDT)
|
||||
if it is enabled. For precise information on timing requirements, you can check
|
||||
performance numbers at https://github.com/espressif/mbedtls/wiki/Performance-Numbers.
|
||||
|
||||
config ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER
|
||||
bool "Free dynamic buffers during WiFi enterprise connection"
|
||||
depends on ESP_WIFI_ENTERPRISE_SUPPORT
|
||||
|
||||
@@ -304,6 +304,9 @@ endif()
|
||||
if(CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_OWE_STA)
|
||||
endif()
|
||||
if(CONFIG_ESP_WIFI_EAP_TLS1_3)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TLSV13)
|
||||
endif()
|
||||
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -37,10 +37,21 @@
|
||||
#include "mbedtls/platform.h"
|
||||
#include "eap_peer/eap.h"
|
||||
|
||||
#ifdef CONFIG_TLSV13
|
||||
#include "psa/crypto.h"
|
||||
#include "md_psa.h"
|
||||
#include "ssl_tls13_keys.h"
|
||||
#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
|
||||
psa_to_ssl_errors, \
|
||||
psa_generic_status_to_mbedtls)
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
|
||||
|
||||
#define TLS_RANDOM_LEN 32
|
||||
#define TLS_HASH_MAX_SIZE 64
|
||||
#define TLS_MASTER_SECRET_LEN 48
|
||||
#define MAX_CIPHERSUITE 32
|
||||
#define MAX_EXPORTER_CONTEXT_LEN 65535
|
||||
|
||||
|
||||
|
||||
@@ -82,8 +93,10 @@ struct tls_connection {
|
||||
struct tls_data tls_io_data;
|
||||
unsigned char master_secret[TLS_MASTER_SECRET_LEN];
|
||||
unsigned char randbytes[2 * TLS_RANDOM_LEN];
|
||||
mbedtls_tls_prf_types tls_prf_type;
|
||||
mbedtls_md_type_t mac;
|
||||
mbedtls_tls_prf_types tls_prf_type;
|
||||
#ifdef CONFIG_TLSV13
|
||||
unsigned char exporter_master_secret[TLS_HASH_MAX_SIZE];
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
};
|
||||
|
||||
static void tls_mbedtls_cleanup(tls_context_t *tls)
|
||||
@@ -201,6 +214,43 @@ static int set_ca_cert(tls_context_t *tls, const unsigned char *cacert, size_t c
|
||||
|
||||
#ifdef CONFIG_SUITEB192
|
||||
static uint16_t tls_sig_algs_for_suiteb[] = {
|
||||
|
||||
#ifdef CONFIG_TLSV13
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA384) && \
|
||||
defined(PSA_WANT_ECC_SECP_R1_384)
|
||||
MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
|
||||
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA512) && \
|
||||
defined(PSA_WANT_ECC_SECP_R1_521)
|
||||
MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
|
||||
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA512)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
|
||||
#endif \
|
||||
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA512 */
|
||||
|
||||
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA384)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
|
||||
#endif \
|
||||
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA384 */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,
|
||||
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,
|
||||
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
#if defined(MBEDTLS_ECDSA_C)
|
||||
MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG( MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512 ),
|
||||
@@ -235,6 +285,60 @@ static void tls_set_suiteb_config(tls_context_t *tls)
|
||||
#endif
|
||||
|
||||
static uint16_t tls_sig_algs_for_eap[] = {
|
||||
|
||||
#ifdef CONFIG_TLSV13
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA256) && \
|
||||
defined(PSA_WANT_ECC_SECP_R1_256)
|
||||
MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
|
||||
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA384) && \
|
||||
defined(PSA_WANT_ECC_SECP_R1_384)
|
||||
MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
|
||||
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA512) && \
|
||||
defined(PSA_WANT_ECC_SECP_R1_521)
|
||||
MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
|
||||
// == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA512)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
|
||||
#endif \
|
||||
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA512 */
|
||||
|
||||
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA384)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
|
||||
#endif \
|
||||
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA384 */
|
||||
|
||||
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA256)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
|
||||
#endif \
|
||||
/* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA256 */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,
|
||||
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,
|
||||
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */
|
||||
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256)
|
||||
MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
|
||||
#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
#if defined(MBEDTLS_ECDSA_C)
|
||||
MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG( MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512 ),
|
||||
@@ -300,123 +404,12 @@ static int tls_disable_key_usages(void *data, mbedtls_x509_crt *cert, int depth,
|
||||
}
|
||||
#endif /*CONFIG_ESP_WIFI_DISABLE_KEY_USAGE_CHECK*/
|
||||
|
||||
static const int eap_ciphersuite_preference[] =
|
||||
{
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
|
||||
#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_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_CCM,
|
||||
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_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_CCM_C)
|
||||
MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
|
||||
#endif
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
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
|
||||
0
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SUITEB192
|
||||
static const int suiteb_rsa_ciphersuite_preference[] =
|
||||
{
|
||||
#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3)
|
||||
MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
|
||||
#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
@@ -428,6 +421,9 @@ static const int suiteb_rsa_ciphersuite_preference[] =
|
||||
|
||||
static const int suiteb_ecc_ciphersuite_preference[] =
|
||||
{
|
||||
#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3)
|
||||
MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
|
||||
#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
@@ -437,6 +433,9 @@ static const int suiteb_ecc_ciphersuite_preference[] =
|
||||
};
|
||||
static const int suiteb_ciphersuite_preference[] =
|
||||
{
|
||||
#if defined(CONFIG_ESP_WIFI_EAP_TLS1_3)
|
||||
MBEDTLS_TLS1_3_AES_256_GCM_SHA384,
|
||||
#endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */
|
||||
#if defined(MBEDTLS_GCM_C)
|
||||
#if defined(MBEDTLS_SHA512_C)
|
||||
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
@@ -469,12 +468,12 @@ static void tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_con
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
/* Set cipher suites if User has explicitly set those
|
||||
* TODO: public API to set EAP ciphers */
|
||||
if (tls->ciphersuite[0]) {
|
||||
mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite);
|
||||
} else if (mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 ||
|
||||
(tls->cacert_ptr && 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)
|
||||
@@ -548,6 +547,22 @@ static int set_client_config(const struct tls_connection_params *cfg, tls_contex
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TLSV13
|
||||
static void tls13_extract_exporter_master_secret(struct tls_connection *conn)
|
||||
{
|
||||
mbedtls_ssl_context *ssl = &conn->tls->ssl;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info;
|
||||
psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ciphersuite_info->mac);
|
||||
|
||||
size_t hash_len = PSA_HASH_LENGTH(hash_alg);
|
||||
assert(hash_len != 0);
|
||||
|
||||
mbedtls_ssl_tls13_application_secrets *app_secrets =
|
||||
&ssl->session_negotiate->app_secrets;
|
||||
os_memcpy(conn->exporter_master_secret, app_secrets->exporter_master_secret, hash_len);
|
||||
}
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
|
||||
static void tls_key_derivation(void *ctx,
|
||||
mbedtls_ssl_key_export_type secret_type,
|
||||
const unsigned char *secret,
|
||||
@@ -562,6 +577,12 @@ static void tls_key_derivation(void *ctx,
|
||||
os_memcpy(conn->randbytes, client_random, TLS_RANDOM_LEN);
|
||||
os_memcpy(conn->randbytes + 32, server_random, TLS_RANDOM_LEN);
|
||||
conn->tls_prf_type = tls_prf_type;
|
||||
|
||||
#ifdef CONFIG_TLSV13
|
||||
if (secret_type == MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET) {
|
||||
tls13_extract_exporter_master_secret(conn);
|
||||
}
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
}
|
||||
|
||||
static int tls_create_mbedtls_handle(struct tls_connection *conn,
|
||||
@@ -593,6 +614,12 @@ static int tls_create_mbedtls_handle(struct tls_connection *conn,
|
||||
|
||||
mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg);
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_SSL_PROTO_TLS1_3) && !defined(CONFIG_TLSV13)
|
||||
/* Disable TLSv1.3 even when enabled in MbedTLS and not enabled in WiFi config.
|
||||
* TODO: Remove Kconfig option for TLSv1.3 when it is matured enough */
|
||||
mbedtls_ssl_conf_max_tls_version(&tls->conf, MBEDTLS_SSL_VERSION_TLS1_2);
|
||||
#endif /* CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 && !CONFIG_TLSV13 */
|
||||
|
||||
ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf);
|
||||
if (ret != 0) {
|
||||
wpa_printf(MSG_ERROR, "mbedtls_ssl_setup returned -0x%x", -ret);
|
||||
@@ -633,6 +660,13 @@ struct tls_connection * tls_connection_init(void *tls_ctx)
|
||||
wpa_printf(MSG_ERROR, "TLS: Failed to allocate connection memory");
|
||||
return NULL;
|
||||
}
|
||||
#ifdef CONFIG_TLSV13
|
||||
psa_status_t status = psa_crypto_init();
|
||||
if (status != PSA_SUCCESS) {
|
||||
wpa_printf(MSG_ERROR, "Failed to initialize PSA crypto, returned %d", (int) status);
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
return conn;
|
||||
}
|
||||
|
||||
@@ -738,7 +772,6 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
tls_context_t *tls = conn->tls;
|
||||
int ret = 0;
|
||||
struct wpabuf *resp;
|
||||
int cli_state;
|
||||
|
||||
/* data freed by sender */
|
||||
conn->tls_io_data.out_data = NULL;
|
||||
@@ -748,17 +781,10 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
|
||||
/* Multiple reads */
|
||||
while (!mbedtls_ssl_is_handshake_over(&tls->ssl)) {
|
||||
cli_state = tls->ssl.MBEDTLS_PRIVATE(state);
|
||||
if (cli_state == MBEDTLS_SSL_CLIENT_CERTIFICATE) {
|
||||
/* Read random data before session completes, not present after handshake */
|
||||
if (tls->ssl.MBEDTLS_PRIVATE(handshake)) {
|
||||
os_memcpy(conn->randbytes, tls->ssl.MBEDTLS_PRIVATE(handshake)->randbytes,
|
||||
TLS_RANDOM_LEN * 2);
|
||||
conn->mac = tls->ssl.MBEDTLS_PRIVATE(handshake)->ciphersuite_info->mac;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER
|
||||
int cli_state = tls->ssl.MBEDTLS_PRIVATE(state);
|
||||
#endif /* CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER */
|
||||
ret = mbedtls_ssl_handshake_step(&tls->ssl);
|
||||
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
@@ -782,7 +808,28 @@ struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
||||
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);
|
||||
if (dummy == NULL) {
|
||||
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TLSV13
|
||||
if (mbedtls_ssl_get_version_number(&conn->tls->ssl) == MBEDTLS_SSL_VERSION_TLS1_3) {
|
||||
*appl_data = wpabuf_alloc_ext_data(dummy, 1);
|
||||
if (appl_data == NULL) {
|
||||
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
|
||||
os_free(dummy);
|
||||
goto end;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
conn->tls_io_data.out_data = wpabuf_alloc_ext_data(dummy, 0);
|
||||
if (conn->tls_io_data.out_data == NULL) {
|
||||
wpa_printf(MSG_INFO, "%s: memory allocation failure. line:%d", __func__, __LINE__);
|
||||
os_free(dummy);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
@@ -997,13 +1044,24 @@ int tls_connection_set_session_ticket_cb(void *tls_ctx,
|
||||
}
|
||||
|
||||
static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, int server_random_first,
|
||||
const char *label, const u8 *context,
|
||||
size_t context_len, int server_random_first,
|
||||
u8 *out, size_t out_len)
|
||||
{
|
||||
int ret;
|
||||
u8 seed[2 * TLS_RANDOM_LEN];
|
||||
u8 *seed, *pos;
|
||||
size_t seed_len = 2 * TLS_RANDOM_LEN;
|
||||
mbedtls_ssl_context *ssl = &conn->tls->ssl;
|
||||
|
||||
if (context_len > MAX_EXPORTER_CONTEXT_LEN) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
// The magic value 2 represents the memory required to store the context length.
|
||||
seed_len += 2 + context_len;
|
||||
}
|
||||
|
||||
if (!ssl) {
|
||||
wpa_printf(MSG_ERROR, "TLS: %s, session ingo is null", __func__);
|
||||
return -1;
|
||||
@@ -1013,6 +1071,11 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
return -1;
|
||||
}
|
||||
|
||||
seed = os_malloc(seed_len);
|
||||
if (!seed) {
|
||||
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);
|
||||
@@ -1020,25 +1083,96 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
||||
os_memcpy(seed, conn->randbytes, 2 * TLS_RANDOM_LEN);
|
||||
}
|
||||
|
||||
if (context) {
|
||||
pos = seed + 2 * TLS_RANDOM_LEN;
|
||||
WPA_PUT_BE16(pos, context_len);
|
||||
pos += 2;
|
||||
os_memcpy(pos, context, context_len);
|
||||
}
|
||||
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN);
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "master", ssl->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(master), TLS_MASTER_SECRET_LEN);
|
||||
|
||||
ret = mbedtls_ssl_tls_prf(conn->tls_prf_type, conn->master_secret, TLS_MASTER_SECRET_LEN,
|
||||
label, seed, 2 * TLS_RANDOM_LEN, out, out_len);
|
||||
label, seed, seed_len, out, out_len);
|
||||
os_free(seed);
|
||||
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "prf failed, ret=%d", ret);
|
||||
return -1;
|
||||
}
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "key", out, out_len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TLSV13
|
||||
/* RFC 8446 Section 7.5 */
|
||||
static int tls13_connection_export_key(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, const u8 *context,
|
||||
size_t context_len, u8 *out, size_t out_len)
|
||||
{
|
||||
int ret;
|
||||
mbedtls_ssl_context *ssl = &conn->tls->ssl;
|
||||
psa_algorithm_t hash_alg;
|
||||
size_t hash_len;
|
||||
unsigned char tmp_secret[PSA_MAC_MAX_SIZE] = { 0 };
|
||||
unsigned char hashed_context[PSA_HASH_MAX_SIZE] = { 0 };
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->handshake->ciphersuite_info;
|
||||
|
||||
hash_alg = mbedtls_md_psa_alg_from_type(ciphersuite_info->mac);
|
||||
hash_len = PSA_HASH_LENGTH(hash_alg);
|
||||
|
||||
ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
|
||||
conn->exporter_master_secret, hash_len,
|
||||
(unsigned char const *) label, (size_t) strlen(label),
|
||||
NULL, 0,
|
||||
MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
|
||||
tmp_secret, hash_len);
|
||||
|
||||
if (ret != 0) {
|
||||
wpa_printf(MSG_ERROR, "%s(): mbedtls_ssl_tls13_derive_secret() failed",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
status = psa_hash_compute(hash_alg, context, context_len, hashed_context,
|
||||
PSA_HASH_LENGTH(hash_alg), &context_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
wpa_printf(MSG_ERROR, "%s(): psa_hash_compute() failed",
|
||||
__func__);
|
||||
ret = PSA_TO_MBEDTLS_ERR(status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mbedtls_ssl_tls13_hkdf_expand_label(hash_alg,
|
||||
tmp_secret, hash_len,
|
||||
MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exporter),
|
||||
hashed_context, context_len,
|
||||
out, out_len);
|
||||
|
||||
if (ret != 0) {
|
||||
wpa_printf(MSG_ERROR, "%s(): psa_hash_compute() failed",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
|
||||
int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
|
||||
const char *label, const u8 *context,
|
||||
size_t context_len, u8 *out, size_t out_len)
|
||||
{
|
||||
return tls_connection_prf(tls_ctx, conn, label, 0, out, out_len);
|
||||
#ifdef CONFIG_TLSV13
|
||||
if (mbedtls_ssl_get_version_number(&conn->tls->ssl) == MBEDTLS_SSL_VERSION_TLS1_3)
|
||||
return tls13_connection_export_key(tls_ctx, conn, label, context, context_len,
|
||||
out, out_len);
|
||||
#endif /* CONFIG_TLSV13 */
|
||||
return tls_connection_prf(tls_ctx, conn, label, context, context_len,
|
||||
0, out, out_len);
|
||||
}
|
||||
|
||||
int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
|
||||
|
||||
@@ -369,6 +369,7 @@ enum wpa_ctrl_req_type {
|
||||
WPA_CTRL_REQ_EAP_PASSPHRASE,
|
||||
WPA_CTRL_REQ_SIM,
|
||||
WPA_CTRL_REQ_PSK_PASSPHRASE,
|
||||
WPA_CTRL_REQ_EXT_CERT_CHECK,
|
||||
NUM_WPA_CTRL_REQS
|
||||
};
|
||||
|
||||
|
||||
@@ -356,7 +356,9 @@ int __must_check tls_global_set_verify(void *tls_ctx, int check_crl,
|
||||
* tls_connection_set_verify - Set certificate verification options
|
||||
* @tls_ctx: TLS context data from tls_init()
|
||||
* @conn: Connection context data from tls_connection_init()
|
||||
* @verify_peer: 1 = verify peer certificate
|
||||
* @verify_peer: 0 = do not verify peer certificate, 1 = verify peer
|
||||
* certificate (require it to be provided), 2 = verify peer certificate if
|
||||
* provided
|
||||
* @flags: Connection flags (TLS_CONN_*)
|
||||
* @session_ctx: Session caching context or %NULL to use default
|
||||
* @session_ctx_len: Length of @session_ctx in bytes.
|
||||
|
||||
@@ -281,13 +281,6 @@ int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
|
||||
params->dh_blob_len)) {
|
||||
wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
|
||||
tlsv1_cred_free(cred);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlsv1_client_set_cred(conn->client, cred) < 0) {
|
||||
tlsv1_cred_free(cred);
|
||||
return -1;
|
||||
@@ -791,6 +784,7 @@ int tls_get_library_version(char *buf, size_t buf_len)
|
||||
void tls_connection_set_success_data(struct tls_connection *conn,
|
||||
struct wpabuf *data)
|
||||
{
|
||||
wpabuf_free(data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ int (*esp_crt_bundle_attach_fn)(void *conf);
|
||||
void eap_peer_config_deinit(struct eap_sm *sm);
|
||||
void eap_peer_blob_deinit(struct eap_sm *sm);
|
||||
void eap_deinit_prev_method(struct eap_sm *sm, const char *txt);
|
||||
static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
|
||||
const char *msg, size_t msglen);
|
||||
|
||||
#ifdef EAP_PEER_METHOD
|
||||
static struct eap_method *eap_methods = NULL;
|
||||
@@ -314,6 +316,15 @@ int eap_peer_register_methods(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void eap_sm_free_key(struct eap_sm *sm)
|
||||
{
|
||||
if (sm->eapKeyData) {
|
||||
bin_clear_free(sm->eapKeyData, sm->eapKeyDataLen);
|
||||
sm->eapKeyData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void eap_deinit_prev_method(struct eap_sm *sm, const char *txt)
|
||||
{
|
||||
if (sm->m == NULL || sm->eap_method_priv == NULL)
|
||||
@@ -713,10 +724,10 @@ _out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
|
||||
static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
|
||||
const char *msg, size_t msglen)
|
||||
{
|
||||
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
|
||||
struct eap_peer_config *config;
|
||||
|
||||
if (sm == NULL)
|
||||
@@ -741,14 +752,14 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field,
|
||||
case WPA_CTRL_REQ_EAP_PASSPHRASE:
|
||||
config->pending_req_passphrase++;
|
||||
break;
|
||||
case WPA_CTRL_REQ_EXT_CERT_CHECK:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
|
||||
#define eap_sm_request(sm, type, msg, msglen) do { } while (0)
|
||||
#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
|
||||
}
|
||||
|
||||
const char * eap_sm_get_method_name(struct eap_sm *sm)
|
||||
{
|
||||
@@ -824,6 +835,7 @@ void eap_sm_abort(struct eap_sm *sm)
|
||||
{
|
||||
wpabuf_free(sm->lastRespData);
|
||||
sm->lastRespData = NULL;
|
||||
eap_sm_free_key(sm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -249,8 +249,8 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv)
|
||||
os_memset(data->key_data, 0, EAP_FAST_KEY_LEN);
|
||||
os_memset(data->emsk, 0, EAP_EMSK_LEN);
|
||||
os_free(data->session_id);
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_free(data->pending_resp);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
@@ -800,7 +800,7 @@ static struct wpabuf * eap_fast_process_crypto_binding(
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
data->phase2_success = 0;
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -814,7 +814,7 @@ static struct wpabuf * eap_fast_process_crypto_binding(
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "EAP-FAST: Failed to derive "
|
||||
"Session-Id");
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1135,7 +1135,7 @@ static int eap_fast_encrypt_response(struct eap_sm *sm,
|
||||
wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 "
|
||||
"frame");
|
||||
}
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1313,14 +1313,14 @@ continue_req:
|
||||
wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 "
|
||||
"TLV frame (len=%lu)",
|
||||
(unsigned long) wpabuf_len(in_decrypted));
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = eap_fast_process_decrypted(sm, data, ret, identifier,
|
||||
in_decrypted, out_data);
|
||||
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1598,7 +1598,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
|
||||
if (sm->waiting_ext_cert_check) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-FAST: Waiting external server certificate validation");
|
||||
wpabuf_free(data->pending_resp);
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
data->pending_resp = resp;
|
||||
return NULL;
|
||||
}
|
||||
@@ -1627,7 +1627,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
|
||||
"EAP-FAST: Could not derive keys");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1636,7 +1636,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
|
||||
/*
|
||||
* Application data included in the handshake message.
|
||||
*/
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = resp;
|
||||
resp = NULL;
|
||||
res = eap_fast_decrypt(sm, data, ret, id, &msg, &resp);
|
||||
@@ -1644,7 +1644,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv,
|
||||
}
|
||||
|
||||
if (res == 1) {
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
return eap_peer_tls_build_ack(id, EAP_TYPE_FAST,
|
||||
data->fast_version);
|
||||
}
|
||||
@@ -1670,9 +1670,9 @@ static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
||||
data->phase2_method->deinit_for_reauth(sm, data->phase2_priv);
|
||||
os_free(data->key_block_p);
|
||||
data->key_block_p = NULL;
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = NULL;
|
||||
wpabuf_free(data->pending_resp);
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
data->pending_resp = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ eap_mschapv2_deinit(struct eap_sm *sm, void *priv)
|
||||
os_free(data->peer_challenge);
|
||||
os_free(data->auth_challenge);
|
||||
wpabuf_free(data->prev_challenge);
|
||||
os_free(data);
|
||||
bin_clear_free(data, sizeof(*data));
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -285,7 +285,7 @@ eap_mschapv2_password_changed(struct eap_sm *sm,
|
||||
WPA_EVENT_PASSWORD_CHANGED
|
||||
"EAP-MSCHAPV2: Password changed successfully");
|
||||
data->prev_error = 0;
|
||||
os_free(config->password);
|
||||
bin_clear_free(config->password, config->password_len);
|
||||
if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
|
||||
/* TODO: update external storage */
|
||||
} else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) {
|
||||
@@ -296,7 +296,8 @@ eap_mschapv2_password_changed(struct eap_sm *sm,
|
||||
config->new_password_len,
|
||||
config->password);
|
||||
}
|
||||
os_free(config->new_password);
|
||||
bin_clear_free(config->new_password,
|
||||
config->new_password_len);
|
||||
} else {
|
||||
config->password = config->new_password;
|
||||
config->password_len = config->new_password_len;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
|
||||
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@@ -59,6 +59,7 @@ struct eap_peap_data {
|
||||
size_t id_len;
|
||||
|
||||
struct wpabuf *pending_phase2_req;
|
||||
struct wpabuf *pending_resp;
|
||||
enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
|
||||
int crypto_binding_used;
|
||||
u8 binding_nonce[32];
|
||||
@@ -70,6 +71,15 @@ struct eap_peap_data {
|
||||
};
|
||||
|
||||
|
||||
static void eap_peap_free_key(struct eap_peap_data *data)
|
||||
{
|
||||
if (data->key_data) {
|
||||
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
|
||||
data->key_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
eap_peap_parse_phase1(struct eap_peap_data *data,
|
||||
const char *phase1)
|
||||
@@ -197,10 +207,11 @@ eap_peap_deinit(struct eap_sm *sm, void *priv)
|
||||
data->phase2_method->deinit(sm, data->phase2_priv);
|
||||
os_free(data->phase2_types);
|
||||
eap_peer_tls_ssl_deinit(sm, &data->ssl);
|
||||
os_free(data->key_data);
|
||||
eap_peap_free_key(data);
|
||||
os_free(data->session_id);
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
os_free(data);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
bin_clear_free(data, sizeof(*data));
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +406,7 @@ eap_tlv_build_result(struct eap_sm *sm,
|
||||
wpabuf_put_be16(msg, status); /* Status */
|
||||
|
||||
if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
|
||||
wpabuf_free(msg);
|
||||
wpabuf_clear_free(msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -710,10 +721,11 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
|
||||
if (*resp == NULL) {
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
wpabuf_clear_free(buf);
|
||||
return -1;
|
||||
}
|
||||
wpabuf_put_buf(*resp, buf);
|
||||
wpabuf_free(buf);
|
||||
wpabuf_clear_free(buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -784,7 +796,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm,
|
||||
|
||||
if (*resp == NULL) {
|
||||
wpa_printf(MSG_ERROR, "phase 2 response failure");
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
|
||||
}
|
||||
/*
|
||||
@@ -849,6 +861,10 @@ eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
|
||||
res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
|
||||
if (res)
|
||||
return res;
|
||||
if (wpabuf_len(in_decrypted) == 0) {
|
||||
wpabuf_free(in_decrypted);
|
||||
return 1;
|
||||
}
|
||||
|
||||
continue_req:
|
||||
wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
|
||||
@@ -872,7 +888,7 @@ continue_req:
|
||||
struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
|
||||
wpabuf_len(in_decrypted));
|
||||
if (nmsg == NULL) {
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
return 0;
|
||||
}
|
||||
nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
|
||||
@@ -882,7 +898,7 @@ continue_req:
|
||||
nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
|
||||
wpabuf_len(in_decrypted));
|
||||
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
in_decrypted = nmsg;
|
||||
}
|
||||
|
||||
@@ -934,7 +950,7 @@ continue_req:
|
||||
wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
|
||||
"EAP frame (len=%lu)",
|
||||
(unsigned long) wpabuf_len(in_decrypted));
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
return 0;
|
||||
}
|
||||
len = be_to_host16(hdr->length);
|
||||
@@ -943,7 +959,7 @@ continue_req:
|
||||
"Phase 2 EAP frame (len=%lu hdr->length=%lu)",
|
||||
(unsigned long) wpabuf_len(in_decrypted),
|
||||
(unsigned long) len);
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
return 0;
|
||||
}
|
||||
if (len < wpabuf_len(in_decrypted)) {
|
||||
@@ -960,7 +976,7 @@ continue_req:
|
||||
case EAP_CODE_REQUEST:
|
||||
if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
|
||||
&resp)) {
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
wpa_printf(MSG_ERROR, "EAP-PEAP: Phase2 Request "
|
||||
"processing failed");
|
||||
return 0;
|
||||
@@ -979,7 +995,7 @@ continue_req:
|
||||
"completed successfully");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
return 0;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
|
||||
@@ -989,7 +1005,7 @@ continue_req:
|
||||
ret->methodState = METHOD_DONE;
|
||||
data->phase2_success = 1;
|
||||
if (data->peap_outer_success == 2) {
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
|
||||
"to finish authentication");
|
||||
return 1;
|
||||
@@ -1035,7 +1051,7 @@ continue_req:
|
||||
break;
|
||||
}
|
||||
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
|
||||
if (resp) {
|
||||
int skip_change2 = 0;
|
||||
@@ -1067,7 +1083,7 @@ continue_req:
|
||||
wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
|
||||
"a Phase 2 frame");
|
||||
}
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1122,6 +1138,34 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
|
||||
wpabuf_set(&msg, pos, left);
|
||||
res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
|
||||
} else {
|
||||
if (sm->waiting_ext_cert_check && data->pending_resp) {
|
||||
struct eap_peer_config *config = eap_get_config(sm);
|
||||
|
||||
if (config->pending_ext_cert_check ==
|
||||
EXT_CERT_CHECK_GOOD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-PEAP: External certificate check succeeded - continue handshake");
|
||||
resp = data->pending_resp;
|
||||
data->pending_resp = NULL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return resp;
|
||||
}
|
||||
|
||||
if (config->pending_ext_cert_check ==
|
||||
EXT_CERT_CHECK_BAD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-PEAP: External certificate check failed - force authentication failure");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-PEAP: Continuing to wait external server certificate validation");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = eap_peer_tls_process_helper(sm, &data->ssl,
|
||||
EAP_TYPE_PEAP,
|
||||
data->peap_version, id, pos,
|
||||
@@ -1135,31 +1179,61 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
||||
if (sm->waiting_ext_cert_check) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-PEAP: Waiting external server certificate validation");
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
data->pending_resp = resp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
|
||||
char label[24] = {0};
|
||||
const char *label;
|
||||
const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
|
||||
const u8 *context = NULL;
|
||||
size_t context_len = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2");
|
||||
os_free(data->key_data);
|
||||
eap_peap_free_key(data);
|
||||
/* draft-josefsson-ppext-eap-tls-eap-05.txt
|
||||
* specifies that PEAPv1 would use "client PEAP
|
||||
* encryption" as the label. However, most existing
|
||||
* PEAPv1 implementations seem to be using the old
|
||||
* label, "client EAP encryption", instead. Use the old
|
||||
* label by default, but allow it to be configured with
|
||||
* phase1 parameter peaplabel=1. */
|
||||
if (data->peap_version > 1 || data->force_new_label)
|
||||
os_strlcpy(label, "client PEAP encryption", 24);
|
||||
else
|
||||
os_strlcpy(label, "client EAP encryption", 24);
|
||||
* phase1 parameter peaplabel=1.
|
||||
*
|
||||
* When using TLS 1.3, draft-ietf-emu-tls-eap-types
|
||||
* defines a new set of label and context parameters.
|
||||
*/
|
||||
if (data->ssl.tls_v13) {
|
||||
label = "EXPORTER_EAP_TLS_Key_Material";
|
||||
context = eap_tls13_context;
|
||||
context_len = sizeof(eap_tls13_context);
|
||||
} else if (data->force_new_label) {
|
||||
label = "client PEAP encryption";
|
||||
} else {
|
||||
label = "client EAP encryption";
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
|
||||
"key derivation", label);
|
||||
data->key_data =
|
||||
eap_peer_tls_derive_key(sm, &data->ssl, label,
|
||||
EAP_TLS_KEY_LEN);
|
||||
context, context_len,
|
||||
EAP_TLS_KEY_LEN +
|
||||
EAP_EMSK_LEN);
|
||||
if (data->key_data) {
|
||||
wpa_hexdump_key(MSG_DEBUG,
|
||||
"EAP-PEAP: Derived key",
|
||||
data->key_data,
|
||||
EAP_TLS_KEY_LEN);
|
||||
wpa_hexdump_key(MSG_DEBUG,
|
||||
"EAP-PEAP: Derived EMSK",
|
||||
data->key_data +
|
||||
EAP_TLS_KEY_LEN,
|
||||
EAP_EMSK_LEN);
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
|
||||
"derive key");
|
||||
@@ -1206,6 +1280,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
|
||||
* Application data included in the handshake message.
|
||||
*/
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = resp;
|
||||
resp = NULL;
|
||||
wpabuf_set(&msg, pos, left);
|
||||
@@ -1219,7 +1294,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
|
||||
}
|
||||
|
||||
if (res == 1) {
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
|
||||
data->peap_version);
|
||||
}
|
||||
@@ -1242,8 +1317,10 @@ static void
|
||||
eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_peap_data *data = priv;
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = NULL;
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
data->pending_resp = NULL;
|
||||
data->crypto_binding_used = 0;
|
||||
}
|
||||
|
||||
@@ -1252,8 +1329,7 @@ static void *
|
||||
eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_peap_data *data = priv;
|
||||
os_free(data->key_data);
|
||||
data->key_data = NULL;
|
||||
eap_peap_free_key(data);
|
||||
os_free(data->session_id);
|
||||
data->session_id = NULL;
|
||||
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
|
||||
@@ -1341,6 +1417,29 @@ eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
|
||||
}
|
||||
|
||||
|
||||
static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
|
||||
{
|
||||
struct eap_peap_data *data = priv;
|
||||
u8 *key;
|
||||
|
||||
if (!data->key_data || !data->phase2_success)
|
||||
return NULL;
|
||||
|
||||
if (data->crypto_binding_used) {
|
||||
/* [MS-PEAP] does not define EMSK derivation */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
*len = EAP_EMSK_LEN;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
static u8 *
|
||||
eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
|
||||
{
|
||||
@@ -1377,6 +1476,7 @@ eap_peer_peap_register(void)
|
||||
eap->process = eap_peap_process;
|
||||
eap->isKeyAvailable = eap_peap_isKeyAvailable;
|
||||
eap->getKey = eap_peap_getKey;
|
||||
eap->get_emsk = eap_peap_get_emsk;
|
||||
eap->get_status = eap_peap_get_status;
|
||||
eap->has_reauth_data = eap_peap_has_reauth_data;
|
||||
eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP peer method: EAP-TLS (RFC 2716)
|
||||
* Copyright (c) 2004-2008, 2012, Jouni Malinen <j@w1.fi>
|
||||
* EAP peer method: EAP-TLS (RFC 5216, RFC 9190)
|
||||
* Copyright (c) 2004-2008, 2012-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@@ -27,6 +27,8 @@ struct eap_tls_data {
|
||||
size_t id_len;
|
||||
void *ssl_ctx;
|
||||
u8 eap_type;
|
||||
struct wpabuf *pending_resp;
|
||||
bool prot_success_received;
|
||||
};
|
||||
|
||||
|
||||
@@ -59,14 +61,24 @@ static void * eap_tls_init(struct eap_sm *sm)
|
||||
}
|
||||
|
||||
|
||||
static void eap_tls_free_key(struct eap_tls_data *data)
|
||||
{
|
||||
if (data->key_data) {
|
||||
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
|
||||
data->key_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void eap_tls_deinit(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_tls_data *data = priv;
|
||||
if (data == NULL)
|
||||
return;
|
||||
eap_peer_tls_ssl_deinit(sm, &data->ssl);
|
||||
os_free(data->key_data);
|
||||
eap_tls_free_key(data);
|
||||
os_free(data->session_id);
|
||||
wpabuf_free(data->pending_resp);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
@@ -110,14 +122,37 @@ static struct wpabuf * eap_tls_failure(struct eap_sm *sm,
|
||||
static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
|
||||
struct eap_method_ret *ret)
|
||||
{
|
||||
const char *label;
|
||||
const u8 eap_tls13_context[] = { EAP_TYPE_TLS };
|
||||
const u8 *context = NULL;
|
||||
size_t context_len = 0;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
|
||||
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_UNCOND_SUCC;
|
||||
if (data->ssl.tls_out) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TLS: Fragment(s) remaining");
|
||||
return;
|
||||
}
|
||||
|
||||
os_free(data->key_data);
|
||||
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
|
||||
"client EAP encryption",
|
||||
if (data->ssl.tls_v13) {
|
||||
label = "EXPORTER_EAP_TLS_Key_Material";
|
||||
context = eap_tls13_context;
|
||||
context_len = 1;
|
||||
|
||||
/* A possible NewSessionTicket may be received before
|
||||
* EAP-Success, so need to allow it to be received. */
|
||||
ret->methodState = METHOD_MAY_CONT;
|
||||
ret->decision = DECISION_COND_SUCC;
|
||||
} else {
|
||||
label = "client EAP encryption";
|
||||
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_UNCOND_SUCC;
|
||||
}
|
||||
|
||||
eap_tls_free_key(data);
|
||||
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
|
||||
context, context_len,
|
||||
EAP_TLS_KEY_LEN +
|
||||
EAP_EMSK_LEN);
|
||||
if (data->key_data) {
|
||||
@@ -154,6 +189,32 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
|
||||
const u8 *pos;
|
||||
struct eap_tls_data *data = priv;
|
||||
|
||||
if (sm->waiting_ext_cert_check && data->pending_resp) {
|
||||
struct eap_peer_config *config = eap_get_config(sm);
|
||||
|
||||
if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TLS: External certificate check succeeded - continue handshake");
|
||||
resp = data->pending_resp;
|
||||
data->pending_resp = NULL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return resp;
|
||||
}
|
||||
|
||||
if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TLS: External certificate check failed - force authentication failure");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TLS: Continuing to wait external server certificate validation");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret,
|
||||
reqData, &left, &flags);
|
||||
if (pos == NULL)
|
||||
@@ -174,7 +235,28 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv,
|
||||
return eap_tls_failure(sm, data, ret, res, resp, id);
|
||||
}
|
||||
|
||||
if (tls_connection_established(data->ssl_ctx, data->ssl.conn))
|
||||
if (sm->waiting_ext_cert_check) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TLS: Waiting external server certificate validation");
|
||||
wpabuf_free(data->pending_resp);
|
||||
data->pending_resp = resp;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* RFC 9190 Section 2.5 */
|
||||
if (res == 2 && data->ssl.tls_v13 && wpabuf_len(resp) == 1 &&
|
||||
*wpabuf_head_u8(resp) == 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TLS: ACKing protected success indication (appl data 0x00)");
|
||||
eap_peer_tls_reset_output(&data->ssl);
|
||||
res = 1;
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_UNCOND_SUCC;
|
||||
data->prot_success_received = true;
|
||||
}
|
||||
|
||||
if (tls_connection_established(data->ssl_ctx, data->ssl.conn) &&
|
||||
(!data->ssl.tls_v13 || data->prot_success_received))
|
||||
eap_tls_success(sm, data, ret);
|
||||
|
||||
if (res == 1) {
|
||||
|
||||
@@ -256,6 +256,8 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
|
||||
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
|
||||
* @data: Data for TLS processing
|
||||
* @label: Label string for deriving the keys, e.g., "client EAP encryption"
|
||||
* @context: Optional extra upper-layer context (max len 2^16)
|
||||
* @context_len: The length of the context value
|
||||
* @len: Length of the key material to generate (usually 64 for MSK)
|
||||
* Returns: Pointer to allocated key on success or %NULL on failure
|
||||
*
|
||||
@@ -264,9 +266,12 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
|
||||
* different label to bind the key usage into the generated material.
|
||||
*
|
||||
* The caller is responsible for freeing the returned buffer.
|
||||
*
|
||||
* Note: To provide the RFC 5705 context, the context variable must be non-NULL.
|
||||
*/
|
||||
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||
const char *label, size_t len)
|
||||
const char *label, const u8 *context,
|
||||
size_t context_len, size_t len)
|
||||
{
|
||||
u8 *out;
|
||||
|
||||
@@ -274,8 +279,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||
if (out == NULL)
|
||||
return NULL;
|
||||
|
||||
if (tls_connection_export_key(data->ssl_ctx, data->conn, label, 0, 0, out,
|
||||
len)) {
|
||||
if (tls_connection_export_key(data->ssl_ctx, data->conn, label,
|
||||
context, context_len, out, len)) {
|
||||
os_free(out);
|
||||
return NULL;
|
||||
}
|
||||
@@ -303,6 +308,30 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
|
||||
struct tls_random keys;
|
||||
u8 *out;
|
||||
|
||||
if (data->tls_v13) {
|
||||
u8 *id, *method_id;
|
||||
const u8 context[] = { eap_type };
|
||||
|
||||
/* Session-Id = <EAP-Type> || Method-Id
|
||||
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
|
||||
* Type-Code, 64)
|
||||
*/
|
||||
*len = 1 + 64;
|
||||
id = os_malloc(*len);
|
||||
if (!id)
|
||||
return NULL;
|
||||
method_id = eap_peer_tls_derive_key(
|
||||
sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 64);
|
||||
if (!method_id) {
|
||||
os_free(id);
|
||||
return NULL;
|
||||
}
|
||||
id[0] = eap_type;
|
||||
os_memcpy(id + 1, method_id, 64);
|
||||
os_free(method_id);
|
||||
return id;
|
||||
}
|
||||
|
||||
/*
|
||||
* TLS library did not support session ID generation,
|
||||
* so get the needed TLS session parameters
|
||||
@@ -616,6 +645,8 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||
*/
|
||||
int res = eap_tls_process_input(sm, data, in_data, in_len,
|
||||
out_data);
|
||||
char buf[20];
|
||||
|
||||
if (res) {
|
||||
/*
|
||||
* Input processing failed (res = -1) or more data is
|
||||
@@ -628,6 +659,12 @@ int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||
* The incoming message has been reassembled and processed. The
|
||||
* response was allocated into data->tls_out buffer.
|
||||
*/
|
||||
|
||||
if (tls_get_version(data->ssl_ctx, data->conn,
|
||||
buf, sizeof(buf)) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "SSL: Using TLS version %s", buf);
|
||||
data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->tls_out == NULL) {
|
||||
|
||||
@@ -78,6 +78,11 @@ struct eap_ssl_data {
|
||||
* client_cert_conf: Whether client certificate has been configured
|
||||
*/
|
||||
bool client_cert_conf;
|
||||
|
||||
/**
|
||||
* tls_v13 - Whether TLS v1.3 or newer is used
|
||||
*/
|
||||
int tls_v13;
|
||||
};
|
||||
|
||||
|
||||
@@ -98,7 +103,8 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
|
||||
struct eap_peer_config *config, u8 eap_type);
|
||||
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);
|
||||
const char *label, const u8 *context,
|
||||
size_t context_len, size_t len);
|
||||
u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
|
||||
struct eap_ssl_data *data, u8 eap_type,
|
||||
size_t *len);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* EAP peer method: EAP-TTLS (RFC 5281)
|
||||
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
@@ -59,6 +59,7 @@ struct eap_ttls_data {
|
||||
size_t id_len;
|
||||
|
||||
struct wpabuf *pending_phase2_req;
|
||||
struct wpabuf *pending_resp;
|
||||
|
||||
#ifdef EAP_TNC
|
||||
int ready_for_tnc;
|
||||
@@ -126,6 +127,15 @@ static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,
|
||||
}
|
||||
|
||||
|
||||
static void eap_ttls_free_key(struct eap_ttls_data *data)
|
||||
{
|
||||
if (data->key_data) {
|
||||
bin_clear_free(data->key_data, EAP_TLS_KEY_LEN);
|
||||
data->key_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_ttls_data *data = priv;
|
||||
@@ -134,9 +144,10 @@ static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
|
||||
eap_ttls_phase2_eap_deinit(sm, data);
|
||||
os_free(data->phase2_eap_types);
|
||||
eap_peer_tls_ssl_deinit(sm, &data->ssl);
|
||||
os_free(data->key_data);
|
||||
eap_ttls_free_key(data);
|
||||
os_free(data->session_id);
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
os_free(data);
|
||||
}
|
||||
|
||||
@@ -186,7 +197,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
|
||||
|
||||
msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
|
||||
if (msg == NULL) {
|
||||
wpabuf_free(*resp);
|
||||
wpabuf_clear_free(*resp);
|
||||
*resp = NULL;
|
||||
return -1;
|
||||
}
|
||||
@@ -196,7 +207,7 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
|
||||
os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
|
||||
pos += wpabuf_len(*resp);
|
||||
AVP_PAD(avp, pos);
|
||||
wpabuf_free(*resp);
|
||||
wpabuf_clear_free(*resp);
|
||||
wpabuf_put(msg, pos - avp);
|
||||
*resp = msg;
|
||||
return 0;
|
||||
@@ -206,10 +217,24 @@ static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
|
||||
static int eap_ttls_v0_derive_key(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data)
|
||||
{
|
||||
os_free(data->key_data);
|
||||
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
|
||||
"ttls keying material",
|
||||
EAP_TLS_KEY_LEN);
|
||||
const char *label;
|
||||
const u8 eap_tls13_context[1] = { EAP_TYPE_TTLS };
|
||||
const u8 *context = NULL;
|
||||
size_t context_len = 0;
|
||||
|
||||
if (data->ssl.tls_v13) {
|
||||
label = "EXPORTER_EAP_TLS_Key_Material";
|
||||
context = eap_tls13_context;
|
||||
context_len = sizeof(eap_tls13_context);
|
||||
} else {
|
||||
label = "ttls keying material";
|
||||
}
|
||||
|
||||
eap_ttls_free_key(data);
|
||||
data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
|
||||
context, context_len,
|
||||
EAP_TLS_KEY_LEN +
|
||||
EAP_EMSK_LEN);
|
||||
if (!data->key_data) {
|
||||
wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive key");
|
||||
return -1;
|
||||
@@ -240,17 +265,18 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
|
||||
static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data, size_t len)
|
||||
{
|
||||
return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
|
||||
return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge",
|
||||
NULL, 0, len);
|
||||
}
|
||||
#endif /* CONFIG_FIPS */
|
||||
|
||||
|
||||
static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
|
||||
u8 method)
|
||||
int vendor, enum eap_type method)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < data->num_phase2_eap_types; i++) {
|
||||
if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||
|
||||
if (data->phase2_eap_types[i].vendor != vendor ||
|
||||
data->phase2_eap_types[i].method != method)
|
||||
continue;
|
||||
|
||||
@@ -297,17 +323,19 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
|
||||
struct eap_ttls_data *data,
|
||||
struct eap_method_ret *ret,
|
||||
struct eap_hdr *hdr, size_t len,
|
||||
u8 method, struct wpabuf **resp)
|
||||
int vendor, enum eap_type method,
|
||||
struct wpabuf **resp)
|
||||
{
|
||||
#ifdef EAP_TNC
|
||||
if (data->tnc_started && data->phase2_method &&
|
||||
data->phase2_priv && method == EAP_TYPE_TNC &&
|
||||
data->phase2_priv &&
|
||||
vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC &&
|
||||
data->phase2_eap_type.method == EAP_TYPE_TNC)
|
||||
return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
|
||||
resp);
|
||||
|
||||
if (data->ready_for_tnc && !data->tnc_started &&
|
||||
method == EAP_TYPE_TNC) {
|
||||
vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
|
||||
"EAP method");
|
||||
data->tnc_started = 1;
|
||||
@@ -321,7 +349,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
|
||||
data->phase2_eap_type.vendor = vendor;
|
||||
data->phase2_eap_type.method = method;
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
|
||||
"Phase 2 EAP vendor %d method %d (TNC)",
|
||||
@@ -335,10 +363,11 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
|
||||
|
||||
if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
|
||||
data->phase2_eap_type.method == EAP_TYPE_NONE)
|
||||
eap_ttls_phase2_select_eap_method(data, method);
|
||||
eap_ttls_phase2_select_eap_method(data, vendor, method);
|
||||
|
||||
if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE)
|
||||
{
|
||||
if (vendor != data->phase2_eap_type.vendor ||
|
||||
method != data->phase2_eap_type.method ||
|
||||
(vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE)) {
|
||||
if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
|
||||
data->num_phase2_eap_types,
|
||||
hdr, resp))
|
||||
@@ -347,8 +376,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
|
||||
}
|
||||
|
||||
if (data->phase2_priv == NULL) {
|
||||
data->phase2_method = eap_peer_get_eap_method(
|
||||
EAP_VENDOR_IETF, method);
|
||||
data->phase2_method = eap_peer_get_eap_method(vendor, method);
|
||||
if (data->phase2_method) {
|
||||
sm->init_phase2 = 1;
|
||||
data->phase2_priv = data->phase2_method->init(sm);
|
||||
@@ -356,8 +384,9 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
|
||||
}
|
||||
}
|
||||
if (data->phase2_priv == NULL || data->phase2_method == NULL) {
|
||||
wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
|
||||
"Phase 2 EAP method %d", method);
|
||||
wpa_printf(MSG_INFO,
|
||||
"EAP-TTLS: failed to initialize Phase 2 EAP method %u:%u",
|
||||
vendor, method);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -386,9 +415,23 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
|
||||
case EAP_TYPE_IDENTITY:
|
||||
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
|
||||
break;
|
||||
case EAP_TYPE_EXPANDED:
|
||||
if (len < sizeof(struct eap_hdr) + 8) {
|
||||
wpa_printf(MSG_INFO,
|
||||
"EAP-TTLS: Too short Phase 2 request (expanded header) (len=%lu)",
|
||||
(unsigned long) len);
|
||||
return -1;
|
||||
}
|
||||
if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
|
||||
WPA_GET_BE24(pos + 1),
|
||||
WPA_GET_BE32(pos + 4),
|
||||
resp) < 0)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
|
||||
*pos, resp) < 0)
|
||||
EAP_VENDOR_IETF, *pos,
|
||||
resp) < 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
@@ -446,7 +489,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
|
||||
challenge = eap_ttls_implicit_challenge(
|
||||
sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
|
||||
if (challenge == NULL) {
|
||||
wpabuf_free(msg);
|
||||
wpabuf_clear_free(msg);
|
||||
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
|
||||
"implicit challenge");
|
||||
return -1;
|
||||
@@ -465,7 +508,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
|
||||
*pos++ = 0; /* Flags */
|
||||
if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) {
|
||||
os_free(challenge);
|
||||
wpabuf_free(msg);
|
||||
wpabuf_clear_free(msg);
|
||||
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get "
|
||||
"random data for peer challenge");
|
||||
return -1;
|
||||
@@ -479,7 +522,7 @@ static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
|
||||
peer_challenge, pos, data->auth_response,
|
||||
data->master_key)) {
|
||||
os_free(challenge);
|
||||
wpabuf_free(msg);
|
||||
wpabuf_clear_free(msg);
|
||||
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
|
||||
"response");
|
||||
return -1;
|
||||
@@ -551,7 +594,7 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
|
||||
challenge = eap_ttls_implicit_challenge(
|
||||
sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
|
||||
if (challenge == NULL) {
|
||||
wpabuf_free(msg);
|
||||
wpabuf_clear_free(msg);
|
||||
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
|
||||
"implicit challenge");
|
||||
return -1;
|
||||
@@ -571,12 +614,26 @@ static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
|
||||
os_memset(pos, 0, 24); /* LM-Response */
|
||||
pos += 24;
|
||||
if (pwhash) {
|
||||
challenge_response(challenge, password, pos); /* NT-Response */
|
||||
/* NT-Response */
|
||||
if (challenge_response(challenge, password, pos)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"EAP-TTLS/MSCHAP: Failed derive password hash");
|
||||
wpabuf_clear_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
|
||||
password, 16);
|
||||
} else {
|
||||
nt_challenge_response(challenge, password, password_len,
|
||||
pos); /* NT-Response */
|
||||
/* NT-Response */
|
||||
if (nt_challenge_response(challenge, password, password_len,
|
||||
pos)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"EAP-TTLS/MSCHAP: Failed derive password");
|
||||
wpabuf_clear_free(msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
|
||||
password, password_len);
|
||||
}
|
||||
@@ -691,7 +748,7 @@ static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
|
||||
challenge = eap_ttls_implicit_challenge(
|
||||
sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
|
||||
if (challenge == NULL) {
|
||||
wpabuf_free(msg);
|
||||
wpabuf_clear_free(msg);
|
||||
wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
|
||||
"implicit challenge");
|
||||
return -1;
|
||||
@@ -999,9 +1056,10 @@ static int eap_ttls_encrypt_response(struct eap_sm *sm,
|
||||
data->ttls_version, identifier,
|
||||
resp, out_data)) {
|
||||
wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to encrypt a Phase 2 frame");
|
||||
wpabuf_clear_free(resp);
|
||||
return -1;
|
||||
}
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1221,7 +1279,7 @@ static int eap_ttls_process_decrypted(struct eap_sm *sm,
|
||||
config->pending_req_password ||
|
||||
config->pending_req_otp ||
|
||||
config->pending_req_new_password) {
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = wpabuf_dup(in_decrypted);
|
||||
}
|
||||
|
||||
@@ -1263,7 +1321,7 @@ static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
|
||||
* processing when EAP request is re-processed after
|
||||
* user input.
|
||||
*/
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = wpabuf_alloc(0);
|
||||
}
|
||||
|
||||
@@ -1336,7 +1394,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
|
||||
in_decrypted = data->pending_phase2_req;
|
||||
data->pending_phase2_req = NULL;
|
||||
if (wpabuf_len(in_decrypted) == 0) {
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
return eap_ttls_implicit_identity_request(
|
||||
sm, data, ret, identifier, out_data);
|
||||
}
|
||||
@@ -1345,6 +1403,7 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
|
||||
|
||||
if ((in_data == NULL || wpabuf_len(in_data) == 0) &&
|
||||
data->phase2_start) {
|
||||
start:
|
||||
return eap_ttls_phase2_start(sm, data, ret, identifier,
|
||||
out_data);
|
||||
}
|
||||
@@ -1359,6 +1418,20 @@ static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
|
||||
retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
|
||||
if (retval)
|
||||
goto done;
|
||||
if (wpabuf_len(in_decrypted) == 0) {
|
||||
wpabuf_free(in_decrypted);
|
||||
goto start;
|
||||
}
|
||||
|
||||
/* RFC 9190 Section 2.5 */
|
||||
if (data->ssl.tls_v13 && wpabuf_len(in_decrypted) == 1 &&
|
||||
*wpabuf_head_u8(in_decrypted) == 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TLS: ACKing protected success indication (appl data 0x00)");
|
||||
eap_peer_tls_reset_output(&data->ssl);
|
||||
wpabuf_free(in_decrypted);
|
||||
return 1;
|
||||
}
|
||||
|
||||
continue_req:
|
||||
data->phase2_start = 0;
|
||||
@@ -1372,7 +1445,7 @@ continue_req:
|
||||
&parse, in_decrypted, out_data);
|
||||
|
||||
done:
|
||||
wpabuf_free(in_decrypted);
|
||||
wpabuf_clear_free(in_decrypted);
|
||||
os_free(parse.eapdata);
|
||||
|
||||
if (retval < 0) {
|
||||
@@ -1393,10 +1466,52 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
|
||||
{
|
||||
int res;
|
||||
|
||||
if (sm->waiting_ext_cert_check && data->pending_resp) {
|
||||
struct eap_peer_config *config = eap_get_config(sm);
|
||||
|
||||
if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: External certificate check succeeded - continue handshake");
|
||||
*out_data = data->pending_resp;
|
||||
data->pending_resp = NULL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: External certificate check failed - force authentication failure");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
sm->waiting_ext_cert_check = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: Continuing to wait external server certificate validation");
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
|
||||
data->ttls_version, identifier,
|
||||
in_data, in_len, out_data);
|
||||
|
||||
if (res < 0) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS processing failed");
|
||||
ret->methodState = METHOD_DONE;
|
||||
ret->decision = DECISION_FAIL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sm->waiting_ext_cert_check) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"EAP-TTLS: Waiting external server certificate validation");
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
data->pending_resp = *out_data;
|
||||
*out_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
|
||||
wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
|
||||
"Phase 2");
|
||||
@@ -1426,7 +1541,7 @@ static int eap_ttls_process_handshake(struct eap_sm *sm,
|
||||
/*
|
||||
* Application data included in the handshake message.
|
||||
*/
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = *out_data;
|
||||
*out_data = NULL;
|
||||
wpabuf_set(&msg, in_data, in_len);
|
||||
@@ -1515,7 +1630,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
|
||||
/* FIX: what about res == -1? Could just move all error processing into
|
||||
* the other functions and get rid of this res==1 case here. */
|
||||
if (res == 1) {
|
||||
wpabuf_free(resp);
|
||||
wpabuf_clear_free(resp);
|
||||
return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
|
||||
data->ttls_version);
|
||||
}
|
||||
@@ -1535,8 +1650,10 @@ static bool eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
|
||||
static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_ttls_data *data = priv;
|
||||
wpabuf_free(data->pending_phase2_req);
|
||||
wpabuf_clear_free(data->pending_phase2_req);
|
||||
data->pending_phase2_req = NULL;
|
||||
wpabuf_clear_free(data->pending_resp);
|
||||
data->pending_resp = NULL;
|
||||
#ifdef EAP_TNC
|
||||
data->ready_for_tnc = 0;
|
||||
data->tnc_started = 0;
|
||||
@@ -1547,8 +1664,7 @@ static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
|
||||
static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
|
||||
{
|
||||
struct eap_ttls_data *data = priv;
|
||||
os_free(data->key_data);
|
||||
data->key_data = NULL;
|
||||
eap_ttls_free_key(data);
|
||||
os_free(data->session_id);
|
||||
data->session_id = NULL;
|
||||
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
|
||||
|
||||
@@ -776,7 +776,8 @@ static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn,
|
||||
hlen = tls_key_x_server_params_hash(
|
||||
conn->rl.tls_version, conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
server_params_end - server_params, hash);
|
||||
server_params_end - server_params, hash,
|
||||
sizeof(hash));
|
||||
}
|
||||
|
||||
if (hlen < 0)
|
||||
|
||||
@@ -380,7 +380,7 @@ int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_alg,
|
||||
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash)
|
||||
size_t server_params_len, u8 *hash, size_t hsz)
|
||||
{
|
||||
u8 *hpos;
|
||||
size_t hlen;
|
||||
@@ -395,6 +395,8 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
hlen = MD5_MAC_LEN;
|
||||
if (hsz < hlen)
|
||||
return -1;
|
||||
if (crypto_hash_finish(ctx, hash, &hlen) < 0)
|
||||
return -1;
|
||||
hpos += hlen;
|
||||
@@ -405,7 +407,7 @@ int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
crypto_hash_update(ctx, client_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_random, TLS_RANDOM_LEN);
|
||||
crypto_hash_update(ctx, server_params, server_params_len);
|
||||
hlen = hash + sizeof(hash) - hpos;
|
||||
hlen = hsz - hlen;
|
||||
if (crypto_hash_finish(ctx, hpos, &hlen) < 0)
|
||||
return -1;
|
||||
hpos += hlen;
|
||||
|
||||
@@ -267,7 +267,8 @@ int tlsv12_key_x_server_params_hash(u16 tls_version, u8 hash_Alg,
|
||||
int tls_key_x_server_params_hash(u16 tls_version, const u8 *client_random,
|
||||
const u8 *server_random,
|
||||
const u8 *server_params,
|
||||
size_t server_params_len, u8 *hash);
|
||||
size_t server_params_len,
|
||||
u8 *hash, size_t hsz);
|
||||
int tls_verify_signature(u16 tls_version, struct crypto_public_key *pk,
|
||||
const u8 *data, size_t data_len,
|
||||
const u8 *pos, size_t len, u8 *alert);
|
||||
|
||||
@@ -620,7 +620,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
|
||||
hlen = tls_key_x_server_params_hash(
|
||||
conn->rl.tls_version, conn->client_random,
|
||||
conn->server_random, server_params,
|
||||
pos - server_params, hash);
|
||||
pos - server_params, hash, sizeof(hash));
|
||||
}
|
||||
|
||||
if (hlen < 0) {
|
||||
|
||||
Reference in New Issue
Block a user