TLS: Fix highest TLS version disabling with internal TLS client

The highest supported TLS version for pre_master_secret needs to be
limited based on the local configuration for the case where the highest
version number is being explicitly disabled. Without this, the server
would likely detect a downgrade attack.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2021-03-14 12:48:19 +02:00
parent 9a9b461fee
commit 6ed0c212e4
3 changed files with 33 additions and 18 deletions

View file

@ -38,9 +38,33 @@ void tlsv1_client_free_dh(struct tlsv1_client *conn)
}
int tls_derive_pre_master_secret(u8 *pre_master_secret)
u16 tls_client_highest_ver(struct tlsv1_client *conn)
{
WPA_PUT_BE16(pre_master_secret, TLS_VERSION);
u16 tls_version = TLS_VERSION;
/* Pick the highest locally enabled TLS version */
#ifdef CONFIG_TLSV12
if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
tls_version == TLS_VERSION_1_2)
tls_version = TLS_VERSION_1_1;
#endif /* CONFIG_TLSV12 */
#ifdef CONFIG_TLSV11
if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
tls_version == TLS_VERSION_1_1)
tls_version = TLS_VERSION_1;
#endif /* CONFIG_TLSV11 */
if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
tls_version == TLS_VERSION_1)
return 0;
return tls_version;
}
int tls_derive_pre_master_secret(struct tlsv1_client *conn,
u8 *pre_master_secret)
{
WPA_PUT_BE16(pre_master_secret, tls_client_highest_ver(conn));
if (os_get_random(pre_master_secret + 2,
TLS_PRE_MASTER_SECRET_LEN - 2))
return -1;
@ -844,6 +868,7 @@ int tlsv1_client_set_cred(struct tlsv1_client *conn,
void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags)
{
conn->flags = flags;
conn->rl.tls_version = tls_client_highest_ver(conn);
}

View file

@ -78,7 +78,9 @@ struct tlsv1_client {
void tls_alert(struct tlsv1_client *conn, u8 level, u8 description);
void tlsv1_client_free_dh(struct tlsv1_client *conn);
int tls_derive_pre_master_secret(u8 *pre_master_secret);
u16 tls_client_highest_ver(struct tlsv1_client *conn);
int tls_derive_pre_master_secret(struct tlsv1_client *conn,
u8 *pre_master_secret);
int tls_derive_keys(struct tlsv1_client *conn,
const u8 *pre_master_secret, size_t pre_master_secret_len);
u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len);

View file

@ -48,21 +48,9 @@ u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len)
struct os_time now;
size_t len, i;
u8 *ext_start;
u16 tls_version = TLS_VERSION;
u16 tls_version = tls_client_highest_ver(conn);
/* Pick the highest locally enabled TLS version */
#ifdef CONFIG_TLSV12
if ((conn->flags & TLS_CONN_DISABLE_TLSv1_2) &&
tls_version == TLS_VERSION_1_2)
tls_version = TLS_VERSION_1_1;
#endif /* CONFIG_TLSV12 */
#ifdef CONFIG_TLSV11
if ((conn->flags & TLS_CONN_DISABLE_TLSv1_1) &&
tls_version == TLS_VERSION_1_1)
tls_version = TLS_VERSION_1;
#endif /* CONFIG_TLSV11 */
if ((conn->flags & TLS_CONN_DISABLE_TLSv1_0) &&
tls_version == TLS_VERSION_1) {
if (!tls_version) {
wpa_printf(MSG_INFO, "TLSv1: No TLS version allowed");
return NULL;
}
@ -474,7 +462,7 @@ static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end)
size_t clen;
int res;
if (tls_derive_pre_master_secret(pre_master_secret) < 0 ||
if (tls_derive_pre_master_secret(conn, pre_master_secret) < 0 ||
tls_derive_keys(conn, pre_master_secret,
TLS_PRE_MASTER_SECRET_LEN)) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys");