diff options
author | Michael Brown <mcb30@ipxe.org> | 2010-06-23 01:01:32 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2010-06-23 01:01:32 +0100 |
commit | 21682afe6905ddc566159471bdb1a51e376e2af1 (patch) | |
tree | 2259721ddf3f895b87e16248a1ccd7dec6839292 /src/net/tls.c | |
parent | 719ba316dfc7c32f12375917301718af51509e5f (diff) | |
download | ipxe-21682afe6905ddc566159471bdb1a51e376e2af1.zip ipxe-21682afe6905ddc566159471bdb1a51e376e2af1.tar.gz ipxe-21682afe6905ddc566159471bdb1a51e376e2af1.tar.bz2 |
[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>
Diffstat (limited to 'src/net/tls.c')
-rw-r--r-- | src/net/tls.c | 93 |
1 files changed, 54 insertions, 39 deletions
diff --git a/src/net/tls.c b/src/net/tls.c index a9d6275..5e22221 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -962,50 +962,65 @@ 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 ); + void *end = ( data + len ); int rc; - /* Sanity check */ - if ( end != ( data + len ) ) { - DBGC ( tls, "TLS %p received overlength Handshake\n", tls ); - DBGC_HD ( tls, data, len ); - return -EINVAL; - } + while ( data != end ) { + 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 *next = ( payload + payload_len ); + + /* Sanity check */ + if ( next > end ) { + DBGC ( tls, "TLS %p received overlength Handshake\n", + tls ); + DBGC_HD ( tls, data, len ); + return -EINVAL; + } - 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; - } + 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, len ); + /* 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 ); - return rc; + /* Abort on failure */ + if ( rc != 0 ) + return rc; + + /* Move to next handshake record */ + data = next; + } + + return 0; } /** |