[tls] Restructure construction of ClientHello message

Define an individual local structure for each extension and a single
structure for the list of extensions.  This makes it viable to add
extensions such as the Supported Elliptic Curves extension, which must
not be present if the list of curves is empty.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2024-01-30 13:38:15 +00:00
parent 17135c83fb
commit 6f70e8be83

View File

@@ -1121,6 +1121,57 @@ static int tls_client_hello ( struct tls_connection *tls,
size_t len ) ) { size_t len ) ) {
struct tls_session *session = tls->session; struct tls_session *session = tls->session;
size_t name_len = strlen ( session->name ); size_t name_len = strlen ( session->name );
struct {
uint16_t type;
uint16_t len;
struct {
uint16_t len;
struct {
uint8_t type;
uint16_t len;
uint8_t name[name_len];
} __attribute__ (( packed )) list[1];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *server_name_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint8_t max;
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *max_fragment_length_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint16_t len;
struct tls_signature_hash_id
code[TLS_NUM_SIG_HASH_ALGORITHMS];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *signature_algorithms_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint8_t len;
uint8_t data[ tls->secure_renegotiation ?
sizeof ( tls->verify.client ) :0 ];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *renegotiation_info_ext;
struct {
uint16_t type;
uint16_t len;
struct {
uint8_t data[session->ticket_len];
} __attribute__ (( packed )) data;
} __attribute__ (( packed )) *session_ticket_ext;
struct {
typeof ( *server_name_ext ) server_name;
typeof ( *max_fragment_length_ext ) max_fragment_length;
typeof ( *signature_algorithms_ext ) signature_algorithms;
typeof ( *renegotiation_info_ext ) renegotiation_info;
typeof ( *session_ticket_ext ) session_ticket;
} __attribute__ (( packed )) *extensions;
struct { struct {
uint32_t type_length; uint32_t type_length;
uint16_t version; uint16_t version;
@@ -1132,42 +1183,7 @@ static int tls_client_hello ( struct tls_connection *tls,
uint8_t compression_methods_len; uint8_t compression_methods_len;
uint8_t compression_methods[1]; uint8_t compression_methods[1];
uint16_t extensions_len; uint16_t extensions_len;
struct { typeof ( *extensions ) extensions;
uint16_t server_name_type;
uint16_t server_name_len;
struct {
uint16_t len;
struct {
uint8_t type;
uint16_t len;
uint8_t name[name_len];
} __attribute__ (( packed )) list[1];
} __attribute__ (( packed )) server_name;
uint16_t max_fragment_length_type;
uint16_t max_fragment_length_len;
struct {
uint8_t max;
} __attribute__ (( packed )) max_fragment_length;
uint16_t signature_algorithms_type;
uint16_t signature_algorithms_len;
struct {
uint16_t len;
struct tls_signature_hash_id
code[TLS_NUM_SIG_HASH_ALGORITHMS];
} __attribute__ (( packed )) signature_algorithms;
uint16_t renegotiation_info_type;
uint16_t renegotiation_info_len;
struct {
uint8_t len;
uint8_t data[ tls->secure_renegotiation ?
sizeof ( tls->verify.client ) :0];
} __attribute__ (( packed )) renegotiation_info;
uint16_t session_ticket_type;
uint16_t session_ticket_len;
struct {
uint8_t data[session->ticket_len];
} __attribute__ (( packed )) session_ticket;
} __attribute__ (( packed )) extensions;
} __attribute__ (( packed )) hello; } __attribute__ (( packed )) hello;
struct tls_cipher_suite *suite; struct tls_cipher_suite *suite;
struct tls_signature_hash_algorithm *sighash; struct tls_signature_hash_algorithm *sighash;
@@ -1188,43 +1204,54 @@ static int tls_client_hello ( struct tls_connection *tls,
hello.cipher_suites[i++] = suite->code; hello.cipher_suites[i++] = suite->code;
hello.compression_methods_len = sizeof ( hello.compression_methods ); hello.compression_methods_len = sizeof ( hello.compression_methods );
hello.extensions_len = htons ( sizeof ( hello.extensions ) ); hello.extensions_len = htons ( sizeof ( hello.extensions ) );
hello.extensions.server_name_type = htons ( TLS_SERVER_NAME ); extensions = &hello.extensions;
hello.extensions.server_name_len
= htons ( sizeof ( hello.extensions.server_name ) ); /* Construct server name extension */
hello.extensions.server_name.len server_name_ext = &extensions->server_name;
= htons ( sizeof ( hello.extensions.server_name.list ) ); server_name_ext->type = htons ( TLS_SERVER_NAME );
hello.extensions.server_name.list[0].type = TLS_SERVER_NAME_HOST_NAME; server_name_ext->len = htons ( sizeof ( server_name_ext->data ) );
hello.extensions.server_name.list[0].len server_name_ext->data.len
= htons ( sizeof ( hello.extensions.server_name.list[0].name )); = htons ( sizeof ( server_name_ext->data.list ) );
memcpy ( hello.extensions.server_name.list[0].name, session->name, server_name_ext->data.list[0].type = TLS_SERVER_NAME_HOST_NAME;
sizeof ( hello.extensions.server_name.list[0].name ) ); server_name_ext->data.list[0].len
hello.extensions.max_fragment_length_type = htons ( sizeof ( server_name_ext->data.list[0].name ) );
= htons ( TLS_MAX_FRAGMENT_LENGTH ); memcpy ( server_name_ext->data.list[0].name, session->name,
hello.extensions.max_fragment_length_len sizeof ( server_name_ext->data.list[0].name ) );
= htons ( sizeof ( hello.extensions.max_fragment_length ) );
hello.extensions.max_fragment_length.max /* Construct maximum fragment length extension */
= TLS_MAX_FRAGMENT_LENGTH_4096; max_fragment_length_ext = &extensions->max_fragment_length;
hello.extensions.signature_algorithms_type max_fragment_length_ext->type = htons ( TLS_MAX_FRAGMENT_LENGTH );
= htons ( TLS_SIGNATURE_ALGORITHMS ); max_fragment_length_ext->len
hello.extensions.signature_algorithms_len = htons ( sizeof ( max_fragment_length_ext->data ) );
= htons ( sizeof ( hello.extensions.signature_algorithms ) ); max_fragment_length_ext->data.max = TLS_MAX_FRAGMENT_LENGTH_4096;
hello.extensions.signature_algorithms.len
= htons ( sizeof ( hello.extensions.signature_algorithms.code)); /* Construct supported signature algorithms extension */
signature_algorithms_ext = &extensions->signature_algorithms;
signature_algorithms_ext->type = htons ( TLS_SIGNATURE_ALGORITHMS );
signature_algorithms_ext->len
= htons ( sizeof ( signature_algorithms_ext->data ) );
signature_algorithms_ext->data.len
= htons ( sizeof ( signature_algorithms_ext->data.code ) );
i = 0 ; for_each_table_entry ( sighash, TLS_SIG_HASH_ALGORITHMS ) i = 0 ; for_each_table_entry ( sighash, TLS_SIG_HASH_ALGORITHMS )
hello.extensions.signature_algorithms.code[i++] = sighash->code; signature_algorithms_ext->data.code[i++] = sighash->code;
hello.extensions.renegotiation_info_type
= htons ( TLS_RENEGOTIATION_INFO ); /* Construct renegotiation information extension */
hello.extensions.renegotiation_info_len renegotiation_info_ext = &extensions->renegotiation_info;
= htons ( sizeof ( hello.extensions.renegotiation_info ) ); renegotiation_info_ext->type = htons ( TLS_RENEGOTIATION_INFO );
hello.extensions.renegotiation_info.len renegotiation_info_ext->len
= sizeof ( hello.extensions.renegotiation_info.data ); = htons ( sizeof ( renegotiation_info_ext->data ) );
memcpy ( hello.extensions.renegotiation_info.data, tls->verify.client, renegotiation_info_ext->data.len
sizeof ( hello.extensions.renegotiation_info.data ) ); = sizeof ( renegotiation_info_ext->data.data );
hello.extensions.session_ticket_type = htons ( TLS_SESSION_TICKET ); memcpy ( renegotiation_info_ext->data.data, tls->verify.client,
hello.extensions.session_ticket_len sizeof ( renegotiation_info_ext->data.data ) );
= htons ( sizeof ( hello.extensions.session_ticket ) );
memcpy ( hello.extensions.session_ticket.data, session->ticket, /* Construct session ticket extension */
sizeof ( hello.extensions.session_ticket.data ) ); session_ticket_ext = &extensions->session_ticket;
session_ticket_ext->type = htons ( TLS_SESSION_TICKET );
session_ticket_ext->len
= htons ( sizeof ( session_ticket_ext->data ) );
memcpy ( session_ticket_ext->data.data, session->ticket,
sizeof ( session_ticket_ext->data.data ) );
return action ( tls, &hello, sizeof ( hello ) ); return action ( tls, &hello, sizeof ( hello ) );
} }