diff --git a/ChangeLog b/ChangeLog index d1a87be76..1b6770a73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,8 @@ Security Features * Add function pk_check_pair() to test if public and private keys match. * Add x509_crl_parse_der(). + * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the + length of an X.509 verification chain. Bugfix * User set CFLAGS were ignore by Cmake with gcc (introduced in 1.3.9, found diff --git a/include/polarssl/config.h b/include/polarssl/config.h index fa15b37c3..a0ec2f3cc 100644 --- a/include/polarssl/config.h +++ b/include/polarssl/config.h @@ -2185,6 +2185,9 @@ /* Debug options */ //#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ +/* X509 options */ +//#define POLARSSL_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ + /* \} name SECTION: Module configuration options */ #include "check_config.h" diff --git a/include/polarssl/x509.h b/include/polarssl/x509.h index 9b0bcb78a..3fe682039 100644 --- a/include/polarssl/x509.h +++ b/include/polarssl/x509.h @@ -45,6 +45,18 @@ * \{ */ +#if !defined(POLARSSL_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define POLARSSL_X509_MAX_INTERMEDIATE_CA 8 +#endif + /** * \name X509 Error codes * \{ diff --git a/library/x509_crt.c b/library/x509_crt.c index 2d72f6acd..4d20889b8 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1834,6 +1834,13 @@ static int x509_crt_verify_child( x509_crt *grandparent; const md_info_t *md_info; + /* path_cnt is 0 for the first intermediate CA */ + if( 1 + path_cnt > POLARSSL_X509_MAX_INTERMEDIATE_CA ) + { + *flags |= BADCERT_NOT_TRUSTED; + return( POLARSSL_ERR_X509_CERT_VERIFY_FAILED ); + } + if( x509_time_expired( &child->valid_to ) ) *flags |= BADCERT_EXPIRED;