TLS: Add support for TLS v1.1 (RFC 4346) with internal TLS
This is disabled by defautl and can be enabled with CONFIG_TLSV11=y build configuration parameter.
This commit is contained in:
parent
3bff59f857
commit
5c47af9a7a
13 changed files with 157 additions and 32 deletions
|
@ -434,6 +434,10 @@ ifndef CONFIG_TLS
|
|||
CONFIG_TLS=openssl
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TLSV11
|
||||
CFLAGS += -DCONFIG_TLSV11
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), openssl)
|
||||
ifdef TLS_FUNCS
|
||||
OBJS += ../src/crypto/tls_openssl.o
|
||||
|
|
|
@ -208,3 +208,39 @@ CONFIG_IPV6=y
|
|||
# considered for builds that are known to be used on devices that meet the
|
||||
# requirements described above.
|
||||
#CONFIG_NO_RANDOM_POOL=y
|
||||
|
||||
# Select TLS implementation
|
||||
# openssl = OpenSSL (default)
|
||||
# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA)
|
||||
# internal = Internal TLSv1 implementation (experimental)
|
||||
# none = Empty template
|
||||
#CONFIG_TLS=openssl
|
||||
|
||||
# Whether to enable TLS/IA support, which is required for EAP-TTLSv1.
|
||||
# You need CONFIG_TLS=gnutls for this to have any effect. Please note that
|
||||
# even though the core GnuTLS library is released under LGPL, this extra
|
||||
# library uses GPL and as such, the terms of GPL apply to the combination
|
||||
# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not
|
||||
# apply for distribution of the resulting binary.
|
||||
#CONFIG_GNUTLS_EXTRA=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used.
|
||||
#CONFIG_TLSV11=y
|
||||
|
||||
# If CONFIG_TLS=internal is used, additional library and include paths are
|
||||
# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
||||
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
||||
# and drawbacks of this option.
|
||||
#CONFIG_INTERNAL_LIBTOMMATH=y
|
||||
#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
||||
#LTM_PATH=/usr/src/libtommath-0.39
|
||||
#CFLAGS += -I$(LTM_PATH)
|
||||
#LIBS += -L$(LTM_PATH)
|
||||
#LIBS_p += -L$(LTM_PATH)
|
||||
#endif
|
||||
# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
||||
# can be configured to include faster routines for exptmod, sqr, and div to
|
||||
# speed up DH and RSA calculation considerably
|
||||
#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TLSv1 client (RFC 2246)
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) client
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -80,8 +80,9 @@ int tls_derive_keys(struct tlsv1_client *conn,
|
|||
|
||||
os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
|
||||
os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN);
|
||||
key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len +
|
||||
conn->rl.iv_size);
|
||||
key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len);
|
||||
if (conn->rl.tls_version == TLS_VERSION_1)
|
||||
key_block_len += 2 * conn->rl.iv_size;
|
||||
if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
|
||||
"key expansion", seed, 2 * TLS_RANDOM_LEN,
|
||||
key_block, key_block_len)) {
|
||||
|
@ -107,12 +108,21 @@ int tls_derive_keys(struct tlsv1_client *conn,
|
|||
os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
|
||||
pos += conn->rl.key_material_len;
|
||||
|
||||
if (conn->rl.tls_version == TLS_VERSION_1) {
|
||||
/* client_write_IV */
|
||||
os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size);
|
||||
pos += conn->rl.iv_size;
|
||||
/* server_write_IV */
|
||||
os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
|
||||
pos += conn->rl.iv_size;
|
||||
} else {
|
||||
/*
|
||||
* Use IV field to set the mask value for TLS v1.1. A fixed
|
||||
* mask of zero is used per the RFC 4346, 6.2.3.2 CBC Block
|
||||
* Cipher option 2a.
|
||||
*/
|
||||
os_memset(conn->rl.write_iv, 0, conn->rl.iv_size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -358,6 +368,8 @@ struct tlsv1_client * tlsv1_client_init(void)
|
|||
suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
|
||||
conn->num_cipher_suites = count;
|
||||
|
||||
conn->rl.tls_version = TLS_VERSION;
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* TLSv1 client - read handshake message
|
||||
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) client - read handshake message
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -38,6 +38,7 @@ static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
|
|||
const u8 *pos, *end;
|
||||
size_t left, len, i;
|
||||
u16 cipher_suite;
|
||||
u16 tls_version;
|
||||
|
||||
if (ct != TLS_CONTENT_TYPE_HANDSHAKE) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; "
|
||||
|
@ -79,15 +80,22 @@ static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct,
|
|||
/* ProtocolVersion server_version */
|
||||
if (end - pos < 2)
|
||||
goto decode_error;
|
||||
if (WPA_GET_BE16(pos) != TLS_VERSION) {
|
||||
tls_version = WPA_GET_BE16(pos);
|
||||
if (tls_version != TLS_VERSION_1 &&
|
||||
(tls_version != TLS_VERSION_1_1 ||
|
||||
TLS_VERSION == TLS_VERSION_1)) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
|
||||
"ServerHello");
|
||||
"ServerHello %u.%u", pos[0], pos[1]);
|
||||
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_PROTOCOL_VERSION);
|
||||
return -1;
|
||||
}
|
||||
pos += 2;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s",
|
||||
tls_version == TLS_VERSION_1_1 ? "1.1" : "1.0");
|
||||
conn->rl.tls_version = tls_version;
|
||||
|
||||
/* Random random */
|
||||
if (end - pos < TLS_RANDOM_LEN)
|
||||
goto decode_error;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TLSv1 client - write handshake message
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) client - write handshake message
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -774,7 +774,8 @@ u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level,
|
|||
/* ContentType type */
|
||||
*pos++ = TLS_CONTENT_TYPE_ALERT;
|
||||
/* ProtocolVersion version */
|
||||
WPA_PUT_BE16(pos, TLS_VERSION);
|
||||
WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version :
|
||||
TLS_VERSION);
|
||||
pos += 2;
|
||||
/* uint16 length (to be filled) */
|
||||
length = pos;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* TLSv1 common definitions
|
||||
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) common definitions
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -17,7 +17,13 @@
|
|||
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
#define TLS_VERSION 0x0301 /* TLSv1 */
|
||||
#define TLS_VERSION_1 0x0301 /* TLSv1 */
|
||||
#define TLS_VERSION_1_1 0x0302 /* TLSv1.1 */
|
||||
#ifdef CONFIG_TLSV11
|
||||
#define TLS_VERSION TLS_VERSION_1_1
|
||||
#else /* CONFIG_TLSV11 */
|
||||
#define TLS_VERSION TLS_VERSION_1
|
||||
#endif /* CONFIG_TLSV11 */
|
||||
#define TLS_RANDOM_LEN 32
|
||||
#define TLS_PRE_MASTER_SECRET_LEN 48
|
||||
#define TLS_MASTER_SECRET_LEN 48
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TLSv1 Record Protocol
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) Record Protocol
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -139,7 +139,7 @@ int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl)
|
|||
* @rl: Pointer to TLS record layer data
|
||||
* @content_type: Content type (TLS_CONTENT_TYPE_*)
|
||||
* @buf: Buffer for the generated TLS message (needs to have extra space for
|
||||
* header and HMAC)
|
||||
* header, IV (TLS v1.1), and HMAC)
|
||||
* @buf_size: Maximum buf size
|
||||
* @payload: Payload to be sent
|
||||
* @payload_len: Length of the payload
|
||||
|
@ -156,6 +156,7 @@ int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
|
|||
u8 *pos, *ct_start, *length, *cpayload;
|
||||
struct crypto_hash *hmac;
|
||||
size_t clen;
|
||||
int explicit_iv;
|
||||
|
||||
pos = buf;
|
||||
if (pos + TLS_RECORD_HEADER_LEN > buf + buf_size)
|
||||
|
@ -165,7 +166,7 @@ int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
|
|||
ct_start = pos;
|
||||
*pos++ = content_type;
|
||||
/* ProtocolVersion version */
|
||||
WPA_PUT_BE16(pos, TLS_VERSION);
|
||||
WPA_PUT_BE16(pos, rl->tls_version);
|
||||
pos += 2;
|
||||
/* uint16 length */
|
||||
length = pos;
|
||||
|
@ -173,6 +174,22 @@ int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf,
|
|||
pos += 2;
|
||||
|
||||
cpayload = pos;
|
||||
explicit_iv = rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL &&
|
||||
rl->iv_size && rl->tls_version == TLS_VERSION_1_1;
|
||||
if (explicit_iv) {
|
||||
/* opaque IV[Cipherspec.block_length] */
|
||||
if (pos + rl->iv_size > buf + buf_size)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Use random number R per the RFC 4346, 6.2.3.2 CBC Block
|
||||
* Cipher option 2a.
|
||||
*/
|
||||
|
||||
if (os_get_random(pos, rl->iv_size))
|
||||
return -1;
|
||||
pos += rl->iv_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* opaque fragment[TLSPlaintext.length]
|
||||
|
@ -343,6 +360,9 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl,
|
|||
return -1;
|
||||
}
|
||||
plen = in_len;
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted "
|
||||
"data", out_data, plen);
|
||||
|
||||
if (rl->iv_size) {
|
||||
/*
|
||||
* TLS v1.0 defines different alert values for various
|
||||
|
@ -355,6 +375,19 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl,
|
|||
* attacks more difficult.
|
||||
*/
|
||||
|
||||
if (rl->tls_version == TLS_VERSION_1_1) {
|
||||
/* Remove opaque IV[Cipherspec.block_length] */
|
||||
if (plen < rl->iv_size) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1.1: Not "
|
||||
"enough room for IV");
|
||||
force_mac_error = 1;
|
||||
goto check_mac;
|
||||
}
|
||||
os_memmove(out_data, out_data + rl->iv_size,
|
||||
plen - rl->iv_size);
|
||||
plen -= rl->iv_size;
|
||||
}
|
||||
|
||||
/* Verify and remove padding */
|
||||
if (plen == 0) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Too short record"
|
||||
|
@ -387,8 +420,8 @@ int tlsv1_record_receive(struct tlsv1_record_layer *rl,
|
|||
}
|
||||
|
||||
check_mac:
|
||||
wpa_hexdump(MSG_MSGDUMP,
|
||||
"TLSv1: Record Layer - Decrypted data",
|
||||
wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted "
|
||||
"data with IV and padding removed",
|
||||
out_data, plen);
|
||||
|
||||
if (plen < rl->hash_size) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* TLSv1 Record Protocol
|
||||
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) Record Protocol
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -35,6 +35,8 @@ enum {
|
|||
};
|
||||
|
||||
struct tlsv1_record_layer {
|
||||
u16 tls_version;
|
||||
|
||||
u8 write_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN];
|
||||
u8 read_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN];
|
||||
u8 write_key[TLS_MAX_WRITE_KEY_LEN];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TLSv1 server (RFC 2246)
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) server
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
|
|
@ -85,15 +85,26 @@ static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct,
|
|||
conn->client_version = WPA_GET_BE16(pos);
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d",
|
||||
conn->client_version >> 8, conn->client_version & 0xff);
|
||||
if (conn->client_version < TLS_VERSION) {
|
||||
if (conn->client_version < TLS_VERSION_1) {
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in "
|
||||
"ClientHello");
|
||||
"ClientHello %u.%u",
|
||||
conn->client_version >> 8,
|
||||
conn->client_version & 0xff);
|
||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||
TLS_ALERT_PROTOCOL_VERSION);
|
||||
return -1;
|
||||
}
|
||||
pos += 2;
|
||||
|
||||
if (TLS_VERSION == TLS_VERSION_1)
|
||||
conn->rl.tls_version = TLS_VERSION_1;
|
||||
else if (conn->client_version > TLS_VERSION_1_1)
|
||||
conn->rl.tls_version = TLS_VERSION_1_1;
|
||||
else
|
||||
conn->rl.tls_version = conn->client_version;
|
||||
wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s",
|
||||
conn->rl.tls_version == TLS_VERSION_1_1 ? "1.1" : "1.0");
|
||||
|
||||
/* Random random */
|
||||
if (end - pos < TLS_RANDOM_LEN)
|
||||
goto decode_error;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* TLSv1 server - write handshake message
|
||||
* TLS v1.0 (RFC 2246) and v1.1 (RFC 4346) server - write handshake message
|
||||
* Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -87,7 +87,7 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
|
|||
pos += 3;
|
||||
/* body - ServerHello */
|
||||
/* ProtocolVersion server_version */
|
||||
WPA_PUT_BE16(pos, TLS_VERSION);
|
||||
WPA_PUT_BE16(pos, conn->rl.tls_version);
|
||||
pos += 2;
|
||||
/* Random random: uint32 gmt_unix_time, opaque random_bytes */
|
||||
os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN);
|
||||
|
@ -764,7 +764,8 @@ u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level,
|
|||
/* ContentType type */
|
||||
*pos++ = TLS_CONTENT_TYPE_ALERT;
|
||||
/* ProtocolVersion version */
|
||||
WPA_PUT_BE16(pos, TLS_VERSION);
|
||||
WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version :
|
||||
TLS_VERSION);
|
||||
pos += 2;
|
||||
/* uint16 length (to be filled) */
|
||||
length = pos;
|
||||
|
|
|
@ -806,6 +806,10 @@ ifndef CONFIG_TLS
|
|||
CONFIG_TLS=openssl
|
||||
endif
|
||||
|
||||
ifdef CONFIG_TLSV11
|
||||
CFLAGS += -DCONFIG_TLSV11
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TLS), openssl)
|
||||
ifdef TLS_FUNCS
|
||||
CFLAGS += -DEAP_TLS_OPENSSL
|
||||
|
|
|
@ -335,6 +335,13 @@ CONFIG_PEERKEY=y
|
|||
# apply for distribution of the resulting binary.
|
||||
#CONFIG_GNUTLS_EXTRA=y
|
||||
|
||||
# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
||||
# can be enabled to get a stronger construction of messages when block ciphers
|
||||
# are used. It should be noted that some existing TLS v1.0 -based
|
||||
# implementation may not be compatible with TLS v1.1 message (ClientHello is
|
||||
# sent prior to negotiating which version will be used)
|
||||
#CONFIG_TLSV11=y
|
||||
|
||||
# If CONFIG_TLS=internal is used, additional library and include paths are
|
||||
# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
||||
# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
||||
|
|
Loading…
Reference in a new issue