From 951b8868011366c8717e7136ba38cabf9d06cc72 Mon Sep 17 00:00:00 2001 From: Max Fillinger Date: Fri, 25 Oct 2024 00:52:24 +0200 Subject: [PATCH] Create MBEDTLS_SSL_KEYING_MATERIAL_EXPORT option Add the option MBEDTLS_SSL_KEYING_MATERIAL_EXPORT to mbedtls_config.h to control if the function mbedtls_ssl_export_keying_material() should be available. By default, the option is disabled. This is because the exporter for TLS 1.2 requires client_random and server_random need to be stored after the handshake is complete. Signed-off-by: Max Fillinger --- include/mbedtls/mbedtls_config.h | 15 +++++++++++++++ include/mbedtls/ssl.h | 10 +++++++++- library/ssl_misc.h | 7 ++++--- library/ssl_tls.c | 7 +++---- programs/ssl/ssl_client2.c | 21 ++++++++++++++------- programs/ssl/ssl_server2.c | 15 +++++++++++---- 6 files changed, 56 insertions(+), 19 deletions(-) diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 45feb5eccb..76be29743c 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -1763,6 +1763,21 @@ */ #define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE +/** +/* + * \def MBEDTLS_SSL_KEYING_MATERIAL_EXPORT + * + * When this option is enabled, the client and server can extract additional + * shared symmetric keys after an SSL handshake using the function + * mbedtls_ssl_export_keying_material(). + * + * The process for deriving the keys is specified in RFC 5705 for TLS 1.2 and + * in RFC 8446, Section 7.5, for TLS 1.3. + * + * Uncomment this macro to enable mbedtls_ssl_export_keying_material(). + */ +//#define MBEDTLS_SSL_KEYING_MATERIAL_EXPORT + /** * \def MBEDTLS_SSL_RENEGOTIATION * diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 3da4ecaf61..ae5eb8de9a 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -729,6 +729,14 @@ union mbedtls_ssl_premaster_secret { /* Length in number of bytes of the TLS sequence number */ #define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8 +/* Helper to state that client_random and server_random need to be stored + * after the handshake is complete. This is required for context serialization + * and for the keying material exporter in TLS 1.2. */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || \ + (defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) && defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#define MBEDTLS_SSL_KEEP_RANDBYTES +#endif + #ifdef __cplusplus extern "C" { #endif @@ -5786,7 +5794,7 @@ int mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf, * * \return 0 on success. An SSL specific error on failure. */ - #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) int mbedtls_ssl_export_keying_material(mbedtls_ssl_context *ssl, uint8_t *out, const size_t key_len, const char *label, const size_t label_len, diff --git a/library/ssl_misc.h b/library/ssl_misc.h index 29254958fc..0fe2800949 100644 --- a/library/ssl_misc.h +++ b/library/ssl_misc.h @@ -1166,10 +1166,11 @@ struct mbedtls_ssl_transform { unsigned char out_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX]; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +#if defined(MBEDTLS_SSL_KEEP_RANDBYTES) /* We need the Hello random bytes in order to re-derive keys from the - * Master Secret and other session info, - * see ssl_tls12_populate_transform() */ + * Master Secret and other session info and for the keying material + * exporter in TLS 1.2. + * See ssl_tls12_populate_transform() */ unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN + MBEDTLS_CLIENT_HELLO_RANDOM_LEN]; /*!< ServerHello.random+ClientHello.random */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 971821ae1b..d631420ad1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -8669,7 +8669,7 @@ static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform, #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */ transform->tls_version = tls_version; -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +#if defined(MBEDTLS_SSL_KEEP_RANDBYTES) memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes)); #endif @@ -10054,8 +10054,7 @@ int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ - -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) static int mbedtls_ssl_tls12_export_keying_material(const mbedtls_ssl_context *ssl, @@ -10176,6 +10175,6 @@ int mbedtls_ssl_export_keying_material(mbedtls_ssl_context *ssl, } } -#endif /* defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) || !defined(MBEDTLS_SSL_PROTO_TLS1_2) */ +#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */ #endif /* MBEDTLS_SSL_TLS_C */ diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 8f7ae0419d..228e7f8761 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -347,11 +347,7 @@ int main(void) " in the form of base64 code (serialize option\n" \ " must be set)\n" \ " default: \"\" (do nothing)\n" \ - " option: a file path\n" \ - " exp_label=%%s Label to input into TLS-Exporter\n" \ - " default: None (don't try to export a key)\n" \ - " exp_len=%%d Length of key to extract from TLS-Exporter \n" \ - " default: 20\n" + " option: a file path\n" #else #define USAGE_SERIALIZATION "" #endif @@ -381,6 +377,16 @@ int main(void) #define USAGE_TLS1_3_KEY_EXCHANGE_MODES "" #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) +#define USAGE_EXPORT \ + " exp_label=%%s Label to input into TLS-Exporter\n" \ + " default: None (don't try to export a key)\n" \ + " exp_len=%%d Length of key to extract from TLS-Exporter \n" \ + " default: 20\n" +#else +#define USAGE_EXPORT "" +#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */ + /* USAGE is arbitrarily split to stay under the portable string literal * length limit: 4095 bytes in C99. */ #define USAGE1 \ @@ -471,6 +477,7 @@ int main(void) " otherwise. The expansion of the macro\n" \ " is printed if it is defined\n" \ USAGE_SERIALIZATION \ + USAGE_EXPORT \ "\n" /* @@ -2574,7 +2581,7 @@ usage: } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) if (opt.exp_label != NULL && opt.exp_len > 0) { unsigned char *exported_key = calloc((size_t) opt.exp_len, sizeof(unsigned int)); if (exported_key == NULL) { @@ -2597,7 +2604,7 @@ usage: mbedtls_printf("\n\n"); fflush(stdout); } -#endif /* defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) */ +#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */ /* * 6. Write the GET request diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 538d0d08e8..2b81fc18ef 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -473,13 +473,19 @@ int main(void) " in the form of base64 code (serialize option\n" \ " must be set)\n" \ " default: \"\" (do nothing)\n" \ - " option: a file path\n" \ + " option: a file path\n" +#else +#define USAGE_SERIALIZATION "" +#endif + +#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) +#define USAGE_EXPORT \ " exp_label=%%s Label to input into TLS-Exporter\n" \ " default: None (don't try to export a key)\n" \ " exp_len=%%d Length of key to extract from TLS-Exporter \n" \ " default: 20\n" #else -#define USAGE_SERIALIZATION "" +#define USAGE_EXPORT "" #endif #define USAGE_KEY_OPAQUE_ALGS \ @@ -589,6 +595,7 @@ int main(void) " otherwise. The expansion of the macro\n" \ " is printed if it is defined\n" \ USAGE_SERIALIZATION \ + USAGE_EXPORT \ "\n" #define PUT_UINT64_BE(out_be, in_le, i) \ @@ -3656,7 +3663,7 @@ handshake: mbedtls_printf("\n"); } -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +#if defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) if (opt.exp_label != NULL && opt.exp_len > 0) { unsigned char *exported_key = calloc((size_t) opt.exp_len, sizeof(unsigned int)); if (exported_key == NULL) { @@ -3679,7 +3686,7 @@ handshake: mbedtls_printf("\n\n"); fflush(stdout); } -#endif /* defined(MBEDTLS_SSL_CONTEXT_SERIALZIATION) */ +#endif /* defined(MBEDTLS_SSL_KEYING_MATERIAL_EXPORT) */ #if defined(MBEDTLS_SSL_DTLS_SRTP) else if (opt.use_srtp != 0) {