Skip to content

Commit 535ee4a

Browse files
committed
Merge remote-tracking branch 'public/pr/2421' into development
* public/pr/2421: (68 commits) Fix unused variable warning in ssl_parse_certificate_coordinate() Add missing compile time guard in ssl_client2 Update programs/ssl/query_config.c ssl_client2: Reset peer CRT info string on reconnect Add further debug statements on assertion failures Fix typo in documentation of ssl_parse_certificate_chain() Add debug output in case of assertion failure Fix typo in SSL ticket documentation Add config sanity check for !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE ssl_client2: Zeroize peer CRT info buffer when reconnecting Reintroduce numerous ssl-opt.sh tests if !MBEDTLS_SSL_KEEP_PEER_CERT ssl_client2: Extract peer CRT info from verification callback Improve documentation of mbedtls_ssl_get_peer_cert() Improve documentation of MBEDTLS_SSL_KEEP_PEER_CERTIFICATE Fix indentation of Doxygen comment in ssl_internal.h Set peer CRT length only after successful allocation Remove question in comment about verify flags on cli vs. server Remove misleading and redundant guard around restartable ECC field Add test for !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE to all.sh Free peer CRT chain immediately after verifying it ...
2 parents 195bdde + 84d9d27 commit 535ee4a

File tree

19 files changed

+898
-449
lines changed

19 files changed

