Browse Source

[tls] Handle multiple handshake records

The handshake record in TLS can contain multiple messages.

Originally-fixed-by: Timothy Stack <tstack@vmware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 years ago
parent
commit
21682afe69
1 changed files with 54 additions and 39 deletions
  1. 54
    39
      src/net/tls.c

+ 54
- 39
src/net/tls.c View File

@@ -962,50 +962,65 @@ static int tls_new_finished ( struct tls_session *tls,
962 962
  */
963 963
 static int tls_new_handshake ( struct tls_session *tls,
964 964
 			       void *data, size_t len ) {
965
-	struct {
966
-		uint8_t type;
967
-		uint8_t length[3];
968
-		uint8_t payload[0];
969
-	} __attribute__ (( packed )) *handshake = data;
970
-	void *payload = &handshake->payload;
971
-	size_t payload_len = tls_uint24 ( handshake->length );
972
-	void *end = ( payload + payload_len );
965
+	void *end = ( data + len );
973 966
 	int rc;
974 967
 
975
-	/* Sanity check */
976
-	if ( end != ( data + len ) ) {
977
-		DBGC ( tls, "TLS %p received overlength Handshake\n", tls );
978
-		DBGC_HD ( tls, data, len );
979
-		return -EINVAL;
980
-	}
968
+	while ( data != end ) {
969
+		struct {
970
+			uint8_t type;
971
+			uint8_t length[3];
972
+			uint8_t payload[0];
973
+		} __attribute__ (( packed )) *handshake = data;
974
+		void *payload = &handshake->payload;
975
+		size_t payload_len = tls_uint24 ( handshake->length );
976
+		void *next = ( payload + payload_len );
977
+
978
+		/* Sanity check */
979
+		if ( next > end ) {
980
+			DBGC ( tls, "TLS %p received overlength Handshake\n",
981
+			       tls );
982
+			DBGC_HD ( tls, data, len );
983
+			return -EINVAL;
984
+		}
981 985
 
982
-	switch ( handshake->type ) {
983
-	case TLS_SERVER_HELLO:
984
-		rc = tls_new_server_hello ( tls, payload, payload_len );
985
-		break;
986
-	case TLS_CERTIFICATE:
987
-		rc = tls_new_certificate ( tls, payload, payload_len );
988
-		break;
989
-	case TLS_SERVER_HELLO_DONE:
990
-		rc = tls_new_server_hello_done ( tls, payload, payload_len );
991
-		break;
992
-	case TLS_FINISHED:
993
-		rc = tls_new_finished ( tls, payload, payload_len );
994
-		break;
995
-	default:
996
-		DBGC ( tls, "TLS %p ignoring handshake type %d\n",
997
-		       tls, handshake->type );
998
-		rc = 0;
999
-		break;
1000
-	}
986
+		switch ( handshake->type ) {
987
+		case TLS_SERVER_HELLO:
988
+			rc = tls_new_server_hello ( tls, payload, payload_len );
989
+			break;
990
+		case TLS_CERTIFICATE:
991
+			rc = tls_new_certificate ( tls, payload, payload_len );
992
+			break;
993
+		case TLS_SERVER_HELLO_DONE:
994
+			rc = tls_new_server_hello_done ( tls, payload,
995
+							 payload_len );
996
+			break;
997
+		case TLS_FINISHED:
998
+			rc = tls_new_finished ( tls, payload, payload_len );
999
+			break;
1000
+		default:
1001
+			DBGC ( tls, "TLS %p ignoring handshake type %d\n",
1002
+			       tls, handshake->type );
1003
+			rc = 0;
1004
+			break;
1005
+		}
1001 1006
 
1002
-	/* Add to handshake digest (except for Hello Requests, which
1003
-	 * are explicitly excluded).
1004
-	 */
1005
-	if ( handshake->type != TLS_HELLO_REQUEST )
1006
-		tls_add_handshake ( tls, data, len );
1007
+		/* Add to handshake digest (except for Hello Requests,
1008
+		 * which are explicitly excluded).
1009
+		 */
1010
+		if ( handshake->type != TLS_HELLO_REQUEST )
1011
+			tls_add_handshake ( tls, data,
1012
+					    sizeof ( *handshake ) +
1013
+					    payload_len );
1007 1014
 
1008
-	return rc;
1015
+		/* Abort on failure */
1016
+		if ( rc != 0 )
1017
+			return rc;
1018
+
1019
+		/* Move to next handshake record */
1020
+		data = next;
1021
+	}
1022
+
1023
+	return 0;
1009 1024
 }
1010 1025
 
1011 1026
 /**

Loading…
Cancel
Save