diff options
Diffstat (limited to 'lib/libssl')
-rw-r--r-- | lib/libssl/src/crypto/asn1/a_gentm.c | 106 | ||||
-rw-r--r-- | lib/libssl/src/crypto/asn1/a_time.c | 25 | ||||
-rw-r--r-- | lib/libssl/src/crypto/asn1/a_time_tm.c | 257 | ||||
-rw-r--r-- | lib/libssl/src/crypto/asn1/a_utctm.c | 80 | ||||
-rw-r--r-- | lib/libssl/src/crypto/asn1/asn1_locl.h | 6 | ||||
-rw-r--r-- | lib/libssl/src/crypto/x509/x509_lcl.h | 1 | ||||
-rw-r--r-- | lib/libssl/src/crypto/x509/x509_vfy.c | 128 |
7 files changed, 332 insertions, 271 deletions
diff --git a/lib/libssl/src/crypto/asn1/a_gentm.c b/lib/libssl/src/crypto/asn1/a_gentm.c index 4cee40437cc..594eb630580 100644 --- a/lib/libssl/src/crypto/asn1/a_gentm.c +++ b/lib/libssl/src/crypto/asn1/a_gentm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_gentm.c,v 1.24 2015/09/30 18:04:02 jsing Exp $ */ +/* $OpenBSD: a_gentm.c,v 1.25 2015/10/02 15:04:45 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -66,86 +66,14 @@ #include <openssl/err.h> #include "o_time.h" +#include "asn1_locl.h" int ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d) { - static const int min[9] = {0, 0, 1, 1, 0, 0, 0, 0, 0}; - static const int max[9] = {99, 99, 12, 31, 23, 59, 59, 12, 59}; - char *a; - int n, i, l, o; - if (d->type != V_ASN1_GENERALIZEDTIME) return (0); - l = d->length; - a = (char *)d->data; - o = 0; - /* GENERALIZEDTIME is similar to UTCTIME except the year is - * represented as YYYY. This stuff treats everything as a two digit - * field so make first two fields 00 to 99 - */ - if (l < 13) - goto err; - for (i = 0; i < 7; i++) { - if ((i == 6) && ((a[o] == 'Z') || - (a[o] == '+') || (a[o] == '-'))) { - i++; - 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; - } - /* Optional fractional seconds: decimal point followed by one - * or more digits. - */ - if (a[o] == '.') { - if (++o > l) - goto err; - i = o; - while ((a[o] >= '0') && (a[o] <= '9') && (o <= l)) - o++; - /* Must have at least one digit after decimal point */ - if (i == o) - goto err; - } - - if (a[o] == 'Z') - o++; - else if ((a[o] == '+') || (a[o] == '-')) { - o++; - if (o + 4 > l) - goto err; - for (i = 7; i < 9; 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; - o++; - } - } else { - /* Missing time zone information. */ - goto err; - } - return (o == l); -err: - return (0); + return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); } int @@ -179,34 +107,26 @@ ASN1_GENERALIZEDTIME_adj_internal(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day, long offset_sec) { char *p; - struct tm *ts; + struct tm *tm; struct tm data; - size_t len = 20; - ts = gmtime_r(&t, &data); - if (ts == NULL) + tm = gmtime_r(&t, &data); + if (tm == NULL) return (NULL); if (offset_day || offset_sec) { - if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) + if (!OPENSSL_gmtime_adj(tm, offset_day, offset_sec)) return NULL; } - p = (char *)s->data; - if ((p == NULL) || ((size_t)s->length < len)) { - p = malloc(len); - if (p == NULL) { - ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, - ERR_R_MALLOC_FAILURE); - return (NULL); - } - free(s->data); - s->data = (unsigned char *)p; + if ((p = gentime_string_from_tm(tm)) == NULL) { + ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE); + return (NULL); } - - snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, - ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); + free(s->data); + s->data = p; s->length = strlen(p); + s->type = V_ASN1_GENERALIZEDTIME; return (s); } diff --git a/lib/libssl/src/crypto/asn1/a_time.c b/lib/libssl/src/crypto/asn1/a_time.c index 25a1805640e..a6c7c8e736a 100644 --- a/lib/libssl/src/crypto/asn1/a_time.c +++ b/lib/libssl/src/crypto/asn1/a_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_time.c,v 1.25 2015/09/30 18:04:02 jsing Exp $ */ +/* $OpenBSD: a_time.c,v 1.26 2015/10/02 15:04:45 beck Exp $ */ /* ==================================================================== * Copyright (c) 1999 The OpenSSL Project. All rights reserved. * @@ -68,7 +68,7 @@ #include <openssl/err.h> #include "o_time.h" - +#include "asn1_locl.h" const ASN1_ITEM ASN1_TIME_it = { .itype = ASN1_ITYPE_MSTRING, @@ -135,11 +135,9 @@ ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec) int ASN1_TIME_check(ASN1_TIME *t) { - if (t->type == V_ASN1_GENERALIZEDTIME) - return ASN1_GENERALIZEDTIME_check(t); - else if (t->type == V_ASN1_UTCTIME) - return ASN1_UTCTIME_check(t); - return 0; + if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME) + return 0; + return (t->type == asn1_time_parse(t->data, t->length, NULL, t->type)); } /* Convert an ASN1_TIME structure to GeneralizedTime */ @@ -210,13 +208,12 @@ ASN1_TIME_set_string(ASN1_TIME *s, const char *str) t.data = (unsigned char *)str; t.flags = 0; - t.type = V_ASN1_UTCTIME; - - if (!ASN1_TIME_check(&t)) { - t.type = V_ASN1_GENERALIZEDTIME; - if (!ASN1_TIME_check(&t)) - return 0; - } + t.type = asn1_time_parse(t.data, t.length, NULL, V_ASN1_UTCTIME); + if (t.type == -1) + t.type = asn1_time_parse(t.data, t.length, NULL, + V_ASN1_GENERALIZEDTIME); + if (t.type == -1) + return 0; if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) return 0; diff --git a/lib/libssl/src/crypto/asn1/a_time_tm.c b/lib/libssl/src/crypto/asn1/a_time_tm.c new file mode 100644 index 00000000000..65f75c68cc6 --- /dev/null +++ b/lib/libssl/src/crypto/asn1/a_time_tm.c @@ -0,0 +1,257 @@ +/* $OpenBSD: a_time_tm.c,v 1.1 2015/10/02 15:04:45 beck Exp $ */ +/* + * Copyright (c) 2015 Bob Beck <beck@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <ctype.h> +#include <sys/limits.h> + +#include <openssl/asn1t.h> +#include <openssl/err.h> + +#include "o_time.h" +#include "asn1_locl.h" + +char * +gentime_string_from_tm(struct tm *tm) +{ + char *ret = NULL; + int year; + year = tm->tm_year + 1900; + if (year < 0 || year > 9999) + return (NULL); + if (asprintf(&ret, "%04u%02u%02u%02u%02u%02uZ", year, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec) == -1) + ret = NULL; + return (ret); +} + +char * +utctime_string_from_tm(struct tm *tm) +{ + char *ret = NULL; + if (tm->tm_year >= 150 || tm->tm_year < 50) + return (NULL); + if (asprintf(&ret, "%02u%02u%02u%02u%02u%02uZ", + tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) + ret = NULL; + return (ret); +} + +/* + * Parse an ASN.1 time string. + * + * mode must be: + * 0 if we expect to parse a time as specified in RFC 5280 from an + * X509 certificate. + * V_ASN1_UTCTIME if we wish to parse a legacy ASN1 UTC time. + * V_ASN1_GENERALIZEDTIME if we wish to parse a legacy ASN1 + * Generalizd time. + * + * Returns: + * -1 if the string was invalid. + * V_ASN1_UTCTIME if the string validated as a UTC time string. + * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string. + * + * Fills in *tm with the corresponding time if tm is non NULL. + */ +#define RFC5280 0 +#define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0')) +int asn1_time_parse(const char * bytes, size_t len, struct tm *tm, int mode) +{ + char *p, *buf = NULL, *dot = NULL, *tz = NULL; + int i, offset, noseconds = 0, type = 0; + struct tm ltm; + struct tm *lt; + size_t tlen; + char tzc; + + if (bytes == NULL) + goto err; + + if (len > INT_MAX) + goto err; + + /* Constrain the RFC5280 case within max/min valid lengths. */ + if (mode == RFC5280 && (len > 15 || len < 13)) + goto err; + + if ((buf = strndup(bytes, len)) == NULL) + goto err; + lt = tm; + if (lt == NULL) { + time_t t = time(NULL); + lt = gmtime_r(&t, <m); + if (lt == NULL) + goto err; + } + + /* + * Find position of the optional fractional seconds, and the + * start of the timezone, while ensuring everything else is + * digits. + */ + for (i = 0; i < len; i++) { + char *t = buf + i; + if (isdigit((unsigned char)*t)) + continue; + if (*t == '.' && dot == NULL) { + dot = t; + continue; + } + if ((*t == 'Z' || *t == '+' || *t == '-') && tz == NULL) { + tz = t; + continue; + } + goto err; + } + + /* + * Timezone is required. For the non-RFC case it may be + * either Z or +- HHMM, but for RFC5280 it may be only Z. + */ + if (tz == NULL) + goto err; + tzc = *tz; + *tz++ = '\0'; + if (tzc == 'Z') { + if (*tz != '\0') + goto err; + offset = 0; + } else if (mode != RFC5280 && (tzc == '+' || tzc == '-') && + (strlen(tz) == 4)) { + int hours, mins; + hours = ATOI2(tz); + mins = ATOI2(tz); + if (hours > 12 || mins > 59) + goto err; + offset = hours * 3600 + mins * 60; + if (tzc == '-') + offset = -offset; + } else + goto err; + + if (mode != RFC5280) { + /* XXX - yuck - OPENSSL_gmtime_adj should go away */ + if (!OPENSSL_gmtime_adj(lt, 0, offset)) + goto err; + } + + /* + * We only allow fractional seconds to be present if we are in + * the non-RFC case of a Generalized time. RFC 5280 forbids + * fractional seconds. + */ + if (dot != NULL) { + if (mode != V_ASN1_GENERALIZEDTIME) + goto err; + *dot++ = '\0'; + if (!isdigit((unsigned char)*dot)) + goto err; + } + + /* + * Validate and convert the time + */ + p = buf; + tlen = strlen(buf); + switch (tlen) { + case 14: + lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ + if (mode == RFC5280 || mode == V_ASN1_GENERALIZEDTIME) + type = V_ASN1_GENERALIZEDTIME; + else + goto err; + /* FALLTHROUGH */ + case 12: + if (type == 0 && mode == V_ASN1_GENERALIZEDTIME) { + /* + * In the non-RFC case of a Generalized time + * seconds may not have been provided. RFC + * 5280 mandates that seconds must be present. + */ + noseconds = 1; + lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */ + type = V_ASN1_GENERALIZEDTIME; + } + /* FALLTHROUGH */ + case 10: + if (type == 0) { + /* + * At this point we must have a UTC time. + * In the RFC 5280 case it must have the + * seconds present. In the non-RFC case + * may have no seconds. + */ + if (mode == V_ASN1_GENERALIZEDTIME) + goto err; + if (tlen == 10) { + if (mode == V_ASN1_UTCTIME) + noseconds = 1; + else + goto err; + } + type = V_ASN1_UTCTIME; + } + lt->tm_year += ATOI2(p); /* yy */ + if (type == V_ASN1_UTCTIME) { + if (lt->tm_year < 50) + lt->tm_year += 100; + } + lt->tm_mon = ATOI2(p); /* mm */ + if ((lt->tm_mon > 12) || !lt->tm_mon) + goto err; + --lt->tm_mon; /* struct tm is 0 - 11 */ + lt->tm_mday = ATOI2(p); /* dd */ + if ((lt->tm_mday > 31) || !lt->tm_mday) + goto err; + lt->tm_hour = ATOI2(p); /* HH */ + if (lt->tm_hour > 23) + goto err; + lt->tm_min = ATOI2(p); /* MM */ + if (lt->tm_min > 59) + goto err; + lt->tm_sec = 0; /* SS */ + if (noseconds) + break; + lt->tm_sec = ATOI2(p); + /* Leap second 60 is not accepted. Reconsider later? */ + if (lt->tm_sec > 59) + goto err; + break; + default: + goto err; + } + + /* RFC 5280 section 4.1.2.5 */ + if (mode == RFC5280 && lt->tm_year < 150 && + type != V_ASN1_UTCTIME) + goto err; + if (mode == RFC5280 && lt->tm_year >= 150 && + type != V_ASN1_GENERALIZEDTIME) + goto err; + + free(buf); + return type; + +err: + free(buf); + return -1; +} diff --git a/lib/libssl/src/crypto/asn1/a_utctm.c b/lib/libssl/src/crypto/asn1/a_utctm.c index ca19a8c7a00..c208d494c3a 100644 --- a/lib/libssl/src/crypto/asn1/a_utctm.c +++ b/lib/libssl/src/crypto/asn1/a_utctm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_utctm.c,v 1.28 2015/09/30 18:26:07 jsing Exp $ */ +/* $OpenBSD: a_utctm.c,v 1.29 2015/10/02 15:04:45 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -64,66 +64,14 @@ #include <openssl/err.h> #include "o_time.h" +#include "asn1_locl.h" int ASN1_UTCTIME_check(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++; - 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 (a[o] == 'Z') - o++; - else if ((a[o] == '+') || (a[o] == '-')) { - 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; - o++; - } - } - return (o == l); - -err: - return (0); + return(d->type == asn1_time_parse(d->data, d->length, NULL, d->type)); } int @@ -159,7 +107,6 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, char *p; struct tm *ts; struct tm data; - size_t len = 20; ts = gmtime_r(&t, &data); if (ts == NULL) @@ -170,23 +117,14 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day, return NULL; } - if ((ts->tm_year < 50) || (ts->tm_year >= 150)) - return NULL; - - p = (char *)s->data; - if ((p == NULL) || ((size_t)s->length < len)) { - p = malloc(len); - if (p == NULL) { - ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE); - return (NULL); - } - free(s->data); - s->data = (unsigned char *)p; + if ((p = utctime_string_from_tm(ts)) == NULL) { + ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE); + return (NULL); } - - snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, - ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec); + free(s->data); + s->data = p; s->length = strlen(p); + s->type = V_ASN1_UTCTIME; return (s); } diff --git a/lib/libssl/src/crypto/asn1/asn1_locl.h b/lib/libssl/src/crypto/asn1/asn1_locl.h index c6c80aa6aa2..d4994c7cee5 100644 --- a/lib/libssl/src/crypto/asn1/asn1_locl.h +++ b/lib/libssl/src/crypto/asn1/asn1_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: asn1_locl.h,v 1.5 2014/06/12 15:49:27 deraadt Exp $ */ +/* $OpenBSD: asn1_locl.h,v 1.6 2015/10/02 15:04:45 beck Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -58,6 +58,10 @@ /* Internal ASN1 structures and functions: not for application use */ +char * gentime_string_from_tm(struct tm *tm); +char * utctime_string_from_tm(struct tm *tm); +int asn1_time_parse(const char *, size_t, struct tm *, int); + /* ASN1 print context structure */ struct asn1_pctx_st { diff --git a/lib/libssl/src/crypto/x509/x509_lcl.h b/lib/libssl/src/crypto/x509/x509_lcl.h index b16df78ad7c..0c1c130d5c8 100644 --- a/lib/libssl/src/crypto/x509/x509_lcl.h +++ b/lib/libssl/src/crypto/x509/x509_lcl.h @@ -57,3 +57,4 @@ */ int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); +int asn1_time_parse(const char *, size_t, struct tm *, int); diff --git a/lib/libssl/src/crypto/x509/x509_vfy.c b/lib/libssl/src/crypto/x509/x509_vfy.c index 8d4d15668ec..c48143f3517 100644 --- a/lib/libssl/src/crypto/x509/x509_vfy.c +++ b/lib/libssl/src/crypto/x509/x509_vfy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: x509_vfy.c,v 1.45 2015/09/14 16:13:39 jsing Exp $ */ +/* $OpenBSD: x509_vfy.c,v 1.46 2015/10/02 15:04:45 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1631,106 +1631,50 @@ X509_cmp_current_time(const ASN1_TIME *ctm) return X509_cmp_time(ctm, NULL); } +/* + * Compare a possibly unvalidated ASN1_TIME string against a time_t + * using RFC 5280 rules for the time string. If *cmp_time is NULL + * the current system time is used. + * + * XXX NOTE that unlike what you expect a "cmp" function to do in C, + * XXX this one is "special", and returns 0 for error. + * + * Returns: + * -1 if the ASN1_time is earlier than OR the same as *cmp_time. + * 1 if the ASN1_time is later than *cmp_time. + * 0 on error. + */ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) { - char *str; - ASN1_TIME atm; - long offset; - char buff1[24], buff2[24], *p; - int i, j; + time_t time1, time2; + struct tm tm1; + int ret = 0; - p = buff1; - i = ctm->length; - str = (char *)ctm->data; - if (ctm->type == V_ASN1_UTCTIME) { - if ((i < 11) || (i > 17)) - return 0; - memcpy(p, str, 10); - p += 10; - str += 10; - i -= 10; - } else { - if (i < 13) - return 0; - memcpy(p, str, 12); - p += 12; - str += 12; - i -= 12; - } + if (cmp_time == NULL) + time2 = time(NULL); + else + time2 = *cmp_time; - if (i < 1) - return 0; - if ((*str == 'Z') || (*str == '-') || (*str == '+')) { - *(p++) = '0'; - *(p++) = '0'; - } else { - if (i < 2) - return 0; - *(p++) = *(str++); - *(p++) = *(str++); - i -= 2; - if (i < 1) - return 0; - /* Skip any fractional seconds... */ - if (*str == '.') { - str++; - i--; - while (i > 1 && (*str >= '0') && (*str <= '9')) { - str++; - i--; - } - } - } - *(p++) = 'Z'; - *(p++) = '\0'; + memset(&tm1, 0, sizeof(tm1)); - if (i < 1) - return 0; - if (*str == 'Z') { - if (i != 1) - return 0; - offset = 0; - } else { - if (i != 5) - return 0; - if ((*str != '+') && (*str != '-')) - return 0; - if (str[1] < '0' || str[1] > '9' || - str[2] < '0' || str[2] > '9' || - str[3] < '0' || str[3] > '9' || - str[4] < '0' || str[4] > '9') - return 0; - offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; - offset += (str[3] - '0') * 10 + (str[4] - '0'); - if (*str == '-') - offset = -offset; - } - atm.type = ctm->type; - atm.flags = 0; - atm.length = sizeof(buff2); - atm.data = (unsigned char *)buff2; + if (asn1_time_parse(ctm->data, ctm->length, &tm1, 0) == -1) + goto out; /* invalid time */ - if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) - return 0; + /* + * Defensively fail if the time string is not representable as + * a time_t. A time_t must be sane if you care about times after + * Jan 19 2038. + */ + if ((time1 = timegm(&tm1)) == -1) + goto out; - if (ctm->type == V_ASN1_UTCTIME) { - i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); - if (i < 50) - i += 100; /* cf. RFC 2459 */ - j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); - if (j < 50) - j += 100; - if (i < j) - return -1; - if (i > j) - return 1; - } - i = strcmp(buff1, buff2); - if (i == 0) /* wait a second then return younger :-) */ - return -1; + if (time1 <= time2) + ret = -1; else - return i; + ret = 1; + out: + return (ret); } ASN1_TIME * |