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:
parent
9a9b461fee
commit
6ed0c212e4
3 changed files with 33 additions and 18 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in a new issue