From 088ce43ffe78b5f45fe9b757cf3fa534ee6bbc59 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Mon, 10 Apr 2017 12:42:31 +0100 Subject: [PATCH] Implement optional CA list suppression in Certificate Request According to RFC5246 the server can indicate the known Certificate Authorities or can constrain the aurhorisation space by sending a certificate list. This part of the message is optional and if omitted, the client may send any certificate in the response. The previous behaviour of mbed TLS was to always send the name of all the CAs that are configured as root CAs. In certain cases this might cause usability and privacy issues for example: - If the list of the CA names is longer than the peers input buffer then the handshake will fail - If the configured CAs belong to third parties, this message gives away information on the relations to these third parties Therefore we introduce an option to suppress the CA list in the Certificate Request message. Providing this feature as a runtime option comes with a little cost in code size and advantages in maintenance and flexibility. --- include/mbedtls/ssl.h | 21 ++++++++++++++++++ library/ssl_srv.c | 51 ++++++++++++++++++++++++------------------- library/ssl_tls.c | 12 ++++++++++ 3 files changed, 61 insertions(+), 23 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 495e02cb0..cb29b8383 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -185,6 +185,9 @@ #define MBEDTLS_SSL_PRESET_DEFAULT 0 #define MBEDTLS_SSL_PRESET_SUITEB 2 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + /* * Default range for DTLS retransmission timer value, in milliseconds. * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. @@ -749,6 +752,10 @@ struct mbedtls_ssl_config #if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) unsigned int fallback : 1; /*!< is this a fallback? */ #endif +#if defined(MBEDTLS_SSL_SRV_C) + unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in + Certificate Request messages? */ +#endif }; @@ -2031,6 +2038,20 @@ void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); #endif /* MBEDTLS_ARC4_C */ +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) /** * \brief Set the maximum fragment length to emit and/or negotiate diff --git a/library/ssl_srv.c b/library/ssl_srv.c index fc0d2d7b4..4c528bb2e 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -2588,35 +2588,40 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) * opaque DistinguishedName<1..2^16-1>; */ p += 2; -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_ca_chain != NULL ) - crt = ssl->handshake->sni_ca_chain; - else -#endif - crt = ssl->conf->ca_chain; total_dn_size = 0; - while( crt != NULL && crt->version != 0 ) + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) { - dn_size = crt->subject_raw.len; +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; - if( end < p || - (size_t)( end - p ) < dn_size || - (size_t)( end - p ) < 2 + dn_size ) + while( crt != NULL && crt->version != 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); - break; + dn_size = crt->subject_raw.len; + + if( end < p || + (size_t)( end - p ) < dn_size || + (size_t)( end - p ) < 2 + dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + *p++ = (unsigned char)( dn_size >> 8 ); + *p++ = (unsigned char)( dn_size ); + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; } - - *p++ = (unsigned char)( dn_size >> 8 ); - *p++ = (unsigned char)( dn_size ); - memcpy( p, crt->subject_raw.p, dn_size ); - p += dn_size; - - MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); - - total_dn_size += 2 + dn_size; - crt = crt->next; } ssl->out_msglen = p - buf; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d9ab83291..00a57ffb8 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6050,6 +6050,14 @@ void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) } #endif +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) { @@ -7232,6 +7240,10 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; #endif +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;