Implement write_partial with dummy exts
Signed-off-by: Jerry Yu <jerry.h.yu@arm.com>
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 5f15b8d..dfb5634 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -1385,6 +1385,9 @@
unsigned hs_type,
size_t total_hs_len );
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+int mbedtls_ssl_write_signature_algorithms_ext(mbedtls_ssl_context* ssl, unsigned char* buf, unsigned char* end, size_t* olen);
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index b06147c..fbc8fd5 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -25,6 +25,8 @@
#if defined(MBEDTLS_SSL_CLI_C)
+#include <string.h>
+
#include "ssl_misc.h"
#include <mbedtls/debug.h>
@@ -137,20 +139,305 @@
return( 0 );
}
+/* Write extensions */
+
+static void ssl_write_supported_versions_ext( mbedtls_ssl_context *ssl,
+ unsigned char* buf,
+ unsigned char* end,
+ size_t* olen );
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+
+static int ssl_write_supported_groups_ext( mbedtls_ssl_context *ssl,
+ unsigned char* buf,
+ unsigned char* end,
+ size_t* olen );
+
+static int ssl_write_key_shares_ext( mbedtls_ssl_context *ssl,
+ unsigned char* buf,
+ unsigned char* end,
+ size_t* olen );
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
static int ssl_client_hello_write_partial( mbedtls_ssl_context* ssl,
unsigned char* buf, size_t buflen,
size_t* len_without_binders,
size_t* len_with_binders )
{
+ /* Extensions */
+
+ /* extension_start
+ * Used during extension writing where the
+ * buffer pointer to the beginning of the
+ * extension list must be kept to write
+ * the total extension list size in the end.
+ */
+
+ int ret;
+ unsigned char* extension_start;
+ size_t cur_ext_len; /* Size of the current extension */
+ size_t total_ext_len; /* Size of list of extensions */
+
+ /* Length information */
+ size_t rand_bytes_len;
+ size_t version_len;
+
+ /* Buffer management */
+ unsigned char* start = buf;
+ unsigned char* end = buf + buflen;
+
+ /* Ciphersuite-related variables */
+ const int* ciphersuites;
+ const mbedtls_ssl_ciphersuite_t* ciphersuite_info;
+ size_t i; /* used to iterate through ciphersuite list */
+ /* ciphersuite_start points to the start of the ciphersuite list, i.e. to the length field*/
+ unsigned char* ciphersuite_start;
+ size_t ciphersuite_count;
+
+ /* Keeping track of the included extensions */
+ ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
+
+ rand_bytes_len = 32;
+
+ /* NOTE:
+ * Even for DTLS 1.3, we are writing a TLS handshake header here.
+ * The actual DTLS 1.3 handshake header is inserted in
+ * the record writing routine mbedtls_ssl_write_record().
+ *
+ * For cTLS the length, and the version field
+ * are elided. The random bytes are shorter.
+ */
+ version_len = 2;
+
+ if( ssl->conf->max_major_ver == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, "
+ "consider using mbedtls_ssl_config_defaults()" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ ssl->major_ver = ssl->conf->min_major_ver;
+ ssl->minor_ver = ssl->conf->min_minor_ver;
+
+ /* For TLS 1.3 we use the legacy version number {0x03, 0x03}
+ * instead of the true version number.
+ *
+ * For DTLS 1.3 we use the legacy version number
+ * {254,253}.
+ *
+ * In cTLS the version number is elided.
+ */
+ *buf++ = 0x03;
+ *buf++ = 0x03;
+ buflen -= version_len;
+
+ /* Write random bytes */
+ memcpy( buf, ssl->handshake->randbytes, rand_bytes_len );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf, rand_bytes_len );
+
+ buf += rand_bytes_len;
+ buflen -= rand_bytes_len;
+
+ /* Versions of TLS before TLS 1.3 supported a
+ * "session resumption" feature which has been merged with pre-shared
+ * keys in this version. A client which has a
+ * cached session ID set by a pre-TLS 1.3 server SHOULD set this
+ * field to that value. In compatibility mode,
+ * this field MUST be non-empty, so a client not offering a
+ * pre-TLS 1.3 session MUST generate a new 32-byte value. This value
+ * need not be random but SHOULD be unpredictable to avoid
+ * implementations fixating on a specific value ( also known as
+ * ossification ). Otherwise, it MUST be set as a zero-length vector
+ * ( i.e., a zero-valued single byte length field ).
+ */
+ if( buflen < 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small to hold ClientHello" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ *buf++ = 0; /* session id length set to zero */
+ buflen -= 1;
+
+ /*
+ * Ciphersuite list
+ *
+ * This is a list of the symmetric cipher options supported by
+ * the client, specifically the record protection algorithm
+ * ( including secret key length ) and a hash to be used with
+ * HKDF, in descending order of client preference.
+ */
+ ciphersuites = ssl->conf->ciphersuite_list;
+
+ if( buflen < 2 /* for ciphersuite list length */ )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small to hold ClientHello" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ /* Skip writing ciphersuite length for now */
+ ciphersuite_count = 0;
+ ciphersuite_start = buf;
+ buf += 2;
+ buflen -= 2;
+
+ for ( i = 0; ciphersuites[i] != 0; i++ )
+ {
+ ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] );
+
+ if( ciphersuite_info == NULL )
+ continue;
+
+ if( ciphersuite_info->min_minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 ||
+ ciphersuite_info->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_4 )
+ continue;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x, %s",
+ (unsigned int) ciphersuites[i], ciphersuite_info->name ) );
+
+ ciphersuite_count++;
+
+ if( buflen < 2 /* for ciphersuite list length */ )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small to hold ClientHello" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ *buf++ = (unsigned char)( ciphersuites[i] >> 8 );
+ *buf++ = (unsigned char)( ciphersuites[i] );
+
+ buflen -= 2;
+
+ }
+
+ /* write ciphersuite length now */
+ *ciphersuite_start++ = (unsigned char)( ciphersuite_count*2 >> 8 );
+ *ciphersuite_start++ = (unsigned char)( ciphersuite_count*2 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %" MBEDTLS_PRINTF_SIZET " ciphersuites", ciphersuite_count ) );
+
+ /* For every TLS 1.3 ClientHello, this vector MUST contain exactly
+ * one byte set to zero, which corresponds to the 'null' compression
+ * method in prior versions of TLS.
+ *
+ * For cTLS this field is elided.
+ */
+ if( buflen < 2 /* for ciphersuite list length */ )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small to hold ClientHello" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ *buf++ = 1;
+ *buf++ = MBEDTLS_SSL_COMPRESS_NULL;
+
+ buflen -= 2;
+
+ /* First write extensions, then the total length */
+ extension_start = buf;
+ total_ext_len = 0;
+ buf += 2;
+
+ /* Supported Versions Extension is mandatory with TLS 1.3.
+ *
+ * For cTLS we only need to provide it if there is more than one version
+ * and currently there is only one.
+ */
+ ssl_write_supported_versions_ext( ssl, buf, end, &cur_ext_len );
+ total_ext_len += cur_ext_len;
+ buf += cur_ext_len;
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+ /* The supported_groups and the key_share extensions are
+ * REQUIRED for ECDHE ciphersuites.
+ */
+ ret = ssl_write_supported_groups_ext( ssl, buf, end, &cur_ext_len );
+ if( ret != 0 )
+ return( ret );
+
+ total_ext_len += cur_ext_len;
+ buf += cur_ext_len;
+
+ /* The supported_signature_algorithms extension is REQUIRED for
+ * certificate authenticated ciphersuites. */
+ ret = mbedtls_ssl_write_signature_algorithms_ext( ssl, buf, end, &cur_ext_len );
+ if( ret != 0 )
+ return( ret );
+
+ total_ext_len += cur_ext_len;
+ buf += cur_ext_len;
+
+ /* We need to send the key shares under three conditions:
+ * 1 ) A certificate-based ciphersuite is being offered. In this case
+ * supported_groups and supported_signature extensions have been successfully added.
+ * 2 ) A PSK-based ciphersuite with ECDHE is offered. In this case the
+ * psk_key_exchange_modes has been added as the last extension.
+ * 3 ) Or, in case all ciphers are supported ( which includes #1 and #2 from above )
+ */
+
+ ret = ssl_write_key_shares_ext( ssl, buf, end, &cur_ext_len );
+ if( ret != 0 )
+ return( ret );
+
+ total_ext_len += cur_ext_len;
+ buf += cur_ext_len;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+ /* Add more extensions here */
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET ,
+ total_ext_len ) );
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", extension_start, total_ext_len );
+
+ /* Write extension length */
+ *extension_start++ = (unsigned char)( ( total_ext_len >> 8 ) & 0xFF );
+ *extension_start++ = (unsigned char)( ( total_ext_len ) & 0xFF );
+
+ *len_without_binders = buf - start;
+ *len_with_binders = ( extension_start + total_ext_len ) - start;
+ return( 0 );
+}
+
+static void ssl_write_supported_versions_ext( mbedtls_ssl_context *ssl,
+ unsigned char* buf,
+ unsigned char* end,
+ size_t* olen )
+{
((void) ssl);
((void) buf);
- ((void) buflen);
- ((void) len_without_binders);
- ((void) len_with_binders);
+ ((void) end);
+ ((void) olen);
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+
+static int ssl_write_supported_groups_ext( mbedtls_ssl_context *ssl,
+ unsigned char* buf,
+ unsigned char* end,
+ size_t* olen )
+{
+ ((void) ssl);
+ ((void) buf);
+ ((void) end);
+ ((void) olen);
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
+static int ssl_write_key_shares_ext( mbedtls_ssl_context *ssl,
+ unsigned char* buf,
+ unsigned char* end,
+ size_t* olen )
+{
+ ((void) ssl);
+ ((void) buf);
+ ((void) end);
+ ((void) olen);
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
#endif /* MBEDTLS_SSL_CLI_C */
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 5aa5d8a..7ec7423 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -70,6 +70,40 @@
ssl->handshake->update_checksum( ssl, hs_hdr, sizeof( hs_hdr ) );
}
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+
+/*
+ * mbedtls_ssl_write_signature_algorithms_ext( )
+ *
+ * enum {
+ * ....
+ * ecdsa_secp256r1_sha256( 0x0403 ),
+ * ecdsa_secp384r1_sha384( 0x0503 ),
+ * ecdsa_secp521r1_sha512( 0x0603 ),
+ * ....
+ * } SignatureScheme;
+ *
+ * struct {
+ * SignatureScheme supported_signature_algorithms<2..2^16-2>;
+ * } SignatureSchemeList;
+ *
+ * Only if we handle at least one key exchange that needs signatures.
+ */
+
+int mbedtls_ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
+ unsigned char* buf,
+ unsigned char* end,
+ size_t* olen )
+{
+ ((void) ssl);
+ ((void) buf);
+ ((void) end);
+ ((void) olen);
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
#endif /* MBEDTLS_SSL_TLS_C */