diff --git a/ChangeLog.d/fix-time-format-pre-2000.txt b/ChangeLog.d/fix-time-format-pre-2000.txt new file mode 100644 index 000000000..414201e3d --- /dev/null +++ b/ChangeLog.d/fix-time-format-pre-2000.txt @@ -0,0 +1,3 @@ +Bugfix + * Encode X.509 dates before 1/1/2000 as UTCTime rather than + GeneralizedTime. Fixes #5465. diff --git a/library/x509write_crt.c b/library/x509write_crt.c index 6d1e7b34d..2992dba06 100644 --- a/library/x509write_crt.c +++ b/library/x509write_crt.c @@ -324,7 +324,7 @@ static int x509_write_time( unsigned char **p, unsigned char *start, /* * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) */ - if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) + if( t[0] < '2' || ( t[0] == '2' && t[1] == '0' && t[2] < '5' ) ) { MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, (const unsigned char *) t + 2, diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data index 888c9abbb..8d9a11a99 100644 --- a/tests/suites/test_suite_x509write.data +++ b/tests/suites/test_suite_x509write.data @@ -58,6 +58,22 @@ Certificate write check Server1 SHA1 depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"data_files/server1.crt":0:0:"data_files/test-ca.crt" +Certificate write check Server1 SHA1, not before 1970 +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20290210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt" + +Certificate write check Server1 SHA1, not after 2050 +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt" + +Certificate write check Server1 SHA1, not before 1970, not after 2050 +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"19700210144406":"20500210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt" + +Certificate write check Server1 SHA1, not before 2050, not after 2059 +depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C +x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20500210144406":"20590210144406":MBEDTLS_MD_SHA1:0:0:0:0:1:-1:"":0:0:"data_files/test-ca.crt" + Certificate write check Server1 SHA1, key_usage depends_on:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_MD5_C x509_crt_check:"data_files/server1.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=PolarSSL Test CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA1:MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION | MBEDTLS_X509_KU_KEY_ENCIPHERMENT:1:0:0:1:-1:"data_files/server1.key_usage.crt":0:0:"data_files/test-ca.crt" diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function index f5001bd8c..8f5c947a3 100644 --- a/tests/suites/test_suite_x509write.function +++ b/tests/suites/test_suite_x509write.function @@ -242,8 +242,10 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, mbedtls_x509write_cert crt; unsigned char buf[4096]; unsigned char check_buf[5000]; + unsigned char *p, *end; + unsigned char tag, sz; mbedtls_mpi serial; - int ret; + int ret, before_tag, after_tag; size_t olen = 0, pem_len = 0, buf_index = 0; int der_len = -1; FILE *f; @@ -374,7 +376,7 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, TEST_EQUAL( flags, 0 ); TEST_EQUAL( ret, 0 ); } - else + else if( *cert_check_file != '\0' ) { f = fopen( cert_check_file, "r" ); TEST_ASSERT( f != NULL ); @@ -395,6 +397,54 @@ void x509_crt_check( char *subject_key_file, char *subject_pwd, if( der_len == 0 ) goto exit; + // Not testing against file, check date format + if( *cert_check_file == '\0' ) + { + // UTC tag if before 2050, 2 digits less for year + if( not_before[0] == '2' && ( not_before[1] > '0' || not_before[2] > '4' ) ) + { + before_tag = MBEDTLS_ASN1_GENERALIZED_TIME; + } + else + { + before_tag = MBEDTLS_ASN1_UTC_TIME; + not_before += 2; + } + if( not_after[0] == '2' && ( not_after[1] > '0' || not_after[2] > '4' ) ) + { + after_tag = MBEDTLS_ASN1_GENERALIZED_TIME; + } + else + { + after_tag = MBEDTLS_ASN1_UTC_TIME; + not_after += 2; + } + end = buf + sizeof( buf ); + for( p = end - der_len ; p < end ; ) + { + tag = *p++; + sz = *p++; + if( tag == MBEDTLS_ASN1_UTC_TIME || tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + { + // Check correct tag and time written + TEST_ASSERT( before_tag == tag ); + TEST_ASSERT( memcmp( p, not_before, sz - 1 ) == 0 ); + p += sz; + tag = *p++; + sz = *p++; + TEST_ASSERT( after_tag == tag ); + TEST_ASSERT( memcmp( p, not_after, sz - 1 ) == 0 ); + break; + } + // Increment if long form ASN1 length + if( sz & 0x80 ) + p += sz & 0x0F; + if( tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + p += sz; + } + TEST_ASSERT( p < end ); + } + #if defined(MBEDTLS_USE_PSA_CRYPTO) // When using PSA crypto, RNG isn't controllable, result length isn't // deterministic over multiple runs, removing a single byte isn't enough to