diff options
author | Michael Brown <mcb30@ipxe.org> | 2023-03-30 16:28:40 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2023-03-30 23:38:43 +0100 |
commit | 1d1cf74a5e58811822bee4b3da3cff7282fcdfca (patch) | |
tree | 6b975a1a33bb9a89d8519f6f17eac2c2e2e697ae /src | |
parent | aa368ba529e13f07658e16507eb8686ef1c07423 (diff) | |
download | ipxe-1d1cf74a5e58811822bee4b3da3cff7282fcdfca.zip ipxe-1d1cf74a5e58811822bee4b3da3cff7282fcdfca.tar.gz ipxe-1d1cf74a5e58811822bee4b3da3cff7282fcdfca.tar.bz2 |
[tls] Handle fragmented handshake recordstlsfrag3
Originally-implemented-by: Christopher Schenk <christopher@cschenk.net>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/ipxe/tls.h | 2 | ||||
-rw-r--r-- | src/net/tls.c | 42 |
2 files changed, 26 insertions, 18 deletions
diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 99c7be0..30bb1c4 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -398,6 +398,8 @@ struct tls_connection { struct io_buffer rx_header_iobuf; /** List of received data buffers */ struct list_head rx_data; + /** Received handshake fragment */ + struct io_buffer *rx_handshake; }; /** RX I/O buffer size diff --git a/src/net/tls.c b/src/net/tls.c index 272ced2..000a8a7 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -388,6 +388,7 @@ static void free_tls ( struct refcnt *refcnt ) { list_del ( &iobuf->list ); free_iob ( iobuf ); } + free_iob ( tls->rx_handshake ); x509_chain_put ( tls->certs ); x509_chain_put ( tls->chain ); x509_root_put ( tls->root ); @@ -2426,17 +2427,13 @@ static int tls_new_handshake ( struct tls_connection *tls, /* Parse header */ if ( sizeof ( *handshake ) > remaining ) { - DBGC ( tls, "TLS %p received underlength Handshake\n", - tls ); - DBGC_HD ( tls, handshake, remaining ); - return -EINVAL_HANDSHAKE; + /* Leave remaining fragment unconsumed */ + break; } payload_len = tls_uint24 ( &handshake->length ); if ( payload_len > ( remaining - sizeof ( *handshake ) ) ) { - DBGC ( tls, "TLS %p received overlength Handshake\n", - tls ); - DBGC_HD ( tls, handshake, remaining ); - return -EINVAL_HANDSHAKE; + /* Leave remaining fragment unconsumed */ + break; } payload = &handshake->payload; record_len = ( sizeof ( *handshake ) + payload_len ); @@ -2554,14 +2551,16 @@ static int tls_new_record ( struct tls_connection *tls, unsigned int type, struct list_head *rx_data ) { int ( * handler ) ( struct tls_connection *tls, struct io_buffer *iobuf ); - struct io_buffer *iobuf; + struct io_buffer *tmp = NULL; + struct io_buffer **iobuf; int rc; /* Deliver data records as-is to the plainstream interface */ if ( type == TLS_TYPE_DATA ) return tls_new_data ( tls, rx_data ); - /* Determine handler */ + /* Determine handler and fragment buffer */ + iobuf = &tmp; switch ( type ) { case TLS_TYPE_CHANGE_CIPHER: handler = tls_new_change_cipher; @@ -2571,6 +2570,7 @@ static int tls_new_record ( struct tls_connection *tls, unsigned int type, break; case TLS_TYPE_HANDSHAKE: handler = tls_new_handshake; + iobuf = &tls->rx_handshake; break; default: DBGC ( tls, "TLS %p unknown record type %d\n", tls, type ); @@ -2579,8 +2579,10 @@ static int tls_new_record ( struct tls_connection *tls, unsigned int type, } /* Merge into a single I/O buffer */ - iobuf = iob_concatenate ( rx_data ); - if ( ! iobuf ) { + if ( *iobuf ) + list_add ( &(*iobuf)->list, rx_data ); + *iobuf = iob_concatenate ( rx_data ); + if ( ! *iobuf ) { DBGC ( tls, "TLS %p could not concatenate non-data record " "type %d\n", tls, type ); rc = -ENOMEM_RX_CONCAT; @@ -2588,19 +2590,23 @@ static int tls_new_record ( struct tls_connection *tls, unsigned int type, } /* Handle record */ - if ( ( rc = handler ( tls, iobuf ) ) != 0 ) + if ( ( rc = handler ( tls, *iobuf ) ) != 0 ) goto err_handle; - /* Sanity check */ - assert ( iob_len ( iobuf ) == 0 ); + /* Discard I/O buffer if empty */ + if ( ! iob_len ( *iobuf ) ) { + free_iob ( *iobuf ); + *iobuf = NULL; + } - /* Free I/O buffer */ - free_iob ( iobuf ); + /* Sanity check */ + assert ( tmp == NULL ); return 0; err_handle: - free_iob ( iobuf ); + free_iob ( *iobuf ); + *iobuf = NULL; err_concatenate: return rc; } |