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
