From 2f3fe70f7e362caf1ac88a258d2a370a988486c9 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Fri, 20 Jan 2017 17:07:46 +0000 Subject: [PATCH 1/2] Fix verify out flags from x509_crt_verify_top() This change fixes a regression introduced by an earlier commit that modified x509_crt_verify_top() to ensure that valid certificates that are after past or future valid in the chain are processed. However the change introduced a change in behaviour that caused the verification flags BADCERT_EXPIRED and BADCERT_FUTURE to always be set whenever there is a failure in the verification regardless of the cause. The fix maintains both behaviours: * Ensure that valid certificates after future and past are verified * Ensure that the correct verification flags are set. To do so, a temporary pointer to the first future or past valid certificate is maintained while traversing the chain. If a truly valid certificate is found then that one is used, otherwise if no valid certificate is found and the end of the chain is reached, the program reverts back to using the future or past valid certificate. --- ChangeLog | 9 +++++++++ library/x509_crt.c | 31 ++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index d4cf85b7e..20c8eaf95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ mbed TLS ChangeLog (Sorted per branch, date) += mbed TLS x.x.x branch released xxxx-xx-xx + +Bugfix + * Fix output certificate verification flags set by x509_crt_verify_top() when + traversing a chain of trusted CA. The issue would cause both flags, + BADCERT_NOT_TRUSTED and BADCERT_EXPIRED, to be set when the verification + conditions are not met regardless of the cause. Found by Harm Verhagen and + inestlerode. #665 #561 + = mbed TLS 1.3.18 branch 2016-10-17 Security diff --git a/library/x509_crt.c b/library/x509_crt.c index 4b831aed3..a3517f64f 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1775,6 +1775,7 @@ static int x509_crt_verify_top( int ca_flags = 0, check_path_cnt; unsigned char hash[POLARSSL_MD_MAX_SIZE]; const md_info_t *md_info; + x509_crt *future_past_ca = NULL; if( x509_time_expired( &child->valid_to ) ) *flags |= BADCERT_EXPIRED; @@ -1823,16 +1824,6 @@ static int x509_crt_verify_top( continue; } - if( x509_time_expired( &trust_ca->valid_to ) ) - { - continue; - } - - if( x509_time_future( &trust_ca->valid_from ) ) - { - continue; - } - if( pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, child->sig_md, hash, md_info->size, child->sig.p, child->sig.len ) != 0 ) @@ -1840,11 +1831,23 @@ static int x509_crt_verify_top( continue; } + if( x509_time_expired( &trust_ca->valid_to ) || + x509_time_future( &trust_ca->valid_from ) ) + { + if( future_past_ca == NULL ) + future_past_ca = trust_ca; + continue; + } + + break; + } + + if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL ) + { /* * Top of chain is signed by a trusted CA */ *flags &= ~BADCERT_NOT_TRUSTED; - break; } /* @@ -1864,6 +1867,12 @@ static int x509_crt_verify_top( ((void) ca_crl); #endif + if( x509_time_expired( &trust_ca->valid_to ) ) + ca_flags |= BADCERT_EXPIRED; + + if( x509_time_future( &trust_ca->valid_from ) ) + ca_flags |= BADCERT_FUTURE; + if( NULL != f_vrfy ) { if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, From 28ba747c8caed5ce2082f9b0635327b05b71f857 Mon Sep 17 00:00:00 2001 From: Andres AG Date: Fri, 20 Jan 2017 17:09:15 +0000 Subject: [PATCH 2/2] Add tests for out flags from x509_crt_verify_top() The tests load certificate chains from files. The CA chains contain a past or future certificate and an invalid certificate. The test then checks that the flags set are BADCERT_EXPIRED or BADCERT_FUTURE. --- .../test-ca2_cat-future-invalid.crt | 27 +++++++++++++++++++ .../data_files/test-ca2_cat-past-invalid.crt | 27 +++++++++++++++++++ tests/suites/test_suite_x509parse.data | 8 ++++++ 3 files changed, 62 insertions(+) create mode 100644 tests/data_files/test-ca2_cat-future-invalid.crt create mode 100644 tests/data_files/test-ca2_cat-past-invalid.crt diff --git a/tests/data_files/test-ca2_cat-future-invalid.crt b/tests/data_files/test-ca2_cat-future-invalid.crt new file mode 100644 index 000000000..b1cfbf054 --- /dev/null +++ b/tests/data_files/test-ca2_cat-future-invalid.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIICIDCCAaWgAwIBAgIBCjAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G +A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN +MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G +A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABIFZMXZJJPoVraugMW4O7TMR+pElVcGwwZwDcj6Yui2kcjeJ +H0M3jR+OOtjwV+gvT8kApPfbcw+yxgSU0UA7OOOjgZ0wgZowCQYDVR0TBAIwADAd +BgNVHQ4EFgQUfmWPPjMDFOXhvmCy4IV/jOdgK3swbgYDVR0jBGcwZYAUnW0gJEkB +PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh +clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG +CCqGSM49BAMCA2kAMGYCMQCsYTyleBFuI4nizuxo/ie5dxJnD0ynwCnRJ+84PZP4 +AQA3HdUz0qNYs4CZ2am9Gz0CMQDr2TNLFA3C3S3pmgXMT0eKzR1Ca1/Nulf0llQZ +Xj09kLboxuemP40IIqhQnpYptMg= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIB+zCCAYCgAwIBAgIBATAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw +DwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQTAe +Fw0yMzA5MjIxNTQ5NDlaFw0zMDEyMzEyMzU5NTlaMD4xCzAJBgNVBAYTAk5MMREw +DwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQTB2 +MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBuww5XUzM5 +WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiyaY7zQa0p +w7RfdadHb9UZKVVpmlM7ILRmFmAzHqNQME4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4E +FgQUnW0gJEkBPyvLeLUZvH4kydv7NnwwHwYDVR0jBBgwFoAUnW0gJEkBPyvLeLUZ +vH4kydv7NnwwDAYIKoZIzj0EAwIFAANnADBkAjB1ZNdOM7KRJiPo45hP17A1sJSH +qHFPEJbml6KdNevoVZ1HqvP8AoFGcPJRpQVtzC0CMDa7JEqn0dOss8EmW9pVF/N2 ++XvzNczj89mWMgPhJJlT+MONQx3LFQO+TMSI9hLdkw== +-----END CERTIFICATE----- diff --git a/tests/data_files/test-ca2_cat-past-invalid.crt b/tests/data_files/test-ca2_cat-past-invalid.crt new file mode 100644 index 000000000..febad7408 --- /dev/null +++ b/tests/data_files/test-ca2_cat-past-invalid.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIB/TCCAYCgAwIBAgIBATAMBggqhkjOPQQDAgUAMD4xCzAJBgNVBAYTAk5MMREw +DwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQTAe +Fw0wMzA5MjQxNTQ5NDhaFw0xMzA5MjQxNTQ5NDhaMD4xCzAJBgNVBAYTAk5MMREw +DwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQTB2 +MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBuww5XUzM5 +WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiyaY7zQa0p +w7RfdadHb9UZKVVpmlM7ILRmFmAzHqNQME4wDAYDVR0TBAUwAwEB/zAdBgNVHQ4E +FgQUnW0gJEkBPyvLeLUZvH4kydv7NnwwHwYDVR0jBBgwFoAUnW0gJEkBPyvLeLUZ +vH4kydv7NnwwDAYIKoZIzj0EAwIFAANpADBmAjEAvQ/49lXXrLYdOIGtTaYWjpZP +tRBXQiGPMzUvmKBk7gM7bF4iFPsdJikyXHmuwv3RAjEA8vtUX8fAAB3fbh5dEXRm +l7tz0Sw/RW6AHFtaIauGkhHqeKIaKIi6WSgHu6x97uyg +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICIDCCAaWgAwIBAgIBCjAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G +A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN +MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G +A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABIFZMXZJJPoVraugMW4O7TMR+pElVcGwwZwDcj6Yui2kcjeJ +H0M3jR+OOtjwV+gvT8kApPfbcw+yxgSU0UA7OOOjgZ0wgZowCQYDVR0TBAIwADAd +BgNVHQ4EFgQUfmWPPjMDFOXhvmCy4IV/jOdgK3swbgYDVR0jBGcwZYAUnW0gJEkB +PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh +clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG +CCqGSM49BAMCA2kAMGYCMQCsYTyleBFuI4nizuxo/ie5dxJnD0ynwCnRJ+84PZP4 +AQA3HdUz0qNYs4CZ2am9Gz0CMQDr2TNLFA3C3S3pmgXMT0eKzR1Ca1/Nulf0llQZ +Xj09kLboxuemP40IIqhQnpYptMg= +-----END CERTIFICATE----- diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index b289fc992..a4d65ff75 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -711,6 +711,14 @@ X509 Certificate verification #85 (Not yet valid CA and valid CA) depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP384R1_ENABLED x509_verify:"data_files/server5.crt":"data_files/test-ca2_cat-past-present.crt":"data_files/crl-ec-sha1.pem":"NULL":0:0:"NULL" +X509 Certificate verification #86 (Not yet valid CA and invalid CA) +depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP384R1_ENABLED:POLARSSL_SHA1_C:POLARSSL_SHA256_C +x509_verify:"data_files/server5.crt":"data_files/test-ca2_cat-future-invalid.crt":"data_files/crl-ec-sha1.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_FUTURE:"NULL" + +X509 Certificate verification #87 (Expired CA and invalid CA) +depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECP_C:POLARSSL_ECP_DP_SECP256R1_ENABLED:POLARSSL_ECP_DP_SECP384R1_ENABLED:POLARSSL_SHA1_C:POLARSSL_SHA256_C +x509_verify:"data_files/server5.crt":"data_files/test-ca2_cat-past-invalid.crt":"data_files/crl-ec-sha1.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_EXPIRED:"NULL" + X509 Certificate verification callback: trusted EE cert depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_SHA256_C:POLARSSL_ECP_DP_SECP256R1_ENABLED x509_verify_callback:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:"depth 0 - serial 53\:A2\:CB\:4B\:12\:4E\:AD\:83\:7D\:A8\:94\:B2 - subject CN=selfsigned, OU=testing, O=PolarSSL, C=NL\n"