The handshake record in TLS can contain multiple messages, however,
gPXE was only expecting one message.  This seems to work fine with
openssl, but the java ssl code seems to send multiple message blocks
in a single record.  So, we need to iterate through them.

For reference: http://en.wikipedia.org/wiki/Transport_Layer_Security

thanks,

tim


VMware, Inc. is providing this patch to you under the terms of the
GPL version 2 and any later version. This patch is provided as
is, with no warranties or support. VMware disclaims all liability
in connection with the use/inability to use this patch.  Any use
of the attached is considered acceptance of the above.

>From dcd0803f05a6c5e933da668d5ff48c7d248d9507 Mon Sep 17 00:00:00 2001
From: tstack <tst...@tstack-dev2.(none)>
Date: Tue, 22 Jun 2010 10:22:29 -0700
Subject: [PATCH] Fix tls handshake handling in gPXE

The handshake record in TLS can contain multiple messages, however,
gPXE was only expecting one message.  This seems to work fine with
openssl, but the java ssl code seems to send multiple message blocks
in a single record.  So, we need to iterate through them.

For reference: http://en.wikipedia.org/wiki/Transport_Layer_Security
---
 src/include/gpxe/tls.h |    7 ++++
 src/net/tls.c          |   90 ++++++++++++++++++++++++++---------------------
 2 files changed, 57 insertions(+), 40 deletions(-)

diff --git a/src/include/gpxe/tls.h b/src/include/gpxe/tls.h
index e2da046..5126bea 100644
--- a/src/include/gpxe/tls.h
+++ b/src/include/gpxe/tls.h
@@ -52,6 +52,13 @@ struct tls_header {
 /** Application data content type */
 #define TLS_TYPE_DATA 23
 
+/** Handshake message type */
+struct tls_handshake_msg {
+	uint8_t type;
+	uint8_t length[3];
+	uint8_t payload[0];
+} __attribute__ (( packed ));
+
 /* Handshake message types */
 #define TLS_HELLO_REQUEST 0
 #define TLS_CLIENT_HELLO 1
diff --git a/src/net/tls.c b/src/net/tls.c
index a5b126e..ecc863f 100644
--- a/src/net/tls.c
+++ b/src/net/tls.c
@@ -964,49 +964,59 @@ static int tls_new_finished ( struct tls_session *tls,
  */
 static int tls_new_handshake ( struct tls_session *tls,
 			       void *data, size_t len ) {
-	struct {
-		uint8_t type;
-		uint8_t length[3];
-		uint8_t payload[0];
-	} __attribute__ (( packed )) *handshake = data;
-	void *payload = &handshake->payload;
-	size_t payload_len = tls_uint24 ( handshake->length );
-	void *end = ( payload + payload_len );
-	int rc;
+	void *data_end = ( data + len );
+	int rc = 0;
+
+	while ( data < data_end ) {
+		struct tls_handshake_msg *handshake = data;
+		void *payload = &handshake->payload;
+		size_t payload_len = tls_uint24 ( handshake->length );
+
+		DBGC ( tls, "TLS %p received Handshake %d %p %d\n",
+		       tls,
+		       handshake->type,
+		       payload,
+		       payload_len );
+		
+		switch ( handshake->type ) {
+		case TLS_SERVER_HELLO:
+			rc = tls_new_server_hello ( tls, payload, payload_len );
+			break;
+		case TLS_CERTIFICATE:
+			rc = tls_new_certificate ( tls, payload, payload_len );
+			break;
+		case TLS_SERVER_HELLO_DONE:
+			rc = tls_new_server_hello_done ( tls, payload, payload_len );
+			break;
+		case TLS_FINISHED:
+			rc = tls_new_finished ( tls, payload, payload_len );
+			break;
+		default:
+			DBGC ( tls, "TLS %p ignoring handshake type %d\n",
+			       tls, handshake->type );
+			rc = 0;
+			break;
+		}
+		
+		/* Add to handshake digest (except for Hello Requests, which
+		 * are explicitly excluded).
+		 */
+		if ( handshake->type != TLS_HELLO_REQUEST )
+			tls_add_handshake ( tls, data,
+					    sizeof ( *handshake ) +
+					    payload_len );
 
-	/* Sanity check */
-	if ( end != ( data + len ) ) {
-		DBGC ( tls, "TLS %p received overlength Handshake\n", tls );
-		DBGC_HD ( tls, data, len );
-		return -EINVAL;
+		data += sizeof ( *handshake ) + payload_len;
 	}
 
-	switch ( handshake->type ) {
-	case TLS_SERVER_HELLO:
-		rc = tls_new_server_hello ( tls, payload, payload_len );
-		break;
-	case TLS_CERTIFICATE:
-		rc = tls_new_certificate ( tls, payload, payload_len );
-		break;
-	case TLS_SERVER_HELLO_DONE:
-		rc = tls_new_server_hello_done ( tls, payload, payload_len );
-		break;
-	case TLS_FINISHED:
-		rc = tls_new_finished ( tls, payload, payload_len );
-		break;
-	default:
-		DBGC ( tls, "TLS %p ignoring handshake type %d\n",
-		       tls, handshake->type );
-		rc = 0;
-		break;
+	if ( data != data_end ) {
+		DBGC ( tls, "TLS %p received overlength Handshake %p %p\n",
+		       tls,
+		       data,
+		       data_end );
+		DBGC_HD ( tls, data, len );
 	}
-
-	/* Add to handshake digest (except for Hello Requests, which
-	 * are explicitly excluded).
-	 */
-	if ( handshake->type != TLS_HELLO_REQUEST )
-		tls_add_handshake ( tls, data, len );
-
+	
 	return rc;
 }
 
-- 
1.6.3.3

_______________________________________________
gPXE-devel mailing list
[email protected]
http://etherboot.org/mailman/listinfo/gpxe-devel

Reply via email to