From 48f3a3d101db13cc63333c0d7aa6e62909ae9c1e Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 29 Aug 2019 06:31:22 +0100 Subject: [PATCH 1/2] Add NSS keylog support to ssl_server2 and ssl_client2 This commit adds command line options - nss_keylog=0/1 - nss_keylog_file=FILENAME to the example programs ssl/ssl_client2 and ssl/ssl_server2 which allow to print and export the session keys in the NSS keylog for debugging purposes. --- programs/ssl/ssl_client2.c | 105 ++++++++++++++++++++++++++++++++++++ programs/ssl/ssl_server2.c | 108 +++++++++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 61b88d10f..c29768a65 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -135,6 +135,8 @@ int main( void ) #define DFL_CA_CALLBACK 0 #define DFL_EAP_TLS 0 #define DFL_REPRODUCIBLE 0 +#define DFL_NSS_KEYLOG 0 +#define DFL_NSS_KEYLOG_FILE NULL #define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: " #define GET_REQUEST_END "\r\n\r\n" @@ -231,8 +233,14 @@ int main( void ) #if defined(MBEDTLS_SSL_EXPORT_KEYS) #define USAGE_EAP_TLS \ " eap_tls=%%d default: 0 (disabled)\n" +#define USAGE_NSS_KEYLOG \ + " nss_keylog=%%d default: 0 (disabled)\n" +#define USAGE_NSS_KEYLOG_FILE \ + " nss_keylog_file=%%s\n" #else #define USAGE_EAP_TLS "" +#define USAGE_NSS_KEYLOG "" +#define USAGE_NSS_KEYLOG_FILE "" #endif /* MBEDTLS_SSL_EXPORT_KEYS */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) @@ -489,6 +497,8 @@ struct options int etm; /* negotiate encrypt then mac? */ int context_crt_cb; /* use context-specific CRT verify callback */ int eap_tls; /* derive EAP-TLS keying material? */ + int nss_keylog; /* export NSS key log material */ + const char *nss_keylog_file; /* NSS key log file */ int cid_enabled; /* whether to use the CID extension or not */ int cid_enabled_renego; /* whether to use the CID extension or not * during renegotiation */ @@ -535,6 +545,81 @@ static int eap_tls_key_derivation ( void *p_expkey, } return( 0 ); } + +static int nss_keylog_export( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen, + unsigned char client_random[32], + unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type ) +{ + char nss_keylog_line[ 200 ]; + size_t const client_random_len = 32; + size_t const master_secret_len = 48; + size_t len = 0; + size_t j; + int ret = 0; + + ((void) p_expkey); + ((void) kb); + ((void) maclen); + ((void) keylen); + ((void) ivlen); + ((void) server_random); + ((void) tls_prf_type); + + len += sprintf( nss_keylog_line + len, + "%s", "CLIENT_RANDOM " ); + + for( j = 0; j < client_random_len; j++ ) + { + len += sprintf( nss_keylog_line + len, + "%02x", client_random[j] ); + } + + len += sprintf( nss_keylog_line + len, " " ); + + for( j = 0; j < master_secret_len; j++ ) + { + len += sprintf( nss_keylog_line + len, + "%02x", ms[j] ); + } + + len += sprintf( nss_keylog_line + len, "\n" ); + nss_keylog_line[ len ] = '\0'; + + mbedtls_printf( "\n" ); + mbedtls_printf( "---------------- NSS KEYLOG -----------------\n" ); + mbedtls_printf( "%s", nss_keylog_line ); + mbedtls_printf( "---------------------------------------------\n" ); + + if( opt.nss_keylog_file != NULL ) + { + FILE *f; + + if( ( f = fopen( opt.nss_keylog_file, "a" ) ) == NULL ) + { + ret = -1; + goto exit; + } + + if( fwrite( nss_keylog_line, 1, len, f ) != len ) + { + ret = -1; + goto exit; + } + + fclose( f ); + } + +exit: + mbedtls_platform_zeroize( nss_keylog_line, + sizeof( nss_keylog_line ) ); + return( ret ); +} #endif static void my_debug( void *ctx, int level, @@ -1204,6 +1289,8 @@ int main( int argc, char *argv[] ) opt.serialize = DFL_SERIALIZE; opt.eap_tls = DFL_EAP_TLS; opt.reproducible = DFL_REPRODUCIBLE; + opt.nss_keylog = DFL_NSS_KEYLOG; + opt.nss_keylog_file = DFL_NSS_KEYLOG_FILE; for( i = 1; i < argc; i++ ) { @@ -1606,6 +1693,16 @@ int main( int argc, char *argv[] ) { opt.reproducible = 1; } + else if( strcmp( p, "nss_keylog" ) == 0 ) + { + opt.nss_keylog = atoi( q ); + if( opt.nss_keylog < 0 || opt.nss_keylog > 1 ) + goto usage; + } + else if( strcmp( p, "nss_keylog_file" ) == 0 ) + { + opt.nss_keylog_file = q; + } else goto usage; } @@ -2145,8 +2242,16 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_SSL_EXPORT_KEYS) if( opt.eap_tls != 0 ) + { mbedtls_ssl_conf_export_keys_ext_cb( &conf, eap_tls_key_derivation, &eap_tls_keying ); + } + else if( opt.nss_keylog != 0 ) + { + mbedtls_ssl_conf_export_keys_ext_cb( &conf, + nss_keylog_export, + NULL ); + } #endif #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 102951b28..f77026297 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -176,6 +176,8 @@ int main( void ) #define DFL_CA_CALLBACK 0 #define DFL_EAP_TLS 0 #define DFL_REPRODUCIBLE 0 +#define DFL_NSS_KEYLOG 0 +#define DFL_NSS_KEYLOG_FILE NULL #define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ @@ -308,8 +310,14 @@ int main( void ) #if defined(MBEDTLS_SSL_EXPORT_KEYS) #define USAGE_EAP_TLS \ " eap_tls=%%d default: 0 (disabled)\n" +#define USAGE_NSS_KEYLOG \ + " nss_keylog=%%d default: 0 (disabled)\n" +#define USAGE_NSS_KEYLOG_FILE \ + " nss_keylog_file=%%s\n" #else #define USAGE_EAP_TLS "" +#define USAGE_NSS_KEYLOG "" +#define USAGE_NSS_KEYLOG_FILE "" #endif /* MBEDTLS_SSL_EXPORT_KEYS */ #if defined(MBEDTLS_SSL_CACHE_C) @@ -487,6 +495,8 @@ int main( void ) USAGE_TICKETS \ USAGE_EAP_TLS \ USAGE_REPRODUCIBLE \ + USAGE_NSS_KEYLOG \ + USAGE_NSS_KEYLOG_FILE \ USAGE_CACHE \ USAGE_MAX_FRAG_LEN \ USAGE_TRUNC_HMAC \ @@ -598,6 +608,8 @@ struct options int dgram_packing; /* allow/forbid datagram packing */ int badmac_limit; /* Limit of records with bad MAC */ int eap_tls; /* derive EAP-TLS keying material? */ + int nss_keylog; /* export NSS key log material */ + const char *nss_keylog_file; /* NSS key log file */ int cid_enabled; /* whether to use the CID extension or not */ int cid_enabled_renego; /* whether to use the CID extension or not * during renegotiation */ @@ -644,6 +656,82 @@ static int eap_tls_key_derivation ( void *p_expkey, } return( 0 ); } + +static int nss_keylog_export( void *p_expkey, + const unsigned char *ms, + const unsigned char *kb, + size_t maclen, + size_t keylen, + size_t ivlen, + unsigned char client_random[32], + unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type ) +{ + char nss_keylog_line[ 200 ]; + size_t const client_random_len = 32; + size_t const master_secret_len = 48; + size_t len = 0; + size_t j; + int ret = 0; + + ((void) p_expkey); + ((void) kb); + ((void) maclen); + ((void) keylen); + ((void) ivlen); + ((void) server_random); + ((void) tls_prf_type); + + len += sprintf( nss_keylog_line + len, + "%s", "CLIENT_RANDOM " ); + + for( j = 0; j < client_random_len; j++ ) + { + len += sprintf( nss_keylog_line + len, + "%02x", client_random[j] ); + } + + len += sprintf( nss_keylog_line + len, " " ); + + for( j = 0; j < master_secret_len; j++ ) + { + len += sprintf( nss_keylog_line + len, + "%02x", ms[j] ); + } + + len += sprintf( nss_keylog_line + len, "\n" ); + nss_keylog_line[ len ] = '\0'; + + mbedtls_printf( "\n" ); + mbedtls_printf( "---------------- NSS KEYLOG -----------------\n" ); + mbedtls_printf( "%s", nss_keylog_line ); + mbedtls_printf( "---------------------------------------------\n" ); + + if( opt.nss_keylog_file != NULL ) + { + FILE *f; + + if( ( f = fopen( opt.nss_keylog_file, "a" ) ) == NULL ) + { + ret = -1; + goto exit; + } + + if( fwrite( nss_keylog_line, 1, len, f ) != len ) + { + ret = -1; + goto exit; + } + + fclose( f ); + } + +exit: + mbedtls_platform_zeroize( nss_keylog_line, + sizeof( nss_keylog_line ) ); + return( ret ); +} + #endif static void my_debug( void *ctx, int level, @@ -1892,6 +1980,8 @@ int main( int argc, char *argv[] ) opt.serialize = DFL_SERIALIZE; opt.eap_tls = DFL_EAP_TLS; opt.reproducible = DFL_REPRODUCIBLE; + opt.nss_keylog = DFL_NSS_KEYLOG; + opt.nss_keylog_file = DFL_NSS_KEYLOG_FILE; for( i = 1; i < argc; i++ ) { @@ -2320,6 +2410,16 @@ int main( int argc, char *argv[] ) { opt.reproducible = 1; } + else if( strcmp( p, "nss_keylog" ) == 0 ) + { + opt.nss_keylog = atoi( q ); + if( opt.nss_keylog < 0 || opt.nss_keylog > 1 ) + goto usage; + } + else if( strcmp( p, "nss_keylog_file" ) == 0 ) + { + opt.nss_keylog_file = q; + } else goto usage; } @@ -2960,8 +3060,16 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_SSL_EXPORT_KEYS) if( opt.eap_tls != 0 ) + { mbedtls_ssl_conf_export_keys_ext_cb( &conf, eap_tls_key_derivation, &eap_tls_keying ); + } + else if( opt.nss_keylog != 0 ) + { + mbedtls_ssl_conf_export_keys_ext_cb( &conf, + nss_keylog_export, + NULL ); + } #endif #if defined(MBEDTLS_SSL_ALPN) From bc5308cb9a54fe0ed74aebbc023e32e9a16234bb Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 9 Sep 2019 11:38:51 +0100 Subject: [PATCH 2/2] ssl_cli/srv2: Indicate nss_keylog and eap_tls are mut. exclusive --- programs/ssl/ssl_client2.c | 9 ++++++++- programs/ssl/ssl_server2.c | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index c29768a65..5e9ad3df8 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -234,7 +234,8 @@ int main( void ) #define USAGE_EAP_TLS \ " eap_tls=%%d default: 0 (disabled)\n" #define USAGE_NSS_KEYLOG \ - " nss_keylog=%%d default: 0 (disabled)\n" + " nss_keylog=%%d default: 0 (disabled)\n" \ + " This cannot be used with eap_tls=1\n" #define USAGE_NSS_KEYLOG_FILE \ " nss_keylog_file=%%s\n" #else @@ -1707,6 +1708,12 @@ int main( int argc, char *argv[] ) goto usage; } + if( opt.nss_keylog != 0 && opt.eap_tls != 0 ) + { + mbedtls_printf( "Error: eap_tls and nss_keylog options cannot be used together.\n" ); + goto usage; + } + /* Event-driven IO is incompatible with the above custom * receive and send functions, as the polling builds on * refers to the underlying net_context. */ diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index f77026297..3683f3cf6 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -311,7 +311,8 @@ int main( void ) #define USAGE_EAP_TLS \ " eap_tls=%%d default: 0 (disabled)\n" #define USAGE_NSS_KEYLOG \ - " nss_keylog=%%d default: 0 (disabled)\n" + " nss_keylog=%%d default: 0 (disabled)\n" \ + " This cannot be used with eap_tls=1\n" #define USAGE_NSS_KEYLOG_FILE \ " nss_keylog_file=%%s\n" #else @@ -2424,6 +2425,12 @@ int main( int argc, char *argv[] ) goto usage; } + if( opt.nss_keylog != 0 && opt.eap_tls != 0 ) + { + mbedtls_printf( "Error: eap_tls and nss_keylog options cannot be used together.\n" ); + goto usage; + } + /* Event-driven IO is incompatible with the above custom * receive and send functions, as the polling builds on * refers to the underlying net_context. */