Validate ASN.1 times according to RFC 5280 Refuse to parse times that are invalid according to RFC 5280, with a few exceptions for compatibility. This can affect test code that relies on making and parsing certificates that contain invalid times. Update-Note: Certificates containing invalid ASN.1 times will no longer parse. Bug: 491, 427 Change-Id: I2a3fe3a4d359ac662340a225d05b360718eb8c29 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/52665 Commit-Queue: Bob Beck <bbe@google.com> Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/a_utctm.c b/crypto/asn1/a_utctm.c index 21ea2cc..ea984c5 100644 --- a/crypto/asn1/a_utctm.c +++ b/crypto/asn1/a_utctm.c
@@ -55,106 +55,26 @@ * [including the GNU Public Licence.] */ #include <openssl/asn1.h> +#include <openssl/bytestring.h> +#include <openssl/err.h> +#include <openssl/mem.h> #include <string.h> #include <time.h> -#include <openssl/err.h> -#include <openssl/mem.h> - #include "internal.h" - int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) { - static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; - static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 }; - char *a; - int n, i, l, o; - - if (d->type != V_ASN1_UTCTIME) - return (0); - l = d->length; - a = (char *)d->data; - o = 0; - - if (l < 11) - goto err; - for (i = 0; i < 6; i++) { - if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { - i++; - if (tm) - tm->tm_sec = 0; - break; - } - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = a[o] - '0'; - if (++o > l) - goto err; - - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = (n * 10) + a[o] - '0'; - if (++o > l) - goto err; - - if ((n < min[i]) || (n > max[i])) - goto err; - if (tm) { - switch (i) { - case 0: - tm->tm_year = n < 50 ? n + 100 : n; - break; - case 1: - tm->tm_mon = n - 1; - break; - case 2: - tm->tm_mday = n; - break; - case 3: - tm->tm_hour = n; - break; - case 4: - tm->tm_min = n; - break; - case 5: - tm->tm_sec = n; - break; - } - } + if (d->type != V_ASN1_UTCTIME) { + return 0; } - if (a[o] == 'Z') - o++; - else if ((a[o] == '+') || (a[o] == '-')) { - int offsign = a[o] == '-' ? 1 : -1, offset = 0; - o++; - if (o + 4 > l) - goto err; - for (i = 6; i < 8; i++) { - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = a[o] - '0'; - o++; - if ((a[o] < '0') || (a[o] > '9')) - goto err; - n = (n * 10) + a[o] - '0'; - if ((n < min[i]) || (n > max[i])) - goto err; - if (tm) { - if (i == 6) - offset = n * 3600; - else if (i == 7) - offset += n * 60; - } - o++; - } - if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign)) - return 0; + CBS cbs; + CBS_init(&cbs, d->data, (size_t)d->length); + if (!CBS_parse_utc_time(&cbs, tm, /*allow_timezone_offset=*/1)) { + return 0; } - return o == l; - err: - return 0; + return 1; } int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)