+898
-449
lines changed

ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ Features
1616
API Changes
1717
* Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`.
1818
See the Features section for more information.
19+
* Allow to opt in to the removal the API mbedtls_ssl_get_peer_cert()
20+
for the benefit of saving RAM, by disabling the new compile-time
21+
option MBEDTLS_SSL_KEEP_PEER_CERTIFICATE (enabled by default for
22+
API stability). Disabling this option makes mbedtls_ssl_get_peer_cert()
23+
always return NULL, and removes the peer_cert field from the
24+
mbedtls_ssl_session structure which otherwise stores the peer's
25+
certificate.
1926

2027
Bugfix
2128
* Fix a compilation issue with mbedtls_ecp_restart_ctx not being defined

include/mbedtls/check_config.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,14 @@
280280
#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
281281
#endif
282282

283+
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) && \
284+
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \
285+
( !defined(MBEDTLS_SHA256_C) && \
286+
!defined(MBEDTLS_SHA512_C) && \
287+
!defined(MBEDTLS_SHA1_C) )
288+
#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C"
289+
#endif
290+
283291
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
284292
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
285293
#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"

include/mbedtls/config.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,28 @@
13741374
*/
13751375
#define MBEDTLS_SSL_FALLBACK_SCSV
13761376

1377+
/**
1378+
* \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
1379+
*
1380+
* This option controls the availability of the API mbedtls_ssl_get_peer_cert()
1381+
* giving access to the peer's certificate after completion of the handshake.
1382+
*
1383+
* Unless you need mbedtls_ssl_peer_cert() in your application, it is
1384+
* recommended to disable this option for reduced RAM usage.
1385+
*
1386+
* \note If this option is disabled, mbedtls_ssl_get_peer_cert() is still
1387+
* defined, but always returns \c NULL.
1388+
*
1389+
* \note This option has no influence on the protection against the
1390+
* triple handshake attack. Even if it is disabled, Mbed TLS will
1391+
* still ensure that certificates do not change during renegotiation,
1392+
* for exaple by keeping a hash of the peer's certificate.
1393+
*
1394+
* Comment this macro to disable storing the peer's certificate
1395+
* after the handshake.
1396+
*/
1397+
#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
1398+
13771399
/**
13781400
* \def MBEDTLS_SSL_HW_RECORD_ACCEL
13791401
*

include/mbedtls/ssl.h

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,25 @@ typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl,
787787
typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl );
788788
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
789789

790+
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) && \
791+
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
792+
#define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48
793+
#if defined(MBEDTLS_SHA256_C)
794+
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256
795+
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32
796+
#elif defined(MBEDTLS_SHA512_C)
797+
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384
798+
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48
799+
#elif defined(MBEDTLS_SHA1_C)
800+
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1
801+
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20
802+
#else
803+
/* This is already checked in check_config.h, but be sure. */
804+
#error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT."
805+
#endif
806+
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED &&
807+
!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
808+
790809
/*
791810
* This structure is used for storing current session data.
792811
*/
@@ -802,7 +821,15 @@ struct mbedtls_ssl_session
802821
unsigned char master[48]; /*!< the master secret */
803822

804823
#if defined(MBEDTLS_X509_CRT_PARSE_C)
805-
mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */
824+
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
825+
mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */
826+
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
827+
/*! The digest of the peer's end-CRT. This must be kept to detect CRT
828+
* changes during renegotiation, mitigating the triple handshake attack. */
829+
unsigned char *peer_cert_digest;
830+
size_t peer_cert_digest_len;
831+
mbedtls_md_type_t peer_cert_digest_type;
832+
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
806833
#endif /* MBEDTLS_X509_CRT_PARSE_C */
807834
uint32_t verify_result; /*!< verification result */
808835

@@ -2972,18 +2999,34 @@ int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl );
29722999

29733000
#if defined(MBEDTLS_X509_CRT_PARSE_C)
29743001
/**
2975-
* \brief Return the peer certificate from the current connection
2976-
*
2977-
* Note: Can be NULL in case no certificate was sent during
2978-
* the handshake. Different calls for the same connection can
2979-
* return the same or different pointers for the same
2980-
* certificate and even a different certificate altogether.
2981-
* The peer cert CAN change in a single connection if
2982-
* renegotiation is performed.
2983-
*
2984-
* \param ssl SSL context
2985-
*
2986-
* \return the current peer certificate
3002+
* \brief Return the peer certificate from the current connection.
3003+
*
3004+
* \param ssl The SSL context to use. This must be initialized and setup.
3005+
*
3006+
* \return The current peer certificate, if available.
3007+
* The returned certificate is owned by the SSL context and
3008+
* is valid only until the next call to the SSL API.
3009+
* \return \c NULL if no peer certificate is available. This might
3010+
* be because the chosen ciphersuite doesn't use CRTs
3011+
* (PSK-based ciphersuites, for example), or because
3012+
* #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled,
3013+
* allowing the stack to free the peer's CRT to save memory.
3014+
*
3015+
* \note For one-time inspection of the peer's certificate during
3016+
* the handshake, consider registering an X.509 CRT verification
3017+
* callback through mbedtls_ssl_conf_verify() instead of calling
3018+
* this function. Using mbedtls_ssl_conf_verify() also comes at
3019+
* the benefit of allowing you to influence the verification
3020+
* process, for example by masking expected and tolerated
3021+
* verification failures.
3022+
*
3023+
* \warning You must not use the pointer returned by this function
3024+
* after any further call to the SSL API, including
3025+
* mbedtls_ssl_read() and mbedtls_ssl_write(); this is
3026+
* because the pointer might change during renegotiation,
3027+
* which happens transparently to the user.
3028+
* If you want to use the certificate across API calls,
3029+
* you must make a copy.
29873030
*/
29883031
const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl );
29893032
#endif /* MBEDTLS_X509_CRT_PARSE_C */

include/mbedtls/ssl_cache.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ struct mbedtls_ssl_cache_entry
7070
mbedtls_time_t timestamp; /*!< entry timestamp */
7171
#endif
7272
mbedtls_ssl_session session; /*!< entry session */
73-
#if defined(MBEDTLS_X509_CRT_PARSE_C)
73+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
74+
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
7475
mbedtls_x509_buf peer_cert; /*!< entry peer_cert */
7576
#endif
7677
mbedtls_ssl_cache_entry *next; /*!< chain pointer */

include/mbedtls/ssl_ciphersuites.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,24 @@ static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ci
486486
}
487487
}
488488

489+
static inline int mbedtls_ssl_ciphersuite_uses_srv_cert( const mbedtls_ssl_ciphersuite_t *info )
490+
{
491+
switch( info->key_exchange )
492+
{
493+
case MBEDTLS_KEY_EXCHANGE_RSA:
494+
case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
495+
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
496+
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
497+
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
498+
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
499+
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
500+
return( 1 );
501+
502+
default:
503+
return( 0 );
504+
}
505+
}
506+
489507
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
490508
static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info )
491509
{

include/mbedtls/ssl_internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,13 @@ struct mbedtls_ssl_handshake_params
331331
ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */
332332
ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */
333333
} ecrs_state; /*!< current (or last) operation */
334+
mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */
334335
size_t ecrs_n; /*!< place for saving a length */
335336
#endif
337+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
338+
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
339+
mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */
340+
#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
336341
#if defined(MBEDTLS_SSL_PROTO_DTLS)
337342
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
338343
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */
@@ -766,6 +771,9 @@ int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl );
766771
void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl );
767772
#endif
768773

774+
int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
775+
const mbedtls_ssl_session *src );
776+
769777
/* constant-time buffer comparison */
770778
static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n )
771779
{

include/mbedtls/x509_crt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ typedef struct mbedtls_x509_crt
7070
mbedtls_x509_time valid_from; /**< Start time of certificate validity. */
7171
mbedtls_x509_time valid_to; /**< End time of certificate validity. */
7272

73+
mbedtls_x509_buf pk_raw;
7374
mbedtls_pk_context pk; /**< Container for the public key context. */
7475

7576
mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */

library/ssl_cache.c

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#endif
4141

4242
#include "mbedtls/ssl_cache.h"
43+
#include "mbedtls/ssl_internal.h"
4344

4445
#include <string.h>
4546

@@ -92,16 +93,24 @@ int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
9293
entry->session.id_len ) != 0 )
9394
continue;
9495

95-
memcpy( session->master, entry->session.master, 48 );
96-
97-
session->verify_result = entry->session.verify_result;
96+
ret = mbedtls_ssl_session_copy( session, &entry->session );
97+
if( ret != 0 )
98+
{
99+
ret = 1;
100+
goto exit;
101+
}
98102

99-
#if defined(MBEDTLS_X509_CRT_PARSE_C)
103+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
104+
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
100105
/*
101106
* Restore peer certificate (without rest of the original chain)
102107
*/
103108
if( entry->peer_cert.p != NULL )
104109
{
110+
/* `session->peer_cert` is NULL after the call to
111+
* mbedtls_ssl_session_copy(), because cache entries
112+
* have the `peer_cert` field set to NULL. */
113+
105114
if( ( session->peer_cert = mbedtls_calloc( 1,
106115
sizeof(mbedtls_x509_crt) ) ) == NULL )
107116
{
@@ -119,7 +128,7 @@ int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
119128
goto exit;
120129
}
121130
}
122-
#endif /* MBEDTLS_X509_CRT_PARSE_C */
131+
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
123132

124133
ret = 0;
125134
goto exit;
@@ -239,9 +248,8 @@ int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
239248
#endif
240249
}
241250

242-
memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) );
243-
244-
#if defined(MBEDTLS_X509_CRT_PARSE_C)
251+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
252+
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
245253
/*
246254
* If we're reusing an entry, free its certificate first
247255
*/
@@ -250,26 +258,43 @@ int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
250258
mbedtls_free( cur->peer_cert.p );
251259
memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) );
252260
}
261+
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
262+
263+
/* Copy the entire session; this temporarily makes a copy of the
264+
* X.509 CRT structure even though we only want to store the raw CRT.
265+
* This inefficiency will go away as soon as we implement on-demand
266+
* parsing of CRTs, in which case there's no need for the `peer_cert`
267+
* field anymore in the first place, and we're done after this call. */
268+
ret = mbedtls_ssl_session_copy( &cur->session, session );
269+
if( ret != 0 )
270+
{
271+
ret = 1;
272+
goto exit;
273+
}
253274

254-
/*
255-
* Store peer certificate
256-
*/
257-
if( session->peer_cert != NULL )
275+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
276+
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
277+
/* If present, free the X.509 structure and only store the raw CRT data. */
278+
if( cur->session.peer_cert != NULL )
258279
{
259-
cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len );
280+
cur->peer_cert.p =
281+
mbedtls_calloc( 1, cur->session.peer_cert->raw.len );
260282
if( cur->peer_cert.p == NULL )
261283
{
262284
ret = 1;
263285
goto exit;
264286
}
265287

266-
memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
267-
session->peer_cert->raw.len );
288+
memcpy( cur->peer_cert.p,
289+
cur->session.peer_cert->raw.p,
290+
cur->session.peer_cert->raw.len );
268291
cur->peer_cert.len = session->peer_cert->raw.len;
269292

293+
mbedtls_x509_crt_free( cur->session.peer_cert );
294+
mbedtls_free( cur->session.peer_cert );
270295
cur->session.peer_cert = NULL;
271296
}
272-
#endif /* MBEDTLS_X509_CRT_PARSE_C */
297+
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
273298

274299
ret = 0;
275300

@@ -311,9 +336,10 @@ void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )
311336

312337
mbedtls_ssl_session_free( &prv->session );
313338

314-
#if defined(MBEDTLS_X509_CRT_PARSE_C)
339+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
340+
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
315341
mbedtls_free( prv->peer_cert.p );
316-
#endif /* MBEDTLS_X509_CRT_PARSE_C */
342+
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
317343

318344
mbedtls_free( prv );
319345
}

0 commit comments

Comments
 (0)