From e59ae23868692cfd657a9a3d0a26fc574a576440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 30 Apr 2019 11:41:40 +0200 Subject: [PATCH 001/114] Start splitting populate_transform() out of derive_keys() This is currently a dummy, just introducing the new name. --- library/ssl_tls.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 913d6f9e2..0db1e9d46 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -977,7 +977,13 @@ int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) ); } -int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +/* + * This function will ultimetaly only be responsible for populating a + * transform structure from data passed as explicit parameters. + * + * For now however it's doing rather more in a rather less explicit way. + */ +static int ssl_populate_transform( mbedtls_ssl_context *ssl ) { int ret = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) @@ -1692,6 +1698,11 @@ end: return( ret ); } +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + return( ssl_populate_transform( ssl ) ); +} + #if defined(MBEDTLS_SSL_PROTO_SSL3) void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) { From 1b00c4f5b35202a1baf0d5c10cd227e8fd90bc0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 30 Apr 2019 11:54:22 +0200 Subject: [PATCH 002/114] Start extraction ssl_set_handshake_prfs() For now just moving code around, will improve signature in the next commit. --- library/ssl_tls.c | 110 ++++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 47 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 0db1e9d46..a3c692df7 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1059,53 +1059,6 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - /* - * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - handshake->tls_prf = ssl3_prf; - handshake->calc_verify = ssl_calc_verify_ssl; - handshake->calc_finished = ssl_calc_finished_ssl; - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) - { - handshake->tls_prf = tls1_prf; - handshake->calc_verify = ssl_calc_verify_tls; - handshake->calc_finished = ssl_calc_finished_tls; - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - { - handshake->tls_prf = tls_prf_sha384; - handshake->calc_verify = ssl_calc_verify_tls_sha384; - handshake->calc_finished = ssl_calc_finished_tls_sha384; - } - else -#endif -#if defined(MBEDTLS_SHA256_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - handshake->tls_prf = tls_prf_sha256; - handshake->calc_verify = ssl_calc_verify_tls_sha256; - handshake->calc_finished = ssl_calc_finished_tls_sha256; - } - else -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - /* * SSLv3: * master = @@ -1698,8 +1651,71 @@ end: return( ret ); } +static int ssl_set_handshake_prfs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = handshake->ciphersuite_info; + + /* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + */ +#if defined(MBEDTLS_SSL_PROTO_SSL3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + { + handshake->tls_prf = ssl3_prf; + handshake->calc_verify = ssl_calc_verify_ssl; + handshake->calc_finished = ssl_calc_finished_ssl; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls1_prf; + handshake->calc_verify = ssl_calc_verify_tls; + handshake->calc_finished = ssl_calc_finished_tls; + } + else +#endif +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA512_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( 0 ); +} + + int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) { + int ret; + + ret = ssl_set_handshake_prfs( ssl ); + if( ret != 0 ) + return( ret ); + return( ssl_populate_transform( ssl ) ); } From 8d2805c784a97a2f70bc46344628986e011e9bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 30 Apr 2019 12:08:59 +0200 Subject: [PATCH 003/114] Fix signature of ssl_set_transform_prfs() --- library/ssl_tls.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index a3c692df7..d1b4e7c98 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1651,17 +1651,26 @@ end: return( ret ); } -static int ssl_set_handshake_prfs( mbedtls_ssl_context *ssl ) +/* + * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + * + * Inputs: + * - SSL/TLS minor version + * - hash associated with the ciphersuite (only used by TLS 1.2) + * + * Ouputs: + * - the tls_prf, calc_verify and calc_finished members of handshake structure + */ +static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, + int minor_ver, + mbedtls_md_type_t hash ) { - mbedtls_ssl_handshake_params *handshake = ssl->handshake; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - ciphersuite_info = handshake->ciphersuite_info; +#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) || !defined(MBEDTLS_SHA512_C) + (void) hash; +#endif - /* - * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions - */ #if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { handshake->tls_prf = ssl3_prf; handshake->calc_verify = ssl_calc_verify_ssl; @@ -1670,7 +1679,7 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_context *ssl ) else #endif #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + if( minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) { handshake->tls_prf = tls1_prf; handshake->calc_verify = ssl_calc_verify_tls; @@ -1680,8 +1689,8 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_context *ssl ) #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA512_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + hash == MBEDTLS_MD_SHA384 ) { handshake->tls_prf = tls_prf_sha384; handshake->calc_verify = ssl_calc_verify_tls_sha384; @@ -1690,7 +1699,7 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_context *ssl ) else #endif #if defined(MBEDTLS_SHA256_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { handshake->tls_prf = tls_prf_sha256; handshake->calc_verify = ssl_calc_verify_tls_sha256; @@ -1700,7 +1709,6 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_context *ssl ) #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } @@ -1711,10 +1719,17 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_context *ssl ) int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) { int ret; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->handshake->ciphersuite_info; - ret = ssl_set_handshake_prfs( ssl ); + ret = ssl_set_handshake_prfs( ssl->handshake, + ssl->minor_ver, + ciphersuite_info->mac ); if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_set_handshake_prfs", ret ); return( ret ); + } return( ssl_populate_transform( ssl ) ); } From 9951b712bd90125de50bc68d18b151f012a160b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 30 Apr 2019 12:08:59 +0200 Subject: [PATCH 004/114] Start extracting ssl_compute_master() For now just moving code around, not changing indentation. Calling convention and signature are going to be adjusted in upcoming commits. --- library/ssl_tls.c | 295 ++++++++++++++++++++++++---------------------- 1 file changed, 157 insertions(+), 138 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d1b4e7c98..1b40f458f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1002,14 +1002,6 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; - /* cf. RFC 5246, Section 8.1: - * "The master secret is always exactly 48 bytes in length." */ - size_t const master_secret_len = 48; - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - unsigned char session_hash[48]; -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - mbedtls_ssl_session *session = ssl->session_negotiate; mbedtls_ssl_transform *transform = ssl->transform_negotiate; mbedtls_ssl_handshake_params *handshake = ssl->handshake; @@ -1059,136 +1051,6 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - /* - * SSLv3: - * master = - * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) - * - * TLSv1+: - * master = PRF( premaster, "master secret", randbytes )[0..47] - */ - if( handshake->resume != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); - } - else - { - /* The label for the KDF used for key expansion. - * This is either "master secret" or "extended master secret" - * depending on whether the Extended Master Secret extension - * is used. */ - char const *lbl = "master secret"; - - /* The salt for the KDF used for key expansion. - * - If the Extended Master Secret extension is not used, - * this is ClientHello.Random + ServerHello.Random - * (see Sect. 8.1 in RFC 5246). - * - If the Extended Master Secret extension is used, - * this is the transcript of the handshake so far. - * (see Sect. 4 in RFC 7627). */ - unsigned char const *salt = handshake->randbytes; - size_t salt_len = 64; - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); - - lbl = "extended master secret"; - salt = session_hash; - ssl->handshake->calc_verify( ssl, session_hash ); -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { -#if defined(MBEDTLS_SHA512_C) - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - { - salt_len = 48; - } - else -#endif /* MBEDTLS_SHA512_C */ - salt_len = 32; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - salt_len = 36; - - MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len ); - } -#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - ssl_use_opaque_psk( ssl ) == 1 ) - { - /* Perform PSK-to-MS expansion in a single step. */ - psa_status_t status; - psa_algorithm_t alg; - psa_key_handle_t psk; - psa_key_derivation_operation_t derivation = - PSA_KEY_DERIVATION_OPERATION_INIT; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); - - psk = ssl->conf->psk_opaque; - if( ssl->handshake->psk_opaque != 0 ) - psk = ssl->handshake->psk_opaque; - - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); - else - alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); - - status = psa_key_derivation( &derivation, psk, alg, - salt, salt_len, - (unsigned char const *) lbl, - (size_t) strlen( lbl ), - master_secret_len ); - if( status != PSA_SUCCESS ) - { - psa_key_derivation_abort( &derivation ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - status = psa_key_derivation_output_bytes( &derivation, - session->master, - master_secret_len ); - if( status != PSA_SUCCESS ) - { - psa_key_derivation_abort( &derivation ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - status = psa_key_derivation_abort( &derivation ); - if( status != PSA_SUCCESS ) - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - else -#endif - { - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - lbl, salt, salt_len, - session->master, - master_secret_len ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", - handshake->premaster, - handshake->pmslen ); - - mbedtls_platform_zeroize( handshake->premaster, - sizeof(handshake->premaster) ); - } - } - /* * Swap the client and server random values. */ @@ -1715,6 +1577,156 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, return( 0 ); } +/* + * Compute master secret + */ +static int ssl_compute_master( mbedtls_ssl_context *ssl ) +{ + int ret; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + mbedtls_ssl_session *session = ssl->session_negotiate; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; + + /* cf. RFC 5246, Section 8.1: + * "The master secret is always exactly 48 bytes in length." */ + size_t const master_secret_len = 48; + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned char session_hash[48]; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + + /* + * SSLv3: + * master = + * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + + * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) + * + * TLSv1+: + * master = PRF( premaster, "master secret", randbytes )[0..47] + */ + if( handshake->resume != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + } + else + { + /* The label for the KDF used for key expansion. + * This is either "master secret" or "extended master secret" + * depending on whether the Extended Master Secret extension + * is used. */ + char const *lbl = "master secret"; + + /* The salt for the KDF used for key expansion. + * - If the Extended Master Secret extension is not used, + * this is ClientHello.Random + ServerHello.Random + * (see Sect. 8.1 in RFC 5246). + * - If the Extended Master Secret extension is used, + * this is the transcript of the handshake so far. + * (see Sect. 4 in RFC 7627). */ + unsigned char const *salt = handshake->randbytes; + size_t salt_len = 64; + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + + lbl = "extended master secret"; + salt = session_hash; + ssl->handshake->calc_verify( ssl, session_hash ); +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + salt_len = 48; + } + else +#endif /* MBEDTLS_SHA512_C */ + salt_len = 32; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + salt_len = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len ); + } +#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_use_opaque_psk( ssl ) == 1 ) + { + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + psa_key_handle_t psk; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); + + psk = ssl->conf->psk_opaque; + if( ssl->handshake->psk_opaque != 0 ) + psk = ssl->handshake->psk_opaque; + + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + + status = psa_key_derivation( &derivation, psk, alg, + salt, salt_len, + (unsigned char const *) lbl, + (size_t) strlen( lbl ), + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, + session->master, + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + else +#endif + { + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + lbl, salt, salt_len, + session->master, + master_secret_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", + handshake->premaster, + handshake->pmslen ); + + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); + } + } + + return( 0 ); +} int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) { @@ -1731,6 +1743,13 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) return( ret ); } + ret = ssl_compute_master( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compute_master", ret ); + return( ret ); + } + return( ssl_populate_transform( ssl ) ); } From 85680c49efb0e75068afba761ad9c1737cba520a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 3 May 2019 09:16:16 +0200 Subject: [PATCH 005/114] Reduce indentation in ssl_compute_master() Exit earlier when there's noting to do. For a small diff, review with 'git show -w'. --- library/ssl_tls.c | 205 ++++++++++++++++++++++------------------------ 1 file changed, 97 insertions(+), 108 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 1b40f458f..a78d6e570 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1578,7 +1578,7 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, } /* - * Compute master secret + * Compute master secret if needed */ static int ssl_compute_master( mbedtls_ssl_context *ssl ) { @@ -1595,134 +1595,123 @@ static int ssl_compute_master( mbedtls_ssl_context *ssl ) unsigned char session_hash[48]; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - /* - * SSLv3: - * master = - * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) - * - * TLSv1+: - * master = PRF( premaster, "master secret", randbytes )[0..47] - */ + /* The label for the KDF used for key expansion. + * This is either "master secret" or "extended master secret" + * depending on whether the Extended Master Secret extension + * is used. */ + char const *lbl = "master secret"; + + /* The salt for the KDF used for key expansion. + * - If the Extended Master Secret extension is not used, + * this is ClientHello.Random + ServerHello.Random + * (see Sect. 8.1 in RFC 5246). + * - If the Extended Master Secret extension is used, + * this is the transcript of the handshake so far. + * (see Sect. 4 in RFC 7627). */ + unsigned char const *salt = handshake->randbytes; + size_t salt_len = 64; + if( handshake->resume != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + return( 0 ); } - else - { - /* The label for the KDF used for key expansion. - * This is either "master secret" or "extended master secret" - * depending on whether the Extended Master Secret extension - * is used. */ - char const *lbl = "master secret"; - - /* The salt for the KDF used for key expansion. - * - If the Extended Master Secret extension is not used, - * this is ClientHello.Random + ServerHello.Random - * (see Sect. 8.1 in RFC 5246). - * - If the Extended Master Secret extension is used, - * this is the transcript of the handshake so far. - * (see Sect. 4 in RFC 7627). */ - unsigned char const *salt = handshake->randbytes; - size_t salt_len = 64; #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); - lbl = "extended master secret"; - salt = session_hash; - ssl->handshake->calc_verify( ssl, session_hash ); + lbl = "extended master secret"; + salt = session_hash; + ssl->handshake->calc_verify( ssl, session_hash ); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { #if defined(MBEDTLS_SHA512_C) - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - { - salt_len = 48; - } - else -#endif /* MBEDTLS_SHA512_C */ - salt_len = 32; + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + salt_len = 48; } else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - salt_len = 36; - - MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len ); +#endif /* MBEDTLS_SHA512_C */ + salt_len = 32; } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + salt_len = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len ); + } #endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - ssl_use_opaque_psk( ssl ) == 1 ) - { - /* Perform PSK-to-MS expansion in a single step. */ - psa_status_t status; - psa_algorithm_t alg; - psa_key_handle_t psk; - psa_key_derivation_operation_t derivation = - PSA_KEY_DERIVATION_OPERATION_INIT; +defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_use_opaque_psk( ssl ) == 1 ) + { + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + psa_key_handle_t psk; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); - psk = ssl->conf->psk_opaque; - if( ssl->handshake->psk_opaque != 0 ) - psk = ssl->handshake->psk_opaque; + psk = ssl->conf->psk_opaque; + if( ssl->handshake->psk_opaque != 0 ) + psk = ssl->handshake->psk_opaque; - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); - else - alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); - - status = psa_key_derivation( &derivation, psk, alg, - salt, salt_len, - (unsigned char const *) lbl, - (size_t) strlen( lbl ), - master_secret_len ); - if( status != PSA_SUCCESS ) - { - psa_key_derivation_abort( &derivation ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - status = psa_key_derivation_output_bytes( &derivation, - session->master, - master_secret_len ); - if( status != PSA_SUCCESS ) - { - psa_key_derivation_abort( &derivation ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - status = psa_key_derivation_abort( &derivation ); - if( status != PSA_SUCCESS ) - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); else -#endif + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + + status = psa_key_derivation( &derivation, psk, alg, + salt, salt_len, + (unsigned char const *) lbl, + (size_t) strlen( lbl ), + master_secret_len ); + if( status != PSA_SUCCESS ) { - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - lbl, salt, salt_len, - session->master, - master_secret_len ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", - handshake->premaster, - handshake->pmslen ); - - mbedtls_platform_zeroize( handshake->premaster, - sizeof(handshake->premaster) ); + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } + + status = psa_key_derivation_output_bytes( &derivation, + session->master, + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + else +#endif + { + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + lbl, salt, salt_len, + session->master, + master_secret_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", + handshake->premaster, + handshake->pmslen ); + + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); } return( 0 ); From de047adfb422d0802bd5c3a6c82c17a08f075025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 3 May 2019 09:46:14 +0200 Subject: [PATCH 006/114] Improve signature of ssl_compute_master() Make it more explicit what's used. Unfortunately, we still need ssl as a parameter for debugging, and because calc_verify wants it as a parameter (for all TLS versions except SSL3 it would actually only need handshake, but SSL3 also accesses session_negotiate). It's also because of calc_verify that we can't make it const yet, but see next commit. --- library/ssl_tls.c | 65 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index a78d6e570..15ce50140 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1579,13 +1579,27 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, /* * Compute master secret if needed + * + * Parameters: + * [in/out] handshake + * [in] resume, premaster, extended_ms, calc_verify, tls_prf + * (PSA-PSK) ciphersuite_info + * [out] premaster (cleared) + * [in] minor_ver (to compute hash_len) + * [in] hash_alg (to compute hash_len) + * [out] master + * [in] ssl: optionally used for debugging, EMS and PSA-PSK + * debug: conf->f_dbg, conf->p_dbg + * EMS: passed to calc_verify (debug + (SSL3) session_negotiate) + * PSA-PSA: conf */ -static int ssl_compute_master( mbedtls_ssl_context *ssl ) +static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, + int minor_ver, + mbedtls_md_type_t hash_alg, + unsigned char *master, + mbedtls_ssl_context *ssl ) { int ret; - mbedtls_ssl_handshake_params *handshake = ssl->handshake; - mbedtls_ssl_session *session = ssl->session_negotiate; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; /* cf. RFC 5246, Section 8.1: * "The master secret is always exactly 48 bytes in length." */ @@ -1611,6 +1625,19 @@ static int ssl_compute_master( mbedtls_ssl_context *ssl ) unsigned char const *salt = handshake->randbytes; size_t salt_len = 64; +#if !defined(MBEDTLS_DEBUG_C) && \ + !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) + (void) ssl; +#endif +#if !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) || !defined(MBEDTLS_SSL_PROTO_TLS1_2) + (void) minor_ver; +#if defined(MBEDTLS_SHA512_C) + (void) hash_alg; +#endif +#endif + if( handshake->resume != 0 ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); @@ -1618,18 +1645,18 @@ static int ssl_compute_master( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + if( handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); lbl = "extended master secret"; salt = session_hash; - ssl->handshake->calc_verify( ssl, session_hash ); + handshake->calc_verify( ssl, session_hash ); #if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { #if defined(MBEDTLS_SHA512_C) - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + if( hash_alg == MBEDTLS_MD_SHA384 ) { salt_len = 48; } @@ -1646,9 +1673,9 @@ static int ssl_compute_master( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ -defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && ssl_use_opaque_psk( ssl ) == 1 ) { /* Perform PSK-to-MS expansion in a single step. */ @@ -1661,10 +1688,10 @@ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); psk = ssl->conf->psk_opaque; - if( ssl->handshake->psk_opaque != 0 ) - psk = ssl->handshake->psk_opaque; + if( handshake->psk_opaque != 0 ) + psk = handshake->psk_opaque; - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + if( hash_alg == MBEDTLS_MD_SHA384 ) alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); else alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); @@ -1681,7 +1708,7 @@ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) } status = psa_key_derivation_output_bytes( &derivation, - session->master, + master, master_secret_len ); if( status != PSA_SUCCESS ) { @@ -1698,7 +1725,7 @@ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) { ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, lbl, salt, salt_len, - session->master, + master, master_secret_len ); if( ret != 0 ) { @@ -1732,7 +1759,11 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) return( ret ); } - ret = ssl_compute_master( ssl ); + ret = ssl_compute_master( ssl->handshake, + ssl->minor_ver, + ciphersuite_info->mac, + ssl->session_negotiate->master, + ssl ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compute_master", ret ); From 0d56aaac7bd557c4b4a1b1fd48adaf6d3390e32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 3 May 2019 09:58:33 +0200 Subject: [PATCH 007/114] Constify ssl_context param of calc_verify() --- include/mbedtls/ssl_internal.h | 2 +- library/ssl_tls.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 63a06334d..bc78ffd50 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -458,7 +458,7 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); - void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); + void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *); void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); mbedtls_ssl_tls_prf_cb *tls_prf; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 15ce50140..41a98e93a 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -855,25 +855,25 @@ static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned c #endif #if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_verify_ssl( const mbedtls_ssl_context *, unsigned char * ); static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_verify_tls( const mbedtls_ssl_context *, unsigned char * ); static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * ); +static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char * ); static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); #endif #if defined(MBEDTLS_SHA512_C) static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char * ); static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ @@ -1597,7 +1597,7 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, int minor_ver, mbedtls_md_type_t hash_alg, unsigned char *master, - mbedtls_ssl_context *ssl ) + const mbedtls_ssl_context *ssl ) { int ret; @@ -1774,7 +1774,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL_PROTO_SSL3) -void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl, unsigned char hash[36] ) { mbedtls_md5_context md5; mbedtls_sha1_context sha1; @@ -1823,7 +1823,7 @@ void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) #endif /* MBEDTLS_SSL_PROTO_SSL3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) +void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl, unsigned char hash[36] ) { mbedtls_md5_context md5; mbedtls_sha1_context sha1; @@ -1851,7 +1851,7 @@ void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) -void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) +void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, unsigned char hash[32] ) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t hash_size; @@ -1894,7 +1894,7 @@ void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32 #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA512_C) -void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] ) +void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, unsigned char hash[48] ) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t hash_size; From de718b99b5181570af5a8f5cc78366ee7223670d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 3 May 2019 11:43:28 +0200 Subject: [PATCH 008/114] Make calc_verify() return the length as well Simplifies ssl_compute_hash(), but unfortunately not so much the other uses. --- include/mbedtls/ssl_internal.h | 2 +- library/ssl_cli.c | 5 +- library/ssl_srv.c | 5 +- library/ssl_tls.c | 84 ++++++++++++++++------------------ 4 files changed, 46 insertions(+), 50 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index bc78ffd50..c584370e3 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -458,7 +458,7 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); - void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *); + void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); mbedtls_ssl_tls_prf_cb *tls_prf; diff --git a/library/ssl_cli.c b/library/ssl_cli.c index f403aa036..57e5d8ab9 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -3625,7 +3625,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) unsigned char hash[48]; unsigned char *hash_start = hash; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; - unsigned int hashlen; + size_t hashlen; void *rs_ctx = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); @@ -3674,7 +3674,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) sign: #endif - ssl->handshake->calc_verify( ssl, hash ); + ssl->handshake->calc_verify( ssl, hash, &hashlen ); #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_1) @@ -3692,7 +3692,6 @@ sign: * sha_hash * SHA(handshake_messages); */ - hashlen = 36; md_alg = MBEDTLS_MD_NONE; /* diff --git a/library/ssl_srv.c b/library/ssl_srv.c index a19179a25..b1da073ec 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -4361,7 +4361,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) } /* Calculate hash and verify signature */ - ssl->handshake->calc_verify( ssl, hash ); + { + size_t dummy_hlen; + ssl->handshake->calc_verify( ssl, hash, &dummy_hlen ); + } if( ( ret = mbedtls_pk_verify( peer_pk, md_alg, hash_start, hashlen, diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 41a98e93a..877fee833 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -855,25 +855,25 @@ static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned c #endif #if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_verify_ssl( const mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_verify_ssl( const mbedtls_ssl_context *, unsigned char *, size_t * ); static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_verify_tls( const mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_verify_tls( const mbedtls_ssl_context *, unsigned char *, size_t * ); static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char * ); +static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char *, size_t * ); static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); #endif #if defined(MBEDTLS_SHA512_C) static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char * ); +static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char *, size_t * ); static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ @@ -1583,19 +1583,15 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, * Parameters: * [in/out] handshake * [in] resume, premaster, extended_ms, calc_verify, tls_prf - * (PSA-PSK) ciphersuite_info + * (PSA-PSK) ciphersuite_info, psk_opaque * [out] premaster (cleared) - * [in] minor_ver (to compute hash_len) - * [in] hash_alg (to compute hash_len) * [out] master * [in] ssl: optionally used for debugging, EMS and PSA-PSK * debug: conf->f_dbg, conf->p_dbg * EMS: passed to calc_verify (debug + (SSL3) session_negotiate) - * PSA-PSA: conf + * PSA-PSA: minor_ver, conf */ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, - int minor_ver, - mbedtls_md_type_t hash_alg, unsigned char *master, const mbedtls_ssl_context *ssl ) { @@ -1630,12 +1626,6 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) (void) ssl; -#endif -#if !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) || !defined(MBEDTLS_SSL_PROTO_TLS1_2) - (void) minor_ver; -#if defined(MBEDTLS_SHA512_C) - (void) hash_alg; -#endif #endif if( handshake->resume != 0 ) @@ -1651,22 +1641,7 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, lbl = "extended master secret"; salt = session_hash; - handshake->calc_verify( ssl, session_hash ); -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { -#if defined(MBEDTLS_SHA512_C) - if( hash_alg == MBEDTLS_MD_SHA384 ) - { - salt_len = 48; - } - else -#endif /* MBEDTLS_SHA512_C */ - salt_len = 32; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - salt_len = 36; + handshake->calc_verify( ssl, session_hash, &salt_len ); MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len ); } @@ -1675,7 +1650,7 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, #if defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && - minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && ssl_use_opaque_psk( ssl ) == 1 ) { /* Perform PSK-to-MS expansion in a single step. */ @@ -1684,6 +1659,7 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, psa_key_handle_t psk; psa_key_derivation_operation_t derivation = PSA_KEY_DERIVATION_OPERATION_INIT; + mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac; MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); @@ -1760,8 +1736,6 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } ret = ssl_compute_master( ssl->handshake, - ssl->minor_ver, - ciphersuite_info->mac, ssl->session_negotiate->master, ssl ); if( ret != 0 ) @@ -1774,7 +1748,9 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL_PROTO_SSL3) -void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl, unsigned char hash[36] ) +void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl, + unsigned char hash[36], + size_t *hlen ) { mbedtls_md5_context md5; mbedtls_sha1_context sha1; @@ -1812,7 +1788,9 @@ void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl, unsigned char hash[36] mbedtls_sha1_update_ret( &sha1, hash + 16, 20 ); mbedtls_sha1_finish_ret( &sha1, hash + 16 ); - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + *hlen = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); mbedtls_md5_free( &md5 ); @@ -1823,7 +1801,9 @@ void ssl_calc_verify_ssl( const mbedtls_ssl_context *ssl, unsigned char hash[36] #endif /* MBEDTLS_SSL_PROTO_SSL3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl, unsigned char hash[36] ) +void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl, + unsigned char hash[36], + size_t *hlen ) { mbedtls_md5_context md5; mbedtls_sha1_context sha1; @@ -1839,7 +1819,9 @@ void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl, unsigned char hash[36] mbedtls_md5_finish_ret( &md5, hash ); mbedtls_sha1_finish_ret( &sha1, hash + 16 ); - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); + *hlen = 36; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); mbedtls_md5_free( &md5 ); @@ -1851,7 +1833,9 @@ void ssl_calc_verify_tls( const mbedtls_ssl_context *ssl, unsigned char hash[36] #if defined(MBEDTLS_SSL_PROTO_TLS1_2) #if defined(MBEDTLS_SHA256_C) -void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, unsigned char hash[32] ) +void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, + unsigned char hash[32], + size_t *hlen ) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t hash_size; @@ -1872,7 +1856,9 @@ void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, unsigned char h MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); return; } - MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, 32 ); + + *hlen = 32; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); #else mbedtls_sha256_context sha256; @@ -1884,7 +1870,9 @@ void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, unsigned char h mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); mbedtls_sha256_finish_ret( &sha256, hash ); - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); + *hlen = 32; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); mbedtls_sha256_free( &sha256 ); @@ -1894,7 +1882,9 @@ void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, unsigned char h #endif /* MBEDTLS_SHA256_C */ #if defined(MBEDTLS_SHA512_C) -void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, unsigned char hash[48] ) +void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, + unsigned char hash[48], + size_t *hlen ) { #if defined(MBEDTLS_USE_PSA_CRYPTO) size_t hash_size; @@ -1915,7 +1905,9 @@ void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, unsigned char h MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); return; } - MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, 48 ); + + *hlen = 48; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); #else mbedtls_sha512_context sha512; @@ -1927,7 +1919,9 @@ void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, unsigned char h mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); mbedtls_sha512_finish_ret( &sha512, hash ); - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); + *hlen = 48; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); mbedtls_sha512_free( &sha512 ); From 040a9517b59971479cbde82e4718121aa83cecfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 6 May 2019 12:05:58 +0200 Subject: [PATCH 009/114] Move handling of randbytes to derive_keys() --- library/ssl_tls.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 877fee833..3e23b6759 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -989,7 +989,6 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_USE_PSA_CRYPTO) int psa_fallthrough; #endif /* MBEDTLS_USE_PSA_CRYPTO */ - unsigned char tmp[64]; unsigned char keyblk[256]; unsigned char *key1; unsigned char *key2; @@ -1006,8 +1005,6 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) mbedtls_ssl_transform *transform = ssl->transform_negotiate; mbedtls_ssl_handshake_params *handshake = ssl->handshake; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); - #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) transform->encrypt_then_mac = session->encrypt_then_mac; @@ -1051,14 +1048,6 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ - /* - * Swap the client and server random values. - */ - memcpy( tmp, handshake->randbytes, 64 ); - memcpy( handshake->randbytes, tmp + 32, 32 ); - memcpy( handshake->randbytes + 32, tmp, 32 ); - mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); - /* * SSLv3: * key block = @@ -1505,11 +1494,8 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_ZLIB_SUPPORT */ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); end: mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); - mbedtls_platform_zeroize( handshake->randbytes, - sizeof( handshake->randbytes ) ); return( ret ); } @@ -1726,6 +1712,9 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = ssl->handshake->ciphersuite_info; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + /* Set PRF, calc_verify and calc_finished function pointers */ ret = ssl_set_handshake_prfs( ssl->handshake, ssl->minor_ver, ciphersuite_info->mac ); @@ -1735,6 +1724,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) return( ret ); } + /* Compute master secret if needed */ ret = ssl_compute_master( ssl->handshake, ssl->session_negotiate->master, ssl ); @@ -1744,7 +1734,32 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) return( ret ); } - return( ssl_populate_transform( ssl ) ); + /* Swap the client and server random values: + * - MS derivation wanted client+server (RFC 5246 8.1) + * - key derivation wants server+client (RFC 5246 6.3) */ + { + unsigned char tmp[64]; + memcpy( tmp, ssl->handshake->randbytes, 64 ); + memcpy( ssl->handshake->randbytes, tmp + 32, 32 ); + memcpy( ssl->handshake->randbytes + 32, tmp, 32 ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + } + + /* Populate transform structure */ + ret = ssl_populate_transform( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_populate_transform", ret ); + return( ret ); + } + + /* We no longer need Server/ClientHello.random values */ + mbedtls_platform_zeroize( ssl->handshake->randbytes, + sizeof( ssl->handshake->randbytes ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); } #if defined(MBEDTLS_SSL_PROTO_SSL3) From d73b47fe2eef8de421f341a655cc29dfce404e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 6 May 2019 12:44:24 +0200 Subject: [PATCH 010/114] Move compress_buf allocation to derive_keys --- library/ssl_tls.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 3e23b6759..ad1430bce 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1460,24 +1460,10 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_CIPHER_MODE_CBC */ + /* Initialize Zlib contexts */ #if defined(MBEDTLS_ZLIB_SUPPORT) - // Initialize compression - // if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) { - if( ssl->compress_buf == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); - ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); - if( ssl->compress_buf == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); - ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; - goto end; - } - } - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); @@ -1757,6 +1743,22 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) mbedtls_platform_zeroize( ssl->handshake->randbytes, sizeof( ssl->handshake->randbytes ) ); + /* Allocate compression buffer */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE && + ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); + ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_COMPRESS_BUFFER_LEN ); + if( ssl->compress_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + } +#endif + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); return( 0 ); From cba40d92bd91329fc285b1e29338ec1b196193c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 6 May 2019 12:55:40 +0200 Subject: [PATCH 011/114] Start refining parameters of populate_transform() Parameters 'handshake' and 'ssl' will be replaced with more fine-grained inputs in follow-up commits. --- library/ssl_tls.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index ad1430bce..6563d9ade 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -978,12 +978,21 @@ int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, } /* - * This function will ultimetaly only be responsible for populating a - * transform structure from data passed as explicit parameters. + * Populate a transform structure with session keys and all the other + * necessary information. * - * For now however it's doing rather more in a rather less explicit way. + * Parameters: + * - [in/out]: transform: structure to populate + * [in] must be just initialised with mbedtls_ssl_transform_init() + * [out] fully populate, ready for use by mbedtls_ssl_{en,de}crypt_buf() + * - [in] session: used members: encrypt_then_max, master, compression + * - [in] handshake: used members: prf, ciphersuite_info, randbytes + * - [in]: ssl: used members: minor_ver, conf->endpoint */ -static int ssl_populate_transform( mbedtls_ssl_context *ssl ) +static int ssl_populate_transform( mbedtls_ssl_transform *transform, + const mbedtls_ssl_session *session, + const mbedtls_ssl_handshake_params *handshake, + const mbedtls_ssl_context *ssl ) { int ret = 0; #if defined(MBEDTLS_USE_PSA_CRYPTO) @@ -1001,10 +1010,6 @@ static int ssl_populate_transform( mbedtls_ssl_context *ssl ) const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; - mbedtls_ssl_session *session = ssl->session_negotiate; - mbedtls_ssl_transform *transform = ssl->transform_negotiate; - mbedtls_ssl_handshake_params *handshake = ssl->handshake; - #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) transform->encrypt_then_mac = session->encrypt_then_mac; @@ -1732,7 +1737,10 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } /* Populate transform structure */ - ret = ssl_populate_transform( ssl ); + ret = ssl_populate_transform( ssl->transform_negotiate, + ssl->session_negotiate, + ssl->handshake, + ssl ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "ssl_populate_transform", ret ); From 344460c913237d720f161ca601dfac6602d3d857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 25 Jul 2019 13:17:38 +0200 Subject: [PATCH 012/114] Work around bug in key exporter API https://github.com/ARMmbed/mbedtls/issues/2759 --- library/ssl_tls.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 6563d9ade..7cfdbf213 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1336,8 +1336,9 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, session->master, keyblk, mac_key_len, keylen, iv_copy_len, - handshake->randbytes + 32, - handshake->randbytes, + /* work around bug in exporter type */ + (unsigned char *) handshake->randbytes + 32, + (unsigned char *) handshake->randbytes, tls_prf_get_type( handshake->tls_prf ) ); } #endif From 9b108c242d1ad9561ddb286fa41c7ad42aca7215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 6 May 2019 13:32:17 +0200 Subject: [PATCH 013/114] Remove "handshake" input from populate_transform() --- library/ssl_tls.c | 54 ++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 7cfdbf213..3930b471c 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -977,6 +977,11 @@ int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) ); } +/* Type for the TLS PRF */ +typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + /* * Populate a transform structure with session keys and all the other * necessary information. @@ -985,13 +990,15 @@ int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, * - [in/out]: transform: structure to populate * [in] must be just initialised with mbedtls_ssl_transform_init() * [out] fully populate, ready for use by mbedtls_ssl_{en,de}crypt_buf() - * - [in] session: used members: encrypt_then_max, master, compression - * - [in] handshake: used members: prf, ciphersuite_info, randbytes - * - [in]: ssl: used members: minor_ver, conf->endpoint + * - [in] session: used: ciphersuite, encrypt_then_mac, master, compression + * - [in] tls_prf: pointer to PRF to use for key derivation + * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random + * - [in] ssl: used members: minor_ver, conf->endpoint */ static int ssl_populate_transform( mbedtls_ssl_transform *transform, const mbedtls_ssl_session *session, - const mbedtls_ssl_handshake_params *handshake, + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], const mbedtls_ssl_context *ssl ) { int ret = 0; @@ -1010,13 +1017,24 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; + /* Copy info about negotiated version and extensions */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) transform->encrypt_then_mac = session->encrypt_then_mac; #endif transform->minor_ver = ssl->minor_ver; - ciphersuite_info = handshake->ciphersuite_info; + /* + * Get various info structures + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( session->ciphersuite ); + if( ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found", + session->ciphersuite ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher ); if( cipher_info == NULL ) { @@ -1054,19 +1072,10 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ /* - * SSLv3: - * key block = - * MD5( master + SHA1( 'A' + master + randbytes ) ) + - * MD5( master + SHA1( 'BB' + master + randbytes ) ) + - * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + - * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + - * ... - * - * TLSv1: - * key block = PRF( master, "key expansion", randbytes ) + * Compute key block using the PRF */ - ret = handshake->tls_prf( session->master, 48, "key expansion", - handshake->randbytes, 64, keyblk, 256 ); + ret = tls_prf( session->master, 48, "key expansion", + randbytes, 64, keyblk, 256 ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); @@ -1076,7 +1085,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 ); MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); /* @@ -1337,9 +1346,9 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, mac_key_len, keylen, iv_copy_len, /* work around bug in exporter type */ - (unsigned char *) handshake->randbytes + 32, - (unsigned char *) handshake->randbytes, - tls_prf_get_type( handshake->tls_prf ) ); + (unsigned char *) randbytes + 32, + (unsigned char *) randbytes, + tls_prf_get_type( tls_prf ) ); } #endif @@ -1740,7 +1749,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) /* Populate transform structure */ ret = ssl_populate_transform( ssl->transform_negotiate, ssl->session_negotiate, - ssl->handshake, + ssl->handshake->tls_prf, + ssl->handshake->randbytes, ssl ); if( ret != 0 ) { From c864f6a2093b416f3d1ca7deeef6a28d7f5a4e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 6 May 2019 13:48:22 +0200 Subject: [PATCH 014/114] Partially rm 'ssl' input from populate_transform() --- library/ssl_tls.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 3930b471c..822d972f6 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -989,16 +989,23 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, * Parameters: * - [in/out]: transform: structure to populate * [in] must be just initialised with mbedtls_ssl_transform_init() - * [out] fully populate, ready for use by mbedtls_ssl_{en,de}crypt_buf() + * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() * - [in] session: used: ciphersuite, encrypt_then_mac, master, compression * - [in] tls_prf: pointer to PRF to use for key derivation * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random - * - [in] ssl: used members: minor_ver, conf->endpoint + * - [in] minor_ver: SSL/TLS minor version + * - [in] endpoint: client or server + * - [in] ssl: optionally used for: + * - MBEDTLS_SSL_HW_RECORD_ACCEL: whole context + * - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys + * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg */ static int ssl_populate_transform( mbedtls_ssl_transform *transform, const mbedtls_ssl_session *session, ssl_tls_prf_t tls_prf, const unsigned char randbytes[64], + int minor_ver, + unsigned endpoint, const mbedtls_ssl_context *ssl ) { int ret = 0; @@ -1017,12 +1024,18 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; +#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \ + !defined(MBEDTLS_SSL_EXPORT_KEYS) && \ + !defined(MBEDTLS_DEBUG_C) + (void) ssl; +#endif + /* Copy info about negotiated version and extensions */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) transform->encrypt_then_mac = session->encrypt_then_mac; #endif - transform->minor_ver = ssl->minor_ver; + transform->minor_ver = minor_ver; /* * Get various info structures @@ -1188,14 +1201,14 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, } #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || + minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) ; /* No need to adjust minlen */ else #endif #if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || + minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { transform->minlen += transform->ivlen; } @@ -1225,7 +1238,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, * Finally setup the cipher contexts, IVs and MAC secrets. */ #if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) { key1 = keyblk + mac_key_len * 2; key2 = keyblk + mac_key_len * 2 + keylen; @@ -1245,7 +1258,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, else #endif /* MBEDTLS_SSL_CLI_C */ #if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) { key1 = keyblk + mac_key_len * 2 + keylen; key2 = keyblk + mac_key_len * 2; @@ -1272,7 +1285,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, #if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) #if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) { if( mac_key_len > sizeof( transform->mac_enc ) ) { @@ -1288,7 +1301,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, #endif /* MBEDTLS_SSL_PROTO_SSL3 */ #if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) + if( minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) { /* For HMAC-based ciphersuites, initialize the HMAC transforms. For AEAD-based ciphersuites, there is nothing to do here. */ @@ -1751,6 +1764,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) ssl->session_negotiate, ssl->handshake->tls_prf, ssl->handshake->randbytes, + ssl->minor_ver, + ssl->conf->endpoint, ssl ); if( ret != 0 ) { From a7505d18eb296e76c3b303cf75ac23c13f328530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 7 May 2019 10:17:56 +0200 Subject: [PATCH 015/114] Enforce promise to not use whole ssl context Configs with no DEBUG_C are used for example in test-ref-configs.pl, which also runs parts of compat.sh or ssl-opt.sh on them, so the added 'ssl = NULL' statements will be exercised in those tests at least. --- library/ssl_tls.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 822d972f6..74cb756e7 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1027,6 +1027,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, #if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \ !defined(MBEDTLS_SSL_EXPORT_KEYS) && \ !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for those cases */ (void) ssl; #endif @@ -1625,6 +1626,7 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) + ssl = NULL; /* make sure we don't use it except for those cases */ (void) ssl; #endif @@ -2312,6 +2314,7 @@ int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, /* The SSL context is only used for debugging purposes! */ #if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif @@ -2741,6 +2744,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, size_t add_data_len; #if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ ((void) ssl); #endif From 31d3ef11f53ac7cd0556dc857fe5f7ccc4698070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 10 May 2019 10:25:00 +0200 Subject: [PATCH 016/114] Fix typo in comment --- library/ssl_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 74cb756e7..5cc52c336 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1521,7 +1521,7 @@ end: * - SSL/TLS minor version * - hash associated with the ciphersuite (only used by TLS 1.2) * - * Ouputs: + * Outputs: * - the tls_prf, calc_verify and calc_finished members of handshake structure */ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, From 6fa57bfae5249667208774fdf32df601a4c7c6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 10 May 2019 10:50:04 +0200 Subject: [PATCH 017/114] Remove 'session' input from populate_tranform() When using this function to deserialize, it's not a problem to have a session structure as input as we'll have one around anyway (most probably freshly deserialised). However for tests it's convenient to be able to build a transform without having a session structure around. Also, removing this structure from parameters makes the function signature more uniform, the only exception left being the ssl param at the end that's hard to avoid for now. --- library/ssl_tls.c | 53 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5cc52c336..92d3d6222 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -990,7 +990,11 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, * - [in/out]: transform: structure to populate * [in] must be just initialised with mbedtls_ssl_transform_init() * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() - * - [in] session: used: ciphersuite, encrypt_then_mac, master, compression + * - [in] ciphersuite + * - [in] master + * - [in] encrypt_then_mac + * - [in] trunc_hmac + * - [in] compression * - [in] tls_prf: pointer to PRF to use for key derivation * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random * - [in] minor_ver: SSL/TLS minor version @@ -1001,7 +1005,17 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg */ static int ssl_populate_transform( mbedtls_ssl_transform *transform, - const mbedtls_ssl_session *session, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac, +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + int trunc_hmac, +#endif +#if defined(MBEDTLS_ZLIB_SUPPORT) + int compression, +#endif ssl_tls_prf_t tls_prf, const unsigned char randbytes[64], int minor_ver, @@ -1034,18 +1048,18 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, /* Copy info about negotiated version and extensions */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) - transform->encrypt_then_mac = session->encrypt_then_mac; + transform->encrypt_then_mac = encrypt_then_mac; #endif transform->minor_ver = minor_ver; /* * Get various info structures */ - ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( session->ciphersuite ); + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite ); if( ciphersuite_info == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found", - session->ciphersuite ) ); + ciphersuite ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -1088,8 +1102,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, /* * Compute key block using the PRF */ - ret = tls_prf( session->master, 48, "key expansion", - randbytes, 64, keyblk, 256 ); + ret = tls_prf( master, 48, "key expansion", randbytes, 64, keyblk, 256 ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); @@ -1097,8 +1110,8 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, } MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", - mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); + mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", master, 48 ); MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 ); MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); @@ -1160,7 +1173,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, * (rfc 6066 page 13 or rfc 2104 section 4), * so we only need to adjust the length here. */ - if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) + if( trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) { transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; @@ -1188,7 +1201,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, * 2. IV except for SSL3 and TLS 1.0 */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + if( encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) { transform->minlen = transform->maclen + cipher_info->block_size; @@ -1348,7 +1361,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, if( ssl->conf->f_export_keys != NULL ) { ssl->conf->f_export_keys( ssl->conf->p_export_keys, - session->master, keyblk, + master, keyblk, mac_key_len, keylen, iv_copy_len ); } @@ -1356,7 +1369,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, if( ssl->conf->f_export_keys_ext != NULL ) { ssl->conf->f_export_keys_ext( ssl->conf->p_export_keys, - session->master, keyblk, + master, keyblk, mac_key_len, keylen, iv_copy_len, /* work around bug in exporter type */ @@ -1491,7 +1504,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, /* Initialize Zlib contexts */ #if defined(MBEDTLS_ZLIB_SUPPORT) - if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) + if( compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); @@ -1763,7 +1776,17 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) /* Populate transform structure */ ret = ssl_populate_transform( ssl->transform_negotiate, - ssl->session_negotiate, + ssl->session_negotiate->ciphersuite, + ssl->session_negotiate->master, +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session_negotiate->encrypt_then_mac, +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl->session_negotiate->trunc_hmac, +#endif +#if defined(MBEDTLS_ZLIB_SUPPORT) + ssl->session_negotiate->compression, +#endif ssl->handshake->tls_prf, ssl->handshake->randbytes, ssl->minor_ver, From 7fa1407adbf2fb19a8f48e5bf25df9a8c4569ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 May 2019 10:07:29 +0200 Subject: [PATCH 018/114] Remove redundant debug message. Two consecutive messages (ie no branch between them) at the same level are not needed, so only keep the one that has the most information. --- library/ssl_tls.c | 2 -- tests/ssl-opt.sh | 84 +++++++++++++++++++++++------------------------ 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 92d3d6222..8972a8d72 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1652,8 +1652,6 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if( handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); - lbl = "extended master secret"; salt = session_hash; handshake->calc_verify( ssl, session_hash, &salt_len ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 44743d4a1..50c569a02 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1939,8 +1939,8 @@ run_test "Extended Master Secret: default" \ -s "found extended master secret extension" \ -s "server hello, adding extended master secret extension" \ -c "found extended_master_secret extension" \ - -c "using extended master secret" \ - -s "using extended master secret" + -c "session hash" \ + -s "session hash" run_test "Extended Master Secret: client enabled, server disabled" \ "$P_SRV debug_level=3 extended_ms=0" \ @@ -1950,8 +1950,8 @@ run_test "Extended Master Secret: client enabled, server disabled" \ -s "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "using extended master secret" \ - -S "using extended master secret" + -C "session hash" \ + -S "session hash" run_test "Extended Master Secret: client disabled, server enabled" \ "$P_SRV debug_level=3 extended_ms=1" \ @@ -1961,8 +1961,8 @@ run_test "Extended Master Secret: client disabled, server enabled" \ -S "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "using extended master secret" \ - -S "using extended master secret" + -C "session hash" \ + -S "session hash" requires_config_enabled MBEDTLS_SSL_PROTO_SSL3 run_test "Extended Master Secret: client SSLv3, server enabled" \ @@ -1973,8 +1973,8 @@ run_test "Extended Master Secret: client SSLv3, server enabled" \ -S "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "using extended master secret" \ - -S "using extended master secret" + -C "session hash" \ + -S "session hash" requires_config_enabled MBEDTLS_SSL_PROTO_SSL3 run_test "Extended Master Secret: client enabled, server SSLv3" \ @@ -1985,8 +1985,8 @@ run_test "Extended Master Secret: client enabled, server SSLv3" \ -S "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "using extended master secret" \ - -S "using extended master secret" + -C "session hash" \ + -S "session hash" # Tests for FALLBACK_SCSV @@ -4782,8 +4782,8 @@ run_test "PSK callback: opaque psk on client, no callback" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4796,8 +4796,8 @@ run_test "PSK callback: opaque psk on client, no callback, SHA-384" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4810,8 +4810,8 @@ run_test "PSK callback: opaque psk on client, no callback, EMS" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -c "using extended master secret"\ - -s "using extended master secret"\ + -c "session hash"\ + -s "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4824,8 +4824,8 @@ run_test "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -c "using extended master secret"\ - -s "using extended master secret"\ + -c "session hash"\ + -s "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4838,8 +4838,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4852,8 +4852,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4865,8 +4865,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=foo psk=abc123 extended_ms=1" \ 0 \ - -c "using extended master secret"\ - -s "using extended master secret"\ + -c "session hash"\ + -s "session hash"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4880,8 +4880,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=foo psk=abc123 extended_ms=1" \ 0 \ - -c "using extended master secret"\ - -s "using extended master secret"\ + -c "session hash"\ + -s "session hash"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4896,8 +4896,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4910,8 +4910,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4923,8 +4923,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=abc psk=dead extended_ms=1" \ 0 \ - -c "using extended master secret"\ - -s "using extended master secret"\ + -c "session hash"\ + -s "session hash"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4938,8 +4938,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=abc psk=dead extended_ms=1" \ 0 \ - -c "using extended master secret"\ - -s "using extended master secret"\ + -c "session hash"\ + -s "session hash"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4954,8 +4954,8 @@ run_test "PSK callback: raw psk on client, mismatching static raw PSK on serv 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4968,8 +4968,8 @@ run_test "PSK callback: raw psk on client, mismatching static opaque PSK on s 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4981,8 +4981,8 @@ run_test "PSK callback: raw psk on client, mismatching static opaque PSK on s psk_identity=def psk=beef" \ 0 \ -C "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4994,8 +4994,8 @@ run_test "PSK callback: raw psk on client, id-matching but wrong raw PSK on s psk_identity=def psk=beef" \ 0 \ -C "skip PMS generation for opaque PSK"\ - -C "using extended master secret"\ - -S "using extended master secret"\ + -C "session hash"\ + -S "session hash"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" From 47e33e11f74d5dac12d51304949aa4d70dcf59d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 May 2019 10:10:17 +0200 Subject: [PATCH 019/114] Clarify comment about TLS versions The previous comment used "TLS" as a shortcut for "TLS 1.0/1.1" which was confusing. This partially reflected the names of the calc_verify/finished that go ssl, tls (for 1.0/1.1) tls_shaxxx (for 1.2), but still it's clearer to be explicit in the comment - and perhaps in the long term the function names could be clarified instead. --- library/ssl_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8972a8d72..40f72996f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1528,7 +1528,7 @@ end: } /* - * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions + * Set appropriate PRF function and other SSL / TLS 1.0/1.1 / TLS1.2 functions * * Inputs: * - SSL/TLS minor version From d91efa47c0e84d4a770737a0255272ea148550e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 May 2019 10:27:20 +0200 Subject: [PATCH 020/114] Fix alignment issues --- library/ssl_tls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 40f72996f..cc1f450b4 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1110,7 +1110,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, } MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", - mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) ); + mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) ); MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", master, 48 ); MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 ); MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); @@ -1810,7 +1810,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) if( ssl->compress_buf == NULL ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); + MBEDTLS_SSL_COMPRESS_BUFFER_LEN ) ); return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); } } From 8faa70e810bc6c520d0ceb3af4d011aeaef074da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 May 2019 12:09:50 +0200 Subject: [PATCH 021/114] Use more specific name in debug message for testing While 'session hash' is currently unique, so suitable to prove that the intended code path has been taken, it's a generic enough phrase that in the future we might add other debug messages containing it in completely unrelated code paths. In order to future-proof the accuracy of the test, let's use a more specific string. --- library/ssl_tls.c | 3 +- tests/ssl-opt.sh | 84 +++++++++++++++++++++++------------------------ 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index cc1f450b4..dc88af295 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1656,7 +1656,8 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, salt = session_hash; handshake->calc_verify( ssl, session_hash, &salt_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash for extended master secret", + session_hash, salt_len ); } #endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 50c569a02..14dd8bfff 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1939,8 +1939,8 @@ run_test "Extended Master Secret: default" \ -s "found extended master secret extension" \ -s "server hello, adding extended master secret extension" \ -c "found extended_master_secret extension" \ - -c "session hash" \ - -s "session hash" + -c "session hash for extended master secret" \ + -s "session hash for extended master secret" run_test "Extended Master Secret: client enabled, server disabled" \ "$P_SRV debug_level=3 extended_ms=0" \ @@ -1950,8 +1950,8 @@ run_test "Extended Master Secret: client enabled, server disabled" \ -s "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "session hash" \ - -S "session hash" + -C "session hash for extended master secret" \ + -S "session hash for extended master secret" run_test "Extended Master Secret: client disabled, server enabled" \ "$P_SRV debug_level=3 extended_ms=1" \ @@ -1961,8 +1961,8 @@ run_test "Extended Master Secret: client disabled, server enabled" \ -S "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "session hash" \ - -S "session hash" + -C "session hash for extended master secret" \ + -S "session hash for extended master secret" requires_config_enabled MBEDTLS_SSL_PROTO_SSL3 run_test "Extended Master Secret: client SSLv3, server enabled" \ @@ -1973,8 +1973,8 @@ run_test "Extended Master Secret: client SSLv3, server enabled" \ -S "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "session hash" \ - -S "session hash" + -C "session hash for extended master secret" \ + -S "session hash for extended master secret" requires_config_enabled MBEDTLS_SSL_PROTO_SSL3 run_test "Extended Master Secret: client enabled, server SSLv3" \ @@ -1985,8 +1985,8 @@ run_test "Extended Master Secret: client enabled, server SSLv3" \ -S "found extended master secret extension" \ -S "server hello, adding extended master secret extension" \ -C "found extended_master_secret extension" \ - -C "session hash" \ - -S "session hash" + -C "session hash for extended master secret" \ + -S "session hash for extended master secret" # Tests for FALLBACK_SCSV @@ -4782,8 +4782,8 @@ run_test "PSK callback: opaque psk on client, no callback" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4796,8 +4796,8 @@ run_test "PSK callback: opaque psk on client, no callback, SHA-384" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4810,8 +4810,8 @@ run_test "PSK callback: opaque psk on client, no callback, EMS" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -c "session hash"\ - -s "session hash"\ + -c "session hash for extended master secret"\ + -s "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4824,8 +4824,8 @@ run_test "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ - -c "session hash"\ - -s "session hash"\ + -c "session hash for extended master secret"\ + -s "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4838,8 +4838,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4852,8 +4852,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4865,8 +4865,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=foo psk=abc123 extended_ms=1" \ 0 \ - -c "session hash"\ - -s "session hash"\ + -c "session hash for extended master secret"\ + -s "session hash for extended master secret"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4880,8 +4880,8 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=foo psk=abc123 extended_ms=1" \ 0 \ - -c "session hash"\ - -s "session hash"\ + -c "session hash for extended master secret"\ + -s "session hash for extended master secret"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4896,8 +4896,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4910,8 +4910,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4923,8 +4923,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=abc psk=dead extended_ms=1" \ 0 \ - -c "session hash"\ - -s "session hash"\ + -c "session hash for extended master secret"\ + -s "session hash for extended master secret"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4938,8 +4938,8 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=abc psk=dead extended_ms=1" \ 0 \ - -c "session hash"\ - -s "session hash"\ + -c "session hash for extended master secret"\ + -s "session hash for extended master secret"\ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ -S "SSL - None of the common ciphersuites is usable" \ @@ -4954,8 +4954,8 @@ run_test "PSK callback: raw psk on client, mismatching static raw PSK on serv 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4968,8 +4968,8 @@ run_test "PSK callback: raw psk on client, mismatching static opaque PSK on s 0 \ -C "skip PMS generation for opaque PSK"\ -s "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4981,8 +4981,8 @@ run_test "PSK callback: raw psk on client, mismatching static opaque PSK on s psk_identity=def psk=beef" \ 0 \ -C "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" @@ -4994,8 +4994,8 @@ run_test "PSK callback: raw psk on client, id-matching but wrong raw PSK on s psk_identity=def psk=beef" \ 0 \ -C "skip PMS generation for opaque PSK"\ - -C "session hash"\ - -S "session hash"\ + -C "session hash for extended master secret"\ + -S "session hash for extended master secret"\ -S "SSL - None of the common ciphersuites is usable" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" From 5a6d6ece6ecda14e17515f5fe8bcf9f2288640a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 15 May 2019 16:13:59 +0200 Subject: [PATCH 022/114] Declare and document session save/load functions The next commit with make the implementation publicly available as well. For now the API is kept unchanged. The save function API has a serious drawback in that the user must guess what an appropriate buffer size is. Internally so far this didn't matter because we were only using that API for ticket creation, and tickets are written to the SSL output buffer whose size is fixed anyway, but for external users this might not be suitable. Improving that is left for later. Also, so far the functions are defined unconditionally. Whether we want to re-use existing flags or introduce a new one is left for later. Finally, currently suggested usage of calling get_session() then session_save() is memory-inefficient in that get_session() already makes a copy. I don't want to recommend accessing `ssl->session` directly as we want to prohibit direct access to struct member in the future. Providing a clean and efficient way is also left to a later commit. --- include/mbedtls/ssl.h | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 652c4f5af..30fd6ecfd 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2348,6 +2348,62 @@ void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); #endif /* MBEDTLS_SSL_CLI_C */ +/** + * \brief Load serialised session data into a session structure. + * On client, this can be used for loading saved sessions + * before resuming them with mbedstls_ssl_set_session(). + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \warning If a peer certificate chain is associated with the session, + * the serialised state will only contain the peer's + * end-entity certificate and the result of the chain + * verification (unless verification was disabled), but not + * the rest of the chain. + * + * \see mbedtls_ssl_session_save() + * \see mbedtls_ssl_set_session() + * + * \param session The session structure to be populated. It must have been + * initialised with mbedtls_ssl_session_init() but not + * populated yet. + * \param buf The buffer holding the serialised session data. It must be a + * readable buffer of at least \p len bytes. + * \param len The size of the serialised data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ); + +/** + * \brief Save session structure as serialised data in a buffer. + * On client, this can be used for saving session data, + * potentially in non-volatile storage, for resuming later. + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \see mbedtls_ssl_session_load() + * \see mbedtls_ssl_get_session() + * + * \param session The session structure to be saved. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p len bytes. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size of the written data in bytes. It must point to a + * valid \c size_t. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ); + /** * \brief Set the list of allowed ciphersuites and the preference * order. First in the list has the highest preference. From a3e7c65101a05479a1d1d0c1ebd50275241b2427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 16 May 2019 10:08:35 +0200 Subject: [PATCH 023/114] Move session save/load function to ssl_tls.c This finishes making these functions public. Next step is to get them tested, but there's currently a blocker for that, see next commit (and the commit after it for tests). --- library/ssl_ticket.c | 190 +------------------------------------------ library/ssl_tls.c | 185 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 186 deletions(-) diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c index ed65bcd63..6dad5d1b2 100644 --- a/library/ssl_ticket.c +++ b/library/ssl_ticket.c @@ -185,189 +185,6 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, return( 0 ); } -/* - * Serialize a session in the following format: - * - * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is enabled: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n+2 peer_cert length = m (0 if no certificate) - * n+3 . n+2+m peer cert ASN.1 - * - * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is disabled: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n length of peer certificate digest = k (0 if no digest) - * n+1 . n+k peer certificate digest (digest type encoded in session) - */ -static int ssl_save_session( const mbedtls_ssl_session *session, - unsigned char *buf, size_t buf_len, - size_t *olen ) -{ - unsigned char *p = buf; - size_t left = buf_len; -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - size_t cert_len; -#else - size_t cert_digest_len; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( left < sizeof( mbedtls_ssl_session ) ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - /* This also copies the values of pointer fields in the - * session to be serialized, but they'll be ignored when - * loading the session through ssl_load_session(). */ - memcpy( p, session, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); - left -= sizeof( mbedtls_ssl_session ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - if( session->peer_cert == NULL ) - cert_len = 0; - else - cert_len = session->peer_cert->raw.len; - - if( left < 3 + cert_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); - *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( cert_len ) & 0xFF ); - left -= 3; - - if( session->peer_cert != NULL ) - memcpy( p, session->peer_cert->raw.p, cert_len ); - - p += cert_len; - left -= cert_len; -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - if( session->peer_cert_digest != NULL ) - cert_digest_len = 0; - else - cert_digest_len = session->peer_cert_digest_len; - - if( left < 1 + cert_digest_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - *p++ = (unsigned char) cert_digest_len; - left--; - - if( session->peer_cert_digest != NULL ) - memcpy( p, session->peer_cert_digest, cert_digest_len ); - - p += cert_digest_len; - left -= cert_digest_len; -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - *olen = p - buf; - - return( 0 ); -} - -/* - * Unserialise session, see ssl_save_session() - */ -static int ssl_load_session( mbedtls_ssl_session *session, - const unsigned char *buf, size_t len ) -{ - const unsigned char *p = buf; - const unsigned char * const end = buf + len; -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - size_t cert_len; -#else - size_t cert_digest_len; -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - memcpy( session, p, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); - - /* Non-NULL pointer fields of `session` are meaningless - * and potentially harmful. Zeroize them for safety. */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - session->peer_cert = NULL; -#else - session->peer_cert_digest = NULL; -#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - session->ticket = NULL; -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) - /* Deserialize CRT from the end of the ticket. */ - if( 3 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; - p += 3; - - if( cert_len != 0 ) - { - int ret; - - if( cert_len > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - - if( session->peer_cert == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - mbedtls_x509_crt_init( session->peer_cert ); - - if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, - p, cert_len ) ) != 0 ) - { - mbedtls_x509_crt_free( session->peer_cert ); - mbedtls_free( session->peer_cert ); - session->peer_cert = NULL; - return( ret ); - } - - p += cert_len; - } -#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - /* Deserialize CRT digest from the end of the ticket. */ - if( 1 > (size_t)( end - p ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - cert_digest_len = (size_t) p[0]; - p++; - - if( cert_digest_len != 0 ) - { - if( cert_digest_len > (size_t)( end - p ) || - cert_digest_len != session->peer_cert_digest_len ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - session->peer_cert_digest = mbedtls_calloc( 1, cert_digest_len ); - if( session->peer_cert_digest == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( session->peer_cert_digest, p, cert_digest_len ); - p += cert_digest_len; - } -#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( p != end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - return( 0 ); -} - /* * Create session ticket, with the following structure: * @@ -427,8 +244,9 @@ int mbedtls_ssl_ticket_write( void *p_ticket, goto cleanup; /* Dump session state */ - if( ( ret = ssl_save_session( session, - state, end - state, &clear_len ) ) != 0 || + if( ( ret = mbedtls_ssl_session_save( session, + state, end - state, + &clear_len ) ) != 0 || (unsigned long) clear_len > 65535 ) { goto cleanup; @@ -551,7 +369,7 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, } /* Actually load session */ - if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 ) + if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 ) goto cleanup; #if defined(MBEDTLS_HAVE_TIME) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index dc88af295..5c67bf7af 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9834,6 +9834,191 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_CLI_C */ +/* + * Serialize a session in the following format: + * + * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is enabled: + * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) + * n . n+2 peer_cert length = m (0 if no certificate) + * n+3 . n+2+m peer cert ASN.1 + * + * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is disabled: + * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) + * n . n length of peer certificate digest = k (0 if no digest) + * n+1 . n+k peer certificate digest (digest type encoded in session) + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t left = buf_len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#else + size_t cert_digest_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( left < sizeof( mbedtls_ssl_session ) ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* This also copies the values of pointer fields in the + * session to be serialized, but they'll be ignored when + * loading the session through ssl_load_session(). */ + memcpy( p, session, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + left -= sizeof( mbedtls_ssl_session ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + if( left < 3 + cert_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len ) & 0xFF ); + left -= 3; + + if( session->peer_cert != NULL ) + memcpy( p, session->peer_cert->raw.p, cert_len ); + + p += cert_len; + left -= cert_len; +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + cert_digest_len = 0; + else + cert_digest_len = session->peer_cert_digest_len; + + if( left < 1 + cert_digest_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + *p++ = (unsigned char) cert_digest_len; + left--; + + if( session->peer_cert_digest != NULL ) + memcpy( p, session->peer_cert_digest, cert_digest_len ); + + p += cert_digest_len; + left -= cert_digest_len; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + *olen = p - buf; + + return( 0 ); +} + +/* + * Unserialise session, see ssl_save_session() + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#else + size_t cert_digest_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( session, p, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + + /* Non-NULL pointer fields of `session` are meaningless + * and potentially harmful. Zeroize them for safety. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + session->peer_cert = NULL; +#else + session->peer_cert_digest = NULL; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + session->ticket = NULL; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* Deserialize CRT from the end of the ticket. */ + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len != 0 ) + { + int ret; + + if( cert_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( session->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Deserialize CRT digest from the end of the ticket. */ + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_digest_len = (size_t) p[0]; + p++; + + if( cert_digest_len != 0 ) + { + if( cert_digest_len > (size_t)( end - p ) || + cert_digest_len != session->peer_cert_digest_len ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + session->peer_cert_digest = mbedtls_calloc( 1, cert_digest_len ); + if( session->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->peer_cert_digest, p, cert_digest_len ); + p += cert_digest_len; + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + /* * Perform a single step of the SSL handshake */ From 35eb80210328c2776e1600804b13dd4e2961a292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 16 May 2019 11:11:08 +0200 Subject: [PATCH 024/114] Add support for serialisation session with ticket On client side, this is required for the main use case where of serialising a session for later resumption, in case tickets are used. On server side, this doesn't change much as ticket_len will always be 0. This unblocks testing the functions by using them in ssl_client2, which will be done in the next commit. --- library/ssl_tls.c | 81 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5c67bf7af..5a4faa7c8 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9836,16 +9836,17 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, /* * Serialize a session in the following format: + * (in the presentation language of TLS, RFC 8446 section 3) * - * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is enabled: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n+2 peer_cert length = m (0 if no certificate) - * n+3 . n+2+m peer cert ASN.1 + * opaque session_struct[n]; // n = sizeof(mbedtls_ssl_session) + * select (MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) { + * case enabled: opaque peer_cert<0..2^24-1>; // length 0 means no cert + * case disabled: uint8_t peer_cert_digest_type; + * opaque peer_cert_digest<0..2^8-1>; + * } + * opaque ticket<0..2^24-1>; // 0 means no ticket * - * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is disabled: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n length of peer certificate digest = k (0 if no digest) - * n+1 . n+k peer certificate digest (digest type encoded in session) + * Only the peer's certificate is saved, not the whole chain. */ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, unsigned char *buf, @@ -9862,16 +9863,22 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Shallow copy of the session structure + */ if( left < sizeof( mbedtls_ssl_session ) ) return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + left -= sizeof( mbedtls_ssl_session ); /* This also copies the values of pointer fields in the * session to be serialized, but they'll be ignored when * loading the session through ssl_load_session(). */ memcpy( p, session, sizeof( mbedtls_ssl_session ) ); p += sizeof( mbedtls_ssl_session ); - left -= sizeof( mbedtls_ssl_session ); + /* + * Copy of the peer's end-entity certificate + */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if( session->peer_cert == NULL ) @@ -9881,6 +9888,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, if( left < 3 + cert_len ) return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + left -= 3 + cert_len; *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); @@ -9888,7 +9896,10 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, left -= 3; if( session->peer_cert != NULL ) + { memcpy( p, session->peer_cert->raw.p, cert_len ); + p += cert_len; + } p += cert_len; left -= cert_len; @@ -9912,6 +9923,27 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Copy of the session ticket if any + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( left < 3 + session->ticket_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + left -= 3 + session->ticket_len; + + *p++ = (unsigned char)( ( session->ticket_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len ) & 0xFF ); + + if( session->ticket != NULL ) + { + memcpy( p, session->ticket, session->ticket_len ); + p += session->ticket_len; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* Done */ + (void) left; *olen = p - buf; return( 0 ); @@ -9934,6 +9966,9 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Shallow session structure + */ if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -9953,6 +9988,9 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, session->ticket = NULL; #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + /* + * Peer certificate + */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* Deserialize CRT from the end of the ticket. */ @@ -10013,6 +10051,31 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Session ticket + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( session->ticket_len != 0 ) + { + if( session->ticket_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket = mbedtls_calloc( 1, session->ticket_len ); + if( session->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->ticket, p, session->ticket_len ); + p += session->ticket_len; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* Done, should have consumed entire buffer */ if( p != end ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); From 21548638b748aa84ebd6ee3cdbbd06a442076cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 16 May 2019 11:39:42 +0200 Subject: [PATCH 025/114] Save session in serialised form in ssl_client2. This provides basic testing for the session (de)serialisation functions, as well as an example of how to use them. Tested locally with tests/ssl-opt.sh -f '^Session resume'. --- programs/ssl/ssl_client2.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 7ba4565c2..342ecddba 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1047,6 +1047,8 @@ int main( int argc, char *argv[] ) mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_ssl_session saved_session; + unsigned char session_data[MBEDTLS_SSL_MAX_CONTENT_LEN]; + size_t session_data_len; #if defined(MBEDTLS_TIMING_C) mbedtls_timing_delay_context timer; #endif @@ -2447,6 +2449,19 @@ int main( int argc, char *argv[] ) goto exit; } + if( ( ret = mbedtls_ssl_session_save( &saved_session, + session_data, sizeof( session_data ), + &session_data_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n", + -ret ); + goto exit; + } + + /* Simulate that serialised state can have a larger lifetime than a + * structure: keep the serialised data but not the structure. */ + mbedtls_ssl_session_free( &saved_session ); + mbedtls_printf( " ok\n" ); } @@ -2886,10 +2901,19 @@ reconnect: goto exit; } + if( ( ret = mbedtls_ssl_session_load( &saved_session, + session_data, + session_data_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_load returned -0x%x\n\n", + -ret ); + goto exit; + } + if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_conf_session returned %d\n\n", - ret ); + mbedtls_printf( " failed\n ! mbedtls_ssl_set_session returned -0x%x\n\n", + -ret ); goto exit; } From b5e4e0a3956a93ce70c0cd7d2bc681312fa85499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 May 2019 11:12:28 +0200 Subject: [PATCH 026/114] Add mbedtls_ssl_get_session_pointer() Avoid useless copy with mbedtls_ssl_get_session() before serialising. Used in ssl_client2 for testing and demonstrating usage, but unfortunately that means mbedtls_ssl_get_session() is no longer tested, which will be fixed in the next commit. --- include/mbedtls/ssl.h | 19 ++++++++++++++++++- library/ssl_tls.c | 8 ++++++++ programs/ssl/ssl_client2.c | 13 +------------ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 30fd6ecfd..072204553 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2387,7 +2387,7 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, * of session cache or session tickets. * * \see mbedtls_ssl_session_load() - * \see mbedtls_ssl_get_session() + * \see mbedtls_ssl_get_session_pointer() * * \param session The session structure to be saved. * \param buf The buffer to write the serialized data to. It must be a @@ -2404,6 +2404,23 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, size_t buf_len, size_t *olen ); +/** + * \brief Get a pointer to the current session structure, for example + * to serialise it. + * + * \warning Ownership of the session remains with the SSL context - the + * returned pointer must not be kept after the connection has + * ended or been renegotiated. + * + * \see mbedtls_ssl_session_save() + * + * \param ssl SSL context + * + * \return A pointer to the current session if successful, + * NULL if no session is active. + */ +const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl ); + /** * \brief Set the list of allowed ciphersuites and the preference * order. First in the list has the highest preference. diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5a4faa7c8..f1ba99a02 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9834,6 +9834,14 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_CLI_C */ +const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return( NULL ); + + return( ssl->session ); +} + /* * Serialize a session in the following format: * (in the presentation language of TLS, RFC 8446 section 3) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 342ecddba..36db80df1 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2442,14 +2442,7 @@ int main( int argc, char *argv[] ) mbedtls_printf(" . Saving session for reuse..." ); fflush( stdout ); - if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n", - -ret ); - goto exit; - } - - if( ( ret = mbedtls_ssl_session_save( &saved_session, + if( ( ret = mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ), session_data, sizeof( session_data ), &session_data_len ) ) != 0 ) { @@ -2458,10 +2451,6 @@ int main( int argc, char *argv[] ) goto exit; } - /* Simulate that serialised state can have a larger lifetime than a - * structure: keep the serialised data but not the structure. */ - mbedtls_ssl_session_free( &saved_session ); - mbedtls_printf( " ok\n" ); } From a7c376576058ae843b03e6b33d185849a8d80554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 May 2019 12:46:26 +0200 Subject: [PATCH 027/114] Add tests for session copy without serialisation --- programs/ssl/ssl_client2.c | 53 ++++++++++++++++++++++++++++---------- tests/ssl-opt.sh | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 13 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 36db80df1..36b78e590 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -113,6 +113,7 @@ int main( void ) #define DFL_DHMLEN -1 #define DFL_RECONNECT 0 #define DFL_RECO_DELAY 0 +#define DFL_RECO_MODE 1 #define DFL_CID_ENABLED 0 #define DFL_CID_VALUE "" #define DFL_CID_ENABLED_RENEGO -1 @@ -376,8 +377,11 @@ int main( void ) " allow_legacy=%%d default: (library default: no)\n" \ USAGE_RENEGO \ " exchanges=%%d default: 1\n" \ - " reconnect=%%d default: 0 (disabled)\n" \ + " reconnect=%%d number of reconnections using session resumption\n" \ + " default: 0 (disabled)\n" \ " reco_delay=%%d default: 0 seconds\n" \ + " reco_mode=%%d 0: copy session, 1: serialise session\n" \ + " default: 1\n" \ " reconnect_hard=%%d default: 0 (disabled)\n" \ USAGE_TICKETS \ USAGE_EAP_TLS \ @@ -458,6 +462,7 @@ struct options int dhmlen; /* minimum DHM params len in bits */ int reconnect; /* attempt to resume session */ int reco_delay; /* delay in seconds before resuming session */ + int reco_mode; /* how to keep the session around */ int reconnect_hard; /* unexpectedly reconnect from the same port */ int tickets; /* enable / disable session tickets */ const char *curves; /* list of supported elliptic curves */ @@ -1166,6 +1171,7 @@ int main( int argc, char *argv[] ) opt.dhmlen = DFL_DHMLEN; opt.reconnect = DFL_RECONNECT; opt.reco_delay = DFL_RECO_DELAY; + opt.reco_mode = DFL_RECO_MODE; opt.reconnect_hard = DFL_RECONNECT_HARD; opt.tickets = DFL_TICKETS; opt.alpn_string = DFL_ALPN_STRING; @@ -1352,6 +1358,12 @@ int main( int argc, char *argv[] ) if( opt.reco_delay < 0 ) goto usage; } + else if( strcmp( p, "reco_mode" ) == 0 ) + { + opt.reco_mode = atoi( q ); + if( opt.reco_mode < 0 ) + goto usage; + } else if( strcmp( p, "reconnect_hard" ) == 0 ) { opt.reconnect_hard = atoi( q ); @@ -2442,13 +2454,25 @@ int main( int argc, char *argv[] ) mbedtls_printf(" . Saving session for reuse..." ); fflush( stdout ); - if( ( ret = mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ), - session_data, sizeof( session_data ), - &session_data_len ) ) != 0 ) + if( opt.reco_mode == 1 ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n", - -ret ); - goto exit; + if( ( ret = mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ), + session_data, sizeof( session_data ), + &session_data_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n", + -ret ); + goto exit; + } + } + else + { + if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n", + -ret ); + goto exit; + } } mbedtls_printf( " ok\n" ); @@ -2890,13 +2914,16 @@ reconnect: goto exit; } - if( ( ret = mbedtls_ssl_session_load( &saved_session, - session_data, - session_data_len ) ) != 0 ) + if( opt.reco_mode == 1 ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_session_load returned -0x%x\n\n", - -ret ); - goto exit; + if( ( ret = mbedtls_ssl_session_load( &saved_session, + session_data, + session_data_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_load returned -0x%x\n\n", + -ret ); + goto exit; + } } if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 ) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 14dd8bfff..bb4081784 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -2239,6 +2239,20 @@ run_test "Session resume using tickets: timeout" \ -S "a session has been resumed" \ -C "a session has been resumed" +run_test "Session resume using tickets: session copy" \ + "$P_SRV debug_level=3 tickets=1 cache_max=0" \ + "$P_CLI debug_level=3 tickets=1 reconnect=1 reco_mode=0" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -s "found session ticket extension" \ + -s "server hello, adding session ticket extension" \ + -c "found session_ticket extension" \ + -c "parse new session ticket" \ + -S "session successfully restored from cache" \ + -s "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + run_test "Session resume using tickets: openssl server" \ "$O_SRV" \ "$P_CLI debug_level=3 tickets=1 reconnect=1" \ @@ -2304,6 +2318,20 @@ run_test "Session resume using tickets, DTLS: timeout" \ -S "a session has been resumed" \ -C "a session has been resumed" +run_test "Session resume using tickets, DTLS: session copy" \ + "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0" \ + "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 reco_mode=0" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -s "found session ticket extension" \ + -s "server hello, adding session ticket extension" \ + -c "found session_ticket extension" \ + -c "parse new session ticket" \ + -S "session successfully restored from cache" \ + -s "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + run_test "Session resume using tickets, DTLS: openssl server" \ "$O_SRV -dtls1" \ "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1" \ @@ -2400,6 +2428,15 @@ run_test "Session resume using cache: no timeout" \ -s "a session has been resumed" \ -c "a session has been resumed" +run_test "Session resume using cache: session copy" \ + "$P_SRV debug_level=3 tickets=0" \ + "$P_CLI debug_level=3 tickets=0 reconnect=1 reco_mode=0" \ + 0 \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + run_test "Session resume using cache: openssl client" \ "$P_SRV debug_level=3 tickets=0" \ "( $O_CLI -sess_out $SESSION; \ @@ -2495,6 +2532,15 @@ run_test "Session resume using cache, DTLS: no timeout" \ -s "a session has been resumed" \ -c "a session has been resumed" +run_test "Session resume using cache, DTLS: session copy" \ + "$P_SRV dtls=1 debug_level=3 tickets=0" \ + "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 reco_mode=0" \ + 0 \ + -s "session successfully restored from cache" \ + -S "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + run_test "Session resume using cache, DTLS: openssl client" \ "$P_SRV dtls=1 debug_level=3 tickets=0" \ "( $O_CLI -dtls1 -sess_out $SESSION; \ From 26f982f50e6a7f55e41d2e7e5dec17a8e7162839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 21 May 2019 11:01:32 +0200 Subject: [PATCH 028/114] Improve save API by always updating olen This allows callers to discover what an appropriate size is. Otherwise they'd have to either try repeatedly, or allocate an overly large buffer (or some combination of those). Adapt documentation an example usage in ssl_client2. --- include/mbedtls/ssl.h | 12 ++++-- library/ssl_tls.c | 81 +++++++++++++++++++------------------- programs/ssl/ssl_client2.c | 32 +++++++++++++-- 3 files changed, 79 insertions(+), 46 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 072204553..92ce32463 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2391,10 +2391,16 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, * * \param session The session structure to be saved. * \param buf The buffer to write the serialized data to. It must be a - * writeable buffer of at least \p len bytes. + * writeable buffer of at least \p len bytes, or may be \c + * NULL if \p len is \c 0. * \param buf_len The number of bytes available for writing in \p buf. - * \param olen The size of the written data in bytes. It must point to a - * valid \c size_t. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f1ba99a02..6f9203daa 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9862,7 +9862,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, size_t *olen ) { unsigned char *p = buf; - size_t left = buf_len; + size_t used = 0; #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) size_t cert_len; @@ -9874,15 +9874,16 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, /* * Shallow copy of the session structure */ - if( left < sizeof( mbedtls_ssl_session ) ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - left -= sizeof( mbedtls_ssl_session ); + used += sizeof( mbedtls_ssl_session ); /* This also copies the values of pointer fields in the * session to be serialized, but they'll be ignored when * loading the session through ssl_load_session(). */ - memcpy( p, session, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); + if( used <= buf_len ) + { + memcpy( p, session, sizeof( mbedtls_ssl_session ) ); + p += sizeof( mbedtls_ssl_session ); + } /* * Copy of the peer's end-entity certificate @@ -9894,40 +9895,37 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, else cert_len = session->peer_cert->raw.len; - if( left < 3 + cert_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - left -= 3 + cert_len; + used += 3 + cert_len; - *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); - *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( cert_len ) & 0xFF ); - left -= 3; - - if( session->peer_cert != NULL ) + if( used <= buf_len ) { - memcpy( p, session->peer_cert->raw.p, cert_len ); - p += cert_len; - } + *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( cert_len ) & 0xFF ); - p += cert_len; - left -= cert_len; + if( session->peer_cert != NULL ) + { + memcpy( p, session->peer_cert->raw.p, cert_len ); + p += cert_len; + } + } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ if( session->peer_cert_digest != NULL ) cert_digest_len = 0; else cert_digest_len = session->peer_cert_digest_len; - if( left < 1 + cert_digest_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + used += 1 + cert_digest_len; - *p++ = (unsigned char) cert_digest_len; - left--; + if( used <= buf_len ) + { + *p++ = (unsigned char) cert_digest_len; - if( session->peer_cert_digest != NULL ) - memcpy( p, session->peer_cert_digest, cert_digest_len ); + if( session->peer_cert_digest != NULL ) + memcpy( p, session->peer_cert_digest, cert_digest_len ); - p += cert_digest_len; - left -= cert_digest_len; + p += cert_digest_len; + } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ @@ -9935,24 +9933,27 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, * Copy of the session ticket if any */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - if( left < 3 + session->ticket_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - left -= 3 + session->ticket_len; + used += 3 + session->ticket_len; - *p++ = (unsigned char)( ( session->ticket_len >> 16 ) & 0xFF ); - *p++ = (unsigned char)( ( session->ticket_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( session->ticket_len ) & 0xFF ); - - if( session->ticket != NULL ) + if( used <= buf_len ) { - memcpy( p, session->ticket, session->ticket_len ); - p += session->ticket_len; + *p++ = (unsigned char)( ( session->ticket_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len ) & 0xFF ); + + if( session->ticket != NULL ) + { + memcpy( p, session->ticket, session->ticket_len ); + p += session->ticket_len; + } } #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ /* Done */ - (void) left; - *olen = p - buf; + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( 0 ); } diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 36b78e590..317fea373 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -38,6 +38,8 @@ #define mbedtls_calloc calloc #define mbedtls_free free #define mbedtls_exit exit +#define mbedtls_calloc calloc +#define mbedtls_free free #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE #endif @@ -1052,8 +1054,8 @@ int main( int argc, char *argv[] ) mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_ssl_session saved_session; - unsigned char session_data[MBEDTLS_SSL_MAX_CONTENT_LEN]; - size_t session_data_len; + unsigned char *session_data = NULL; + size_t session_data_len = 0; #if defined(MBEDTLS_TIMING_C) mbedtls_timing_delay_context timer; #endif @@ -2456,8 +2458,25 @@ int main( int argc, char *argv[] ) if( opt.reco_mode == 1 ) { + /* free any previously saved data */ + mbedtls_free( session_data ); + session_data = NULL; + + /* get size of the buffer needed */ + mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ), + NULL, 0, &session_data_len ); + session_data = mbedtls_calloc( 1, session_data_len ); + if( session_data == NULL ) + { + mbedtls_printf( " failed\n ! alloc %u bytes for session data\n", + (unsigned) session_data_len ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + /* actually save session data */ if( ( ret = mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ), - session_data, sizeof( session_data ), + session_data, session_data_len, &session_data_len ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_session_saved returned -0x%04x\n\n", @@ -2476,6 +2495,12 @@ int main( int argc, char *argv[] ) } mbedtls_printf( " ok\n" ); + + if( opt.reco_mode == 1 ) + { + mbedtls_printf( " [ Saved %u bytes of session data]\n", + (unsigned) session_data_len ); + } } #if defined(MBEDTLS_X509_CRT_PARSE_C) @@ -2999,6 +3024,7 @@ exit: mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); + mbedtls_free( session_data ); #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) From 6eac11b007e0430c5914e7b4c540d43435f173b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 23 May 2019 09:30:55 +0200 Subject: [PATCH 029/114] Start adding unit test for session serialisation This initial test ensures that a load-save function is the identity. It is so far incomplete in that it only tests sessions without tickets or certificate. This will be improved in the next commits. --- tests/suites/test_suite_ssl.data | 3 ++ tests/suites/test_suite_ssl.function | 47 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 72092cdbd..aec0e9ccc 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -8752,3 +8752,6 @@ ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA384:"1234567890abcdef1234567890abcdef12345678 SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA256 SHA-256 not enabled depends_on:!MBEDTLS_SHA256_C ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA256:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"7f9998393198a02c8d731ccc2ef90b2c":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE + +Session serialisation, load-save +ssl_serialise_session_load_save: diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 104a52f22..12287bae1 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -605,3 +605,50 @@ exit: mbedtls_free( output ); } /* END_CASE */ + +/* BEGIN_CASE */ +void ssl_serialise_session_load_save( ) +{ + mbedtls_ssl_session session; + unsigned char *buf1 = NULL, *buf2 = NULL; + size_t len0, len1, len2; + + /* + * Test that a load-save pair is the identity + */ + + mbedtls_ssl_session_init( &session ); + + /* Get desired buffer size for serialising */ + TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &len0 ) + == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Allocate first buffer */ + buf1 = mbedtls_calloc( 1, len0 ); + TEST_ASSERT( buf1 != NULL ); + + /* Serialise to buffer and free session lived session */ + TEST_ASSERT( mbedtls_ssl_session_save( &session, buf1, len0, &len1 ) + == 0 ); + TEST_ASSERT( len0 == len1 ); + mbedtls_ssl_session_free( &session ); + + /* Restore session from serialised data */ + TEST_ASSERT( mbedtls_ssl_session_load( &session, buf1, len1) == 0 ); + + /* Allocate second buffer and serialise to it */ + buf2 = mbedtls_calloc( 1, len0 ); + TEST_ASSERT( buf1 != NULL ); + TEST_ASSERT( mbedtls_ssl_session_save( &session, buf2, len0, &len2 ) + == 0 ); + + /* Make sure both serialised versions are identical */ + TEST_ASSERT( len1 == len2 ); + TEST_ASSERT( memcmp( buf1, buf2, len1 ) == 0 ); + +exit: + mbedtls_ssl_session_free( &session ); + mbedtls_free( buf1 ); + mbedtls_free( buf2 ); +} +/* END_CASE */ From 3caa6caf4ad8aadb99521506645e6b0f5f7a0d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 23 May 2019 10:06:14 +0200 Subject: [PATCH 030/114] Improve load-save test with tickets and certs --- tests/suites/test_suite_ssl.data | 24 ++++++++++- tests/suites/test_suite_ssl.function | 62 +++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index aec0e9ccc..206d46f82 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -8753,5 +8753,25 @@ SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA256 SHA-256 not enabled depends_on:!MBEDTLS_SHA256_C ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA256:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"7f9998393198a02c8d731ccc2ef90b2c":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -Session serialisation, load-save -ssl_serialise_session_load_save: +Session serialisation, load-save: no ticket, no cert +ssl_serialise_session_load_save:0:"" + +Session serialisation, load-save: small ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_load_save:42:"" + +Session serialisation, load-save: large ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_load_save:1023:"" + +Session serialisation, load-save: no ticket, cert +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_load_save:0:"data_files/server5.crt" + +Session serialisation, load-save: small ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_load_save:42:"data_files/server5.crt" + +Session serialisation, load-save: large ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_load_save:1023:"data_files/server5.crt" diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 12287bae1..7e79ece5b 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -267,6 +267,63 @@ cleanup: return( ret ); } +/* + * Populate a session structure for serialisation tests. + * Choose dummy values, mostly non-0 to distinguish from the init default. + */ +static int ssl_populate_session( mbedtls_ssl_session *session, + int ticket_len, + const char *crt_file ) +{ +#if defined(MBEDTLS_HAVE_TIME) + session->start = mbedtls_time( NULL ) - 42; +#endif + session->ciphersuite = 0xabcd; + session->compression = 1; + session->id_len = sizeof( session->id ); + memset( session->id, 66, session->id_len ); + memset( session->master, 17, sizeof( session-> master ) ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( strlen( crt_file ) != 0 ) + { + int ret; + ret = mbedtls_x509_crt_parse_file( session->peer_cert, crt_file ); + if( ret != 0 ) + return( ret ); + } +#else + (void) crt_file; +#endif + session->verify_result = 0xdeadbeef; + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( ticket_len != 0 ) + { + session->ticket = mbedtls_calloc( 1, ticket_len ); + if( session-> ticket == NULL ) + return( -1 ); + memset( session->ticket, 33, ticket_len ); + } + session->ticket_len = ticket_len; + session->ticket_lifetime = 86401; +#else + (void) ticket_len; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + session->mfl_code = 1; +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + session->trunc_hmac = 1; +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + session->encrypt_then_mac = 1; +#endif + + return( 0 ); +} + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -607,7 +664,7 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void ssl_serialise_session_load_save( ) +void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) { mbedtls_ssl_session session; unsigned char *buf1 = NULL, *buf2 = NULL; @@ -619,6 +676,9 @@ void ssl_serialise_session_load_save( ) mbedtls_ssl_session_init( &session ); + /* Prepare a dummy session to work on */ + ssl_populate_session( &session, ticket_len, crt_file ); + /* Get desired buffer size for serialising */ TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &len0 ) == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); From 5b1674e0ba93ce4ac0e552a7660b1b12a8ead06b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 23 May 2019 12:56:17 +0200 Subject: [PATCH 031/114] Disable test for load-save identity This test appeared to be passing for the wrong reason, it's actually not appropriate for the current implementation. The serialised data contains values of pointers to heap-allocated buffers. There is no reason these should be identical after a load-save pair. They just happened to be identical when I first ran the test due to the place of session_free() in the test code and the fact that the libc's malloc() reused the same buffers. The test no longer passes if other malloc() implementations are used (for example, when compiling with asan which avoids re-using the buffer, probably for better error detection). So, disable this test for now (we can re-enable it when we changed how sessions are serialised, which will be done in a future PR, hence the name of the dummy macro in depends_on). In the next commit we're going to add a test that save-load is the identity instead - which will be more work in testing as it will require checking each field manually, but at least is reliable. --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 7e79ece5b..a150e8050 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -663,7 +663,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_SEE_FUTURE_PR */ void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) { mbedtls_ssl_session session; From f5fa0aa664aa3ef4c23adab35919850cc7c826de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 23 May 2019 10:38:11 +0200 Subject: [PATCH 032/114] Add test for session_save() on small buffers --- tests/suites/test_suite_ssl.data | 23 ++++++++++++++++++ tests/suites/test_suite_ssl.function | 36 ++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 206d46f82..b166a9a93 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -8775,3 +8775,26 @@ ssl_serialise_session_load_save:42:"data_files/server5.crt" Session serialisation, load-save: large ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ssl_serialise_session_load_save:1023:"data_files/server5.crt" + +Session serialisation, save buffer size: no ticket, no cert +ssl_serialise_session_save_buf_size:0:"" + +Session serialisation, save buffer size: small ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_save_buf_size:42:"" + +Session serialisation, save buffer size: large ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_save_buf_size:1023:"" + +Session serialisation, save buffer size: no ticket, cert +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_save_buf_size:0:"data_files/server5.crt" + +Session serialisation, save buffer size: small ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_save_buf_size:42:"data_files/server5.crt" + +Session serialisation, save buffer size: large ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_save_buf_size:1023:"data_files/server5.crt" diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index a150e8050..61ff41608 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -712,3 +712,39 @@ exit: mbedtls_free( buf2 ); } /* END_CASE */ + +/* BEGIN_CASE */ +void ssl_serialise_session_save_buf_size( int ticket_len, char *crt_file ) +{ + mbedtls_ssl_session session; + unsigned char *buf = NULL; + size_t good_len, bad_len, test_len; + + /* + * Test that session_save() fails cleanly on small buffers + */ + + mbedtls_ssl_session_init( &session ); + + /* Prepare dummy session and get serialised size */ + ssl_populate_session( &session, ticket_len, crt_file ); + TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &good_len ) + == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Try all possible bad lengths */ + for( bad_len = 1; bad_len < good_len; bad_len++ ) + { + /* Allocate exact size so that asan/valgrind can detect any overwrite */ + mbedtls_free( buf ); + TEST_ASSERT( ( buf = mbedtls_calloc( 1, bad_len ) ) != NULL ); + TEST_ASSERT( mbedtls_ssl_session_save( &session, buf, bad_len, + &test_len ) + == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + TEST_ASSERT( test_len == good_len ); + } + +exit: + mbedtls_ssl_session_free( &session ); + mbedtls_free( buf ); +} +/* END_CASE */ From a3d831b9e67cb8521073dfe7f15b07c53f9294c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 23 May 2019 12:28:45 +0200 Subject: [PATCH 033/114] Add test for session_load() from small buffers This uncovered a bug that led to a double-free (in practice, in general could be free() on any invalid value): initially the session structure is loaded with `memcpy()` which copies the previous values of pointers peer_cert and ticket to heap-allocated buffers (or any other value if the input is attacker-controlled). Now if we exit before we got a chance to replace those invalid values with valid ones (for example because the input buffer is too small, or because the second malloc() failed), then the next call to session_free() is going to call free() on invalid pointers. This bug is fixed in this commit by always setting the pointers to NULL right after they've been read from the serialised state, so that the invalid values can never be used. (An alternative would be to NULL-ify them when writing, which was rejected mostly because we need to do it when reading anyway (as the consequences of free(invalid) are too severe to take any risk), so doing it when writing as well is redundant and a waste of code size.) Also, while thinking about what happens in case of errors, it became apparent to me that it was bad practice to leave the session structure in an half-initialised state and rely on the caller to call session_free(), so this commit also ensures we always clear the structure when loading failed. --- library/ssl_tls.c | 26 ++++++++++++++--- tests/suites/test_suite_ssl.data | 23 +++++++++++++++ tests/suites/test_suite_ssl.function | 42 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 6f9203daa..cc70510cb 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9959,11 +9959,14 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, } /* - * Unserialise session, see ssl_save_session() + * Unserialise session, see mbedtls_ssl_session_save(). + * + * This internal version is wrapped by a public function that cleans up in + * case of error. */ -int mbedtls_ssl_session_load( mbedtls_ssl_session *session, - const unsigned char *buf, - size_t len ) +static int ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) { const unsigned char *p = buf; const unsigned char * const end = buf + len; @@ -10091,6 +10094,21 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, return( 0 ); } +/* + * Unserialise session: public wrapper for error cleaning + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_session_load( session, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_session_free( session ); + + return( ret ); +} + /* * Perform a single step of the SSL handshake */ diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index b166a9a93..d41fcd01d 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -8798,3 +8798,26 @@ ssl_serialise_session_save_buf_size:42:"data_files/server5.crt" Session serialisation, save buffer size: large ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ssl_serialise_session_save_buf_size:1023:"data_files/server5.crt" + +Session serialisation, load buffer size: no ticket, no cert +ssl_serialise_session_load_buf_size:0:"" + +Session serialisation, load buffer size: small ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_load_buf_size:42:"" + +Session serialisation, load buffer size: large ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_load_buf_size:1023:"" + +Session serialisation, load buffer size: no ticket, cert +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_load_buf_size:0:"data_files/server5.crt" + +Session serialisation, load buffer size: small ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_load_buf_size:42:"data_files/server5.crt" + +Session serialisation, load buffer size: large ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_load_buf_size:1023:"data_files/server5.crt" diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 61ff41608..8a184d0f8 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -748,3 +748,45 @@ exit: mbedtls_free( buf ); } /* END_CASE */ + +/* BEGIN_CASE */ +void ssl_serialise_session_load_buf_size( int ticket_len, char *crt_file ) +{ + mbedtls_ssl_session session; + unsigned char *good_buf = NULL, *bad_buf = NULL; + size_t good_len, bad_len; + + /* + * Test that session_load() fails cleanly on small buffers + */ + + mbedtls_ssl_session_init( &session ); + + /* Prepare serialised session data */ + ssl_populate_session( &session, ticket_len, crt_file ); + TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &good_len ) + == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + TEST_ASSERT( ( good_buf = mbedtls_calloc( 1, good_len ) ) != NULL ); + TEST_ASSERT( mbedtls_ssl_session_save( &session, good_buf, good_len, + &good_len ) == 0 ); + mbedtls_ssl_session_free( &session ); + + /* Try all possible bad lengths */ + for( bad_len = 0; bad_len < good_len; bad_len++ ) + { + /* Allocate exact size so that asan/valgrind can detect any overread */ + mbedtls_free( bad_buf ); + bad_buf = mbedtls_calloc( 1, bad_len ? bad_len : 1 ); + TEST_ASSERT( bad_buf != NULL ); + memcpy( bad_buf, good_buf, bad_len ); + + TEST_ASSERT( mbedtls_ssl_session_load( &session, bad_buf, bad_len ) + == MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +exit: + mbedtls_ssl_session_free( &session ); + mbedtls_free( good_buf ); + mbedtls_free( bad_buf ); +} +/* END_CASE */ From 6b840704c4dda13b0224f23672ba6c363f95ebbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 09:40:17 +0200 Subject: [PATCH 034/114] Fix populate_session() and its usage in tests Not checking the return value allowed a bug to go undetected, fix the bug and check the return value. --- tests/suites/test_suite_ssl.function | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 8a184d0f8..61c17e121 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -288,6 +288,11 @@ static int ssl_populate_session( mbedtls_ssl_session *session, if( strlen( crt_file ) != 0 ) { int ret; + + session->peer_cert = mbedtls_calloc( 1, sizeof( *session->peer_cert ) ); + if( session->peer_cert == NULL ) + return( -1 ); + ret = mbedtls_x509_crt_parse_file( session->peer_cert, crt_file ); if( ret != 0 ) return( ret ); @@ -677,7 +682,7 @@ void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) mbedtls_ssl_session_init( &session ); /* Prepare a dummy session to work on */ - ssl_populate_session( &session, ticket_len, crt_file ); + TEST_ASSERT( ssl_populate_session( &session, ticket_len, crt_file ) == 0 ); /* Get desired buffer size for serialising */ TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &len0 ) @@ -727,7 +732,7 @@ void ssl_serialise_session_save_buf_size( int ticket_len, char *crt_file ) mbedtls_ssl_session_init( &session ); /* Prepare dummy session and get serialised size */ - ssl_populate_session( &session, ticket_len, crt_file ); + TEST_ASSERT( ssl_populate_session( &session, ticket_len, crt_file ) == 0 ); TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &good_len ) == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); @@ -763,7 +768,7 @@ void ssl_serialise_session_load_buf_size( int ticket_len, char *crt_file ) mbedtls_ssl_session_init( &session ); /* Prepare serialised session data */ - ssl_populate_session( &session, ticket_len, crt_file ); + TEST_ASSERT( ssl_populate_session( &session, ticket_len, crt_file ) == 0 ); TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &good_len ) == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); TEST_ASSERT( ( good_buf = mbedtls_calloc( 1, good_len ) ) != NULL ); From f9deaece430c0d3493a0712f56e6296ca749c9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 09:41:39 +0200 Subject: [PATCH 035/114] Add test that save-load is the identity This test works regardless of the serialisation format and embedded pointers in it, contrary to the load-save test, though it requires more maintenance of the test code (sync the member list with the struct definition). --- tests/suites/test_suite_ssl.data | 23 ++++++++ tests/suites/test_suite_ssl.function | 86 ++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index d41fcd01d..4041de229 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -8753,6 +8753,29 @@ SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA256 SHA-256 not enabled depends_on:!MBEDTLS_SHA256_C ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA256:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"7f9998393198a02c8d731ccc2ef90b2c":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +Session serialisation, save-load: no ticket, no cert +ssl_serialise_session_save_load:0:"" + +Session serialisation, save-load: small ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_save_load:42:"" + +Session serialisation, save-load: large ticket, no cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C +ssl_serialise_session_save_load:1023:"" + +Session serialisation, save-load: no ticket, cert +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_save_load:0:"data_files/server5.crt" + +Session serialisation, save-load: small ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_save_load:42:"data_files/server5.crt" + +Session serialisation, save-load: large ticket, cert +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ssl_serialise_session_save_load:1023:"data_files/server5.crt" + Session serialisation, load-save: no ticket, no cert ssl_serialise_session_load_save:0:"" diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 61c17e121..1c5f67c16 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -668,6 +668,92 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void ssl_serialise_session_save_load( int ticket_len, char *crt_file ) +{ + mbedtls_ssl_session original, restored; + unsigned char *buf = NULL; + size_t len; + + /* + * Test that a save-load pair is the identity + */ + + mbedtls_ssl_session_init( &original ); + mbedtls_ssl_session_init( &restored ); + + /* Prepare a dummy session to work on */ + TEST_ASSERT( ssl_populate_session( &original, ticket_len, crt_file ) == 0 ); + + /* Serialise it */ + TEST_ASSERT( mbedtls_ssl_session_save( &original, NULL, 0, &len ) + == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + TEST_ASSERT( ( buf = mbedtls_calloc( 1, len ) ) != NULL ); + TEST_ASSERT( mbedtls_ssl_session_save( &original, buf, len, &len ) + == 0 ); + + /* Restore session from serialised data */ + TEST_ASSERT( mbedtls_ssl_session_load( &restored, buf, len) == 0 ); + + /* + * Make sure both session structures are identical + */ +#if defined(MBEDTLS_HAVE_TIME) + TEST_ASSERT( original.start == restored.start ); +#endif + TEST_ASSERT( original.ciphersuite == restored.ciphersuite ); + TEST_ASSERT( original.compression == restored.compression ); + TEST_ASSERT( original.id_len == restored.id_len ); + TEST_ASSERT( memcmp( original.id, + restored.id, sizeof( original.id ) ) == 0 ); + TEST_ASSERT( memcmp( original.master, + restored.master, sizeof( original.master ) ) == 0 ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + TEST_ASSERT( ( original.peer_cert == NULL ) == + ( restored.peer_cert == NULL ) ); + if( original.peer_cert != NULL ) + { + TEST_ASSERT( original.peer_cert->raw.len == + restored.peer_cert->raw.len ); + TEST_ASSERT( memcmp( original.peer_cert->raw.p, + restored.peer_cert->raw.p, + original.peer_cert->raw.len ) == 0 ); + } +#endif + TEST_ASSERT( original.verify_result == restored.verify_result ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + TEST_ASSERT( original.ticket_len == restored.ticket_len ); + if( original.ticket_len != 0 ) + { + TEST_ASSERT( original.ticket != NULL ); + TEST_ASSERT( restored.ticket != NULL ); + TEST_ASSERT( memcmp( original.ticket, + restored.ticket, original.ticket_len ) == 0 ); + } + TEST_ASSERT( original.ticket_lifetime == restored.ticket_lifetime ); +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + TEST_ASSERT( original.mfl_code == restored.mfl_code ); +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + TEST_ASSERT( original.trunc_hmac == restored.trunc_hmac ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + TEST_ASSERT( original.encrypt_then_mac == restored.encrypt_then_mac ); +#endif + +exit: + mbedtls_ssl_session_free( &original ); + mbedtls_ssl_session_free( &restored ); + mbedtls_free( buf ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SEE_FUTURE_PR */ void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) { From 7b3a8875a4b563da2284ce7bc82d328316b769a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 09:48:05 +0200 Subject: [PATCH 036/114] Add list of coupled functions to struct definition --- include/mbedtls/ssl.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 92ce32463..be2159f1b 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -845,6 +845,14 @@ typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); /* * This structure is used for storing current session data. + * + * Note: when changing this definition, we need to check and update: + * - in tests/suites/test_suite_ssl.function: + * ssl_populate_session() and ssl_serialise_session_save_load() + * - in library/ssl_tls.c: + * mbedtls_ssl_session_init() and mbedtls_ssl_session_free() + * mbedtls_ssl_session_save() and ssl_session_load() + * ssl_session_copy() */ struct mbedtls_ssl_session { From b40799035b02da0348e6432a2e5e80fe0e5d95ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 09:52:10 +0200 Subject: [PATCH 037/114] Fix another wrong check for errors in test code --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 1c5f67c16..f1a793bda 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -789,7 +789,7 @@ void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) /* Allocate second buffer and serialise to it */ buf2 = mbedtls_calloc( 1, len0 ); - TEST_ASSERT( buf1 != NULL ); + TEST_ASSERT( buf2 != NULL ); TEST_ASSERT( mbedtls_ssl_session_save( &session, buf2, len0, &len2 ) == 0 ); From 220403b954080df4f939b9a993af16aafd05a189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 09:54:21 +0200 Subject: [PATCH 038/114] Fix style issues and typos in test code --- tests/suites/test_suite_ssl.function | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index f1a793bda..f172e1e75 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -272,8 +272,8 @@ cleanup: * Choose dummy values, mostly non-0 to distinguish from the init default. */ static int ssl_populate_session( mbedtls_ssl_session *session, - int ticket_len, - const char *crt_file ) + int ticket_len, + const char *crt_file ) { #if defined(MBEDTLS_HAVE_TIME) session->start = mbedtls_time( NULL ) - 42; @@ -282,7 +282,7 @@ static int ssl_populate_session( mbedtls_ssl_session *session, session->compression = 1; session->id_len = sizeof( session->id ); memset( session->id, 66, session->id_len ); - memset( session->master, 17, sizeof( session-> master ) ); + memset( session->master, 17, sizeof( session->master ) ); #if defined(MBEDTLS_X509_CRT_PARSE_C) if( strlen( crt_file ) != 0 ) @@ -306,7 +306,7 @@ static int ssl_populate_session( mbedtls_ssl_session *session, if( ticket_len != 0 ) { session->ticket = mbedtls_calloc( 1, ticket_len ); - if( session-> ticket == NULL ) + if( session->ticket == NULL ) return( -1 ); memset( session->ticket, 33, ticket_len ); } @@ -778,14 +778,14 @@ void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) buf1 = mbedtls_calloc( 1, len0 ); TEST_ASSERT( buf1 != NULL ); - /* Serialise to buffer and free session lived session */ + /* Serialise to buffer and free live session */ TEST_ASSERT( mbedtls_ssl_session_save( &session, buf1, len0, &len1 ) == 0 ); TEST_ASSERT( len0 == len1 ); mbedtls_ssl_session_free( &session ); /* Restore session from serialised data */ - TEST_ASSERT( mbedtls_ssl_session_load( &session, buf1, len1) == 0 ); + TEST_ASSERT( mbedtls_ssl_session_load( &session, buf1, len1 ) == 0 ); /* Allocate second buffer and serialise to it */ buf2 = mbedtls_calloc( 1, len0 ); From 1f6033a479a528e0b6b01ebb74ccb63a2e2476c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 10:17:52 +0200 Subject: [PATCH 039/114] Fix undeclared dependency on FS_IO in test code Found by 'all.sh test_no_platform' and by 'tests/scripts/test-ref-configs.pl'. --- tests/suites/test_suite_ssl.data | 24 ++++++++++++------------ tests/suites/test_suite_ssl.function | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 4041de229..a3e640b7f 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -8765,15 +8765,15 @@ depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C ssl_serialise_session_save_load:1023:"" Session serialisation, save-load: no ticket, cert -depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_save_load:0:"data_files/server5.crt" Session serialisation, save-load: small ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_save_load:42:"data_files/server5.crt" Session serialisation, save-load: large ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_save_load:1023:"data_files/server5.crt" Session serialisation, load-save: no ticket, no cert @@ -8788,15 +8788,15 @@ depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C ssl_serialise_session_load_save:1023:"" Session serialisation, load-save: no ticket, cert -depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_load_save:0:"data_files/server5.crt" Session serialisation, load-save: small ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_load_save:42:"data_files/server5.crt" Session serialisation, load-save: large ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_load_save:1023:"data_files/server5.crt" Session serialisation, save buffer size: no ticket, no cert @@ -8811,15 +8811,15 @@ depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C ssl_serialise_session_save_buf_size:1023:"" Session serialisation, save buffer size: no ticket, cert -depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_save_buf_size:0:"data_files/server5.crt" Session serialisation, save buffer size: small ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_save_buf_size:42:"data_files/server5.crt" Session serialisation, save buffer size: large ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_save_buf_size:1023:"data_files/server5.crt" Session serialisation, load buffer size: no ticket, no cert @@ -8834,13 +8834,13 @@ depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C ssl_serialise_session_load_buf_size:1023:"" Session serialisation, load buffer size: no ticket, cert -depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_load_buf_size:0:"data_files/server5.crt" Session serialisation, load buffer size: small ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_load_buf_size:42:"data_files/server5.crt" Session serialisation, load buffer size: large ticket, cert -depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO ssl_serialise_session_load_buf_size:1023:"data_files/server5.crt" diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index f172e1e75..2b755edf4 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -284,7 +284,7 @@ static int ssl_populate_session( mbedtls_ssl_session *session, memset( session->id, 66, session->id_len ); memset( session->master, 17, sizeof( session->master ) ); -#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_FS_IO) if( strlen( crt_file ) != 0 ) { int ret; From 6472263eade048c65973e77f3afea2ed3dcbcca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 10:23:55 +0200 Subject: [PATCH 040/114] Add a ChangeLog entry for session serialisation --- ChangeLog | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d84769208..1740eba55 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,10 @@ Features changed its IP or port. The feature is enabled at compile-time by setting MBEDTLS_SSL_DTLS_CONNECTION_ID (disabled by default), and at run-time through the new APIs mbedtls_ssl_conf_cid() and mbedtls_ssl_set_cid(). + * Add new API functions mbedtls_ssl_session_save() and + mbedtls_ssl_session_load() to allow serialising a session, for example to + store it in non-volatile storage, and later using it for TLS session + resumption. API Changes * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, @@ -96,7 +100,6 @@ Bugfix * Fix propagation of restart contexts in restartable EC operations. This could previously lead to segmentation faults in builds using an address-sanitizer and enabling but not using MBEDTLS_ECP_RESTARTABLE. - Changes * Server's RSA certificate in certs.c was SHA-1 signed. In the default mbedTLS configuration only SHA-2 signed certificates are accepted. @@ -139,6 +142,15 @@ Changes * Adds fuzz targets, especially for continuous fuzzing with OSS-Fuzz. Contributed by Philippe Antoine (Catena cyber). +API Changes + * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, + and the used tls-prf. + * Add public API for tls-prf function, according to requested enum. + * Add DER-encoded test CRTs to library/certs.c, allowing + the example programs ssl_server2 and ssl_client2 to be run + if MBEDTLS_FS_IO and MBEDTLS_PEM_PARSE_C are unset. Fixes #2254. + * The HAVEGE state type now uses uint32_t elements instead of int. + = mbed TLS 2.17.0 branch released 2019-03-19 Features From 4d591d6d3feabf0982dbf16b5773ccf770dfc1da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 10:26:41 +0200 Subject: [PATCH 041/114] Demonstrate safe usage (zeroize) in ssl_client2 --- programs/ssl/ssl_client2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 317fea373..1fc86c5d7 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2459,8 +2459,12 @@ int main( int argc, char *argv[] ) if( opt.reco_mode == 1 ) { /* free any previously saved data */ - mbedtls_free( session_data ); - session_data = NULL; + if( session_data != NULL ) + { + mbedtls_platform_zeroize( session_data, session_data_len ); + mbedtls_free( session_data ); + session_data = NULL; + } /* get size of the buffer needed */ mbedtls_ssl_session_save( mbedtls_ssl_get_session_pointer( &ssl ), @@ -3024,6 +3028,8 @@ exit: mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); + if( session_data != NULL ) + mbedtls_platform_zeroize( session_data, session_data_len ); mbedtls_free( session_data ); #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ From df9bc2193bb95dd06a524e0f6880240fe75d241e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 27 May 2019 09:58:07 +0200 Subject: [PATCH 042/114] Improve documentation --- include/mbedtls/ssl.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index be2159f1b..270a77e29 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2382,6 +2382,8 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + * \return Another negative value for other kinds of errors (for + * example, unsupported features in the embedded certificate). */ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, const unsigned char *buf, @@ -2422,16 +2424,16 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, * \brief Get a pointer to the current session structure, for example * to serialise it. * - * \warning Ownership of the session remains with the SSL context - the - * returned pointer must not be kept after the connection has - * ended or been renegotiated. + * \warning Ownership of the session remains with the SSL context, and + * the returned pointer is only guaranteed to be valid until + * the next API call operating on the same \p ssl context. * * \see mbedtls_ssl_session_save() * - * \param ssl SSL context + * \param ssl The SSL context. * - * \return A pointer to the current session if successful, - * NULL if no session is active. + * \return A pointer to the current session if successful. + * \return \c NULL if no session is active. */ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_context *ssl ); From 686adb4d54a4eb352350862788d5a95505fc275d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 3 Jun 2019 09:55:16 +0200 Subject: [PATCH 043/114] Normalize spelling to serialiZation We have explicit recommendations to use US spelling for technical writing, so let's apply this to code as well for uniformity. (My fingers tend to prefer UK spelling, so this needs to be fixed in many places.) sed -i 's/\([Ss]eriali\)s/\1z/g' **/*.[ch] **/*.function **/*.data ChangeLog --- ChangeLog | 2 +- include/mbedtls/ssl.h | 14 ++-- library/ssl_tls.c | 4 +- programs/ssl/ssl_client2.c | 2 +- tests/suites/test_suite_ssl.data | 96 ++++++++++++++-------------- tests/suites/test_suite_ssl.function | 28 ++++---- 6 files changed, 73 insertions(+), 73 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1740eba55..459e81042 100644 --- a/ChangeLog +++ b/ChangeLog @@ -32,7 +32,7 @@ Features MBEDTLS_SSL_DTLS_CONNECTION_ID (disabled by default), and at run-time through the new APIs mbedtls_ssl_conf_cid() and mbedtls_ssl_set_cid(). * Add new API functions mbedtls_ssl_session_save() and - mbedtls_ssl_session_load() to allow serialising a session, for example to + mbedtls_ssl_session_load() to allow serializing a session, for example to store it in non-volatile storage, and later using it for TLS session resumption. diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 270a77e29..ed7d7ee2d 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -848,7 +848,7 @@ typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); * * Note: when changing this definition, we need to check and update: * - in tests/suites/test_suite_ssl.function: - * ssl_populate_session() and ssl_serialise_session_save_load() + * ssl_populate_session() and ssl_serialize_session_save_load() * - in library/ssl_tls.c: * mbedtls_ssl_session_init() and mbedtls_ssl_session_free() * mbedtls_ssl_session_save() and ssl_session_load() @@ -2357,14 +2357,14 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session #endif /* MBEDTLS_SSL_CLI_C */ /** - * \brief Load serialised session data into a session structure. + * \brief Load serialized session data into a session structure. * On client, this can be used for loading saved sessions * before resuming them with mbedstls_ssl_set_session(). * On server, this can be used for alternative implementations * of session cache or session tickets. * * \warning If a peer certificate chain is associated with the session, - * the serialised state will only contain the peer's + * the serialized state will only contain the peer's * end-entity certificate and the result of the chain * verification (unless verification was disabled), but not * the rest of the chain. @@ -2375,9 +2375,9 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session * \param session The session structure to be populated. It must have been * initialised with mbedtls_ssl_session_init() but not * populated yet. - * \param buf The buffer holding the serialised session data. It must be a + * \param buf The buffer holding the serialized session data. It must be a * readable buffer of at least \p len bytes. - * \param len The size of the serialised data in bytes. + * \param len The size of the serialized data in bytes. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. @@ -2390,7 +2390,7 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, size_t len ); /** - * \brief Save session structure as serialised data in a buffer. + * \brief Save session structure as serialized data in a buffer. * On client, this can be used for saving session data, * potentially in non-volatile storage, for resuming later. * On server, this can be used for alternative implementations @@ -2422,7 +2422,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, /** * \brief Get a pointer to the current session structure, for example - * to serialise it. + * to serialize it. * * \warning Ownership of the session remains with the SSL context, and * the returned pointer is only guaranteed to be valid until diff --git a/library/ssl_tls.c b/library/ssl_tls.c index cc70510cb..8342a3ee6 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9959,7 +9959,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, } /* - * Unserialise session, see mbedtls_ssl_session_save(). + * Unserialize session, see mbedtls_ssl_session_save(). * * This internal version is wrapped by a public function that cleans up in * case of error. @@ -10095,7 +10095,7 @@ static int ssl_session_load( mbedtls_ssl_session *session, } /* - * Unserialise session: public wrapper for error cleaning + * Unserialize session: public wrapper for error cleaning */ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, const unsigned char *buf, diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 1fc86c5d7..0d7cb667e 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -382,7 +382,7 @@ int main( void ) " reconnect=%%d number of reconnections using session resumption\n" \ " default: 0 (disabled)\n" \ " reco_delay=%%d default: 0 seconds\n" \ - " reco_mode=%%d 0: copy session, 1: serialise session\n" \ + " reco_mode=%%d 0: copy session, 1: serialize session\n" \ " default: 1\n" \ " reconnect_hard=%%d default: 0 (disabled)\n" \ USAGE_TICKETS \ diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index a3e640b7f..01517c19c 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -8753,94 +8753,94 @@ SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_SHA256 SHA-256 not enabled depends_on:!MBEDTLS_SHA256_C ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_SHA256:"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef":"test tls_prf label":"7f9998393198a02c8d731ccc2ef90b2c":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -Session serialisation, save-load: no ticket, no cert -ssl_serialise_session_save_load:0:"" +Session serialization, save-load: no ticket, no cert +ssl_serialize_session_save_load:0:"" -Session serialisation, save-load: small ticket, no cert +Session serialization, save-load: small ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_save_load:42:"" +ssl_serialize_session_save_load:42:"" -Session serialisation, save-load: large ticket, no cert +Session serialization, save-load: large ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_save_load:1023:"" +ssl_serialize_session_save_load:1023:"" -Session serialisation, save-load: no ticket, cert +Session serialization, save-load: no ticket, cert depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_save_load:0:"data_files/server5.crt" +ssl_serialize_session_save_load:0:"data_files/server5.crt" -Session serialisation, save-load: small ticket, cert +Session serialization, save-load: small ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_save_load:42:"data_files/server5.crt" +ssl_serialize_session_save_load:42:"data_files/server5.crt" -Session serialisation, save-load: large ticket, cert +Session serialization, save-load: large ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_save_load:1023:"data_files/server5.crt" +ssl_serialize_session_save_load:1023:"data_files/server5.crt" -Session serialisation, load-save: no ticket, no cert -ssl_serialise_session_load_save:0:"" +Session serialization, load-save: no ticket, no cert +ssl_serialize_session_load_save:0:"" -Session serialisation, load-save: small ticket, no cert +Session serialization, load-save: small ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_load_save:42:"" +ssl_serialize_session_load_save:42:"" -Session serialisation, load-save: large ticket, no cert +Session serialization, load-save: large ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_load_save:1023:"" +ssl_serialize_session_load_save:1023:"" -Session serialisation, load-save: no ticket, cert +Session serialization, load-save: no ticket, cert depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_load_save:0:"data_files/server5.crt" +ssl_serialize_session_load_save:0:"data_files/server5.crt" -Session serialisation, load-save: small ticket, cert +Session serialization, load-save: small ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_load_save:42:"data_files/server5.crt" +ssl_serialize_session_load_save:42:"data_files/server5.crt" -Session serialisation, load-save: large ticket, cert +Session serialization, load-save: large ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_load_save:1023:"data_files/server5.crt" +ssl_serialize_session_load_save:1023:"data_files/server5.crt" -Session serialisation, save buffer size: no ticket, no cert -ssl_serialise_session_save_buf_size:0:"" +Session serialization, save buffer size: no ticket, no cert +ssl_serialize_session_save_buf_size:0:"" -Session serialisation, save buffer size: small ticket, no cert +Session serialization, save buffer size: small ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_save_buf_size:42:"" +ssl_serialize_session_save_buf_size:42:"" -Session serialisation, save buffer size: large ticket, no cert +Session serialization, save buffer size: large ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_save_buf_size:1023:"" +ssl_serialize_session_save_buf_size:1023:"" -Session serialisation, save buffer size: no ticket, cert +Session serialization, save buffer size: no ticket, cert depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_save_buf_size:0:"data_files/server5.crt" +ssl_serialize_session_save_buf_size:0:"data_files/server5.crt" -Session serialisation, save buffer size: small ticket, cert +Session serialization, save buffer size: small ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_save_buf_size:42:"data_files/server5.crt" +ssl_serialize_session_save_buf_size:42:"data_files/server5.crt" -Session serialisation, save buffer size: large ticket, cert +Session serialization, save buffer size: large ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_save_buf_size:1023:"data_files/server5.crt" +ssl_serialize_session_save_buf_size:1023:"data_files/server5.crt" -Session serialisation, load buffer size: no ticket, no cert -ssl_serialise_session_load_buf_size:0:"" +Session serialization, load buffer size: no ticket, no cert +ssl_serialize_session_load_buf_size:0:"" -Session serialisation, load buffer size: small ticket, no cert +Session serialization, load buffer size: small ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_load_buf_size:42:"" +ssl_serialize_session_load_buf_size:42:"" -Session serialisation, load buffer size: large ticket, no cert +Session serialization, load buffer size: large ticket, no cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C -ssl_serialise_session_load_buf_size:1023:"" +ssl_serialize_session_load_buf_size:1023:"" -Session serialisation, load buffer size: no ticket, cert +Session serialization, load buffer size: no ticket, cert depends_on:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_load_buf_size:0:"data_files/server5.crt" +ssl_serialize_session_load_buf_size:0:"data_files/server5.crt" -Session serialisation, load buffer size: small ticket, cert +Session serialization, load buffer size: small ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_load_buf_size:42:"data_files/server5.crt" +ssl_serialize_session_load_buf_size:42:"data_files/server5.crt" -Session serialisation, load buffer size: large ticket, cert +Session serialization, load buffer size: large ticket, cert depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_X509_USE_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_FS_IO -ssl_serialise_session_load_buf_size:1023:"data_files/server5.crt" +ssl_serialize_session_load_buf_size:1023:"data_files/server5.crt" diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 2b755edf4..5a32ac9a8 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -268,7 +268,7 @@ cleanup: } /* - * Populate a session structure for serialisation tests. + * Populate a session structure for serialization tests. * Choose dummy values, mostly non-0 to distinguish from the init default. */ static int ssl_populate_session( mbedtls_ssl_session *session, @@ -669,7 +669,7 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void ssl_serialise_session_save_load( int ticket_len, char *crt_file ) +void ssl_serialize_session_save_load( int ticket_len, char *crt_file ) { mbedtls_ssl_session original, restored; unsigned char *buf = NULL; @@ -685,14 +685,14 @@ void ssl_serialise_session_save_load( int ticket_len, char *crt_file ) /* Prepare a dummy session to work on */ TEST_ASSERT( ssl_populate_session( &original, ticket_len, crt_file ) == 0 ); - /* Serialise it */ + /* Serialize it */ TEST_ASSERT( mbedtls_ssl_session_save( &original, NULL, 0, &len ) == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); TEST_ASSERT( ( buf = mbedtls_calloc( 1, len ) ) != NULL ); TEST_ASSERT( mbedtls_ssl_session_save( &original, buf, len, &len ) == 0 ); - /* Restore session from serialised data */ + /* Restore session from serialized data */ TEST_ASSERT( mbedtls_ssl_session_load( &restored, buf, len) == 0 ); /* @@ -755,7 +755,7 @@ exit: /* END_CASE */ /* BEGIN_CASE depends_on:MBEDTLS_SEE_FUTURE_PR */ -void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) +void ssl_serialize_session_load_save( int ticket_len, char *crt_file ) { mbedtls_ssl_session session; unsigned char *buf1 = NULL, *buf2 = NULL; @@ -770,7 +770,7 @@ void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) /* Prepare a dummy session to work on */ TEST_ASSERT( ssl_populate_session( &session, ticket_len, crt_file ) == 0 ); - /* Get desired buffer size for serialising */ + /* Get desired buffer size for serializing */ TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &len0 ) == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); @@ -778,22 +778,22 @@ void ssl_serialise_session_load_save( int ticket_len, char *crt_file ) buf1 = mbedtls_calloc( 1, len0 ); TEST_ASSERT( buf1 != NULL ); - /* Serialise to buffer and free live session */ + /* Serialize to buffer and free live session */ TEST_ASSERT( mbedtls_ssl_session_save( &session, buf1, len0, &len1 ) == 0 ); TEST_ASSERT( len0 == len1 ); mbedtls_ssl_session_free( &session ); - /* Restore session from serialised data */ + /* Restore session from serialized data */ TEST_ASSERT( mbedtls_ssl_session_load( &session, buf1, len1 ) == 0 ); - /* Allocate second buffer and serialise to it */ + /* Allocate second buffer and serialize to it */ buf2 = mbedtls_calloc( 1, len0 ); TEST_ASSERT( buf2 != NULL ); TEST_ASSERT( mbedtls_ssl_session_save( &session, buf2, len0, &len2 ) == 0 ); - /* Make sure both serialised versions are identical */ + /* Make sure both serialized versions are identical */ TEST_ASSERT( len1 == len2 ); TEST_ASSERT( memcmp( buf1, buf2, len1 ) == 0 ); @@ -805,7 +805,7 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void ssl_serialise_session_save_buf_size( int ticket_len, char *crt_file ) +void ssl_serialize_session_save_buf_size( int ticket_len, char *crt_file ) { mbedtls_ssl_session session; unsigned char *buf = NULL; @@ -817,7 +817,7 @@ void ssl_serialise_session_save_buf_size( int ticket_len, char *crt_file ) mbedtls_ssl_session_init( &session ); - /* Prepare dummy session and get serialised size */ + /* Prepare dummy session and get serialized size */ TEST_ASSERT( ssl_populate_session( &session, ticket_len, crt_file ) == 0 ); TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &good_len ) == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); @@ -841,7 +841,7 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void ssl_serialise_session_load_buf_size( int ticket_len, char *crt_file ) +void ssl_serialize_session_load_buf_size( int ticket_len, char *crt_file ) { mbedtls_ssl_session session; unsigned char *good_buf = NULL, *bad_buf = NULL; @@ -853,7 +853,7 @@ void ssl_serialise_session_load_buf_size( int ticket_len, char *crt_file ) mbedtls_ssl_session_init( &session ); - /* Prepare serialised session data */ + /* Prepare serialized session data */ TEST_ASSERT( ssl_populate_session( &session, ticket_len, crt_file ) == 0 ); TEST_ASSERT( mbedtls_ssl_session_save( &session, NULL, 0, &good_len ) == MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); From 51a0bfd9bc07a549368eb0b87f79291fb96ae4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 31 Jul 2019 10:40:26 +0200 Subject: [PATCH 044/114] Fix bug in cert digest serialisation This bug was present since cert digest had been introduced, which highlights the need for testing. While at it, fix a bug in the comment explaining the format - this was introduced by me copy-pasting to hastily from current baremetal, that has a different format (see next PR in the series for the same in development). --- library/ssl_tls.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8342a3ee6..db09bf8ee 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9849,8 +9849,7 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co * opaque session_struct[n]; // n = sizeof(mbedtls_ssl_session) * select (MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) { * case enabled: opaque peer_cert<0..2^24-1>; // length 0 means no cert - * case disabled: uint8_t peer_cert_digest_type; - * opaque peer_cert_digest<0..2^8-1>; + * case disabled: opaque peer_cert_digest<0..2^8-1>; * } * opaque ticket<0..2^24-1>; // 0 means no ticket * @@ -9910,7 +9909,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, } } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - if( session->peer_cert_digest != NULL ) + if( session->peer_cert_digest == NULL ) cert_digest_len = 0; else cert_digest_len = session->peer_cert_digest_len; From ee13a732d66f084061e33bd048a2ddec99884fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 29 Jul 2019 13:00:39 +0200 Subject: [PATCH 045/114] Fix serialization tests for !SSL_KEEP_PEER_CERT The chosen fix matches what's currently done in the baremetal branch - except the `#ifdef` have been adapted because now in baremetal the digest is not kept if renegotiation is disabled. --- tests/suites/test_suite_ssl.function | 50 +++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 5a32ac9a8..25ef95d6f 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -287,19 +287,44 @@ static int ssl_populate_session( mbedtls_ssl_session *session, #if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_FS_IO) if( strlen( crt_file ) != 0 ) { + mbedtls_x509_crt tmp_crt; int ret; + mbedtls_x509_crt_init( &tmp_crt ); + ret = mbedtls_x509_crt_parse_file( &tmp_crt, crt_file ); + if( ret != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* Move temporary CRT. */ session->peer_cert = mbedtls_calloc( 1, sizeof( *session->peer_cert ) ); if( session->peer_cert == NULL ) return( -1 ); - - ret = mbedtls_x509_crt_parse_file( session->peer_cert, crt_file ); + *session->peer_cert = tmp_crt; + memset( &tmp_crt, 0, sizeof( tmp_crt ) ); +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Calculate digest of temporary CRT. */ + session->peer_cert_digest = + mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ); + if( session->peer_cert_digest == NULL ) + return( -1 ); + ret = mbedtls_md( mbedtls_md_info_from_type( + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ), + tmp_crt.raw.p, tmp_crt.raw.len, + session->peer_cert_digest ); if( ret != 0 ) return( ret ); + session->peer_cert_digest_type = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; + session->peer_cert_digest_len = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + mbedtls_x509_crt_free( &tmp_crt ); } -#else +#else /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO */ (void) crt_file; -#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO */ session->verify_result = 0xdeadbeef; #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) @@ -710,6 +735,7 @@ void ssl_serialize_session_save_load( int ticket_len, char *crt_file ) restored.master, sizeof( original.master ) ) == 0 ); #if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) TEST_ASSERT( ( original.peer_cert == NULL ) == ( restored.peer_cert == NULL ) ); if( original.peer_cert != NULL ) @@ -720,7 +746,21 @@ void ssl_serialize_session_save_load( int ticket_len, char *crt_file ) restored.peer_cert->raw.p, original.peer_cert->raw.len ) == 0 ); } -#endif +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + TEST_ASSERT( original.peer_cert_digest_type == + restored.peer_cert_digest_type ); + TEST_ASSERT( original.peer_cert_digest_len == + restored.peer_cert_digest_len ); + TEST_ASSERT( ( original.peer_cert_digest == NULL ) == + ( restored.peer_cert_digest == NULL ) ); + if( original.peer_cert_digest != NULL ) + { + TEST_ASSERT( memcmp( original.peer_cert_digest, + restored.peer_cert_digest, + original.peer_cert_digest_len ) == 0 ); + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ TEST_ASSERT( original.verify_result == restored.verify_result ); #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) From f743c03ea7fbe0946aafb5b77b8128096dd5d9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 24 May 2019 12:06:29 +0200 Subject: [PATCH 046/114] Add new ABI-independent format for serialization --- library/ssl_tls.c | 269 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 213 insertions(+), 56 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index db09bf8ee..4a886ae0e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9846,14 +9846,23 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co * Serialize a session in the following format: * (in the presentation language of TLS, RFC 8446 section 3) * - * opaque session_struct[n]; // n = sizeof(mbedtls_ssl_session) - * select (MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) { - * case enabled: opaque peer_cert<0..2^24-1>; // length 0 means no cert - * case disabled: opaque peer_cert_digest<0..2^8-1>; - * } - * opaque ticket<0..2^24-1>; // 0 means no ticket + * uint64 start_time; + * uint8 ciphersuite[2]; // defined by the standard + * uint8 compression; // 0 or 1 + * uint8 session_id_len; // at most 32 + * opaque session_id[32]; + * opaque master[48]; // fixed length in the standard + * uint32 verify_result; + * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert + * opaque ticket<0..2^24-1>; // length 0 means no ticket + * uint32 ticket_lifetime; + * uint8 mfl_code; // up to 255 according to standard + * uint8 trunc_hmac; // 0 or 1 + * uint8 encrypt_then_mac; // 0 or 1 * - * Only the peer's certificate is saved, not the whole chain. + * The order is the same as in the definition of the structure, except + * verify_result is put before peer_cert so that all mandatory fields come + * together in one block. */ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, unsigned char *buf, @@ -9862,30 +9871,69 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, { unsigned char *p = buf; size_t used = 0; +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) size_t cert_len; -#else - size_t cert_digest_len; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ - /* - * Shallow copy of the session structure - */ - used += sizeof( mbedtls_ssl_session ); - /* This also copies the values of pointer fields in the - * session to be serialized, but they'll be ignored when - * loading the session through ssl_load_session(). */ + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + used += 8; + if( used <= buf_len ) { - memcpy( p, session, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); + start = (uint64_t) session->start; + + *p++ = (unsigned char)( ( start >> 56 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 48 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 40 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 32 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( start >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( start ) & 0xFF ); + } +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + used += 2 /* ciphersuite */ + + 1 /* compression */ + + 1 /* id_len */ + + sizeof( session->id ) + + sizeof( session->master ) + + 4; /* verify_result */ + + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( session->ciphersuite >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ciphersuite ) & 0xFF ); + + *p++ = (unsigned char)( session->compression & 0xFF ); + + *p++ = (unsigned char)( session->id_len & 0xFF ); + memcpy( p, session->id, 32 ); + p += 32; + + memcpy( p, session->master, 48 ); + p += 48; + + *p++ = (unsigned char)( ( session->verify_result >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( session->verify_result >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->verify_result >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->verify_result ) & 0xFF ); } /* - * Copy of the peer's end-entity certificate + * Peer's end-entity certificate */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) @@ -9909,30 +9957,35 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, } } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ - if( session->peer_cert_digest == NULL ) - cert_digest_len = 0; - else - cert_digest_len = session->peer_cert_digest_len; - - used += 1 + cert_digest_len; - - if( used <= buf_len ) + if( session->peer_cert_digest != NULL ) { - *p++ = (unsigned char) cert_digest_len; - - if( session->peer_cert_digest != NULL ) - memcpy( p, session->peer_cert_digest, cert_digest_len ); - - p += cert_digest_len; + used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; + if( used <= buf_len ) + { + *p++ = (unsigned char) session->peer_cert_digest_type; + *p++ = (unsigned char) session->peer_cert_digest_len; + memcpy( p, session->peer_cert_digest, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; + } + } + else + { + used += 2; + if( used <= buf_len ) + { + *p++ = (unsigned char) MBEDTLS_MD_NONE; + *p++ = 0; + } } #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* - * Copy of the session ticket if any + * Session ticket if any, plus associated data */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - used += 3 + session->ticket_len; + used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ if( used <= buf_len ) { @@ -9945,9 +9998,38 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, memcpy( p, session->ticket, session->ticket_len ); p += session->ticket_len; } + + *p++ = (unsigned char)( ( session->ticket_lifetime >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_lifetime ) & 0xFF ); } #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + used += 1; + + if( used <= buf_len ) + *p++ = session->mfl_code; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + used += 1; + + if( used <= buf_len ) + *p++ = (unsigned char)( ( session->trunc_hmac ) & 0xFF ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + used += 1; + + if( used <= buf_len ) + *p++ = (unsigned char)( ( session->encrypt_then_mac ) & 0xFF ); +#endif + /* Done */ *olen = used; @@ -9958,7 +10040,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, } /* - * Unserialize session, see mbedtls_ssl_session_save(). + * Unserialize session, see mbedtls_ssl_session_save() for format. * * This internal version is wrapped by a public function that cleans up in * case of error. @@ -9969,25 +10051,61 @@ static int ssl_session_load( mbedtls_ssl_session *session, { const unsigned char *p = buf; const unsigned char * const end = buf + len; +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) size_t cert_len; -#else - size_t cert_digest_len; #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* - * Shallow session structure + * Time */ - if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) +#if defined(MBEDTLS_HAVE_TIME) + if( 8 > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - memcpy( session, p, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); + start = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; - /* Non-NULL pointer fields of `session` are meaningless - * and potentially harmful. Zeroize them for safety. */ + session->start = (time_t) start; +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + if( 2 + 1 + 1 + 32 + 48 + 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ciphersuite = ( p[0] << 8 ) | p[1]; + p += 2; + + session->compression = *p++; + + session->id_len = *p++; + memcpy( session->id, p, 32 ); + p += 32; + + memcpy( session->master, p, 48 ); + p += 48; + + session->verify_result = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; + + /* Immediately clear invalid pointer values that have been read, in case + * we exit early before we replaced them with valid ones. */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) session->peer_cert = NULL; @@ -10038,32 +10156,38 @@ static int ssl_session_load( mbedtls_ssl_session *session, } #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ /* Deserialize CRT digest from the end of the ticket. */ - if( 1 > (size_t)( end - p ) ) + if( 2 > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - cert_digest_len = (size_t) p[0]; - p++; + session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; + session->peer_cert_digest_len = (size_t) *p++; - if( cert_digest_len != 0 ) + if( session->peer_cert_digest_len != 0 ) { - if( cert_digest_len > (size_t)( end - p ) || - cert_digest_len != session->peer_cert_digest_len ) - { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type( session->peer_cert_digest_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - session->peer_cert_digest = mbedtls_calloc( 1, cert_digest_len ); + if( session->peer_cert_digest_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert_digest = + mbedtls_calloc( 1, session->peer_cert_digest_len ); if( session->peer_cert_digest == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - memcpy( session->peer_cert_digest, p, cert_digest_len ); - p += cert_digest_len; + memcpy( session->peer_cert_digest, p, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; } #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* - * Session ticket + * Session ticket and associated data */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) if( 3 > (size_t)( end - p ) ) @@ -10084,8 +10208,41 @@ static int ssl_session_load( mbedtls_ssl_session *session, memcpy( session->ticket, p, session->ticket_len ); p += session->ticket_len; } + + if( 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_lifetime = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->mfl_code = *p++; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->trunc_hmac = *p++; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->encrypt_then_mac = *p++; +#endif + /* Done, should have consumed entire buffer */ if( p != end ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); From eef4c753f1cbfcdf4118724b0c1209aaec020f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 May 2019 10:21:30 +0200 Subject: [PATCH 047/114] Adapt buffering test to new ticket size The size of the ticket used in this test dropped from 192 to 143 bytes, so move all sizes used in this test down 50 bytes. Also, we now need to adapt the server response size as the default size would otherwise collide with the new mtu value. --- tests/scripts/all.sh | 2 +- tests/ssl-opt.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 60176800f..903739421 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -743,7 +743,7 @@ component_test_small_ssl_dtls_max_buffering () { component_test_small_mbedtls_ssl_dtls_max_buffering () { msg "build: small MBEDTLS_SSL_DTLS_MAX_BUFFERING #1" - scripts/config.pl set MBEDTLS_SSL_DTLS_MAX_BUFFERING 240 + scripts/config.pl set MBEDTLS_SSL_DTLS_MAX_BUFFERING 190 CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index bb4081784..e0136a0f6 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -8318,11 +8318,11 @@ run_test "DTLS reordering: Buffer encrypted Finished message" \ # without fragmentation or be reassembled within the bounds of # MBEDTLS_SSL_DTLS_MAX_BUFFERING. Achieve this by testing with a PSK-based # handshake, omitting CRTs. -requires_config_value_at_least "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 240 -requires_config_value_at_most "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 280 +requires_config_value_at_least "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 190 +requires_config_value_at_most "MBEDTLS_SSL_DTLS_MAX_BUFFERING" 230 run_test "DTLS reordering: Buffer encrypted Finished message, drop for fragmented NewSessionTicket" \ -p "$P_PXY delay_srv=NewSessionTicket delay_srv=NewSessionTicket delay_ccs=1" \ - "$P_SRV mtu=190 dgram_packing=0 psk=abc123 psk_identity=foo cookies=0 dtls=1 debug_level=2" \ + "$P_SRV mtu=140 response_size=90 dgram_packing=0 psk=abc123 psk_identity=foo cookies=0 dtls=1 debug_level=2" \ "$P_CLI dgram_packing=0 dtls=1 debug_level=2 force_ciphersuite=TLS-PSK-WITH-AES-128-CCM-8 psk=abc123 psk_identity=foo" \ 0 \ -s "Buffer record from epoch 1" \ From aa75583ced5166edf21ebcef7ff6f7713c19a72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 3 Jun 2019 10:53:47 +0200 Subject: [PATCH 048/114] Re-enable test that now works with new format Previously the test didn't work because of embedded pointer values that are not predictable. Now it works as we no longer serialize such values. --- tests/suites/test_suite_ssl.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 25ef95d6f..4faa5d33f 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -794,7 +794,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_SEE_FUTURE_PR */ +/* BEGIN_CASE */ void ssl_serialize_session_load_save( int ticket_len, char *crt_file ) { mbedtls_ssl_session session; From a835da5cb194800c15145b4212f4febe56f8cea5 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 16 May 2019 12:39:07 +0100 Subject: [PATCH 049/114] Add Mbed TLS version to SSL sessions The format of serialized SSL sessions depends on the version and the configuration of Mbed TLS; attempts to restore sessions established in different versions and/or configurations lead to undefined behaviour. This commit adds an 3-byte version header to the serialized session generated and cleanly fails ticket parsing in case a session from a non-matching version of Mbed TLS is presented. --- library/ssl_tls.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 4a886ae0e..b6c585f4d 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -47,6 +47,7 @@ #include "mbedtls/ssl.h" #include "mbedtls/ssl_internal.h" #include "mbedtls/platform_util.h" +#include "mbedtls/version.h" #include @@ -9842,10 +9843,22 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co return( ssl->session ); } +/* + * Define ticket header determining Mbed TLS version + * and structure of the ticket. + */ + + static unsigned char ssl_serialized_session_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + }; + /* * Serialize a session in the following format: * (in the presentation language of TLS, RFC 8446 section 3) * + * opaque mbedtls_version[3]; // major, minor, patch * uint64 start_time; * uint8 ciphersuite[2]; // defined by the standard * uint8 compression; // 0 or 1 @@ -9881,6 +9894,19 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Add version identifier + */ + + used += sizeof( ssl_serialized_session_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ); + p += sizeof( ssl_serialized_session_header ); + } + /* * Time */ @@ -10060,6 +10086,21 @@ static int ssl_session_load( mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Check version identifier + */ + + if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + if( memcmp( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ) != 0 ) + { + /* A more specific error code might be used here. */ + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + p += sizeof( ssl_serialized_session_header ); + /* * Time */ From f878707b8f41c675ca4b0e93e1fe751ffbfcc9ab Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 16 May 2019 12:41:07 +0100 Subject: [PATCH 050/114] Add configuration identifier to serialized SSL sessions This commit adds space for two bytes in the header of serizlied SSL sessions which can be used to determine the structure of the remaining serialized session in the respective version of Mbed TLS. Specifically, if parts of the session depend on whether specific compile-time options are set or not, the setting of these options can be encoded in the added space. This commit doesn't yet make use of the fields. --- library/ssl_tls.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b6c585f4d..ca52752c2 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9848,17 +9848,26 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co * and structure of the ticket. */ - static unsigned char ssl_serialized_session_header[] = { - MBEDTLS_VERSION_MAJOR, - MBEDTLS_VERSION_MINOR, - MBEDTLS_VERSION_PATCH, - }; +static unsigned char ssl_serialized_session_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + 0xFF /* TBD */, + 0xFF /* TBD */ +}; /* * Serialize a session in the following format: * (in the presentation language of TLS, RFC 8446 section 3) * * opaque mbedtls_version[3]; // major, minor, patch + * opaque session_format[2]; // version-specific 16-bit field determining + * // the format of the remaining serialized + * // data. For example, it could be a bitfield + * // indicating the setting of those compile- + * // time configuration options influencing + * // the format of the serialized data. + * // Unused so far. * uint64 start_time; * uint8 ciphersuite[2]; // defined by the standard * uint8 compression; // 0 or 1 From 94ef3b35f41b22addc6624ec02846d25edc03744 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 16 May 2019 12:50:45 +0100 Subject: [PATCH 051/114] Encode relevant parts of the config in serialized session header This commit makes use of the added space in the session header to encode the state of those parts of the compile-time configuration which influence the structure of the serialized session in the present version of Mbed TLS. Specifically, these are - the options which influence the presence/omission of fields from mbedtls_ssl_session (which is currently shallow-copied into the serialized session) - the setting of MBEDTLS_X509_CRT_PARSE_C, which determines whether the serialized session contains a CRT-length + CRT-value pair after the shallow-copied mbedtls_ssl_session instance. - the setting of MBEDTLS_SSL_SESSION_TICKETS, which determines whether the serialized session contains a session ticket. --- library/ssl_tls.c | 96 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 6 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index ca52752c2..f60c63290 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9848,12 +9848,81 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co * and structure of the ticket. */ +/* + * Define bitflag determining structure of mbedtls_ssl_session. + */ + +#if defined(MBEDTLS_HAVE_TIME) +#define SSL_SERIALIZED_SESSION_STRUCT_TIME_BIT 1 +#else +#define SSL_SERIALIZED_SESSION_STRUCT_TIME_BIT 0 +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define SSL_SERIALIZED_SESSION_STRUCT_CRT_BIT 1 +#else +#define SSL_SERIALIZED_SESSION_STRUCT_CRT_BIT 0 +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_STRUCT_CLIENT_BIT 1 +#else +#define SSL_SERIALIZED_SESSION_STRUCT_CLIENT_BIT 0 +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define SSL_SERIALIZED_SESSION_STRUCT_MFL_BIT 1 +#else +#define SSL_SERIALIZED_SESSION_STRUCT_MFL_BIT 0 +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#define SSL_SERIALIZED_SESSION_STRUCT_TRUNC_HMAC_BIT 1 +#else +#define SSL_SERIALIZED_SESSION_STRUCT_TRUNC_HMAC_BIT 0 +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define SSL_SERIALIZED_SESSION_STRUCT_ETM_BIT 1 +#else +#define SSL_SERIALIZED_SESSION_STRUCT_ETM_BIT 0 +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#define SSL_SERIALIZED_SESSION_STRUCT_BYTE \ + ( (uint8_t) ( ( SSL_SERIALIZED_SESSION_STRUCT_TIME_BIT << 0 ) | \ + ( SSL_SERIALIZED_SESSION_STRUCT_CRT_BIT << 1 ) | \ + ( SSL_SERIALIZED_SESSION_STRUCT_CLIENT_BIT << 2 ) | \ + ( SSL_SERIALIZED_SESSION_STRUCT_MFL_BIT << 3 ) | \ + ( SSL_SERIALIZED_SESSION_STRUCT_TRUNC_HMAC_BIT << 4 ) | \ + ( SSL_SERIALIZED_SESSION_STRUCT_ETM_BIT << 5 ) ) ) + +/* + * Define bitflag determining compile-time settings influencing + * structure of the ticket outside of the session structure. + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#define SSL_SERIALIZED_SESSION_CONFIG_BYTE \ + ( (uint8_t) ( ( SSL_SERIALIZED_SESSION_CONFIG_CRT << 0 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << 1 ) ) ) + static unsigned char ssl_serialized_session_header[] = { - MBEDTLS_VERSION_MAJOR, - MBEDTLS_VERSION_MINOR, - MBEDTLS_VERSION_PATCH, - 0xFF /* TBD */, - 0xFF /* TBD */ + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + SSL_SERIALIZED_SESSION_STRUCT_BYTE, + SSL_SERIALIZED_SESSION_CONFIG_BYTE }; /* @@ -9867,7 +9936,22 @@ static unsigned char ssl_serialized_session_header[] = { * // indicating the setting of those compile- * // time configuration options influencing * // the format of the serialized data. - * // Unused so far. + * // + * // In this version, we use: + * // - Bits 8-15 (second byte) + * // Bitflag determining structure of + * // mbedtls_ssl_session + * // - Bit 0: + * // 0/1 depending on state of + * // MBEDTLS_X509_CRT_PARSE_C. + * // This determines whether the session + * // is followed by a certificate. + * // - Bit 1: + * // 0/1 depending on state of + * // MBEDTLS_SSL_SESSION_TICKETS + * // This determines whether the certificate + * // is followed by a session ticket. + * // - Bits 2-7: Unused so far * uint64 start_time; * uint8 ciphersuite[2]; // defined by the standard * uint8 compression; // 0 or 1 From 861d0bbbf22eac0dced35b8e9e6f8123462828fc Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 21 May 2019 16:39:30 +0100 Subject: [PATCH 052/114] Add negative tests for unexpected ver/cfg in session deserialization --- tests/suites/test_suite_ssl.data | 12 +++++++ tests/suites/test_suite_ssl.function | 50 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 01517c19c..89dc54802 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -58,6 +58,18 @@ ssl_dtls_replay:"abcd12340000abcd12340100":"abcd123400ff":0 SSL SET_HOSTNAME memory leak: call ssl_set_hostname twice ssl_set_hostname_twice:"server0":"server1" +SSL session serialization: Wrong major version +ssl_session_serialize_version_check:1:0:0:0 + +SSL session serialization: Wrong minor version +ssl_session_serialize_version_check:1:0:0:0 + +SSL session serialization: Wrong patch version +ssl_session_serialize_version_check:1:0:0:0 + +SSL session serialization: Wrong config +ssl_session_serialize_version_check:1:0:0:0 + Record crypt, AES-128-CBC, 1.2, SHA-384 depends_on:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SHA512_C ssl_crypt_record:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_MD_SHA384:0:0:MBEDTLS_SSL_MINOR_VERSION_3:0:0 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 4faa5d33f..80c0ab044 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -921,3 +921,53 @@ exit: mbedtls_free( bad_buf ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:!MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY */ +void ssl_session_serialize_version_check( int corrupt_major, + int corrupt_minor, + int corrupt_patch, + int corrupt_config ) +{ + unsigned char serialized_session[ 2048 ]; + size_t serialized_session_len; + + mbedtls_ssl_session session; + mbedtls_ssl_session_init( &session ); + + /* Infer length of serialized session. */ + TEST_ASSERT( mbedtls_ssl_session_save( &session, + serialized_session, + sizeof( serialized_session ), + &serialized_session_len ) == 0 ); + + mbedtls_ssl_session_free( &session ); + + /* Without any modification, we should be able to successfully + * de-serialize the session - double-check that. */ + TEST_ASSERT( mbedtls_ssl_session_load( &session, + serialized_session, + serialized_session_len ) == 0 ); + mbedtls_ssl_session_free( &session ); + + if( corrupt_major ) + serialized_session[0] ^= (uint8_t) 0x1; + + if( corrupt_minor ) + serialized_session[1] ^= (uint8_t) 0x1; + + if( corrupt_patch ) + serialized_session[2] ^= (uint8_t) 0x1; + + if( corrupt_config ) + { + serialized_session[3] ^= (uint8_t) 0x1; + serialized_session[4] ^= (uint8_t) 0x1; + serialized_session[5] ^= (uint8_t) 0x1; + } + + TEST_ASSERT( mbedtls_ssl_session_load( &session, + serialized_session, + serialized_session_len ) == + MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); +} +/* END_CASE */ From bb54d5a3b13b488f43c969baffc9d1769abf3a1f Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 28 May 2019 13:58:14 +0100 Subject: [PATCH 053/114] Use consistent spelling of 'serialise/serialize' in SSL test suite --- tests/suites/test_suite_ssl.data | 14 +++++----- tests/suites/test_suite_ssl.function | 38 ++++++++++++++-------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index 89dc54802..efe2f5661 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -59,16 +59,16 @@ SSL SET_HOSTNAME memory leak: call ssl_set_hostname twice ssl_set_hostname_twice:"server0":"server1" SSL session serialization: Wrong major version -ssl_session_serialize_version_check:1:0:0:0 +ssl_session_serialise_version_check:1:0:0:0 -SSL session serialization: Wrong minor version -ssl_session_serialize_version_check:1:0:0:0 +SSL session serialisation: Wrong minor version +ssl_session_serialise_version_check:0:1:0:0 -SSL session serialization: Wrong patch version -ssl_session_serialize_version_check:1:0:0:0 +SSL session serialisation: Wrong patch version +ssl_session_serialise_version_check:0:0:1:0 -SSL session serialization: Wrong config -ssl_session_serialize_version_check:1:0:0:0 +SSL session serialisation: Wrong config +ssl_session_serialise_version_check:0:0:0:1 Record crypt, AES-128-CBC, 1.2, SHA-384 depends_on:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SHA512_C diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 80c0ab044..51f00f3e9 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -922,52 +922,52 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:!MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY */ -void ssl_session_serialize_version_check( int corrupt_major, +/* BEGIN_CASE depends_on */ +void ssl_session_serialise_version_check( int corrupt_major, int corrupt_minor, int corrupt_patch, int corrupt_config ) { - unsigned char serialized_session[ 2048 ]; - size_t serialized_session_len; + unsigned char serialised_session[ 2048 ]; + size_t serialised_session_len; mbedtls_ssl_session session; mbedtls_ssl_session_init( &session ); - /* Infer length of serialized session. */ + /* Infer length of serialised session. */ TEST_ASSERT( mbedtls_ssl_session_save( &session, - serialized_session, - sizeof( serialized_session ), - &serialized_session_len ) == 0 ); + serialised_session, + sizeof( serialised_session ), + &serialised_session_len ) == 0 ); mbedtls_ssl_session_free( &session ); /* Without any modification, we should be able to successfully - * de-serialize the session - double-check that. */ + * de-serialise the session - double-check that. */ TEST_ASSERT( mbedtls_ssl_session_load( &session, - serialized_session, - serialized_session_len ) == 0 ); + serialised_session, + serialised_session_len ) == 0 ); mbedtls_ssl_session_free( &session ); if( corrupt_major ) - serialized_session[0] ^= (uint8_t) 0x1; + serialised_session[0] ^= (uint8_t) 0x1; if( corrupt_minor ) - serialized_session[1] ^= (uint8_t) 0x1; + serialised_session[1] ^= (uint8_t) 0x1; if( corrupt_patch ) - serialized_session[2] ^= (uint8_t) 0x1; + serialised_session[2] ^= (uint8_t) 0x1; if( corrupt_config ) { - serialized_session[3] ^= (uint8_t) 0x1; - serialized_session[4] ^= (uint8_t) 0x1; - serialized_session[5] ^= (uint8_t) 0x1; + serialised_session[3] ^= (uint8_t) 0x1; + serialised_session[4] ^= (uint8_t) 0x1; + serialised_session[5] ^= (uint8_t) 0x1; } TEST_ASSERT( mbedtls_ssl_session_load( &session, - serialized_session, - serialized_session_len ) == + serialised_session, + serialised_session_len ) == MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } /* END_CASE */ From f37d91830a5d27aa6fec2cf0debd60a6b92e8a0e Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 28 May 2019 13:59:44 +0100 Subject: [PATCH 054/114] Session serialization: Fail with BAD_INPUT_DATA if buffer too small --- library/ssl_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f60c63290..2121ac992 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -10184,7 +10184,7 @@ static int ssl_session_load( mbedtls_ssl_session *session, */ if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); if( memcmp( p, ssl_serialized_session_header, sizeof( ssl_serialized_session_header ) ) != 0 ) From 50b596666d11501712a9405c400dc5db2b9f2016 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 28 May 2019 14:30:45 +0100 Subject: [PATCH 055/114] Improve doc'n of config-identifying bitfield in serialized session --- library/ssl_tls.c | 121 +++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 70 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 2121ac992..d0859517e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9849,122 +9849,103 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co */ /* - * Define bitflag determining structure of mbedtls_ssl_session. + * Define bitflag determining compile-time settings influencing + * structure of serialized SSL sessions. */ -#if defined(MBEDTLS_HAVE_TIME) -#define SSL_SERIALIZED_SESSION_STRUCT_TIME_BIT 1 +#if defined(MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY) +#define SSL_SERIALIZED_SESSION_CONFIG_LOCAL 1 #else -#define SSL_SERIALIZED_SESSION_STRUCT_TIME_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_LOCAL 0 +#endif /* MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY */ + +#if defined(MBEDTLS_HAVE_TIME) +#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_X509_CRT_PARSE_C) -#define SSL_SERIALIZED_SESSION_STRUCT_CRT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 #else -#define SSL_SERIALIZED_SESSION_STRUCT_CRT_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 0 #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) -#define SSL_SERIALIZED_SESSION_STRUCT_CLIENT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 1 #else -#define SSL_SERIALIZED_SESSION_STRUCT_CLIENT_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 0 #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -#define SSL_SERIALIZED_SESSION_STRUCT_MFL_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 1 #else -#define SSL_SERIALIZED_SESSION_STRUCT_MFL_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 0 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -#define SSL_SERIALIZED_SESSION_STRUCT_TRUNC_HMAC_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 1 #else -#define SSL_SERIALIZED_SESSION_STRUCT_TRUNC_HMAC_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 0 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -#define SSL_SERIALIZED_SESSION_STRUCT_ETM_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 1 #else -#define SSL_SERIALIZED_SESSION_STRUCT_ETM_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 0 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ -#define SSL_SERIALIZED_SESSION_STRUCT_BYTE \ - ( (uint8_t) ( ( SSL_SERIALIZED_SESSION_STRUCT_TIME_BIT << 0 ) | \ - ( SSL_SERIALIZED_SESSION_STRUCT_CRT_BIT << 1 ) | \ - ( SSL_SERIALIZED_SESSION_STRUCT_CLIENT_BIT << 2 ) | \ - ( SSL_SERIALIZED_SESSION_STRUCT_MFL_BIT << 3 ) | \ - ( SSL_SERIALIZED_SESSION_STRUCT_TRUNC_HMAC_BIT << 4 ) | \ - ( SSL_SERIALIZED_SESSION_STRUCT_ETM_BIT << 5 ) ) ) - -/* - * Define bitflag determining compile-time settings influencing - * structure of the ticket outside of the session structure. - */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - #if defined(MBEDTLS_SSL_SESSION_TICKETS) #define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 #else #define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 #endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#define SSL_SERIALIZED_SESSION_CONFIG_BYTE \ - ( (uint8_t) ( ( SSL_SERIALIZED_SESSION_CONFIG_CRT << 0 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << 1 ) ) ) +#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ + ( (uint16_t) ( ( SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT << 0 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT << 1 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT << 2 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT << 3 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT << 4 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT << 5 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CRT << 6 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << 7 ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_LOCAL << 8 ) ) ) static unsigned char ssl_serialized_session_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, - SSL_SERIALIZED_SESSION_STRUCT_BYTE, - SSL_SERIALIZED_SESSION_CONFIG_BYTE + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF, + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF, }; /* * Serialize a session in the following format: * (in the presentation language of TLS, RFC 8446 section 3) * - * opaque mbedtls_version[3]; // major, minor, patch - * opaque session_format[2]; // version-specific 16-bit field determining - * // the format of the remaining serialized - * // data. For example, it could be a bitfield - * // indicating the setting of those compile- - * // time configuration options influencing - * // the format of the serialized data. - * // - * // In this version, we use: - * // - Bits 8-15 (second byte) - * // Bitflag determining structure of - * // mbedtls_ssl_session - * // - Bit 0: - * // 0/1 depending on state of - * // MBEDTLS_X509_CRT_PARSE_C. - * // This determines whether the session - * // is followed by a certificate. - * // - Bit 1: - * // 0/1 depending on state of - * // MBEDTLS_SSL_SESSION_TICKETS - * // This determines whether the certificate - * // is followed by a session ticket. - * // - Bits 2-7: Unused so far + * opaque mbedtls_version[3]; // major, minor, patch + * opaque session_format[2]; // version-specific 16-bit field determining + * // the format of the remaining + * // serialized data. + * // In this version, this indicates whether + * // MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY + * // is set, plus the setting of those compile- + * // time configuration options which influence + * // the structure of mbedtls_ssl_session. * uint64 start_time; - * uint8 ciphersuite[2]; // defined by the standard - * uint8 compression; // 0 or 1 - * uint8 session_id_len; // at most 32 + * uint8 ciphersuite[2]; // defined by the standard + * uint8 compression; // 0 or 1 + * uint8 session_id_len; // at most 32 * opaque session_id[32]; - * opaque master[48]; // fixed length in the standard + * opaque master[48]; // fixed length in the standard * uint32 verify_result; - * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert - * opaque ticket<0..2^24-1>; // length 0 means no ticket + * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert + * opaque ticket<0..2^24-1>; // length 0 means no ticket * uint32 ticket_lifetime; - * uint8 mfl_code; // up to 255 according to standard - * uint8 trunc_hmac; // 0 or 1 - * uint8 encrypt_then_mac; // 0 or 1 + * uint8 mfl_code; // up to 255 according to standard + * uint8 trunc_hmac; // 0 or 1 + * uint8 encrypt_then_mac; // 0 or 1 * * The order is the same as in the definition of the structure, except * verify_result is put before peer_cert so that all mandatory fields come From dc28b6c5e164e86b6ad2f3d5c6cbb4cea42093d1 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 29 May 2019 11:08:00 +0100 Subject: [PATCH 056/114] Note that ver+fmt bytes in serialized data must not be removed --- library/ssl_tls.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d0859517e..b436abbd4 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9928,7 +9928,12 @@ static unsigned char ssl_serialized_session_header[] = { * opaque session_format[2]; // version-specific 16-bit field determining * // the format of the remaining * // serialized data. - * // In this version, this indicates whether + * + * Note: When updating the format, remember to keep + * these version+format bytes. + * + * // In this version, `session_format` + * // indicates whether * // MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY * // is set, plus the setting of those compile- * // time configuration options which influence From 3e08866e06aa1865badf869ae4af9c5a05aeff6c Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 29 May 2019 11:10:18 +0100 Subject: [PATCH 057/114] Use def'n consts for bits in config-identifier of serialized data --- library/ssl_tls.c | 51 ++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b436abbd4..3a33ab45f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9860,39 +9860,39 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co #endif /* MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY */ #if defined(MBEDTLS_HAVE_TIME) -#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 #else -#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 #endif /* MBEDTLS_HAVE_TIME */ #if defined(MBEDTLS_X509_CRT_PARSE_C) -#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 #else -#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) -#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 #else -#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 #else -#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 1 #else -#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC 0 #endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 #else -#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) @@ -9901,16 +9901,25 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co #define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 #endif /* MBEDTLS_SSL_SESSION_TICKETS */ +#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 +#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5 +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6 +#define SSL_SERIALIZED_SESSION_CONFIG_LOCAL_BIT 7 + #define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ - ( (uint16_t) ( ( SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT << 0 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT << 1 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT << 2 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT << 3 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT << 4 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT << 5 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_CRT << 6 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << 7 ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_LOCAL << 8 ) ) ) + ( (uint16_t) ( \ + ( SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_LOCAL << SSL_SERIALIZED_SESSION_CONFIG_LOCAL_BIT ) ) ) static unsigned char ssl_serialized_session_header[] = { MBEDTLS_VERSION_MAJOR, From 363b646dd87f29e146ceb54c97f07ef78715e2e1 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 29 May 2019 12:44:28 +0100 Subject: [PATCH 058/114] Use US spelling 'serialize' instead of UK spelling 'serialise' --- tests/suites/test_suite_ssl.data | 14 ++++---- tests/suites/test_suite_ssl.function | 52 ++++++++++++++-------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index efe2f5661..45765deeb 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -59,16 +59,16 @@ SSL SET_HOSTNAME memory leak: call ssl_set_hostname twice ssl_set_hostname_twice:"server0":"server1" SSL session serialization: Wrong major version -ssl_session_serialise_version_check:1:0:0:0 +ssl_session_serialize_version_check:1:0:0:0 -SSL session serialisation: Wrong minor version -ssl_session_serialise_version_check:0:1:0:0 +SSL session serialization: Wrong minor version +ssl_session_serialize_version_check:0:1:0:0 -SSL session serialisation: Wrong patch version -ssl_session_serialise_version_check:0:0:1:0 +SSL session serialization: Wrong patch version +ssl_session_serialize_version_check:0:0:1:0 -SSL session serialisation: Wrong config -ssl_session_serialise_version_check:0:0:0:1 +SSL session serialization: Wrong config +ssl_session_serialize_version_check:0:0:0:1 Record crypt, AES-128-CBC, 1.2, SHA-384 depends_on:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SHA512_C diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 51f00f3e9..a3d1c0056 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -922,52 +922,52 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on */ -void ssl_session_serialise_version_check( int corrupt_major, +/* BEGIN_CASE */ +void ssl_session_serialize_version_check( int corrupt_major, int corrupt_minor, int corrupt_patch, int corrupt_config ) { - unsigned char serialised_session[ 2048 ]; - size_t serialised_session_len; + unsigned char serialized_session[ 2048 ]; + size_t serialized_session_len; mbedtls_ssl_session session; mbedtls_ssl_session_init( &session ); - /* Infer length of serialised session. */ + /* Infer length of serialized session. */ TEST_ASSERT( mbedtls_ssl_session_save( &session, - serialised_session, - sizeof( serialised_session ), - &serialised_session_len ) == 0 ); + serialized_session, + sizeof( serialized_session ), + &serialized_session_len ) == 0 ); - mbedtls_ssl_session_free( &session ); + mbedtls_ssl_session_free( &session ); - /* Without any modification, we should be able to successfully - * de-serialise the session - double-check that. */ + /* Without any modification, we should be able to successfully + * de-serialize the session - double-check that. */ TEST_ASSERT( mbedtls_ssl_session_load( &session, - serialised_session, - serialised_session_len ) == 0 ); + serialized_session, + serialized_session_len ) == 0 ); mbedtls_ssl_session_free( &session ); - if( corrupt_major ) - serialised_session[0] ^= (uint8_t) 0x1; + if( corrupt_major ) + serialized_session[0] ^= (uint8_t) 0x1; - if( corrupt_minor ) - serialised_session[1] ^= (uint8_t) 0x1; + if( corrupt_minor ) + serialized_session[1] ^= (uint8_t) 0x1; - if( corrupt_patch ) - serialised_session[2] ^= (uint8_t) 0x1; + if( corrupt_patch ) + serialized_session[2] ^= (uint8_t) 0x1; - if( corrupt_config ) + if( corrupt_config ) { - serialised_session[3] ^= (uint8_t) 0x1; - serialised_session[4] ^= (uint8_t) 0x1; - serialised_session[5] ^= (uint8_t) 0x1; + serialized_session[3] ^= (uint8_t) 0x1; + serialized_session[4] ^= (uint8_t) 0x1; + serialized_session[5] ^= (uint8_t) 0x1; } - TEST_ASSERT( mbedtls_ssl_session_load( &session, - serialised_session, - serialised_session_len ) == + TEST_ASSERT( mbedtls_ssl_session_load( &session, + serialized_session, + serialized_session_len ) == MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } /* END_CASE */ From fe1275e3fe2811131a16cf11ff0eca089d1be1a4 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 29 May 2019 12:45:21 +0100 Subject: [PATCH 059/114] Improve test for detection of ver/cfg corruption in serialized data This commit improves the test exercising the behaviour of session deserialization when facing an unexpected version or config, by testing ver/cfg corruption at any bit in the ver/cfg header of the serialized data; previously, it had only tested the first bit of each byte. --- tests/suites/test_suite_ssl.function | 55 +++++++++++++++++----------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index a3d1c0056..018322b9e 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -930,44 +930,57 @@ void ssl_session_serialize_version_check( int corrupt_major, { unsigned char serialized_session[ 2048 ]; size_t serialized_session_len; - + unsigned cur_byte; mbedtls_ssl_session session; + uint8_t should_corrupt_byte[] = { corrupt_major == 1, + corrupt_minor == 1, + corrupt_patch == 1, + corrupt_config == 1, + corrupt_config == 1 }; + mbedtls_ssl_session_init( &session ); - /* Infer length of serialized session. */ + /* Infer length of serialized session. */ TEST_ASSERT( mbedtls_ssl_session_save( &session, serialized_session, sizeof( serialized_session ), &serialized_session_len ) == 0 ); - mbedtls_ssl_session_free( &session ); + mbedtls_ssl_session_free( &session ); - /* Without any modification, we should be able to successfully + /* Without any modification, we should be able to successfully * de-serialize the session - double-check that. */ TEST_ASSERT( mbedtls_ssl_session_load( &session, serialized_session, serialized_session_len ) == 0 ); mbedtls_ssl_session_free( &session ); - if( corrupt_major ) - serialized_session[0] ^= (uint8_t) 0x1; - - if( corrupt_minor ) - serialized_session[1] ^= (uint8_t) 0x1; - - if( corrupt_patch ) - serialized_session[2] ^= (uint8_t) 0x1; - - if( corrupt_config ) + /* Go through the bytes in the serialized session header and + * corrupt them bit-by-bit. */ + for( cur_byte = 0; cur_byte < sizeof( should_corrupt_byte ); cur_byte++ ) { - serialized_session[3] ^= (uint8_t) 0x1; - serialized_session[4] ^= (uint8_t) 0x1; - serialized_session[5] ^= (uint8_t) 0x1; + int cur_bit; + unsigned char * const byte = &serialized_session[ cur_byte ]; + + if( should_corrupt_byte[ cur_byte ] == 0 ) + continue; + + for( cur_bit = 0; cur_bit < CHAR_BIT; cur_bit++ ) + { + unsigned char const corrupted_bit = 0x1u << cur_bit; + /* Modify a single bit in the serialized session. */ + *byte ^= corrupted_bit; + + /* Attempt to deserialize */ + TEST_ASSERT( mbedtls_ssl_session_load( &session, + serialized_session, + serialized_session_len ) == + MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* Undo the change */ + *byte ^= corrupted_bit; + } } - TEST_ASSERT( mbedtls_ssl_session_load( &session, - serialized_session, - serialized_session_len ) == - MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } /* END_CASE */ From f9b3303eb9c08736d81ace696339187e3943c310 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 3 Jun 2019 12:58:39 +0100 Subject: [PATCH 060/114] Introduce specific error for ver/cfg mismatch on deserialization This commit introduces a new SSL error code `MBEDTLS_ERR_SSL_VERSION_MISMATCH` which can be used to indicate operation failure due to a mismatch of version or configuration. It is put to use in the implementation of `mbedtls_ssl_session_load()` to signal the attempt to de-serialize a session which has been serialized in a build of Mbed TLS using a different version or configuration. --- include/mbedtls/error.h | 1 + include/mbedtls/ssl.h | 4 ++++ library/error.c | 2 ++ library/ssl_tls.c | 3 +-- tests/suites/test_suite_ssl.function | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 20a245a06..06bb1c9ca 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -100,6 +100,7 @@ * ECP 4 10 (Started from top) * MD 5 5 * HKDF 5 1 (Started from top) + * SSL 5 1 (Started from 0x5F00) * CIPHER 6 8 (Started from 0x6080) * SSL 6 24 (Started from top, plus 0x6000) * SSL 7 32 diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index ed7d7ee2d..35e9936ab 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -127,6 +127,7 @@ #define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */ #define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 /**< Internal-only message signaling that a message arrived early. */ #define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 /**< An encrypted DTLS-frame with an unexpected CID was received. */ +#define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 /**< An operation failed due to an unexpected version or configuration. */ #define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 /**< A cryptographic operation is in progress. Try again later. */ /* @@ -2382,6 +2383,9 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * was generated in a different version or configuration of + * Mbed TLS. * \return Another negative value for other kinds of errors (for * example, unsupported features in the embedded certificate). */ diff --git a/library/error.c b/library/error.c index e401a841c..23a0f97e3 100644 --- a/library/error.c +++ b/library/error.c @@ -525,6 +525,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_CID) ) mbedtls_snprintf( buf, buflen, "SSL - An encrypted DTLS-frame with an unexpected CID was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_VERSION_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "SSL - An operation failed due to an unexpected version or configuration" ); if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) ) mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" ); #endif /* MBEDTLS_SSL_TLS_C */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 3a33ab45f..b75ee32bc 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -10184,8 +10184,7 @@ static int ssl_session_load( mbedtls_ssl_session *session, if( memcmp( p, ssl_serialized_session_header, sizeof( ssl_serialized_session_header ) ) != 0 ) { - /* A more specific error code might be used here. */ - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); } p += sizeof( ssl_serialized_session_header ); diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 018322b9e..2fa716b4b 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -975,7 +975,7 @@ void ssl_session_serialize_version_check( int corrupt_major, TEST_ASSERT( mbedtls_ssl_session_load( &session, serialized_session, serialized_session_len ) == - MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + MBEDTLS_ERR_SSL_VERSION_MISMATCH ); /* Undo the change */ *byte ^= corrupted_bit; From be34e8e9c011752094bcd7aa96f2139d6a897f94 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 4 Jun 2019 09:43:16 +0100 Subject: [PATCH 061/114] Remove reference to outdated compile-time option --- library/ssl_tls.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b75ee32bc..466747cd9 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9853,12 +9853,6 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co * structure of serialized SSL sessions. */ -#if defined(MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY) -#define SSL_SERIALIZED_SESSION_CONFIG_LOCAL 1 -#else -#define SSL_SERIALIZED_SESSION_CONFIG_LOCAL 0 -#endif /* MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY */ - #if defined(MBEDTLS_HAVE_TIME) #define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 #else @@ -9908,7 +9902,6 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co #define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4 #define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5 #define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6 -#define SSL_SERIALIZED_SESSION_CONFIG_LOCAL_BIT 7 #define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ ( (uint16_t) ( \ @@ -9918,8 +9911,7 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co ( SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT ) | \ ( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT ) | \ ( SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) | \ - ( SSL_SERIALIZED_SESSION_CONFIG_LOCAL << SSL_SERIALIZED_SESSION_CONFIG_LOCAL_BIT ) ) ) + ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) ) ) static unsigned char ssl_serialized_session_header[] = { MBEDTLS_VERSION_MAJOR, @@ -9941,11 +9933,9 @@ static unsigned char ssl_serialized_session_header[] = { * Note: When updating the format, remember to keep * these version+format bytes. * - * // In this version, `session_format` - * // indicates whether - * // MBEDTLS_SSL_SERIALIZED_STRUCTURES_LOCAL_ONLY - * // is set, plus the setting of those compile- - * // time configuration options which influence + * // In this version, `session_format` determines + * // the setting of those compile-time + * // configuration options which influence * // the structure of mbedtls_ssl_session. * uint64 start_time; * uint8 ciphersuite[2]; // defined by the standard From afa8f71700bb056fb5e8cdbe02979d722dc34dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 May 2019 12:28:17 +0200 Subject: [PATCH 062/114] Add new config MBEDTLS_SSL_CONTEXT_SERIALIZATION This is enabled by default as we generally enable things by default unless there's a reason not to (experimental, deprecated, security risk). We need a compile-time option because, even though the functions themselves can be easily garbage-collected by the linker, implementing them will require saving 64 bytes of Client/ServerHello.random values after the handshake, that would otherwise not be needed, and people who don't need this feature shouldn't have to pay the price of increased RAM usage. --- include/mbedtls/config.h | 27 +++++++++++++++++++++++++++ library/version_features.c | 3 +++ programs/ssl/query_config.c | 8 ++++++++ 3 files changed, 38 insertions(+) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 8e00fc477..4e7849325 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1403,6 +1403,33 @@ */ //#define MBEDTLS_SSL_ASYNC_PRIVATE +/** + * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION + * + * Enable the APIs for serialization of a full SSL context: + * mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). + * + * This pair of functions allows one side of a connection to serialize the + * context associated with the connection, then free or re-use that context + * while the serialized state is persisted elsewhere, and finally deserialize + * that state to a live context for resuming read/write operations on the + * connection, in a way that's transparent to the peer, since from a protocol + * point of view, the state of the connection is unaffected. + * + * Note: this is distinct from TLS session resumption, which is part of the + * protocol and fully visible by the peer. TLS session resumption enables + * establishing new connections associated to a saved session with shorter, + * lighter handshakes, while context serialization is a local optimisation in + * handling a single, potentially long-lived connection. + * + * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are + * saved after the handshake to allow for more efficient serialization, so if + * you don't need this feature you'll save RAM by disabling it. + * + * Comment to disable the context serialization APIs. + */ +#define MBEDTLS_SSL_CONTEXT_SERIALIZATION + /** * \def MBEDTLS_SSL_DEBUG_ALL * diff --git a/library/version_features.c b/library/version_features.c index e83899d0a..cc47dacc9 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -459,6 +459,9 @@ static const char * const features[] = { #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) "MBEDTLS_SSL_ASYNC_PRIVATE", #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + "MBEDTLS_SSL_CONTEXT_SERIALIZATION", +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ #if defined(MBEDTLS_SSL_DEBUG_ALL) "MBEDTLS_SSL_DEBUG_ALL", #endif /* MBEDTLS_SSL_DEBUG_ALL */ diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index c6d19bf09..361ec0000 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -1266,6 +1266,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + if( strcmp( "MBEDTLS_SSL_CONTEXT_SERIALIZATION", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONTEXT_SERIALIZATION ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + #if defined(MBEDTLS_SSL_DEBUG_ALL) if( strcmp( "MBEDTLS_SSL_DEBUG_ALL", config ) == 0 ) { From ac87e28bb2fe40879f44332a0cc186fd160fadd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 28 May 2019 13:02:16 +0200 Subject: [PATCH 063/114] Declare and document ssl_context_save()/load() Also introduce stub definitions so that things compile and link. --- include/mbedtls/ssl.h | 88 +++++++++++++++++++++++++++++++++++++++++++ library/ssl_tls.c | 34 +++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 35e9936ab..326a48c15 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3879,6 +3879,94 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); */ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); +/** + * \brief Save a live connection as serialized data in a buffer. + * This allows to free or re-use the SSL context while still + * picking up the connection later in a way that it entirely + * transparent to the peer. + * + * \see mbedtls_ssl_context_load() + * + * \note This feature is currently only available under certain + * conditions, see the documentation of return value + * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. + * + * \note When the function succeeds, it calls + * mbedtls_ssl_session_reset() on \p ssl which as a result is + * no longer associated with the connection that has been + * serialized. This avoid creating copies of the session + * state. You're then free to either re-use the context + * structure for a different connection, or call + * mbedtls_ssl_session_free() on it. + * + * \param ssl The SSL context to save. On success, it is no longer + * associated with the connection that has been serialized. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p len bytes, or may be \c + * NULL if \p len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handsahke is in + * progress, or there is pending data for reading or sending, + * or the connection does not use DTLS 1.2 with and AEAD + * ciphersuite, or renegotiation is enabled. + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ); +/** + * \brief Load serialized connection data to an SSL context. + * + * \see mbedtls_ssl_context_save() + * + * \warning The same serialized data must never be loaded into more + * that one context. In order to ensure that, after + * successfully loading serialized data to an SSL context, you + * should immediately destroy or invalidate all copies of the + * serialized data that was loaded. Loading the same data in + * more than one context would cause severe security failures + * including but not limited to loss of confidentiality. + * + * \note Before calling this function, the SSL context must be + * prepared either by calling mbedtls_ssl_setup() on it with + * the same ::mbedtls_ssl_config structure that was used in + * the original connection, and not using it with any other + * function between mbedtls_ssl_setup() and this one, or by + * calling mbedtls_ssl_session_reset() on a context that was + * previously prepared as above but used in the meantime. + * + * \note After calling this function sucessfully, you still need to + * configure some connection-specific callback and settings + * before you can use the connection again. Specifically, you + * want to call at least mbedtls_ssl_set_bio() and possibly + * mbedtls_ssl_set_timer_cb(). You might also want to call + * mbedtls_ssl_set_mtu() if new information about the PMTU is + * available - otherwise the saved information will be used. + * + * \param ssl The SSL context structure to be populated. It must have + * been prepared as described in the note above. + * \param buf The buffer holding the serialized connection data. It must + * be a readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ); + /** * \brief Initialize an SSL configuration context * Just makes the context ready for diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 466747cd9..143d4da9c 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11278,6 +11278,40 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); } +/* + * Serialize a full SSL context + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + /* Unimplemented yet */ + (void) ssl; + + if( buf != NULL ) + memset( buf, 0, buf_len ); + + *olen = 0; + + return( 0 ); +} + +/* + * Deserialize a full SSL context + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* Unimplemented yet */ + (void) ssl; + (void) buf; + (void) len; + + return( 0 ); +} + /* * Free an SSL context */ From 6d8f128790ebd5069f545f78a5e8614954a954ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 5 Jun 2019 09:47:18 +0200 Subject: [PATCH 064/114] Fix typos, grammar and wording in documentation --- include/mbedtls/config.h | 10 +++++----- include/mbedtls/ssl.h | 30 +++++++++++++++++------------- library/ssl_tls.c | 4 ++-- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 4e7849325..877d52e3f 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1406,20 +1406,20 @@ /** * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION * - * Enable the APIs for serialization of a full SSL context: - * mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). + * Enable serialization of the TLS context structures, through use of the + * functions mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). * * This pair of functions allows one side of a connection to serialize the * context associated with the connection, then free or re-use that context * while the serialized state is persisted elsewhere, and finally deserialize * that state to a live context for resuming read/write operations on the - * connection, in a way that's transparent to the peer, since from a protocol - * point of view, the state of the connection is unaffected. + * connection. From a protocol perspective, the state of the connection is + * unaffected, in particular this is entirely transparent to the peer. * * Note: this is distinct from TLS session resumption, which is part of the * protocol and fully visible by the peer. TLS session resumption enables * establishing new connections associated to a saved session with shorter, - * lighter handshakes, while context serialization is a local optimisation in + * lighter handshakes, while context serialization is a local optimization in * handling a single, potentially long-lived connection. * * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 326a48c15..2010fd517 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3880,24 +3880,25 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); /** - * \brief Save a live connection as serialized data in a buffer. - * This allows to free or re-use the SSL context while still - * picking up the connection later in a way that it entirely - * transparent to the peer. + * \brief Save an active connection as serialized data in a buffer. + * This allows the freeing or re-using of the SSL context + * while still picking up the connection later in a way that + * it entirely transparent to the peer. * * \see mbedtls_ssl_context_load() * * \note This feature is currently only available under certain - * conditions, see the documentation of return value + * conditions, see the documentation of the return value * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. * - * \note When the function succeeds, it calls + * \note When this function succeeds, it calls * mbedtls_ssl_session_reset() on \p ssl which as a result is * no longer associated with the connection that has been - * serialized. This avoid creating copies of the session + * serialized. This avoids creating copies of the session * state. You're then free to either re-use the context * structure for a different connection, or call - * mbedtls_ssl_session_free() on it. + * mbedtls_ssl_session_free() on it. See the documentation of + * mbedtls_ssl_session_reset() for more details. * * \param ssl The SSL context to save. On success, it is no longer * associated with the connection that has been serialized. @@ -3915,7 +3916,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. - * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handsahke is in + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in * progress, or there is pending data for reading or sending, * or the connection does not use DTLS 1.2 with and AEAD * ciphersuite, or renegotiation is enabled. @@ -3945,10 +3946,13 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, * calling mbedtls_ssl_session_reset() on a context that was * previously prepared as above but used in the meantime. * - * \note After calling this function sucessfully, you still need to - * configure some connection-specific callback and settings - * before you can use the connection again. Specifically, you - * want to call at least mbedtls_ssl_set_bio() and possibly + * \note Before or after calling this function successfully, you + * also need to configure some connection-specific callback + * and settings before you can use the connection again + * (unless they were already set before calling + * mbedtls_ssl_session_reset() and the values are suitable for + * the present connection). Specifically, you want to call + * at least mbedtls_ssl_set_bio() and possibly * mbedtls_ssl_set_timer_cb(). You might also want to call * mbedtls_ssl_set_mtu() if new information about the PMTU is * available - otherwise the saved information will be used. diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 143d4da9c..a978899d6 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11286,7 +11286,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, size_t buf_len, size_t *olen ) { - /* Unimplemented yet */ + /* Unimplemented */ (void) ssl; if( buf != NULL ) @@ -11304,7 +11304,7 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { - /* Unimplemented yet */ + /* Unimplemented */ (void) ssl; (void) buf; (void) len; From d0a86f96dc495d4e705c6c7b1820e5ec13f552a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 11 Jun 2019 11:25:10 +0200 Subject: [PATCH 065/114] Clarify documentation of mbedtls_ssl_context_load() --- include/mbedtls/ssl.h | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 2010fd517..376780474 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3939,23 +3939,42 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, * including but not limited to loss of confidentiality. * * \note Before calling this function, the SSL context must be - * prepared either by calling mbedtls_ssl_setup() on it with + * prepared in one of the two following ways. The first way is + * to take a context freshly initialised with + * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with * the same ::mbedtls_ssl_config structure that was used in - * the original connection, and not using it with any other - * function between mbedtls_ssl_setup() and this one, or by - * calling mbedtls_ssl_session_reset() on a context that was + * the original connection. The second way is to + * call mbedtls_ssl_session_reset() on a context that was * previously prepared as above but used in the meantime. + * Either way, you must not use the context to perform a + * handshake between calling mbedtls_ssl_setup() or + * mbedtls_ssl_session_reset() and calling this function. You + * may however call other setter functions in that time frame + * as indicated in the note below. * * \note Before or after calling this function successfully, you - * also need to configure some connection-specific callback + * also need to configure some connection-specific callbacks * and settings before you can use the connection again * (unless they were already set before calling * mbedtls_ssl_session_reset() and the values are suitable for * the present connection). Specifically, you want to call - * at least mbedtls_ssl_set_bio() and possibly - * mbedtls_ssl_set_timer_cb(). You might also want to call - * mbedtls_ssl_set_mtu() if new information about the PMTU is - * available - otherwise the saved information will be used. + * at least mbedtls_ssl_set_bio(). If you're using a read + * timeout (that is, you called + * mbedtls_ssl_conf_read_timeout() with a non-zero timeout) + * and non-blocking I/O, you also need to set timer callbacks + * by calling mbedtls_ssl_set_timer_cb(). All other SSL setter + * functions are not necessary to call, either because they're + * only used in handshakes, or because the setting is already + * saved. You might choose to call them anyway, for example in + * order to share code between the cases of establishing a new + * connection and the case of loading an already-established + * connection. + * + * \note If you have new information about the path MTU, you want to + * call mbedtls_ssl_set_mtu() after calling this function, as + * otherwise this function would overwrite your + * newly-configured value with the value that was active when + * the context was saved. * * \param ssl The SSL context structure to be populated. It must have * been prepared as described in the note above. From 9831c8a14c2a12925ef312278bf49fd1b91b20de Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 29 May 2019 13:33:32 +0300 Subject: [PATCH 066/114] Add option for serialization in ssl_client/server2 --- programs/ssl/ssl_client2.c | 11 +++++++++++ programs/ssl/ssl_server2.c | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 0d7cb667e..eaaacac9c 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -132,6 +132,8 @@ int main( void ) #define DFL_FALLBACK -1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 +#define DFL_SERIALIZE 0 +#define DFL_EXTENDED_MS_ENFORCE -1 #define DFL_CA_CALLBACK 0 #define DFL_EAP_TLS 0 #define DFL_REPRODUCIBLE 0 @@ -411,6 +413,7 @@ int main( void ) " configuration macro is defined and 1\n" \ " otherwise. The expansion of the macro\n" \ " is printed if it is defined\n" \ + " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ " acceptable ciphersuite names:\n" #define ALPN_LIST_SIZE 10 @@ -483,6 +486,7 @@ struct options int cid_enabled_renego; /* whether to use the CID extension or not * during renegotiation */ const char *cid_val; /* the CID to use for incoming messages */ + int serialize; /* serialize/deserialize connection */ const char *cid_val_renego; /* the CID to use for incoming messages * after renegotiation */ int reproducible; /* make communication reproducible */ @@ -1186,6 +1190,7 @@ int main( int argc, char *argv[] ) opt.extended_ms = DFL_EXTENDED_MS; opt.etm = DFL_ETM; opt.dgram_packing = DFL_DGRAM_PACKING; + opt.serialize = DFL_SERIALIZE; opt.eap_tls = DFL_EAP_TLS; opt.reproducible = DFL_REPRODUCIBLE; @@ -1574,6 +1579,12 @@ int main( int argc, char *argv[] ) { return query_config( q ); } + else if( strcmp( p, "serialize") == 0 ) + { + opt.serialize = atoi( q ); + if( opt.serialize < 0 || opt.serialize > 1) + goto usage; + } else if( strcmp( p, "eap_tls" ) == 0 ) { opt.eap_tls = atoi( q ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 3279cda9e..7c431a01a 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -171,6 +171,8 @@ int main( void ) #define DFL_DGRAM_PACKING 1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 +#define DFL_SERIALIZE 0 +#define DFL_EXTENDED_MS_ENFORCE -1 #define DFL_CA_CALLBACK 0 #define DFL_EAP_TLS 0 #define DFL_REPRODUCIBLE 0 @@ -499,6 +501,7 @@ int main( void ) " configuration macro is defined and 1\n" \ " otherwise. The expansion of the macro\n" \ " is printed if it is defined\n" \ + " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ " acceptable ciphersuite names:\n" #define ALPN_LIST_SIZE 10 @@ -590,6 +593,7 @@ struct options int cid_enabled_renego; /* whether to use the CID extension or not * during renegotiation */ const char *cid_val; /* the CID to use for incoming messages */ + int serialize; /* serialize/deserialize connection */ const char *cid_val_renego; /* the CID to use for incoming messages * after renegotiation */ int reproducible; /* make communication reproducible */ @@ -1872,6 +1876,7 @@ int main( int argc, char *argv[] ) opt.badmac_limit = DFL_BADMAC_LIMIT; opt.extended_ms = DFL_EXTENDED_MS; opt.etm = DFL_ETM; + opt.serialize = DFL_SERIALIZE; opt.eap_tls = DFL_EAP_TLS; opt.reproducible = DFL_REPRODUCIBLE; @@ -2286,6 +2291,12 @@ int main( int argc, char *argv[] ) { return query_config( q ); } + else if( strcmp( p, "serialize") == 0 ) + { + opt.serialize = atoi( q ); + if( opt.serialize < 0 || opt.serialize > 1) + goto usage; + } else if( strcmp( p, "eap_tls" ) == 0 ) { opt.eap_tls = atoi( q ); From 77e6665ffbd240f799fbcb5d14f77e57a83b3941 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 29 May 2019 15:15:08 +0300 Subject: [PATCH 067/114] Serialization/deserialization in ssl_client2 --- programs/ssl/ssl_client2.c | 51 +++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index eaaacac9c..80caba4a8 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2907,7 +2907,56 @@ send_request: } /* - * 7c. Continue doing data exchanges? + * 7c. Simulate serialize/deserialize and go back to data exchange + */ + if( opt.serialize != 0) + { + size_t len; + unsigned char *buf = NULL; + + opt.serialize = 0; + mbedtls_printf( " Serializing live connection..." ); + + if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len) ) != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + + goto exit; + } + + if( ( buf = mbedtls_calloc(1, len) ) == NULL ) + { + mbedtls_printf( " failed\n ! Couldn't allocate buffer for serialized context" ); + + goto exit; + } + + if( ( ret = mbedtls_ssl_context_save( &ssl, buf, len, &len ) ) != 0 ) + { + mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + + goto exit; + } + + mbedtls_ssl_free( &ssl ); + + mbedtls_printf( " Deserializing connection..." ); + + mbedtls_ssl_init( &ssl ); + + if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) + { + mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned -0x%x\n\n", -ret ); + + goto exit; + } + + goto send_request; + } + + + /* + * 7d. Continue doing data exchanges? */ if( --opt.exchanges > 0 ) goto send_request; From af3062968602cac911e2238608f2fe8311c1d70b Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 29 May 2019 15:40:49 +0300 Subject: [PATCH 068/114] Rely on opt.exchanges for sending after serialization --- programs/ssl/ssl_client2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 80caba4a8..435546679 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2950,8 +2950,6 @@ send_request: goto exit; } - - goto send_request; } From 5a3a16cb1bd5f587e676e010979151cf0fb32fa8 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 29 May 2019 15:41:21 +0300 Subject: [PATCH 069/114] Serialize/deserialize for ssl_server2 --- programs/ssl/ssl_server2.c | 48 +++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 7c431a01a..58447e5e9 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3918,7 +3918,53 @@ data_exchange: ret = 0; /* - * 7b. Continue doing data exchanges? + * 7b. Simulate serialize/deserialize and go back to data exchange + */ + if( opt.serialize != 0) + { + size_t len; + unsigned char *buf = NULL; + + opt.serialize = 0; + mbedtls_printf( " Serializing live connection..." ); + + if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len) ) != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + + goto exit; + } + + if( ( buf = mbedtls_calloc(1, len) ) == NULL ) + { + mbedtls_printf( " failed\n ! Couldn't allocate buffer for serialized context" ); + + goto exit; + } + + if( ( ret = mbedtls_ssl_context_save( &ssl, buf, len, &len ) ) != 0 ) + { + mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + + goto exit; + } + + mbedtls_ssl_free( &ssl ); + + mbedtls_printf( " Deserializing connection..." ); + + mbedtls_ssl_init( &ssl ); + + if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) + { + mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned -0x%x\n\n", -ret ); + + goto exit; + } + } + + /* + * 7c. Continue doing data exchanges? */ if( --exchanges_left > 0 ) goto data_exchange; From bbc7b419030209ec07dabb7b69a950b91d1ff00f Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jun 2019 11:06:31 +0300 Subject: [PATCH 070/114] Use MBEDTLS_SSL_CONTEXT_SERIALIZATION flag --- programs/ssl/ssl_client2.c | 12 ++++++++++-- programs/ssl/ssl_server2.c | 11 ++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 435546679..1efa83afa 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -344,6 +344,13 @@ int main( void ) #define USAGE_ECRESTART "" #endif +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +#define USAGE_SERIALIZATION \ + " serialize=%%d default: 0 (do not serialize/deserialize)\n" +#else +#define USAGE_SERIALIZATION "" +#endif + #define USAGE \ "\n usage: ssl_client2 param=<>...\n" \ "\n acceptable parameters:\n" \ @@ -413,7 +420,7 @@ int main( void ) " configuration macro is defined and 1\n" \ " otherwise. The expansion of the macro\n" \ " is printed if it is defined\n" \ - " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ + USAGE_SERIALIZATION \ " acceptable ciphersuite names:\n" #define ALPN_LIST_SIZE 10 @@ -2909,6 +2916,7 @@ send_request: /* * 7c. Simulate serialize/deserialize and go back to data exchange */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) if( opt.serialize != 0) { size_t len; @@ -2951,7 +2959,7 @@ send_request: goto exit; } } - +#endif /* * 7d. Continue doing data exchanges? diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 58447e5e9..090340f19 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -437,6 +437,13 @@ int main( void ) #define USAGE_CURVES "" #endif +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +#define USAGE_SERIALIZATION \ + " serialize=%%d default: 0 (do not serialize/deserialize)\n" +#else +#define USAGE_SERIALIZATION "" +#endif + #define USAGE \ "\n usage: ssl_server2 param=<>...\n" \ "\n acceptable parameters:\n" \ @@ -501,7 +508,7 @@ int main( void ) " configuration macro is defined and 1\n" \ " otherwise. The expansion of the macro\n" \ " is printed if it is defined\n" \ - " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ + USAGE_SERIALIZATION \ " acceptable ciphersuite names:\n" #define ALPN_LIST_SIZE 10 @@ -3920,6 +3927,7 @@ data_exchange: /* * 7b. Simulate serialize/deserialize and go back to data exchange */ +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) if( opt.serialize != 0) { size_t len; @@ -3962,6 +3970,7 @@ data_exchange: goto exit; } } +#endif /* * 7c. Continue doing data exchanges? From 2937d81eb883db5f6a93a77c70b28543dcea7f68 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jun 2019 11:33:23 +0300 Subject: [PATCH 071/114] Add serialization tests to ssl-opt.sh --- tests/ssl-opt.sh | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index e0136a0f6..341a142c4 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1280,6 +1280,32 @@ run_test "Truncated HMAC, DTLS: client enabled, server enabled" \ -S "dumping 'expected mac' (20 bytes)" \ -s "dumping 'expected mac' (10 bytes)" +# Tests for Context serialization + +requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION +run_test "Context serialization, client serializes/deserializes" + "$P_SRV serialize=0 exchanges=2" \ + "$P_CLI serialize=1 exchanges=2" \ + 0 \ + -c "Deserializing connection..." + -S "Deserializing connection..." + +requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION +run_test "Context serialization, server serializes/deserializes" + "$P_SRV serialize=1 exchanges=2" \ + "$P_CLI serialize=0 exchanges=2" \ + 0 \ + -C "Deserializing connection..." + -s "Deserializing connection..." + +requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION +run_test "Context serialization, both serialize/deserialize" + "$P_SRV serialize=1 exchanges=2" \ + "$P_CLI serialize=1 exchanges=2" \ + 0 \ + -c "Deserializing connection..." + -s "Deserializing connection..." + # Tests for DTLS Connection ID extension # So far, the CID API isn't implemented, so we can't From cbee1b3bdac66bf45f4a88838d5afc4bcb384f84 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jun 2019 15:18:19 +0300 Subject: [PATCH 072/114] Add missing slashes to tests --- tests/ssl-opt.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 341a142c4..751f8bcd5 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1283,27 +1283,27 @@ run_test "Truncated HMAC, DTLS: client enabled, server enabled" \ # Tests for Context serialization requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "Context serialization, client serializes/deserializes" +run_test "Context serialization, client serializes/deserializes" \ "$P_SRV serialize=0 exchanges=2" \ "$P_CLI serialize=1 exchanges=2" \ 0 \ - -c "Deserializing connection..." + -c "Deserializing connection..." \ -S "Deserializing connection..." requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "Context serialization, server serializes/deserializes" +run_test "Context serialization, server serializes/deserializes" \ "$P_SRV serialize=1 exchanges=2" \ "$P_CLI serialize=0 exchanges=2" \ 0 \ - -C "Deserializing connection..." + -C "Deserializing connection..." \ -s "Deserializing connection..." requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "Context serialization, both serialize/deserialize" +run_test "Context serialization, both serialize/deserialize" \ "$P_SRV serialize=1 exchanges=2" \ "$P_CLI serialize=1 exchanges=2" \ 0 \ - -c "Deserializing connection..." + -c "Deserializing connection..." \ -s "Deserializing connection..." # Tests for DTLS Connection ID extension From a0b2cd6f82aae31b8b3c1823f38cb2b3ddb41bf9 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jun 2019 15:21:13 +0300 Subject: [PATCH 073/114] ssl-opt.sh tests for serialization are currently using stub implementation --- tests/ssl-opt.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 751f8bcd5..141b8ac62 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1283,7 +1283,7 @@ run_test "Truncated HMAC, DTLS: client enabled, server enabled" \ # Tests for Context serialization requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "Context serialization, client serializes/deserializes" \ +run_test "(STUB) Context serialization, client serializes/deserializes" \ "$P_SRV serialize=0 exchanges=2" \ "$P_CLI serialize=1 exchanges=2" \ 0 \ @@ -1291,7 +1291,7 @@ run_test "Context serialization, client serializes/deserializes" \ -S "Deserializing connection..." requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "Context serialization, server serializes/deserializes" \ +run_test "(STUB) Context serialization, server serializes/deserializes" \ "$P_SRV serialize=1 exchanges=2" \ "$P_CLI serialize=0 exchanges=2" \ 0 \ @@ -1299,7 +1299,7 @@ run_test "Context serialization, server serializes/deserializes" \ -s "Deserializing connection..." requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "Context serialization, both serialize/deserialize" \ +run_test "(STUB) Context serialization, both serialize/deserialize" \ "$P_SRV serialize=1 exchanges=2" \ "$P_CLI serialize=1 exchanges=2" \ 0 \ From 378d64daad6287f6b1a3f0b561ea67ec0e3fb1f8 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jun 2019 15:22:55 +0300 Subject: [PATCH 074/114] Remove mbedtls_ssl_free() and mbedtls_ssl_init() from serialization flow in test --- programs/ssl/ssl_client2.c | 4 ---- programs/ssl/ssl_server2.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 1efa83afa..495827c7c 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2946,12 +2946,8 @@ send_request: goto exit; } - mbedtls_ssl_free( &ssl ); - mbedtls_printf( " Deserializing connection..." ); - mbedtls_ssl_init( &ssl ); - if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned -0x%x\n\n", -ret ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 090340f19..88748b1d7 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3957,12 +3957,8 @@ data_exchange: goto exit; } - mbedtls_ssl_free( &ssl ); - mbedtls_printf( " Deserializing connection..." ); - mbedtls_ssl_init( &ssl ); - if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned -0x%x\n\n", -ret ); From 93c6ff23924818e8775165a080c62d83bb955f1f Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jun 2019 15:36:18 +0300 Subject: [PATCH 075/114] Address review comments for code-style issues --- programs/ssl/ssl_client2.c | 19 ++++++++++++------- programs/ssl/ssl_server2.c | 17 +++++++++++------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 495827c7c..3456dd3df 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2925,23 +2925,27 @@ send_request: opt.serialize = 0; mbedtls_printf( " Serializing live connection..." ); - if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len) ) != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ) ) + != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " + "-0x%x\n\n", -ret ); goto exit; } - if( ( buf = mbedtls_calloc(1, len) ) == NULL ) + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) { - mbedtls_printf( " failed\n ! Couldn't allocate buffer for serialized context" ); + mbedtls_printf( " failed\n ! Couldn't allocate buffer for " + "serialized context" ); goto exit; } if( ( ret = mbedtls_ssl_context_save( &ssl, buf, len, &len ) ) != 0 ) { - mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " + "-0x%x\n\n", -ret ); goto exit; } @@ -2950,12 +2954,13 @@ send_request: if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) { - mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned -0x%x\n\n", -ret ); + mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned " + "-0x%x\n\n", -ret ); goto exit; } } -#endif +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /* * 7d. Continue doing data exchanges? diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 88748b1d7..173593bdd 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3936,23 +3936,27 @@ data_exchange: opt.serialize = 0; mbedtls_printf( " Serializing live connection..." ); - if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len) ) != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ) ) + != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " + "-0x%x\n\n", -ret ); goto exit; } if( ( buf = mbedtls_calloc(1, len) ) == NULL ) { - mbedtls_printf( " failed\n ! Couldn't allocate buffer for serialized context" ); + mbedtls_printf( " failed\n ! Couldn't allocate buffer for " + "serialized context" ); goto exit; } if( ( ret = mbedtls_ssl_context_save( &ssl, buf, len, &len ) ) != 0 ) { - mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned -0x%x\n\n", -ret ); + mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " + "-0x%x\n\n", -ret ); goto exit; } @@ -3961,12 +3965,13 @@ data_exchange: if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) { - mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned -0x%x\n\n", -ret ); + mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned " + "-0x%x\n\n", -ret ); goto exit; } } -#endif +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /* * 7c. Continue doing data exchanges? From 1d1657f11c229d0db303532ad8978b22f467730e Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 4 Jun 2019 16:03:28 +0300 Subject: [PATCH 076/114] Allow stub implementation of the context_save for now --- programs/ssl/ssl_client2.c | 7 +++++-- programs/ssl/ssl_server2.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 3456dd3df..37aecc8b0 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2925,8 +2925,11 @@ send_request: opt.serialize = 0; mbedtls_printf( " Serializing live connection..." ); - if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ) ) - != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ); + + /* Allow stub implementation returning 0 for now */ + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL && + ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 173593bdd..cae278521 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3936,8 +3936,11 @@ data_exchange: opt.serialize = 0; mbedtls_printf( " Serializing live connection..." ); - if( ( ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ) ) - != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ); + + /* Allow stub implementation returning 0 for now */ + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL && + ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); From 12021ee115e5ca4253531273ad8e3738f24f3c7c Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Thu, 6 Jun 2019 10:23:16 +0300 Subject: [PATCH 077/114] Fix spacing --- programs/ssl/ssl_server2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index cae278521..f3858044a 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3948,7 +3948,7 @@ data_exchange: goto exit; } - if( ( buf = mbedtls_calloc(1, len) ) == NULL ) + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) { mbedtls_printf( " failed\n ! Couldn't allocate buffer for " "serialized context" ); From 304d61cede3df47cc3a8b67d929c85541b9e2465 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Thu, 6 Jun 2019 10:40:52 +0300 Subject: [PATCH 078/114] Add option for ssl-context re-initialization flow --- programs/ssl/ssl_client2.c | 30 +++++++++++++++++++++++++++--- programs/ssl/ssl_server2.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 37aecc8b0..47d7d73a6 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -346,7 +346,9 @@ int main( void ) #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) #define USAGE_SERIALIZATION \ - " serialize=%%d default: 0 (do not serialize/deserialize)\n" + " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ + " options: 1 (serialize)\n" \ + " 2 (serialize with re-initialization)\n" #else #define USAGE_SERIALIZATION "" #endif @@ -1589,7 +1591,7 @@ int main( int argc, char *argv[] ) else if( strcmp( p, "serialize") == 0 ) { opt.serialize = atoi( q ); - if( opt.serialize < 0 || opt.serialize > 1) + if( opt.serialize < 0 || opt.serialize > 2) goto usage; } else if( strcmp( p, "eap_tls" ) == 0 ) @@ -2917,7 +2919,7 @@ send_request: * 7c. Simulate serialize/deserialize and go back to data exchange */ #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) - if( opt.serialize != 0) + if( opt.serialize != 0 ) { size_t len; unsigned char *buf = NULL; @@ -2953,6 +2955,28 @@ send_request: goto exit; } + if( opt.serialize == 2 ) + { + mbedtls_ssl_free( &ssl ); + + mbedtls_ssl_init( &ssl ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( opt.nbio == 2 ) + mbedtls_ssl_set_bio( &ssl, &server_fd, delayed_send, delayed_recv, NULL ); + else + mbedtls_ssl_set_bio( &ssl, &server_fd, + mbedtls_net_send, mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + + } + mbedtls_printf( " Deserializing connection..." ); if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index f3858044a..8502a6a1a 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -439,7 +439,9 @@ int main( void ) #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) #define USAGE_SERIALIZATION \ - " serialize=%%d default: 0 (do not serialize/deserialize)\n" + " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ + " options: 1 (serialize)\n" \ + " 2 (serialize with re-initialization)\n" #else #define USAGE_SERIALIZATION "" #endif @@ -2301,7 +2303,7 @@ int main( int argc, char *argv[] ) else if( strcmp( p, "serialize") == 0 ) { opt.serialize = atoi( q ); - if( opt.serialize < 0 || opt.serialize > 1) + if( opt.serialize < 0 || opt.serialize > 2) goto usage; } else if( strcmp( p, "eap_tls" ) == 0 ) @@ -3928,7 +3930,7 @@ data_exchange: * 7b. Simulate serialize/deserialize and go back to data exchange */ #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) - if( opt.serialize != 0) + if( opt.serialize != 0 ) { size_t len; unsigned char *buf = NULL; @@ -3964,6 +3966,27 @@ data_exchange: goto exit; } + if( opt.serialize == 2 ) + { + mbedtls_ssl_free( &ssl ); + + mbedtls_ssl_init( &ssl ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( opt.nbio == 2 ) + mbedtls_ssl_set_bio( &ssl, &client_fd, delayed_send, delayed_recv, NULL ); + else + mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + + } + mbedtls_printf( " Deserializing connection..." ); if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) From c2376f049a9cc582e83d9aaec05f279d83b0a50e Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Thu, 6 Jun 2019 10:44:14 +0300 Subject: [PATCH 079/114] Add tests for re-init flow for context serialization --- tests/ssl-opt.sh | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 141b8ac62..b62a4b035 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1282,30 +1282,60 @@ run_test "Truncated HMAC, DTLS: client enabled, server enabled" \ # Tests for Context serialization +skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, client serializes/deserializes" \ +run_test "(STUB) Context serialization, client serializes" \ "$P_SRV serialize=0 exchanges=2" \ "$P_CLI serialize=1 exchanges=2" \ 0 \ -c "Deserializing connection..." \ -S "Deserializing connection..." +skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, server serializes/deserializes" \ +run_test "(STUB) Context serialization, server serializes" \ "$P_SRV serialize=1 exchanges=2" \ "$P_CLI serialize=0 exchanges=2" \ 0 \ -C "Deserializing connection..." \ -s "Deserializing connection..." +skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, both serialize/deserialize" \ +run_test "(STUB) Context serialization, both serialize" \ "$P_SRV serialize=1 exchanges=2" \ "$P_CLI serialize=1 exchanges=2" \ 0 \ -c "Deserializing connection..." \ -s "Deserializing connection..." +skip_next_test +requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION +run_test "(STUB) Context serialization, re-init, client serializes" \ + "$P_SRV serialize=0 exchanges=2" \ + "$P_CLI serialize=2 exchanges=2" \ + 0 \ + -c "Deserializing connection..." \ + -S "Deserializing connection..." + +skip_next_test +requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION +run_test "(STUB) Context serialization, re-init, server serializes" \ + "$P_SRV serialize=2 exchanges=2" \ + "$P_CLI serialize=0 exchanges=2" \ + 0 \ + -C "Deserializing connection..." \ + -s "Deserializing connection..." + +skip_next_test +requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION +run_test "(STUB) Context serialization, re-init, both serialize" \ + "$P_SRV serialize=2 exchanges=2" \ + "$P_CLI serialize=2 exchanges=2" \ + 0 \ + -c "Deserializing connection..." \ + -s "Deserializing connection..." + # Tests for DTLS Connection ID extension # So far, the CID API isn't implemented, so we can't From 15b3a7ae4d2b93e5e87160f27a1a7f65aa73acef Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Thu, 6 Jun 2019 15:10:07 +0300 Subject: [PATCH 080/114] Fix compiler warnings --- programs/ssl/ssl_client2.c | 12 ++++++------ programs/ssl/ssl_server2.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 47d7d73a6..8ecf9ca5a 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2921,13 +2921,13 @@ send_request: #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) if( opt.serialize != 0 ) { - size_t len; - unsigned char *buf = NULL; + size_t buf_len; + unsigned char *context_buf = NULL; opt.serialize = 0; mbedtls_printf( " Serializing live connection..." ); - ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ); + ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &buf_len ); /* Allow stub implementation returning 0 for now */ if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL && @@ -2939,7 +2939,7 @@ send_request: goto exit; } - if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + if( ( context_buf = mbedtls_calloc( 1, buf_len ) ) == NULL ) { mbedtls_printf( " failed\n ! Couldn't allocate buffer for " "serialized context" ); @@ -2947,7 +2947,7 @@ send_request: goto exit; } - if( ( ret = mbedtls_ssl_context_save( &ssl, buf, len, &len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); @@ -2979,7 +2979,7 @@ send_request: mbedtls_printf( " Deserializing connection..." ); - if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned " "-0x%x\n\n", -ret ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 8502a6a1a..16c8f918d 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3932,13 +3932,13 @@ data_exchange: #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) if( opt.serialize != 0 ) { - size_t len; - unsigned char *buf = NULL; + size_t buf_len; + unsigned char *context_buf = NULL; opt.serialize = 0; mbedtls_printf( " Serializing live connection..." ); - ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &len ); + ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &buf_len ); /* Allow stub implementation returning 0 for now */ if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL && @@ -3950,7 +3950,7 @@ data_exchange: goto exit; } - if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + if( ( context_buf = mbedtls_calloc( 1, buf_len ) ) == NULL ) { mbedtls_printf( " failed\n ! Couldn't allocate buffer for " "serialized context" ); @@ -3958,7 +3958,7 @@ data_exchange: goto exit; } - if( ( ret = mbedtls_ssl_context_save( &ssl, buf, len, &len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); @@ -3989,7 +3989,7 @@ data_exchange: mbedtls_printf( " Deserializing connection..." ); - if( ( ret = mbedtls_ssl_context_load( &ssl, buf, len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned " "-0x%x\n\n", -ret ); From 1a7f7936f3d9aa8473d15af4b520bc780be2e78f Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Fri, 7 Jun 2019 08:39:24 +0300 Subject: [PATCH 081/114] Fix spacing --- programs/ssl/ssl_client2.c | 4 ++-- programs/ssl/ssl_server2.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 8ecf9ca5a..9856744d4 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -347,8 +347,8 @@ int main( void ) #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) #define USAGE_SERIALIZATION \ " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ - " options: 1 (serialize)\n" \ - " 2 (serialize with re-initialization)\n" + " options: 1 (serialize)\n" \ + " 2 (serialize with re-initialization)\n" #else #define USAGE_SERIALIZATION "" #endif diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 16c8f918d..9b836987b 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -440,8 +440,8 @@ int main( void ) #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) #define USAGE_SERIALIZATION \ " serialize=%%d default: 0 (do not serialize/deserialize)\n" \ - " options: 1 (serialize)\n" \ - " 2 (serialize with re-initialization)\n" + " options: 1 (serialize)\n" \ + " 2 (serialize with re-initialization)\n" #else #define USAGE_SERIALIZATION "" #endif From 8e2532196df9869e7eb5dc63239e04d1265000c2 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Thu, 13 Jun 2019 11:45:06 +0300 Subject: [PATCH 082/114] Set timer callbacks with serialization --- programs/ssl/ssl_client2.c | 5 +++++ programs/ssl/ssl_server2.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 9856744d4..41735af04 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2975,6 +2975,11 @@ send_request: mbedtls_net_send, mbedtls_net_recv, opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); +#if defined(MBEDTLS_TIMING_C) + if( opt.nbio != 0 && opt.read_timeout != 0 ) + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); +#endif /* MBEDTLS_TIMING_C */ } mbedtls_printf( " Deserializing connection..." ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 9b836987b..42d1e77ea 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3985,6 +3985,11 @@ data_exchange: mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); +#if defined(MBEDTLS_TIMING_C) + if( opt.nbio != 0 && opt.read_timeout != 0 ) + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); +#endif /* MBEDTLS_TIMING_C */ } mbedtls_printf( " Deserializing connection..." ); From ddf72a1cf633e0c943958eba2a6cb4e1eac3ba21 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Thu, 13 Jun 2019 12:22:50 +0300 Subject: [PATCH 083/114] Fix style issues --- programs/ssl/ssl_client2.c | 22 +++++++++++++--------- programs/ssl/ssl_server2.c | 23 ++++++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 41735af04..a9ab07fe4 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2947,7 +2947,8 @@ send_request: goto exit; } - if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, + buf_len, &buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); @@ -2963,28 +2964,31 @@ send_request: if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", - -ret ); + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned " + " -0x%x\n\n", -ret ); goto exit; } if( opt.nbio == 2 ) - mbedtls_ssl_set_bio( &ssl, &server_fd, delayed_send, delayed_recv, NULL ); + mbedtls_ssl_set_bio( &ssl, &server_fd, delayed_send, + delayed_recv, NULL ); else mbedtls_ssl_set_bio( &ssl, &server_fd, - mbedtls_net_send, mbedtls_net_recv, - opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + mbedtls_net_send, mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); #if defined(MBEDTLS_TIMING_C) if( opt.nbio != 0 && opt.read_timeout != 0 ) - mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, - mbedtls_timing_get_delay ); + mbedtls_ssl_set_timer_cb( &ssl, &timer, + mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); #endif /* MBEDTLS_TIMING_C */ } mbedtls_printf( " Deserializing connection..." ); - if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, buf_len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, + buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned " "-0x%x\n\n", -ret ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 42d1e77ea..6f6f4dd7e 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3958,7 +3958,8 @@ data_exchange: goto exit; } - if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, + buf_len, &buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); @@ -3974,27 +3975,31 @@ data_exchange: if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", - -ret ); + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned " + "-0x%x\n\n", -ret ); goto exit; } if( opt.nbio == 2 ) - mbedtls_ssl_set_bio( &ssl, &client_fd, delayed_send, delayed_recv, NULL ); + mbedtls_ssl_set_bio( &ssl, &client_fd, delayed_send, + delayed_recv, NULL ); else - mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, - opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, + mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); #if defined(MBEDTLS_TIMING_C) if( opt.nbio != 0 && opt.read_timeout != 0 ) - mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, - mbedtls_timing_get_delay ); + mbedtls_ssl_set_timer_cb( &ssl, &timer, + mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); #endif /* MBEDTLS_TIMING_C */ } mbedtls_printf( " Deserializing connection..." ); - if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, buf_len ) ) != 0 ) + if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, + buf_len ) ) != 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_context_load returned " "-0x%x\n\n", -ret ); From 96fb0ee9cf618339e5467eedfcba74145ba80c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 Jul 2019 12:54:17 +0200 Subject: [PATCH 084/114] Save Hello random bytes for later use --- include/mbedtls/ssl_internal.h | 6 ++++++ library/ssl_tls.c | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index c584370e3..11d66eec4 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -642,6 +642,12 @@ struct mbedtls_ssl_transform z_stream ctx_deflate; /*!< compression context */ z_stream ctx_inflate; /*!< decompression context */ #endif + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + /* We need the Hello random bytes in order to re-derive keys from the + * Master Secret and other session info, see ssl_populate_transform() */ + unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */ +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ }; /* diff --git a/library/ssl_tls.c b/library/ssl_tls.c index a978899d6..07201478b 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1046,13 +1046,19 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform, (void) ssl; #endif - /* Copy info about negotiated version and extensions */ + /* + * Some data just needs copying into the structure + */ #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) transform->encrypt_then_mac = encrypt_then_mac; #endif transform->minor_ver = minor_ver; +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + memcpy( transform->randbytes, randbytes, sizeof( transform->randbytes ) ); +#endif + /* * Get various info structures */ From 1aaf66940ef7dbc68e39be7f8938fa8aaad7701c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2019 14:14:05 +0200 Subject: [PATCH 085/114] Implement usage checks in context_save() Enforce restrictions indicated in the documentation. This allows to make some simplifying assumptions (no need to worry about saving IVs for CBC in TLS < 1.1, nor about saving handshake data) and guarantees that all values marked as "forced" in the design document have the intended values and can be skipped when serialising. Some of the "forced" values are not checked because their value is a consequence of other checks (for example, session_negotiated == NULL outside handshakes). We do however check that session and transform are not NULL (even if that's also a consequence of the initial handshake being over) as we're going to dereference them and static analyzers may appreciate the info. --- include/mbedtls/ssl.h | 3 ++- include/mbedtls/ssl_internal.h | 15 +++++++++++++++ library/ssl_tls.c | 29 +++++++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 376780474..13320145f 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3918,13 +3918,14 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in * progress, or there is pending data for reading or sending, - * or the connection does not use DTLS 1.2 with and AEAD + * or the connection does not use DTLS 1.2 with an AEAD * ciphersuite, or renegotiation is enabled. */ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, unsigned char *buf, size_t buf_len, size_t *olen ); + /** * \brief Load serialized connection data to an SSL context. * diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 11d66eec4..f703da99b 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -650,6 +650,21 @@ struct mbedtls_ssl_transform #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ }; +/* + * Return 1 if the transform uses an AEAD cipher, 0 otherwise. + * Equivalently, return 0 if a separate MAC is used, 1 otherwise. + */ +static inline int mbedtls_ssl_transform_uses_aead( + const mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) + return( transform->maclen == 0 && transform->taglen != 0 ); +#else + (void) transform; + return( 1 ); +#endif +} + /* * Internal representation of record frames * diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 07201478b..247459f12 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11292,9 +11292,34 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, size_t buf_len, size_t *olen ) { - /* Unimplemented */ - (void) ssl; + /* + * Enforce current usage restrictions + */ + if( /* The initial handshake is over ... */ + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->handshake != NULL || + /* ... and the various sub-structures are indeed ready. */ + ssl->transform == NULL || + ssl->session == NULL || + /* There is no pending incoming or outgoing data ... */ + mbedtls_ssl_check_pending( ssl ) != 0 || + ssl->out_left != 0 || + /* We're using DTLS 1.2 ... */ + ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 || + /* ... with an AEAD ciphersuite. */ + mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 || + /* Renegotation is disabled. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED +#endif + ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Unimplemented */ if( buf != NULL ) memset( buf, 0, buf_len ); From 00400c2bf645976a250622f9b01a41ff1391b966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 10 Jul 2019 14:58:45 +0200 Subject: [PATCH 086/114] Document internal serialisation format This mainly follows the design document (saving all fields marked "saved" in the main structure and the transform sub-structure) with two exceptions: - things related to renegotiation are excluded here (there weren't quite in the design document as the possibility of allowing renegotiation was still on the table, which is no longer is) - also, ssl.secure_renegotiation (which is not guarded by MBEDTLS_SSL_RENEGOTIATION because it's used in initial handshakes even with renegotiation disabled) is still excluded, as we don't need it after the handshake. - things related to Connection ID are added, as they weren't present at the time the design document was written. The exact format of the header (value of the bitflag indicating compile-time options, whether and how to merge it with the serialized session header) will be determined later. --- library/ssl_tls.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 247459f12..cfd5cc8b2 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11286,6 +11286,41 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) /* * Serialize a full SSL context + * + * The format of the serialized data is: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * // header + * opaque mbedtls_version[3]; // major, minor, patch + * opaque context_format[n]; // version-specific field determining + * // the format of the remaining + * // serialized data. (n TBD) + * Note: When updating the format, remember to keep + * these version+format bytes. (To be confirmed.) + * + * // session sub-structure + * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() + * // transform sub-structure + * uint8 random[64]; // ServerHello.random+ClientHello.random + * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value + * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use + * // fields from ssl_context + * uint32 badmac_seen; // DTLS: number of records with failing MAC + * uint64 in_window_top; // DTLS: last validated record seq_num + * uint64 in_window; // DTLS: bitmask for replay protection + * uint8 disable_datagram_packing; // DTLS: only one record per datagram + * uint64 cur_out_ctr; // Record layer: outgoing sequence number + * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) + * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol + * + * Note that many fields of the ssl_context or sub-structures are not + * serialized, as they fall in one of the following categories: + * + * 1. forced value (eg in_left must be 0) + * 2. pointer to dynamically-allocated memory (eg session, transform) + * 3. value can be re-derived from other data (eg session keys from MS) + * 4. value was temporary (eg content of input buffer) + * 5. value will be provided by the user again (eg I/O callbacks and context) */ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, unsigned char *buf, From 0ff76407d245166caea505cffa3273fbbae24067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2019 09:56:30 +0200 Subject: [PATCH 087/114] Add usage checks in context_load() --- library/ssl_tls.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index cfd5cc8b2..d555c5a73 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11370,8 +11370,36 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { + /* + * The context should have been freshly setup or reset. + * Give the user an error in case of obvious misuse. + * (Checking session is useful because if won't be NULL if we're + * renegotiating, or if the user mistakenly loaded a session first.) + */ + if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST || + ssl->session != NULL ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * We can't check that the config matches the initial one, but we can at + * least check it matches the requirements for serializing. + */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->conf->max_major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->min_major_ver > MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 || + ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED +#endif + ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Unimplemented */ - (void) ssl; (void) buf; (void) len; From 4c90e858b5b251f45232dfc2533e5685c4b5d133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2019 10:58:10 +0200 Subject: [PATCH 088/114] Add (stub) header writing and checking The number of meaning of the flags will be determined later, when handling the relevant struct members. For now three bytes are reserved as an example, but this number may change later. --- include/mbedtls/ssl.h | 2 ++ library/ssl_tls.c | 64 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 13320145f..89b560a27 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3985,6 +3985,8 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * comes from a different Mbed TLS version or build. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. */ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d555c5a73..e838c20d1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11284,6 +11284,17 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); } +static unsigned char ssl_serialized_context_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF, + ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF, + 0, /* placeholder */ + 0, /* placeholder */ + 0, /* placeholder */ +}; + /* * Serialize a full SSL context * @@ -11292,9 +11303,9 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) * * // header * opaque mbedtls_version[3]; // major, minor, patch - * opaque context_format[n]; // version-specific field determining + * opaque context_format[5]; // version-specific field determining * // the format of the remaining - * // serialized data. (n TBD) + * // serialized data. * Note: When updating the format, remember to keep * these version+format bytes. (To be confirmed.) * @@ -11327,6 +11338,9 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, size_t buf_len, size_t *olen ) { + unsigned char *p = buf; + size_t used = 0; + /* * Enforce current usage restrictions */ @@ -11354,11 +11368,25 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - /* Unimplemented */ - if( buf != NULL ) - memset( buf, 0, buf_len ); + /* + * Version and format identifier + */ + used += sizeof( ssl_serialized_context_header ); - *olen = 0; + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ); + p += sizeof( ssl_serialized_context_header ); + } + + /* + * Done + */ + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( 0 ); } @@ -11370,6 +11398,9 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) { + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + /* * The context should have been freshly setup or reset. * Give the user an error in case of obvious misuse. @@ -11399,9 +11430,24 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - /* Unimplemented */ - (void) buf; - (void) len; + /* + * Check version identifier + */ + if( (size_t)( end - p ) < sizeof( ssl_serialized_context_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_context_header ); + + /* + * Done - should have consumed entire buffer + */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( 0 ); } From 4b7e6b925f4a6785b3d5e7ccb2d3eabb0131e979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 11 Jul 2019 12:50:53 +0200 Subject: [PATCH 089/114] Add session saving/loading For now, the header (version+format bytes) is duplicated. This might be optimized later. --- include/mbedtls/ssl.h | 11 +++++- library/ssl_tls.c | 86 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 92 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 89b560a27..bf7a320c1 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3912,7 +3912,11 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * \note \p olen is updated to the correct value regardless of * whether \p buf_len was large enough. This makes it possible * to determine the necessary size by calling this function - * with \p buf set to \c NULL and \p buf_len to \c 0. + * with \p buf set to \c NULL and \p buf_len to \c 0. However, + * the value of \p olen is only guaranteed to be correct when + * the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or + * \c 0. If the return value is different, then the value of + * \p olen is undefined. * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. @@ -3977,6 +3981,11 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, * newly-configured value with the value that was active when * the context was saved. * + * \note When this function returns an error code, it calls + * mbedtls_ssl_free() on \p ssl. In this case, you need to + * prepare the context with the usual sequence starting with a + * call to mbedtls_ssl_init() if you want to use it again. + * * \param ssl The SSL context structure to be populated. It must have * been prepared as described in the note above. * \param buf The buffer holding the serialized connection data. It must diff --git a/library/ssl_tls.c b/library/ssl_tls.c index e838c20d1..f6d6156f9 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11340,6 +11340,8 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, { unsigned char *p = buf; size_t used = 0; + size_t session_len; + int ret = 0; /* * Enforce current usage restrictions @@ -11380,6 +11382,29 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, p += sizeof( ssl_serialized_context_header ); } + /* + * Session (length + data) + */ + ret = mbedtls_ssl_session_save( ssl->session, NULL, 0, &session_len ); + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + return( ret ); + + used += 4 + session_len; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( session_len >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( session_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session_len ) & 0xFF ); + + ret = mbedtls_ssl_session_save( ssl->session, + p, session_len, &session_len ); + if( ret != 0 ) + return( ret ); + + p += session_len; + } + /* * Done */ @@ -11388,18 +11413,25 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, if( used > buf_len ) return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used ); + return( 0 ); } /* - * Deserialize a full SSL context + * Unserialize context, see mbedtls_ssl_context_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error. */ -int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) +static int ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) { const unsigned char *p = buf; const unsigned char * const end = buf + len; + size_t session_len; + int ret; /* * The context should have been freshly setup or reset. @@ -11430,6 +11462,8 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } + MBEDTLS_SSL_DEBUG_BUF( 4, "context to load", buf, len ); + /* * Check version identifier */ @@ -11443,6 +11477,35 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, } p += sizeof( ssl_serialized_context_header ); + /* + * Session + */ + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session_len = ( (size_t) p[0] << 24 ) | + ( (size_t) p[1] << 16 ) | + ( (size_t) p[2] << 8 ) | + ( (size_t) p[3] ); + p += 4; + + ssl->session = mbedtls_calloc( 1, sizeof( mbedtls_ssl_session ) ); + if( ssl->session == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + mbedtls_ssl_session_init( ssl->session ); + + ssl->session_in = ssl->session; + ssl->session_out = ssl->session; + + if( (size_t)( end - p ) < session_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = mbedtls_ssl_session_load( ssl->session, p, session_len ); + if( ret != 0 ) + return( ret ); + + p += session_len; + /* * Done - should have consumed entire buffer */ @@ -11452,6 +11515,21 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, return( 0 ); } +/* + * Unserialize context: public wrapper for error cleaning + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *context, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_context_load( context, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_free( context ); + + return( ret ); +} + /* * Free an SSL context */ From a88399c0918c79251429db39b9eb8fc55fe570f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 12 Jul 2019 10:41:55 +0200 Subject: [PATCH 090/114] Improve demo/testing code in client/server2 Previously it was missing reset in case 1, and in case 2 the code was never executed as the option value was reset to 0. Tighten checking of return values of save(NULL, 0) now that it works. Also, improve the printed output as well as the comments. I checked manually that everything now works and fail in the expected way: save, reset-or-reinit and load all succeed, but the subsequent read or write fails. --- programs/ssl/ssl_client2.c | 40 +++++++++++++++++++-------- programs/ssl/ssl_server2.c | 55 ++++++++++++++++++++++++++++++++------ 2 files changed, 76 insertions(+), 19 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index a9ab07fe4..37b047cc4 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2924,14 +2924,10 @@ send_request: size_t buf_len; unsigned char *context_buf = NULL; - opt.serialize = 0; - mbedtls_printf( " Serializing live connection..." ); + mbedtls_printf( " . Serializing live connection..." ); ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &buf_len ); - - /* Allow stub implementation returning 0 for now */ - if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL && - ret != 0 ) + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) { mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); @@ -2950,14 +2946,32 @@ send_request: if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) { - mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " + mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); goto exit; } + mbedtls_printf( " ok\n" ); + + if( opt.serialize == 1 ) + { + mbedtls_printf( " . Reseting context..." ); + + if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned " + "-0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + if( opt.serialize == 2 ) { + mbedtls_printf( " . Freeing and reinitializing context..." ); + mbedtls_ssl_free( &ssl ); mbedtls_ssl_init( &ssl ); @@ -2965,7 +2979,7 @@ send_request: if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned " - " -0x%x\n\n", -ret ); + "-0x%x\n\n", -ret ); goto exit; } @@ -2973,8 +2987,8 @@ send_request: mbedtls_ssl_set_bio( &ssl, &server_fd, delayed_send, delayed_recv, NULL ); else - mbedtls_ssl_set_bio( &ssl, &server_fd, - mbedtls_net_send, mbedtls_net_recv, + mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, + mbedtls_net_recv, opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); #if defined(MBEDTLS_TIMING_C) @@ -2983,9 +2997,11 @@ send_request: mbedtls_timing_set_delay, mbedtls_timing_get_delay ); #endif /* MBEDTLS_TIMING_C */ + + mbedtls_printf( " ok\n" ); } - mbedtls_printf( " Deserializing connection..." ); + mbedtls_printf( " . Deserializing connection..." ); if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, buf_len ) ) != 0 ) @@ -2995,6 +3011,8 @@ send_request: goto exit; } + + mbedtls_printf( " ok\n" ); } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 6f6f4dd7e..5b7d17379 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3935,14 +3935,10 @@ data_exchange: size_t buf_len; unsigned char *context_buf = NULL; - opt.serialize = 0; - mbedtls_printf( " Serializing live connection..." ); + mbedtls_printf( " . Serializing live connection..." ); ret = mbedtls_ssl_context_save( &ssl, NULL, 0, &buf_len ); - - /* Allow stub implementation returning 0 for now */ - if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL && - ret != 0 ) + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) { mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); @@ -3961,14 +3957,47 @@ data_exchange: if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) { - mbedtls_printf( "failed\n ! mbedtls_ssl_context_save returned " + mbedtls_printf( " failed\n ! mbedtls_ssl_context_save returned " "-0x%x\n\n", -ret ); goto exit; } + mbedtls_printf( " ok\n" ); + + /* + * This simulates a workflow where you have a long-lived server + * instance, potentially with a pool of ssl_context objects, and you + * just want to re-use one while the connection is inactive: in that + * case you can just reset() it, and then it's ready to receive + * serialized data from another connection (or the same here). + */ + if( opt.serialize == 1 ) + { + mbedtls_printf( " . Reseting context..." ); + + if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned " + "-0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + /* + * This simulates a workflow where you have one server instance per + * connection, and want to release it entire when the connection is + * inactive, and spawn it again when needed again - this would happen + * between ssl_free() and ssl_init() below, together with any other + * teardown/startup code needed - for example, preparing the + * ssl_config again (see section 3 "setup stuff" in this file). + */ if( opt.serialize == 2 ) { + mbedtls_printf( " . Freeing and reinitializing context..." ); + mbedtls_ssl_free( &ssl ); mbedtls_ssl_init( &ssl ); @@ -3980,6 +4009,12 @@ data_exchange: goto exit; } + /* + * This illustrates the minimum amount of things you need to set + * up, however you could set up much more if desired, for example + * if you want to share your set up code between the case of + * establishing a new connection and this case. + */ if( opt.nbio == 2 ) mbedtls_ssl_set_bio( &ssl, &client_fd, delayed_send, delayed_recv, NULL ); @@ -3994,9 +4029,11 @@ data_exchange: mbedtls_timing_set_delay, mbedtls_timing_get_delay ); #endif /* MBEDTLS_TIMING_C */ + + mbedtls_printf( " ok\n" ); } - mbedtls_printf( " Deserializing connection..." ); + mbedtls_printf( " . Deserializing connection..." ); if( ( ret = mbedtls_ssl_context_load( &ssl, context_buf, buf_len ) ) != 0 ) @@ -4006,6 +4043,8 @@ data_exchange: goto exit; } + + mbedtls_printf( " ok\n" ); } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ From b9dfc9fd30e22bca28447cdc8bf1fba4f9371b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 12 Jul 2019 10:50:19 +0200 Subject: [PATCH 091/114] Fix English in comments --- library/ssl_tls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f6d6156f9..f1510a349 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -10150,7 +10150,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, } /* - * Unserialize session, see mbedtls_ssl_session_save() for format. + * Deserialize session, see mbedtls_ssl_session_save() for format. * * This internal version is wrapped by a public function that cleans up in * case of error. @@ -10375,7 +10375,7 @@ static int ssl_session_load( mbedtls_ssl_session *session, } /* - * Unserialize session: public wrapper for error cleaning + * Deserialize session: public wrapper for error cleaning */ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, const unsigned char *buf, @@ -11419,7 +11419,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, } /* - * Unserialize context, see mbedtls_ssl_context_save() for format. + * Deserialize context, see mbedtls_ssl_context_save() for format. * * This internal version is wrapped by a public function that cleans up in * case of error. @@ -11516,7 +11516,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, } /* - * Unserialize context: public wrapper for error cleaning + * Deserialize context: public wrapper for error cleaning */ int mbedtls_ssl_context_load( mbedtls_ssl_context *context, const unsigned char *buf, From c2a7b891a1804151e23cb17e9506efc091cfe8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jul 2019 09:04:11 +0200 Subject: [PATCH 092/114] Add transform (de)serialization --- library/ssl_tls.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f1510a349..2d068faad 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11405,6 +11405,31 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, p += session_len; } + /* + * Transform + */ + used += sizeof( ssl->transform->randbytes ); + if( used <= buf_len ) + { + memcpy( p, ssl->transform->randbytes, + sizeof( ssl->transform->randbytes ) ); + p += sizeof( ssl->transform->randbytes ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len; + if( used <= buf_len ) + { + *p++ = ssl->transform->in_cid_len; + memcpy( p, ssl->transform->in_cid, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + *p++ = ssl->transform->out_cid_len; + memcpy( p, ssl->transform->out_cid, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + /* * Done */ @@ -11418,6 +11443,22 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, return( 0 ); } +/* + * Helper to get TLS 1.2 PRF from ciphersuite + * (Duplicates bits of logic from ssl_set_handshake_prfs().) + */ +typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); +static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + return ciphersuite_info->mac == MBEDTLS_MD_SHA384 ? tls_prf_sha384 : tls_prf_sha256; +} + /* * Deserialize context, see mbedtls_ssl_context_save() for format. * @@ -11506,6 +11547,69 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, p += session_len; + /* + * Transform + */ + + /* Allocate and initialize structure */ + ssl->transform = mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) ); + if( ssl->transform == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + mbedtls_ssl_transform_init( ssl->transform ); + + ssl->transform_in = ssl->transform; + ssl->transform_out = ssl->transform; + + /* Read random bytes and populate structure */ + if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = ssl_populate_transform( ssl->transform, + ssl->session->ciphersuite, + ssl->session->master, +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session->encrypt_then_mac, +#endif +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + ssl->session->trunc_hmac, +#endif +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ +#if defined(MBEDTLS_ZLIB_SUPPORT) + ssl->session->compression, +#endif + ssl_tls12prf_from_cs( ssl->session->ciphersuite ), + p, /* currently pointing to randbytes */ + MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */ + ssl->conf->endpoint, + ssl ); + if( ret != 0 ) + return( ret ); + + p += sizeof( ssl->transform->randbytes ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Read connection IDs and store them */ + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->transform->in_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->in_cid, p, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + ssl->transform->out_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->out_cid_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->out_cid, p, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + /* * Done - should have consumed entire buffer */ From 3309a6799665fab6fb9c61aa50897745908bdc30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jul 2019 10:31:11 +0200 Subject: [PATCH 093/114] Fix memory leak in client/server2 context_buf was never free()d. Moreover, since we want to free it on error paths as well, and even properly zeroize it in order to demonstrate good memory hygiene, we need to make it and its length main()-scoped. --- programs/ssl/ssl_client2.c | 15 ++++++++++++++- programs/ssl/ssl_server2.c | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 37b047cc4..4efd73f2c 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1083,6 +1083,10 @@ int main( int argc, char *argv[] ) #endif char *p, *q; const int *list; +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + unsigned char *context_buf = NULL; + size_t context_buf_len; +#endif #if defined(MBEDTLS_SSL_EXPORT_KEYS) unsigned char eap_tls_keymaterial[16]; unsigned char eap_tls_iv[8]; @@ -2922,7 +2926,6 @@ send_request: if( opt.serialize != 0 ) { size_t buf_len; - unsigned char *context_buf = NULL; mbedtls_printf( " . Serializing live connection..." ); @@ -2942,6 +2945,7 @@ send_request: goto exit; } + context_buf_len = buf_len; if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) @@ -3012,6 +3016,10 @@ send_request: goto exit; } + mbedtls_free( context_buf ); + context_buf = NULL; + context_buf_len = 0; + mbedtls_printf( " ok\n" ); } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ @@ -3152,6 +3160,11 @@ exit: if( session_data != NULL ) mbedtls_platform_zeroize( session_data, session_data_len ); mbedtls_free( session_data ); +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + if( context_buf != NULL ) + mbedtls_platform_zeroize( context_buf, context_buf_len ); + mbedtls_free( context_buf ); +#endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 5b7d17379..dbdb29959 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -1727,6 +1727,10 @@ int main( int argc, char *argv[] ) size_t cid_len = 0; size_t cid_renego_len = 0; #endif +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + unsigned char *context_buf = NULL; + size_t context_buf_len; +#endif int i; char *p, *q; @@ -3933,7 +3937,6 @@ data_exchange: if( opt.serialize != 0 ) { size_t buf_len; - unsigned char *context_buf = NULL; mbedtls_printf( " . Serializing live connection..." ); @@ -3953,6 +3956,7 @@ data_exchange: goto exit; } + context_buf_len = buf_len; if( ( ret = mbedtls_ssl_context_save( &ssl, context_buf, buf_len, &buf_len ) ) != 0 ) @@ -4044,6 +4048,10 @@ data_exchange: goto exit; } + mbedtls_free( context_buf ); + context_buf = NULL; + context_buf_len = 0; + mbedtls_printf( " ok\n" ); } #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ @@ -4155,6 +4163,12 @@ exit: mbedtls_free( buf ); +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + if( context_buf != NULL ) + mbedtls_platform_zeroize( context_buf, context_buf_len ); + mbedtls_free( context_buf ); +#endif + #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_memory_buffer_alloc_status(); From c86c5df0814946c3e1835c1103eaf46aeb1ef689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jul 2019 11:23:03 +0200 Subject: [PATCH 094/114] Add saved fields from top-level structure --- library/ssl_tls.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 2d068faad..d20cce1ed 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11430,6 +11430,88 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + /* + * Saved fields from top-level ssl_context structure + */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + used += 4; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( ssl->badmac_seen >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->badmac_seen >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->badmac_seen >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->badmac_seen ) & 0xFF ); + } +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + used += 16; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( ssl->in_window_top >> 56 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 48 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 40 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 32 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window_top ) & 0xFF ); + + *p++ = (unsigned char)( ( ssl->in_window >> 56 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 48 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 40 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 32 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 24 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->in_window ) & 0xFF ); + } +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 1; + if( used <= buf_len ) + { + *p++ = ssl->disable_datagram_packing; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + used += 8; + if( used <= buf_len ) + { + memcpy( p, ssl->cur_out_ctr, 8 ); + p += 8; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 2; + if( used <= buf_len ) + { + *p++ = (unsigned char)( ( ssl->mtu >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( ssl->mtu ) & 0xFF ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + const uint8_t alpn_len = ssl->alpn_chosen + ? strlen( ssl->alpn_chosen ) + : 0; + + used += 1 + alpn_len; + if( used <= buf_len ) + { + *p++ = alpn_len; + + if( ssl->alpn_chosen != NULL ) + { + memcpy( p, ssl->alpn_chosen, alpn_len ); + p += alpn_len; + } + } + } +#endif /* MBEDTLS_SSL_ALPN */ + /* * Done */ @@ -11610,6 +11692,98 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, p += ssl->transform->out_cid_len; #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + /* + * Saved fields from top-level ssl_context structure + */ +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->badmac_seen = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( (size_t)( end - p ) < 16 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->in_window_top = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; + + ssl->in_window = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->disable_datagram_packing = *p++; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( (size_t)( end - p ) < 8 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->cur_out_ctr, p, 8 ); + p += 8; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->mtu = ( p[0] << 8 ) | p[1]; + p += 2; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + uint8_t alpn_len; + const char **cur; + + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + alpn_len = *p++; + + if( alpn_len != 0 && ssl->conf->alpn_list != NULL ) + { + /* alpn_chosen should point to an item in the configured list */ + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + if( strlen( *cur ) == alpn_len && + memcmp( p, cur, alpn_len ) == 0 ) + { + ssl->alpn_chosen = *cur; + break; + } + } + } + + /* can only happen on conf mismatch */ + if( alpn_len != 0 && ssl->alpn_chosen == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + p += alpn_len; + } +#endif /* MBEDTLS_SSL_ALPN */ + /* * Done - should have consumed entire buffer */ From 0eb3eac0239be23023a6b55c3771d40a1fe9c7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jul 2019 11:53:51 +0200 Subject: [PATCH 095/114] Add setting of forced fields when deserializing --- library/ssl_tls.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d20cce1ed..a70564896 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11784,6 +11784,31 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_ALPN */ + /* + * Forced fields from top-level ssl_context structure + * + * Most of them already set to the correct value by mbedtls_ssl_init() and + * mbedtls_ssl_reset(), so we only need to set the remaining ones. + */ + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->in_epoch = 1; +#endif + + /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, + * which we don't want - otherwise we'd end up freeing the wrong transform + * by calling ssl_handshake_wrapup_free_hs_transform() inappropriately. */ + if( ssl->handshake != NULL ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + } + /* * Done - should have consumed entire buffer */ From 13c8e68477c58d07647ab5c753c221ab659fd54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Jul 2019 12:23:22 +0200 Subject: [PATCH 096/114] Change requirements for setting timer callback The code wants timer callbacks to be set (checked in fetch_input()), and can't easily check whether we're using nbio, so it seems easier to require the callbacks to be always set rather than only with nbio as was previously done. --- include/mbedtls/ssl.h | 15 ++++++--------- programs/ssl/ssl_client2.c | 1 - programs/ssl/ssl_server2.c | 1 - 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index bf7a320c1..c1c4298c8 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3963,15 +3963,12 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, * (unless they were already set before calling * mbedtls_ssl_session_reset() and the values are suitable for * the present connection). Specifically, you want to call - * at least mbedtls_ssl_set_bio(). If you're using a read - * timeout (that is, you called - * mbedtls_ssl_conf_read_timeout() with a non-zero timeout) - * and non-blocking I/O, you also need to set timer callbacks - * by calling mbedtls_ssl_set_timer_cb(). All other SSL setter - * functions are not necessary to call, either because they're - * only used in handshakes, or because the setting is already - * saved. You might choose to call them anyway, for example in - * order to share code between the cases of establishing a new + * at least mbedtls_ssl_set_bio() and + * mbedtls_ssl_set_timer_cb(). All other SSL setter functions + * are not necessary to call, either because they're only used + * in handshakes, or because the setting is already saved. You + * might choose to call them anyway, for example in order to + * share code between the cases of establishing a new * connection and the case of loading an already-established * connection. * diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 4efd73f2c..b93d645e5 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2996,7 +2996,6 @@ send_request: opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); #if defined(MBEDTLS_TIMING_C) - if( opt.nbio != 0 && opt.read_timeout != 0 ) mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index dbdb29959..7ac3a82ea 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -4028,7 +4028,6 @@ data_exchange: opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); #if defined(MBEDTLS_TIMING_C) - if( opt.nbio != 0 && opt.read_timeout != 0 ) mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay ); From 862b3196d6fc165116a0296c24bee0387933fbee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 14:13:43 +0200 Subject: [PATCH 097/114] Enable serialisation tests in ssl-opt.sh They currently pass in a default build. --- tests/ssl-opt.sh | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index b62a4b035..67d3b9f85 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1282,56 +1282,50 @@ run_test "Truncated HMAC, DTLS: client enabled, server enabled" \ # Tests for Context serialization -skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, client serializes" \ - "$P_SRV serialize=0 exchanges=2" \ - "$P_CLI serialize=1 exchanges=2" \ +run_test "Context serialization, client serializes" \ + "$P_SRV dtls=1 serialize=0 exchanges=2" \ + "$P_CLI dtls=1 serialize=1 exchanges=2" \ 0 \ -c "Deserializing connection..." \ -S "Deserializing connection..." -skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, server serializes" \ - "$P_SRV serialize=1 exchanges=2" \ - "$P_CLI serialize=0 exchanges=2" \ +run_test "Context serialization, server serializes" \ + "$P_SRV dtls=1 serialize=1 exchanges=2" \ + "$P_CLI dtls=1 serialize=0 exchanges=2" \ 0 \ -C "Deserializing connection..." \ -s "Deserializing connection..." -skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, both serialize" \ - "$P_SRV serialize=1 exchanges=2" \ - "$P_CLI serialize=1 exchanges=2" \ +run_test "Context serialization, both serialize" \ + "$P_SRV dtls=1 serialize=1 exchanges=2" \ + "$P_CLI dtls=1 serialize=1 exchanges=2" \ 0 \ -c "Deserializing connection..." \ -s "Deserializing connection..." -skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, re-init, client serializes" \ - "$P_SRV serialize=0 exchanges=2" \ - "$P_CLI serialize=2 exchanges=2" \ +run_test "Context serialization, re-init, client serializes" \ + "$P_SRV dtls=1 serialize=0 exchanges=2" \ + "$P_CLI dtls=1 serialize=2 exchanges=2" \ 0 \ -c "Deserializing connection..." \ -S "Deserializing connection..." -skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, re-init, server serializes" \ - "$P_SRV serialize=2 exchanges=2" \ - "$P_CLI serialize=0 exchanges=2" \ +run_test "Context serialization, re-init, server serializes" \ + "$P_SRV dtls=1 serialize=2 exchanges=2" \ + "$P_CLI dtls=1 serialize=0 exchanges=2" \ 0 \ -C "Deserializing connection..." \ -s "Deserializing connection..." -skip_next_test requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION -run_test "(STUB) Context serialization, re-init, both serialize" \ - "$P_SRV serialize=2 exchanges=2" \ - "$P_CLI serialize=2 exchanges=2" \ +run_test "Context serialization, re-init, both serialize" \ + "$P_SRV dtls=1 serialize=2 exchanges=2" \ + "$P_CLI dtls=1 serialize=2 exchanges=2" \ 0 \ -c "Deserializing connection..." \ -s "Deserializing connection..." From 142ba736d900d854474cd9da9bdb81b707573bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 14:43:30 +0200 Subject: [PATCH 098/114] Re-use buffer allocated by handshake_init() This fixes a memory leak as well (found by running ssl-opt.sh in an Asan build). --- library/ssl_tls.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index a70564896..8d75cf3d2 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11612,13 +11612,12 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, ( (size_t) p[3] ); p += 4; - ssl->session = mbedtls_calloc( 1, sizeof( mbedtls_ssl_session ) ); - if( ssl->session == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - mbedtls_ssl_session_init( ssl->session ); - + /* This has been allocated by ssl_handshake_init(), called by + * by either ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->session = ssl->session_negotiate; ssl->session_in = ssl->session; ssl->session_out = ssl->session; + ssl->session_negotiate = NULL; if( (size_t)( end - p ) < session_len ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -11633,14 +11632,12 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, * Transform */ - /* Allocate and initialize structure */ - ssl->transform = mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) ); - if( ssl->transform == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - mbedtls_ssl_transform_init( ssl->transform ); - + /* This has been allocated by ssl_handshake_init(), called by + * by either ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->transform = ssl->transform_negotiate; ssl->transform_in = ssl->transform; ssl->transform_out = ssl->transform; + ssl->transform_negotiate = NULL; /* Read random bytes and populate structure */ if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) ) From 9df5a82079db7ba79ae18a6a08e785cbf275ad66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 14:51:09 +0200 Subject: [PATCH 099/114] Actually reset the context on save as advertised Also fix some wording in the documentation while at it. --- include/mbedtls/ssl.h | 6 ++++-- library/ssl_tls.c | 2 +- programs/ssl/ssl_client2.c | 12 ++---------- programs/ssl/ssl_server2.c | 12 ++---------- 4 files changed, 9 insertions(+), 23 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index c1c4298c8..272c3b920 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3894,10 +3894,10 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * \note When this function succeeds, it calls * mbedtls_ssl_session_reset() on \p ssl which as a result is * no longer associated with the connection that has been - * serialized. This avoids creating copies of the session + * serialized. This avoids creating copies of the connection * state. You're then free to either re-use the context * structure for a different connection, or call - * mbedtls_ssl_session_free() on it. See the documentation of + * mbedtls_ssl_free() on it. See the documentation of * mbedtls_ssl_session_reset() for more details. * * \param ssl The SSL context to save. On success, it is no longer @@ -3920,6 +3920,8 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed + * while reseting the context. * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in * progress, or there is pending data for reading or sending, * or the connection does not use DTLS 1.2 with an AEAD diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8d75cf3d2..60e9ab0e2 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11522,7 +11522,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used ); - return( 0 ); + return( ssl_session_reset_int( ssl, 0 ) ); } /* diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index b93d645e5..bcccd1de3 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2960,16 +2960,8 @@ send_request: if( opt.serialize == 1 ) { - mbedtls_printf( " . Reseting context..." ); - - if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned " - "-0x%x\n\n", -ret ); - goto exit; - } - - mbedtls_printf( " ok\n" ); + /* nothing to do here, done by context_save() already */ + mbedtls_printf( " . Context has been reset... ok" ); } if( opt.serialize == 2 ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 7ac3a82ea..102951b28 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -3978,16 +3978,8 @@ data_exchange: */ if( opt.serialize == 1 ) { - mbedtls_printf( " . Reseting context..." ); - - if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) - { - mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned " - "-0x%x\n\n", -ret ); - goto exit; - } - - mbedtls_printf( " ok\n" ); + /* nothing to do here, done by context_save() already */ + mbedtls_printf( " . Context has been reset... ok" ); } /* From 5ea13b854aa7f400a56c1515a56b7629dbf2eae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 15:02:54 +0200 Subject: [PATCH 100/114] Fix compiler warning: comparing signed to unsigned Since the type of cid_len is unsigned but shorter than int, it gets "promoted" to int (which is also the type of the result), unless we make the other operand an unsigned int which then forces the expression to unsigned int as well. --- library/ssl_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 60e9ab0e2..8212baa30 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11674,7 +11674,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, ssl->transform->in_cid_len = *p++; - if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1 ) + if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1u ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); memcpy( ssl->transform->in_cid, p, ssl->transform->in_cid_len ); From 5c0e377532c456020322dc126ca8a70f4a1da852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 16:13:17 +0200 Subject: [PATCH 101/114] Provide serialisation API only if it's enabled --- include/mbedtls/ssl.h | 2 ++ library/ssl_tls.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 272c3b920..118263809 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3879,6 +3879,7 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); */ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) /** * \brief Save an active connection as serialized data in a buffer. * This allows the freeing or re-using of the SSL context @@ -4000,6 +4001,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /** * \brief Initialize an SSL configuration context diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8212baa30..0deeb9d2f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11284,6 +11284,7 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); } +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) static unsigned char ssl_serialized_context_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, @@ -11829,6 +11830,7 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *context, return( ret ); } +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ /* * Free an SSL context From 4e9370ba913a8b0749e6c59de05eeabcdf659cd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 16:31:16 +0200 Subject: [PATCH 102/114] Implement config-checking header to context s11n Modelled after the config-checking header from session s11n. The list of relevant config flags was established by manually checking the fields serialized in the format, and which config.h flags they depend on. This probably deserves double-checking by reviewers. --- library/ssl_tls.c | 48 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 0deeb9d2f..c4619106f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11285,15 +11285,53 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) } #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 0u +#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_ALPN) +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u +#endif /* MBEDTLS_SSL_ALPN */ + +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 + +#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ + ( (uint32_t) ( \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT ) | \ + 0u ) ) + static unsigned char ssl_serialized_context_header[] = { MBEDTLS_VERSION_MAJOR, MBEDTLS_VERSION_MINOR, MBEDTLS_VERSION_PATCH, ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 8 ) & 0xFF, ( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG >> 0 ) & 0xFF, - 0, /* placeholder */ - 0, /* placeholder */ - 0, /* placeholder */ + ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 16 ) & 0xFF, + ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 8 ) & 0xFF, + ( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG >> 0 ) & 0xFF, }; /* @@ -11307,8 +11345,8 @@ static unsigned char ssl_serialized_context_header[] = { * opaque context_format[5]; // version-specific field determining * // the format of the remaining * // serialized data. - * Note: When updating the format, remember to keep - * these version+format bytes. (To be confirmed.) + * Note: When updating the format, remember to keep these + * version+format bytes. (We may make their size part of the API.) * * // session sub-structure * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() From 45ac1f0c92256cb69cb5a2566ef174ff41d0ec95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 16:52:45 +0200 Subject: [PATCH 103/114] Avoid duplication of session format header --- library/ssl_tls.c | 84 ++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index c4619106f..0333cd5e5 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9961,10 +9961,11 @@ static unsigned char ssl_serialized_session_header[] = { * verify_result is put before peer_cert so that all mandatory fields come * together in one block. */ -int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, - unsigned char *buf, - size_t buf_len, - size_t *olen ) +static int ssl_session_save( const mbedtls_ssl_session *session, + unsigned char omit_header, + unsigned char *buf, + size_t buf_len, + size_t *olen ) { unsigned char *p = buf; size_t used = 0; @@ -9978,17 +9979,20 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, #endif /* MBEDTLS_X509_CRT_PARSE_C */ - /* - * Add version identifier - */ - - used += sizeof( ssl_serialized_session_header ); - - if( used <= buf_len ) + if( !omit_header ) { - memcpy( p, ssl_serialized_session_header, - sizeof( ssl_serialized_session_header ) ); - p += sizeof( ssl_serialized_session_header ); + /* + * Add version identifier + */ + + used += sizeof( ssl_serialized_session_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ); + p += sizeof( ssl_serialized_session_header ); + } } /* @@ -10149,13 +10153,25 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, return( 0 ); } +/* + * Public wrapper for ssl_session_save() + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + return( ssl_session_save( session, 0, buf, buf_len, olen ) ); +} + /* * Deserialize session, see mbedtls_ssl_session_save() for format. * * This internal version is wrapped by a public function that cleans up in - * case of error. + * case of error, and has an extra option omit_header. */ static int ssl_session_load( mbedtls_ssl_session *session, + unsigned char omit_header, const unsigned char *buf, size_t len ) { @@ -10170,19 +10186,22 @@ static int ssl_session_load( mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ - /* - * Check version identifier - */ - - if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( memcmp( p, ssl_serialized_session_header, - sizeof( ssl_serialized_session_header ) ) != 0 ) + if( !omit_header ) { - return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + /* + * Check version identifier + */ + + if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_session_header ); } - p += sizeof( ssl_serialized_session_header ); /* * Time @@ -10381,7 +10400,7 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, const unsigned char *buf, size_t len ) { - int ret = ssl_session_load( session, buf, len ); + int ret = ssl_session_load( session, 0, buf, len ); if( ret != 0 ) mbedtls_ssl_session_free( session ); @@ -11424,7 +11443,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, /* * Session (length + data) */ - ret = mbedtls_ssl_session_save( ssl->session, NULL, 0, &session_len ); + ret = ssl_session_save( ssl->session, 1, NULL, 0, &session_len ); if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) return( ret ); @@ -11436,8 +11455,8 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, *p++ = (unsigned char)( ( session_len >> 8 ) & 0xFF ); *p++ = (unsigned char)( ( session_len ) & 0xFF ); - ret = mbedtls_ssl_session_save( ssl->session, - p, session_len, &session_len ); + ret = ssl_session_save( ssl->session, 1, + p, session_len, &session_len ); if( ret != 0 ) return( ret ); @@ -11661,9 +11680,12 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, if( (size_t)( end - p ) < session_len ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - ret = mbedtls_ssl_session_load( ssl->session, p, session_len ); + ret = ssl_session_load( ssl->session, 1, p, session_len ); if( ret != 0 ) + { + mbedtls_ssl_session_free( ssl->session ); return( ret ); + } p += session_len; From 9a96fd7ac3b3eea85e8b7737c040e1c7b7e299e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Jul 2019 17:11:24 +0200 Subject: [PATCH 104/114] Fix compile error in reduced configurations Found by running scripts/baremetal.h --rom --gcc --check after adding MBEDTLS_SSL_CONTEXT_SERIALIZATION to baremetal.h --- library/ssl_tls.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 0333cd5e5..b0454ceb8 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11421,9 +11421,9 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 || /* Renegotation is disabled. */ #if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || #endif - ) + 0 ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -11596,7 +11596,11 @@ static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id ) const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); - return ciphersuite_info->mac == MBEDTLS_MD_SHA384 ? tls_prf_sha384 : tls_prf_sha256; +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + return( tls_prf_sha384 ); +#endif + return( tls_prf_sha256 ); } /* @@ -11636,9 +11640,9 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 || ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 || #if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || #endif - ) + 0 ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } From f041f4e19cf53522ce25256438384b9cbd0f2dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 24 Jul 2019 00:58:27 +0200 Subject: [PATCH 105/114] Fix MSVC warning We know the length of the ALPN string is always less than 255, so the cast to uint8_t is safe. --- library/ssl_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b0454ceb8..3971fd7a6 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11553,7 +11553,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, #if defined(MBEDTLS_SSL_ALPN) { const uint8_t alpn_len = ssl->alpn_chosen - ? strlen( ssl->alpn_chosen ) + ? (uint8_t) strlen( ssl->alpn_chosen ) : 0; used += 1 + alpn_len; From 4ca930f8b92e691905a992ec59f7eac8865b3abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 26 Jul 2019 16:31:53 +0200 Subject: [PATCH 106/114] Fix a typo in a comment --- library/ssl_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 3971fd7a6..5960f3d2e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11621,7 +11621,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, /* * The context should have been freshly setup or reset. * Give the user an error in case of obvious misuse. - * (Checking session is useful because if won't be NULL if we're + * (Checking session is useful because it won't be NULL if we're * renegotiating, or if the user mistakenly loaded a session first.) */ if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST || From e458869b3fa94468f3babb702e9c533d0ec03806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 29 Jul 2019 12:28:52 +0200 Subject: [PATCH 107/114] Improve reability and debugability of large if Breaking into a series of statements makes things easier when stepping through the code in a debugger. Previous comments we stating the opposite or what the code tested for (what we want vs what we're erroring out on) which was confusing. Also expand a bit on the reasons for these restrictions. --- library/ssl_tls.c | 57 ++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5960f3d2e..138e1da0d 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11402,31 +11402,42 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, int ret = 0; /* - * Enforce current usage restrictions + * Enforce usage restrictions, see "return BAD_INPUT_DATA" in + * this function's documentation. + * + * These are due to assumptions/limitations in the implementation. Some of + * them are likely to stay (no handshake in progress) some might go away + * (only DTLS) but are currently used to simplify the implementation. */ - if( /* The initial handshake is over ... */ - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || - ssl->handshake != NULL || - /* ... and the various sub-structures are indeed ready. */ - ssl->transform == NULL || - ssl->session == NULL || - /* There is no pending incoming or outgoing data ... */ - mbedtls_ssl_check_pending( ssl ) != 0 || - ssl->out_left != 0 || - /* We're using DTLS 1.2 ... */ - ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || - ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 || - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 || - /* ... with an AEAD ciphersuite. */ - mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 || - /* Renegotation is disabled. */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || -#endif - 0 ) - { + /* The initial handshake must be over */ + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } + if( ssl->handshake != NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* Double-check that sub-structures are indeed ready */ + if( ssl->transform == NULL || ssl->session == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* There must be no pending incoming or outgoing data */ + if( mbedtls_ssl_check_pending( ssl ) != 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( ssl->out_left != 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* Protocol must be DLTS, not TLS */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* Version must be 1.2 */ + if( ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* We must be using an AEAD ciphersuite */ + if( mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* Renegotiation must not be enabled */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); +#endif /* * Version and format identifier From c84bd24224c8e0f058fb9fb797a849e06dac9be5 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Fri, 16 Aug 2019 12:06:56 +0300 Subject: [PATCH 108/114] Add missing guards for mac usage There were couple of cases where guards were missing when no ciphersuites are using mac. --- library/ssl_tls.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 138e1da0d..930613b68 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1008,12 +1008,14 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, static int ssl_populate_transform( mbedtls_ssl_transform *transform, int ciphersuite, const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) int encrypt_then_mac, -#endif +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) int trunc_hmac, -#endif +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ #if defined(MBEDTLS_ZLIB_SUPPORT) int compression, #endif @@ -1784,12 +1786,14 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) ret = ssl_populate_transform( ssl->transform_negotiate, ssl->session_negotiate->ciphersuite, ssl->session_negotiate->master, +#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) ssl->session_negotiate->encrypt_then_mac, -#endif +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ #if defined(MBEDTLS_SSL_TRUNCATED_HMAC) ssl->session_negotiate->trunc_hmac, -#endif +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ +#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */ #if defined(MBEDTLS_ZLIB_SUPPORT) ssl->session_negotiate->compression, #endif From b9ca1b086818d3702ebcf47a4af54d6988d7dd23 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 20 Aug 2019 12:05:57 +0300 Subject: [PATCH 109/114] Fix parameter name in doxygen --- include/mbedtls/ssl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 118263809..458857f6c 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3904,8 +3904,8 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); * \param ssl The SSL context to save. On success, it is no longer * associated with the connection that has been serialized. * \param buf The buffer to write the serialized data to. It must be a - * writeable buffer of at least \p len bytes, or may be \c - * NULL if \p len is \c 0. + * writeable buffer of at least \p buf_len bytes, or may be \c + * NULL if \p buf_len is \c 0. * \param buf_len The number of bytes available for writing in \p buf. * \param olen The size in bytes of the data that has been or would have * been written. It must point to a valid \c size_t. From bccf03591f38d8fd07f48fc8df54ee5881368db2 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Tue, 20 Aug 2019 12:11:48 +0300 Subject: [PATCH 110/114] Remove duplicate entries from ChangeLog --- ChangeLog | 9 --------- 1 file changed, 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 459e81042..31273cded 100644 --- a/ChangeLog +++ b/ChangeLog @@ -142,15 +142,6 @@ Changes * Adds fuzz targets, especially for continuous fuzzing with OSS-Fuzz. Contributed by Philippe Antoine (Catena cyber). -API Changes - * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, - and the used tls-prf. - * Add public API for tls-prf function, according to requested enum. - * Add DER-encoded test CRTs to library/certs.c, allowing - the example programs ssl_server2 and ssl_client2 to be run - if MBEDTLS_FS_IO and MBEDTLS_PEM_PARSE_C are unset. Fixes #2254. - * The HAVEGE state type now uses uint32_t elements instead of int. - = mbed TLS 2.17.0 branch released 2019-03-19 Features From 8c51b7cd9427e9ab10a399270e66307bc0452e49 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 21 Aug 2019 13:45:05 +0300 Subject: [PATCH 111/114] Add debug messages Add debug messages to easier identify which condition fails with usage restrictions in mbedtls_ssl_context_save() --- library/ssl_tls.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 930613b68..c60c5f7ed 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11415,32 +11415,62 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, */ /* The initial handshake must be over */ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Initial handshake isn't over" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } if( ssl->handshake != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Handshake isn't completed" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } /* Double-check that sub-structures are indeed ready */ if( ssl->transform == NULL || ssl->session == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Serialised structures aren't ready" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } /* There must be no pending incoming or outgoing data */ if( mbedtls_ssl_check_pending( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending incoming data" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } if( ssl->out_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } /* Protocol must be DLTS, not TLS */ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } /* Version must be 1.2 */ if( ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } /* We must be using an AEAD ciphersuite */ if( mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only AEAD ciphersuites supported" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } /* Renegotiation must not be enabled */ #if defined(MBEDTLS_SSL_RENEGOTIATION) if( ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Renegotiation must not be enabled" ) ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } #endif /* From b7b486cfd1d591ab8eb984bb95d7b823a37555c9 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 21 Aug 2019 15:30:44 +0300 Subject: [PATCH 112/114] Fix compiler warning Fix a compiler warning when MBEDTLS_SHA512_C isn't defined. --- library/ssl_tls.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index c60c5f7ed..99d306533 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11638,12 +11638,14 @@ typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen, unsigned char *dstbuf, size_t dlen ); static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id ) { +#if defined(MBEDTLS_SHA512_C) const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); -#if defined(MBEDTLS_SHA512_C) if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) return( tls_prf_sha384 ); +#else + (void) ciphersuite_id; #endif return( tls_prf_sha256 ); } From 9e90df58c01700612f7100f86fd92a36e81284e3 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Fri, 23 Aug 2019 09:08:31 +0300 Subject: [PATCH 113/114] Add changelog entry to record checking Add changelog entry to record checking. The record checking feature is used with Connection ID and SSL context serialisation. --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 31273cded..a0eee53bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -35,6 +35,11 @@ Features mbedtls_ssl_session_load() to allow serializing a session, for example to store it in non-volatile storage, and later using it for TLS session resumption. + * Add a new API function mbedtls_ssl_check_record() to allow checking that + an incoming record is valid, authentic and has not been seen before. This + feature can be used alongside Connection ID and SSL context serialisation. + The feature is enabled at compile-time by MBEDTLS_SSL_RECORD_CHECKING + option. API Changes * Extend the MBEDTLS_SSL_EXPORT_KEYS to export the handshake randbytes, From 472a2a2fcd8b28eeeeba1bb4b99821e3fb147102 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Fri, 23 Aug 2019 13:13:52 +0300 Subject: [PATCH 114/114] Don't redefine calloc and free --- programs/ssl/ssl_client2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index bcccd1de3..61b88d10f 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -38,8 +38,6 @@ #define mbedtls_calloc calloc #define mbedtls_free free #define mbedtls_exit exit -#define mbedtls_calloc calloc -#define mbedtls_free free #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE #endif