CONFIG_TLS=openssl
endif
+ifdef CONFIG_TLSV11
+CFLAGS += -DCONFIG_TLSV11
+endif
+
ifeq ($(CONFIG_TLS), openssl)
ifdef TLS_FUNCS
OBJS += ../src/crypto/tls_openssl.o
# 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
/*
- * 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
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)) {
os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
pos += conn->rl.key_material_len;
- /* 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;
+ 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;
}
suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
conn->num_cipher_suites = count;
+ conn->rl.tls_version = TLS_VERSION;
+
return conn;
}
/*
- * 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
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; "
/* 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;
/*
- * 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
/* 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;
/*
- * 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
#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
/*
- * 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
* @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
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)
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;
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]
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
* 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"
}
check_mac:
- wpa_hexdump(MSG_MSGDUMP,
- "TLSv1: Record Layer - Decrypted data",
- out_data, plen);
+ wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted "
+ "data with IV and padding removed",
+ out_data, plen);
if (plen < rl->hash_size) {
wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no "
/*
- * 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
};
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];
/*
- * 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
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;
/*
- * 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
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);
/* 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;
CONFIG_TLS=openssl
endif
+ifdef CONFIG_TLSV11
+CFLAGS += -DCONFIG_TLSV11
+endif
+
ifeq ($(CONFIG_TLS), openssl)
ifdef TLS_FUNCS
CFLAGS += -DEAP_TLS_OPENSSL
# 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