Add option for relaxed X509 time verification.
The certificates are not valid according to the RFC, but are in wide
distribution across the internet. Hence the request to add a
compile-time flag to accept these certificates if wanted by the
application.
If POLARSSL_RELAXED_X509_DATE is enabled it will allow dates without
seconds, and allow dates with timezones (but doesn't actually use
the timezone).
Patch provided by OpenVPN.
diff --git a/ChangeLog b/ChangeLog
index 3b7c3ab..7ab61d3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
mbed TLS ChangeLog (Sorted per branch, date)
+= mbed TLS 1.3.x
+
+Changes
+ * Add compile time option for relaxed X509 time verification to enable
+ accepting certificates with non-standard time format (that is without
+ seconds or with a time zone). Patch provided by OpenVPN.
+
= mbed TLS 1.3.17 branch 2016-06-28
Security
diff --git a/include/polarssl/config.h b/include/polarssl/config.h
index 8fdf36e..4e52790 100644
--- a/include/polarssl/config.h
+++ b/include/polarssl/config.h
@@ -1177,6 +1177,17 @@
//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
/**
+ * \def POLARSSL_X509_ALLOW_RELAXED_DATE
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering ASN.1 UTCTime or ASN.1 GeneralizedTime without seconds or
+ * with a time zone.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define POLARSSL_X509_ALLOW_RELAXED_DATE
+
+/**
* \def POLARSSL_X509_CHECK_KEY_USAGE
*
* Enable verification of the keyUsage extension (CA and leaf certificates).
diff --git a/library/x509.c b/library/x509.c
index ab105d8..0d54beb 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -490,6 +490,88 @@
}
/*
+ * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) field.
+ */
+static int x509_parse_time( unsigned char **p, size_t len, unsigned int yearlen, x509_time *time )
+{
+ int ret;
+
+ /*
+ * minimum length is 10 or 12 depending on yearlen
+ */
+ if ( len < yearlen + 8 )
+ return POLARSSL_ERR_X509_INVALID_DATE;
+ len -= yearlen + 8;
+
+ /*
+ * parse year, month, day, hour, minute
+ */
+ CHECK( x509_parse_int( p, yearlen, &time->year ) );
+ if ( 2 == yearlen )
+ {
+ if ( time->year < 50 )
+ time->year += 100;
+
+ time->year += 1900;
+ }
+
+ CHECK( x509_parse_int( p, 2, &time->mon ) );
+ CHECK( x509_parse_int( p, 2, &time->day ) );
+ CHECK( x509_parse_int( p, 2, &time->hour ) );
+ CHECK( x509_parse_int( p, 2, &time->min ) );
+
+ /*
+ * parse seconds if present
+ */
+ if ( len >= 2 && **p >= '0' && **p <= '9' )
+ {
+ CHECK( x509_parse_int( p, 2, &time->sec ) );
+ len -= 2;
+ }
+ else
+ {
+#if defined(POLARSSL_X509_ALLOW_RELAXED_DATE)
+ /*
+ * if relaxed mode, allow seconds to be absent
+ */
+ time->sec = 0;
+#else
+ return POLARSSL_ERR_X509_INVALID_DATE;
+#endif
+ }
+
+ /*
+ * parse trailing 'Z' if present
+ */
+ if ( 1 == len && 'Z' == **p )
+ {
+ (*p)++;
+ return 0;
+ }
+#if defined(POLARSSL_X509_ALLOW_RELAXED_DATE)
+ /*
+ * if relaxed mode, allow timezone to be present
+ */
+ else if ( 5 == len && ( '+' == **p || '-' == **p ) )
+ {
+ int tz; /* throwaway timezone */
+
+ (*p)++;
+ CHECK( x509_parse_int( p, 4, &tz ) );
+
+ return 0;
+ }
+#endif
+ /*
+ * okay if no trailing 'Z' or timezone specified
+ */
+ else if ( 0 == len )
+ return 0;
+ else
+ return POLARSSL_ERR_X509_INVALID_DATE;
+}
+
+/*
* Time ::= CHOICE {
* utcTime UTCTime,
* generalTime GeneralizedTime }
@@ -515,20 +597,7 @@
if( ret != 0 )
return( POLARSSL_ERR_X509_INVALID_DATE + ret );
- CHECK( x509_parse_int( p, 2, &time->year ) );
- CHECK( x509_parse_int( p, 2, &time->mon ) );
- CHECK( x509_parse_int( p, 2, &time->day ) );
- CHECK( x509_parse_int( p, 2, &time->hour ) );
- CHECK( x509_parse_int( p, 2, &time->min ) );
- if( len > 10 )
- CHECK( x509_parse_int( p, 2, &time->sec ) );
- if( len > 12 && *(*p)++ != 'Z' )
- return( POLARSSL_ERR_X509_INVALID_DATE );
-
- time->year += 100 * ( time->year < 50 );
- time->year += 1900;
-
- return( 0 );
+ return x509_parse_time( p, len, 2, time );
}
else if( tag == ASN1_GENERALIZED_TIME )
{
@@ -538,17 +607,7 @@
if( ret != 0 )
return( POLARSSL_ERR_X509_INVALID_DATE + ret );
- CHECK( x509_parse_int( p, 4, &time->year ) );
- CHECK( x509_parse_int( p, 2, &time->mon ) );
- CHECK( x509_parse_int( p, 2, &time->day ) );
- CHECK( x509_parse_int( p, 2, &time->hour ) );
- CHECK( x509_parse_int( p, 2, &time->min ) );
- if( len > 12 )
- CHECK( x509_parse_int( p, 2, &time->sec ) );
- if( len > 14 && *(*p)++ != 'Z' )
- return( POLARSSL_ERR_X509_INVALID_DATE );
-
- return( 0 );
+ return x509_parse_time( p, len, 4, time );
}
else
return( POLARSSL_ERR_X509_INVALID_DATE +