summaryrefslogtreecommitdiffstats
path: root/src/net/tls.c
diff options
context:
space:
mode:
authorMichael Brown2010-06-23 02:01:32 +0200
committerMichael Brown2010-06-23 02:01:32 +0200
commit21682afe6905ddc566159471bdb1a51e376e2af1 (patch)
tree2259721ddf3f895b87e16248a1ccd7dec6839292 /src/net/tls.c
parent[refcnt] Add ref_no_free handler (diff)
downloadipxe-21682afe6905ddc566159471bdb1a51e376e2af1.tar.gz
ipxe-21682afe6905ddc566159471bdb1a51e376e2af1.tar.xz
ipxe-21682afe6905ddc566159471bdb1a51e376e2af1.zip
[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.c93
1 files changed, 54 insertions, 39 deletions
diff --git a/src/net/tls.c b/src/net/tls.c
index a9d62758..5e22221d 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;
}
/**