Skip to contentSkip to conversation

tls: Only accept the Certificate Request in client mode

PATCH New Andrew Zaborowski 1 participant 11 messages Dec 22, 2018 Kbuild

lore
Share & tools
lore
#0 lore raw

PATCH 1/11 tls: Only accept the Certificate Request in client mode

---
 ell/tls.c | 6 ++++++
 1 file changed, 6 insertions(+)
ell/tls.c +6 -0
index eab9cc2..f4cd94c 100644
@@ -2312,6 +2312,12 @@ static void tls_handle_handshake(struct l_tls *tls, int type,
 		break;
 
 	case TLS_CERTIFICATE_REQUEST:
+		if (tls->server) {
+			TLS_DISCONNECT(TLS_ALERT_UNEXPECTED_MESSAGE, 0,
+					"Message invalid in server mode");
+			break;
+		}
+
 		/*
 		 * Server sends this optionally so in the WAIT_HELLO_DONE
 		 * state we accept either this or a Server Hello Done (below).
Signature · 1 line
2.19.1
#1 lore raw

PATCH 2/11 tls: Add Hello extension sending support

Declare a struct for ServerHello/ClientHello extensions with write and handle callbacks, modify our ServerHello and ClientHello message builders to append the extensions to the messages.

---
 ell/tls-private.h |  18 +++++++++
 ell/tls.c         | 101 ++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 112 insertions(+), 7 deletions(-)
ell/tls-private.h +18 -0
index 0908b9c..5ea8208 100644
@@ -99,6 +99,24 @@ struct tls_compression_method {
 	const char *name;
 };
 
+struct tls_hello_extension {
+	const char *name;
+	const char *short_name;
+	uint16_t id;
+	ssize_t (*client_write)(struct l_tls *tls, uint8_t *buf, size_t len);
+	/* Handle a Client Hello extension (on server), can't be NULL */
+	bool (*client_handle)(struct l_tls *tls,
+				const uint8_t *buf, size_t len);
+	/* Handle a Client Hello extension's absence (on server) */
+	bool (*client_handle_absent)(struct l_tls *tls);
+	ssize_t (*server_write)(struct l_tls *tls, uint8_t *buf, size_t len);
+	/* Handle a Server Hello extension (on client) */
+	bool (*server_handle)(struct l_tls *tls,
+				const uint8_t *buf, size_t len);
+	/* Handle a Server Hello extension's absence (on client) */
+	bool (*server_handle_absent)(struct l_tls *tls);
+};
+
 enum tls_handshake_state {
 	TLS_HANDSHAKE_WAIT_START,
 	TLS_HANDSHAKE_WAIT_HELLO,
ell/tls.c +94 -7

149 lines not on this page · raw message

Signature · 1 line
2.19.1
#2 lore raw

PATCH 3/11 tls: Parse and process received extensions

In reply to Andrew Zaborowski

On the server call the .client_handle callbacks for each supported extension in the received ClientHello and pass the list of extensions we've handled to the ServerHello builder. On the client, process the extension responses in the ServerHello by calling .server_handle callbacks.

---
 ell/tls.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 154 insertions(+), 25 deletions(-)
ell/tls.c +154 -25
index ffa09e1..f8ba3d0 100644
@@ -1577,6 +1577,135 @@ static bool tls_verify_finished(struct l_tls *tls, const uint8_t *received,
 	return true;
 }
 
+static bool tls_ptr_match(const void *a, const void *b)
+{
+	return a == b;
+}
+
+static bool tls_handle_hello_extensions(struct l_tls *tls,
+					const uint8_t *buf, size_t len,
+					struct l_queue *seen)
+{
+	unsigned int i;
+	const struct tls_hello_extension *extension;
+	bool client_hello = tls->server;
+	uint16_t extensions_size;
+
+	if (!len)
+		return true;
+
+	if (len < 2 || len > 2 + 65535)
+		goto decode_error;
+
+	extensions_size = l_get_be16(buf);
+	len -= 2;
+	buf += 2;
+
+	if (len != extensions_size)
+		goto decode_error;
+
+	while (len) {
+		uint16_t ext_id;
+		size_t ext_len;
+		bool (*handler)(struct l_tls *tls,
+				const uint8_t *buf, size_t len);
+
+		if (len < 4)
+			goto decode_error;
+
+		ext_id = l_get_be16(buf + 0);
+		ext_len = l_get_be16(buf + 2);
+		buf += 4;
+		len -= 4;
+
+		if (ext_len > len)
+			goto decode_error;
+
+		/*
+		 * RFC 5246, Section 7.4.1.4: "There MUST NOT be more than
+		 * one extension of the same type."
+		 */
+		if (l_queue_find(seen, tls_ptr_match, L_UINT_TO_PTR(ext_id))) {
+			TLS_DEBUG("Duplicate extension %u", ext_id);
+			goto decode_error;
+		}
+
+		l_queue_push_tail(seen, L_UINT_TO_PTR(ext_id));
+
+		extension = NULL;
+
+		for (i = 0; tls_extensions[i].name; i++)
+			if (tls_extensions[i].id == ext_id) {
+				extension = &tls_extensions[i];
+				break;
+			}
+
+		if (!extension)
+			goto next;
+
+		handler = client_hello ?
+			extension->client_handle : extension->server_handle;
+
+		/*
+		 * RFC 5246, Section 7.4.1.4: "If a client receives an
+		 * extension type in ServerHello that it did not request in
+		 * the associated ClientHello, it MUST abort the handshake
+		 * with an unsupported_extension fatal alert."
+		 */
+		if (!client_hello && !handler) {
+			TLS_DISCONNECT(TLS_ALERT_UNSUPPORTED_EXTENSION, 0,
+					"%s extension not expected in "
+					"a ServerHello", extension->name);
+			return false;
+		}
+
+		if (!handler(tls, buf, ext_len)) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"Hello %s extension parse error",
+					extension->name);
+			return false;
+		}
+
+next:
+		buf += ext_len;
+		len -= ext_len;
+	}
+
+	/*
+	 * Trigger any actions needed when an extension is missing and its
+	 * handler has not been called yet.
+	 */
+	for (i = 0; tls_extensions[i].name; i++) {
+		bool (*handler)(struct l_tls *tls);
+
+		extension = &tls_extensions[i];
+		handler = client_hello ?
+			extension->client_handle_absent :
+			extension->server_handle_absent;
+
+		if (!handler)
+			continue;
+
+		if (l_queue_find(seen, tls_ptr_match,
+					L_UINT_TO_PTR(extension->id)))
+			continue;
+
+		if (!handler(tls)) {
+			TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+					"Hello %s extension missing",
+					extension->name);
+			return false;
+		}
+	}
+
+	return true;
+
+decode_error:
+	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
+			"Hello extensions decode error");
+	return false;
+}
+
 static void tls_handle_client_hello(struct l_tls *tls,
 					const uint8_t *buf, size_t len)
 {
@@ -1585,6 +1714,7 @@ static void tls_handle_client_hello(struct l_tls *tls,
 	const uint8_t *cipher_suites;
 	const uint8_t *compression_methods;
 	int i;
+	struct l_queue *extensions_offered = NULL;
 
 	/* Do we have enough for ProtocolVersion + Random + SessionID size? */
 	if (len < 2 + 32 + 1)
@@ -1626,22 +1756,12 @@ static void tls_handle_client_hello(struct l_tls *tls,
 
 	len -= compression_methods_size;
 
-	if (len) {
-		uint16_t extensions_size;
+	extensions_offered = l_queue_new();
 
-		if (len < 2 || len > 2 + 65535)
-			goto decode_error;
-
-		extensions_size = l_get_be16(compression_methods +
-						compression_methods_size);
-		len -= 2;
-
-		if (len != extensions_size)
-			goto decode_error;
-
-		/* TODO: validate each extension in the vector, 7.4.1.4 */
-		/* TODO: check for duplicates? */
-	}
+	if (!tls_handle_hello_extensions(tls, compression_methods +
+					compression_methods_size,
+					len, extensions_offered))
+		goto cleanup;
 
 	/*
 	 * Note: if the client is supplying a SessionID we know it is false
@@ -1664,7 +1784,7 @@ static void tls_handle_client_hello(struct l_tls *tls,
 		TLS_DISCONNECT(TLS_ALERT_PROTOCOL_VERSION, 0,
 				"Client version too low: %02x",
 				tls->client_version);
-		return;
+		goto cleanup;
 	}
 
 	tls->negotiated_version = TLS_VERSION < tls->client_version ?
@@ -1697,13 +1817,13 @@ static void tls_handle_client_hello(struct l_tls *tls,
 		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
 				"No common cipher suites matching negotiated "
 				"TLS version and our certificate's key type");
-		return;
+		goto cleanup;
 	}
 
 	if (!tls_set_prf_hmac(tls)) {
 		TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
 				"Error selecting the PRF HMAC");
-		return;
+		goto cleanup;
 	}
 
 	TLS_DEBUG("Negotiated %s", tls->pending.cipher_suite->name);
@@ -1714,7 +1834,7 @@ static void tls_handle_client_hello(struct l_tls *tls,
 	if (!memchr(compression_methods, 0, compression_methods_size)) {
 		TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
 				"No common compression methods");
-		return;
+		goto cleanup;
 	}
 
 	while (compression_methods_size) {
@@ -1730,8 +1850,10 @@ static void tls_handle_client_hello(struct l_tls *tls,
 
 	TLS_DEBUG("Negotiated %s", tls->pending.compression_method->name);
 
-	if (!tls_send_server_hello(tls, NULL))
-		return;
+	if (!tls_send_server_hello(tls, extensions_offered))
+		goto cleanup;
+
+	l_queue_destroy(extensions_offered, NULL);
 
 	if (tls->pending.cipher_suite->key_xchg->certificate_check && tls->cert)
 		if (!tls_send_certificate(tls))
@@ -1756,6 +1878,9 @@ static void tls_handle_client_hello(struct l_tls *tls,
 decode_error:
 	TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
 			"ClientHello decode error");
+
+cleanup:
+	l_queue_destroy(extensions_offered, NULL);
 }
 
 static void tls_handle_server_hello(struct l_tls *tls,
@@ -1764,6 +1889,8 @@ static void tls_handle_server_hello(struct l_tls *tls,
 	uint8_t session_id_size, cipher_suite_id[2], compression_method_id;
 	const char *error;
 	int i;
+	struct l_queue *extensions_seen;
+	bool result;
 
 	/* Do we have enough for ProtocolVersion + Random + SessionID len ? */
 	if (len < 2 + 32 + 1)
@@ -1782,11 +1909,13 @@ static void tls_handle_server_hello(struct l_tls *tls,
 	compression_method_id = buf[35 + session_id_size + 2];
 	len -= session_id_size + 2 + 1;
 
-	if (len != 0) { /* We know we haven't solicited any extensions */
-		TLS_DISCONNECT(TLS_ALERT_UNSUPPORTED_EXTENSION, 0,
-				"ServerHello contains extensions");
+	extensions_seen = l_queue_new();
+	result = tls_handle_hello_extensions(tls, buf + 38 + session_id_size,
+						len, extensions_seen);
+	l_queue_destroy(extensions_seen, NULL);
+
+	if (!result)
 		return;
-	}
 
 	tls->negotiated_version = l_get_be16(buf);
 
Signature · 1 line
2.19.1
#3 lore raw

PATCH 4/11 tls: Implement the Supported Elliptic Curves extension

In reply to Andrew Zaborowski

Defined in RFC 8422 5.1.1

---
 Makefile.am          |   1 +
 ell/tls-extensions.c | 108 +++++++++++++++++++++++++++++++++++++++++++
 ell/tls-private.h    |  10 ++++
 ell/tls.c            |   3 +-
 4 files changed, 120 insertions(+), 2 deletions(-)
 create mode 100644 ell/tls-extensions.c
Makefile.am +1 -0
index 8401972..297c395 100644
@@ -102,6 +102,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
 			ell/tls-private.h \
 			ell/tls.c \
 			ell/tls-record.c \
+			ell/tls-extensions.c \
 			ell/uuid.c \
 			ell/key.c \
 			ell/pkcs5-private.h \
ell/tls-extensions.c new file +108 -0

108 lines not on this page · raw message

ell/tls-private.h +10 -0
index 5ea8208..d1cfcac 100644
@@ -117,6 +117,15 @@ struct tls_hello_extension {
 	bool (*server_handle_absent)(struct l_tls *tls);
 };
 
+extern const struct tls_hello_extension tls_extensions[];
+
+struct tls_named_curve {
+	const char *name;
+	uint16_t id;
+	unsigned int l_group;
+	size_t point_bytes;
+};
+
 enum tls_handshake_state {
 	TLS_HANDSHAKE_WAIT_START,
 	TLS_HANDSHAKE_WAIT_HELLO,
@@ -198,6 +207,7 @@ struct l_tls {
 	size_t peer_pubkey_size;
 	enum handshake_hash_type signature_hash;
 	const struct tls_hash_algorithm *prf_hmac;
+	const struct tls_named_curve *negotiated_curve;
 
 	/* SecurityParameters current and pending */
 
ell/tls.c +1 -2
index f8ba3d0..ed7f0c7 100644
@@ -191,6 +191,7 @@ static void tls_reset_handshake(struct l_tls *tls)
 	tls->peer_cert = NULL;
 	tls->peer_pubkey = NULL;
 	tls->peer_pubkey_size = 0;
+	tls->negotiated_curve = NULL;
 
 	for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
 		tls_drop_handshake_hash(tls, hash);
@@ -709,8 +710,6 @@ static const struct tls_hash_algorithm *tls_set_prf_hmac(struct l_tls *tls)
 	return NULL;
 }
 
-static const struct tls_hello_extension tls_extensions[] = {};
-
 enum tls_handshake_type {
 	TLS_HELLO_REQUEST	= 0,
 	TLS_CLIENT_HELLO	= 1,
Signature · 1 line
2.19.1
#4 lore raw

PATCH 5/11 tls: Implement the Supported Point Formats extension

In reply to Andrew Zaborowski

Defined in RFC 8422 5.1.2

---
 ell/tls-extensions.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
ell/tls-extensions.c +42 -0
index 749b8e6..3d75037 100644
@@ -96,6 +96,40 @@ static bool tls_elliptic_curves_client_absent(struct l_tls *tls)
 	return true;
 }
 
+static bool tls_ec_point_formats_client_handle(struct l_tls *tls,
+						const uint8_t *buf, size_t len)
+{
+	if (len < 2)
+		return false;
+
+	if (buf[0] != len - 1)
+		return false;
+
+	if (!memchr(buf + 1, 0, len - 1)) {
+		TLS_DEBUG("Uncompressed point format missing");
+		return false;
+	}
+
+	return true;
+}
+
+/*
+ * For compatibility with clients respond to a valid Client Hello Supported
+ * Point Formats extension with the hardcoded confirmation that we do
+ * support the single valid point format.  As a client we never send this
+ * extension so we never have to handle a server response to it either.
+ */
+static ssize_t tls_ec_point_formats_server_write(struct l_tls *tls,
+						uint8_t *buf, size_t len)
+{
+	if (len < 2)
+		return -ENOMEM;
+
+	buf[0] = 0x01;	/* ec_point_format_list length */
+	buf[1] = 0x00;	/* uncompressed */
+	return 2;
+}
+
 const struct tls_hello_extension tls_extensions[] = {
 	{
 		"Supported Elliptic Curves", "elliptic_curves", 10,
@@ -104,5 +138,13 @@ const struct tls_hello_extension tls_extensions[] = {
 		tls_elliptic_curves_client_absent,
 		NULL, NULL, NULL,
 	},
+	{
+		"Supported Point Formats", "ec_point_formats", 11,
+		NULL,
+		tls_ec_point_formats_client_handle,
+		NULL,
+		tls_ec_point_formats_server_write,
+		NULL, NULL,
+	},
 	{}
 };
Signature · 1 line
2.19.1
#5 lore raw

PATCH 6/11 tls: Allow user to set custom list of cipher suites

In reply to Andrew Zaborowski

TLS "security profiles" define which minimum cipher suites and other parameter values are allowed in a specific usage scenario for TLS, for example WPA3 in theory requires a specific security profile for its TLS-based EAP method. This will also allow the unit tests to test individual cipher suites.

---
 ell/tls-private.h |   5 +
 ell/tls.c         | 260 +++++++++++++++++++++++++++++++---------------
 2 files changed, 181 insertions(+), 84 deletions(-)
ell/tls-private.h +5 -0
index d1cfcac..938c358 100644
@@ -180,6 +180,8 @@ struct l_tls {
 	struct l_key *priv_key;
 	size_t priv_key_size;
 
+	struct tls_cipher_suite **cipher_suite_pref_list;
+
 	/* Record layer */
 
 	uint8_t *record_buf;
@@ -267,6 +269,9 @@ void tls_tx_record(struct l_tls *tls, enum tls_content_type type,
 bool tls_handle_message(struct l_tls *tls, const uint8_t *message,
 			int len, enum tls_content_type type, uint16_t version);
 
+/* Optionally limit allowed cipher suites to a custom set */
+bool tls_set_cipher_suites(struct l_tls *tls, const char **suite_list);
+
 int tls_parse_certificate_list(const void *data, size_t len,
 				struct l_certchain **out_certchain);
 
ell/tls.c +176 -84

351 lines not on this page · raw message

Signature · 1 line
2.19.1
#6 lore raw

PATCH 7/11 tls: Move cipher suite definitions to tls-suites.c

In reply to Andrew Zaborowski

Move the cipher suite-specific code to new file ell/tls-suites.c. Unfortunately this requires a few functions and arrays to be exported from tls.c.

---
 Makefile.am       |   1 +
 ell/tls-private.h |  25 +++
 ell/tls-suites.c  | 450 ++++++++++++++++++++++++++++++++++++++++++++
 ell/tls.c         | 465 ++--------------------------------------------
 4 files changed, 490 insertions(+), 451 deletions(-)
 create mode 100644 ell/tls-suites.c
Makefile.am +1 -0
index 297c395..3eecbe0 100644
@@ -103,6 +103,7 @@ ell_libell_la_SOURCES = $(linux_headers) \
 			ell/tls.c \
 			ell/tls-record.c \
 			ell/tls-extensions.c \
+			ell/tls-suites.c \
 			ell/uuid.c \
 			ell/key.c \
 			ell/pkcs5-private.h \
ell/tls-private.h +25 -0
index 938c358..442dc02 100644
@@ -56,6 +56,8 @@ struct tls_hash_algorithm {
 	const char *name;
 };
 
+extern const struct tls_hash_algorithm tls_handshake_hash_data[];
+
 typedef bool (*tls_get_hash_t)(struct l_tls *tls, uint8_t tls_id,
 				uint8_t *out, size_t *len,
 				enum l_checksum_type *type);
@@ -94,6 +96,8 @@ struct tls_cipher_suite {
 	enum l_checksum_type prf_hmac;
 };
 
+extern struct tls_cipher_suite *tls_cipher_suite_pref[];
+
 struct tls_compression_method {
 	int id;
 	const char *name;
@@ -145,6 +149,19 @@ enum tls_content_type {
 	TLS_CT_APPLICATION_DATA		= 23,
 };
 
+enum tls_handshake_type {
+	TLS_HELLO_REQUEST	= 0,
+	TLS_CLIENT_HELLO	= 1,
+	TLS_SERVER_HELLO	= 2,
+	TLS_CERTIFICATE		= 11,
+	TLS_SERVER_KEY_EXCHANGE	= 12,
+	TLS_CERTIFICATE_REQUEST	= 13,
+	TLS_SERVER_HELLO_DONE	= 14,
+	TLS_CERTIFICATE_VERIFY	= 15,
+	TLS_CLIENT_KEY_EXCHANGE	= 16,
+	TLS_FINISHED		= 20,
+};
+
 /*
  * Support the minimum required set of handshake hash types for the
  * Certificate Verify digital signature and the Finished PRF seed so we
@@ -269,9 +286,17 @@ void tls_tx_record(struct l_tls *tls, enum tls_content_type type,
 bool tls_handle_message(struct l_tls *tls, const uint8_t *message,
 			int len, enum tls_content_type type, uint16_t version);
 
+#define TLS_HANDSHAKE_HEADER_SIZE	4
+
+void tls_tx_handshake(struct l_tls *tls, int type, uint8_t *buf, size_t length);
+
 /* Optionally limit allowed cipher suites to a custom set */
 bool tls_set_cipher_suites(struct l_tls *tls, const char **suite_list);
 
+void tls_generate_master_secret(struct l_tls *tls,
+				const uint8_t *pre_master_secret,
+				int pre_master_secret_len);
+
 int tls_parse_certificate_list(const void *data, size_t len,
 				struct l_certchain **out_certchain);
 
ell/tls-suites.c new file +450 -0

450 lines not on this page · raw message

ell/tls.c +14 -451

536 lines not on this page · raw message

Signature · 1 line
2.19.1
#7 lore raw

PATCH 8/11 tls: Add ServerKeyExchange callbacks to key exchange struct

In reply to Andrew Zaborowski

TLS Key Exchange algorithms using ephemeral keys (DHE_* and ECDHE_*) need to use the ServerKeyExchange message during the handshake unlike our current RSA key exchanhe, provide callbacks for sending and receiving those messages.

---
 ell/tls-private.h |  4 ++++
 ell/tls.c         | 61 +++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 55 insertions(+), 10 deletions(-)
ell/tls-private.h +4 -0
index 442dc02..c2a311b 100644
@@ -73,6 +73,10 @@ struct tls_key_exchange_algorithm {
 	void (*handle_client_key_exchange)(struct l_tls *tls,
 						const uint8_t *buf, size_t len);
 
+	bool (*send_server_key_exchange)(struct l_tls *tls);
+	void (*handle_server_key_exchange)(struct l_tls *tls,
+						const uint8_t *buf, size_t len);
+
 	ssize_t (*sign)(struct l_tls *tls, uint8_t *out, size_t len,
 			tls_get_hash_t get_hash);
 	bool (*verify)(struct l_tls *tls, const uint8_t *in, size_t len,
ell/tls.c +51 -10

89 lines not on this page · raw message

Signature · 1 line
2.19.1
#8 lore raw

PATCH 9/11 tls: ECHDE_RSA key exchange implementation server side

In reply to Andrew Zaborowski

Add a new key exchange definition with the callbacks needed to handle the server side of the ECDHE_RSA key exchange, defined in RFC 8422. Key Exchange method-specific state is kept in a struct allocated by the method and pointed to by a void pointer in the l_tls struct so that the internals of the method are kept in tls-suites.c

---
 ell/tls-private.h |   4 +
 ell/tls-suites.c  | 223 ++++++++++++++++++++++++++++++++++++++++++++++
 ell/tls.c         |  22 +++++
 3 files changed, 249 insertions(+)
ell/tls-private.h +4 -0
index c2a311b..bb7d58d 100644
@@ -66,6 +66,7 @@ struct tls_key_exchange_algorithm {
 	uint8_t id;
 
 	bool certificate_check;
+	bool need_ecc;
 
 	bool (*validate_cert_key_type)(struct l_cert *cert);
 
@@ -81,6 +82,8 @@ struct tls_key_exchange_algorithm {
 			tls_get_hash_t get_hash);
 	bool (*verify)(struct l_tls *tls, const uint8_t *in, size_t len,
 			tls_get_hash_t get_hash);
+
+	void (*free_params)(struct l_tls *tls);
 };
 
 struct tls_mac_algorithm {
@@ -246,6 +249,7 @@ struct l_tls {
 		 * 6.3 v1.2 + two IVs of 32 bytes.
 		 */
 		uint8_t key_block[192];
+		void *key_xchg_params;
 	} pending;
 
 	enum tls_cipher_type cipher_type[2];
ell/tls-suites.c +223 -0

235 lines not on this page · raw message

ell/tls.c +22 -0
index 0aa04a1..fc8ab41 100644
@@ -186,6 +186,10 @@ static void tls_reset_handshake(struct l_tls *tls)
 
 	memset(tls->pending.key_block, 0, sizeof(tls->pending.key_block));
 
+	if (tls->pending.cipher_suite &&
+			tls->pending.cipher_suite->key_xchg->free_params)
+		tls->pending.cipher_suite->key_xchg->free_params(tls);
+
 	l_cert_free(tls->peer_cert);
 	l_key_free(tls->peer_pubkey);
 
@@ -472,6 +476,24 @@ static bool tls_cipher_suite_is_compatible(struct l_tls *tls,
 		return false;
 	}
 
+	/*
+	 * On the server we know what elliptic curve we'll be using as soon
+	 * as we've processed the ClientHello so for EC-based key exchange
+	 * methods require that a curve has been selected.
+	 */
+	if (suite->key_xchg->need_ecc && tls->server &&
+			!tls->negotiated_curve) {
+		if (error) {
+			*error = error_buf;
+			snprintf(error_buf, sizeof(error_buf),
+					"No common supported elliptic curves "
+					"with the client, can't use %s",
+					suite->name);
+		}
+
+		return false;
+	}
+
 	return true;
 }
 
Signature · 1 line
2.19.1
#9 lore raw

PATCH 10/11 tls: ECHDE_RSA key exchange implementation client side

In reply to Andrew Zaborowski

Add the handler for the ECDHE ServerKeyExchange message rx and a builder for the ClientKeyExchange message tx, both specified in RFC 8422.

---
 ell/tls-extensions.c |  11 ++++
 ell/tls-private.h    |   2 +
 ell/tls-suites.c     | 145 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+)
ell/tls-extensions.c +11 -0
index 3d75037..be2fa10 100644
@@ -148,3 +148,14 @@ const struct tls_hello_extension tls_extensions[] = {
 	},
 	{}
 };
+
+const struct tls_named_curve *tls_find_curve(uint16_t id)
+{
+	unsigned int i;
+
+	for (i = 0; i < L_ARRAY_SIZE(tls_curve_pref); i++)
+		if (tls_curve_pref[i].id == id)
+			return &tls_curve_pref[i];
+
+	return NULL;
+}
ell/tls-private.h +2 -0
index bb7d58d..3f68a1d 100644
@@ -305,6 +305,8 @@ void tls_generate_master_secret(struct l_tls *tls,
 				const uint8_t *pre_master_secret,
 				int pre_master_secret_len);
 
+const struct tls_named_curve *tls_find_curve(uint16_t id);
+
 int tls_parse_certificate_list(const void *data, size_t len,
 				struct l_certchain **out_certchain);
 
ell/tls-suites.c +145 -0

159 lines not on this page · raw message

Signature · 1 line
2.19.1
#10 lore raw

PATCH 11/11 tls: Add cipher suites using the ECDHE_RSA key exchange

In reply to Andrew Zaborowski

Add all cipher suites defined in RFC 8422 that we can now support with the new ECDHE_RSA key exchange (see section 6 for the full list of ECDH-based cipher suites)

---
 ell/tls-suites.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
ell/tls-suites.c +39 -0
index 4ec6d54..dff2e3a 100644
@@ -802,15 +802,54 @@ static struct tls_cipher_suite tls_rsa_with_rc4_128_md5 = {
 	.encryption = &tls_aes256_gcm,
 	.prf_hmac = L_CHECKSUM_SHA384,
 	.key_xchg = &tls_rsa,
+}, tls_ecdhe_rsa_with_3des_ede_cbc_sha = {
+	.id = { 0xc0, 0x12 },
+	.name = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+	.verify_data_length = 12,
+	.encryption = &tls_3des_ede,
+	.mac = &tls_sha,
+	.key_xchg = &tls_ecdhe_rsa,
+}, tls_ecdhe_rsa_with_aes_128_cbc_sha = {
+	.id = { 0xc0, 0x13 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+	.verify_data_length = 12,
+	.encryption = &tls_aes128,
+	.mac = &tls_sha,
+	.key_xchg = &tls_ecdhe_rsa,
+}, tls_ecdhe_rsa_with_aes_256_cbc_sha = {
+	.id = { 0xc0, 0x14 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+	.verify_data_length = 12,
+	.encryption = &tls_aes256,
+	.mac = &tls_sha,
+	.key_xchg = &tls_ecdhe_rsa,
+}, tls_ecdhe_rsa_with_aes_128_gcm_sha256 = {
+	.id = { 0xc0, 0x2f },
+	.name = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+	.verify_data_length = 12,
+	.encryption = &tls_aes128_gcm,
+	.key_xchg = &tls_ecdhe_rsa,
+}, tls_ecdhe_rsa_with_aes_256_gcm_sha384 = {
+	.id = { 0xc0, 0x30 },
+	.name = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+	.verify_data_length = 12,
+	.encryption = &tls_aes256_gcm,
+	.prf_hmac = L_CHECKSUM_SHA384,
+	.key_xchg = &tls_ecdhe_rsa,
 };
 
 struct tls_cipher_suite *tls_cipher_suite_pref[] = {
+	&tls_ecdhe_rsa_with_aes_256_cbc_sha,
+	&tls_ecdhe_rsa_with_aes_128_cbc_sha,
 	&tls_rsa_with_aes_256_cbc_sha,
 	&tls_rsa_with_aes_128_cbc_sha,
 	&tls_rsa_with_aes_256_cbc_sha256,
 	&tls_rsa_with_aes_128_cbc_sha256,
+	&tls_ecdhe_rsa_with_aes_256_gcm_sha384,
+	&tls_ecdhe_rsa_with_aes_128_gcm_sha256,
 	&tls_rsa_with_aes_256_gcm_sha384,
 	&tls_rsa_with_aes_128_gcm_sha256,
+	&tls_ecdhe_rsa_with_3des_ede_cbc_sha,
 	&tls_rsa_with_3des_ede_cbc_sha,
 	&tls_rsa_with_rc4_128_sha,
 	&tls_rsa_with_rc4_128_md5,
Signature · 1 line
2.19.1