summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libcrypto/asn1/a_gentm.c153
-rw-r--r--lib/libcrypto/asn1/a_time.c117
-rw-r--r--lib/libcrypto/asn1/a_time_tm.c462
-rw-r--r--lib/libcrypto/asn1/a_utctm.c173
-rw-r--r--lib/libcrypto/asn1/asn1_locl.h6
-rw-r--r--lib/libcrypto/x509/x509_lcl.h1
-rw-r--r--lib/libcrypto/x509/x509_vfy.c45
7 files changed, 348 insertions, 609 deletions
diff --git a/lib/libcrypto/asn1/a_gentm.c b/lib/libcrypto/asn1/a_gentm.c
deleted file mode 100644
index 594eb630580..00000000000
--- a/lib/libcrypto/asn1/a_gentm.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* $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.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-/* GENERALIZEDTIME implementation, written by Steve Henson. Based on UTCTIME */
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include <openssl/asn1.h>
-#include <openssl/err.h>
-
-#include "o_time.h"
-#include "asn1_locl.h"
-
-int
-ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d)
-{
- if (d->type != V_ASN1_GENERALIZEDTIME)
- return (0);
- return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
-}
-
-int
-ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
-{
- ASN1_GENERALIZEDTIME t;
-
- t.type = V_ASN1_GENERALIZEDTIME;
- t.length = strlen(str);
- t.data = (unsigned char *)str;
- if (ASN1_GENERALIZEDTIME_check(&t)) {
- if (s != NULL) {
- if (!ASN1_STRING_set((ASN1_STRING *)s,
- (unsigned char *)str, t.length))
- return 0;
- s->type = V_ASN1_GENERALIZEDTIME;
- }
- return (1);
- } else
- return (0);
-}
-
-ASN1_GENERALIZEDTIME *
-ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t)
-{
- return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
-}
-
-static ASN1_GENERALIZEDTIME *
-ASN1_GENERALIZEDTIME_adj_internal(ASN1_GENERALIZEDTIME *s, time_t t,
- int offset_day, long offset_sec)
-{
- char *p;
- struct tm *tm;
- struct tm data;
-
- tm = gmtime_r(&t, &data);
- if (tm == NULL)
- return (NULL);
-
- if (offset_day || offset_sec) {
- if (!OPENSSL_gmtime_adj(tm, offset_day, offset_sec))
- return NULL;
- }
-
- if ((p = gentime_string_from_tm(tm)) == NULL) {
- ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE);
- return (NULL);
- }
- free(s->data);
- s->data = p;
- s->length = strlen(p);
-
- s->type = V_ASN1_GENERALIZEDTIME;
- return (s);
-}
-
-ASN1_GENERALIZEDTIME *
-ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
- long offset_sec)
-{
- ASN1_GENERALIZEDTIME *tmp = NULL, *ret;
-
- if (s == NULL) {
- tmp = ASN1_GENERALIZEDTIME_new();
- if (tmp == NULL)
- return NULL;
- s = tmp;
- }
-
- ret = ASN1_GENERALIZEDTIME_adj_internal(s, t, offset_day, offset_sec);
- if (ret == NULL && tmp != NULL)
- ASN1_GENERALIZEDTIME_free(tmp);
-
- return ret;
-
-}
diff --git a/lib/libcrypto/asn1/a_time.c b/lib/libcrypto/asn1/a_time.c
index a6c7c8e736a..7a3742fd70b 100644
--- a/lib/libcrypto/asn1/a_time.c
+++ b/lib/libcrypto/asn1/a_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_time.c,v 1.26 2015/10/02 15:04:45 beck Exp $ */
+/* $OpenBSD: a_time.c,v 1.27 2015/10/19 16:32:37 beck Exp $ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
@@ -105,118 +105,3 @@ ASN1_TIME_free(ASN1_TIME *a)
{
ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it);
}
-
-ASN1_TIME *
-ASN1_TIME_set(ASN1_TIME *s, time_t t)
-{
- return ASN1_TIME_adj(s, t, 0, 0);
-}
-
-ASN1_TIME *
-ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
-{
- struct tm *ts;
- struct tm data;
-
- ts = gmtime_r(&t, &data);
- if (ts == NULL) {
- ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME);
- return NULL;
- }
- if (offset_day || offset_sec) {
- if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
- return NULL;
- }
- if ((ts->tm_year >= 50) && (ts->tm_year < 150))
- return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
- return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
-}
-
-int
-ASN1_TIME_check(ASN1_TIME *t)
-{
- 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 */
-static ASN1_GENERALIZEDTIME *
-ASN1_TIME_to_generalizedtime_internal(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
-{
- ASN1_GENERALIZEDTIME *ret;
- char *str;
- int newlen;
- int i;
-
- if (!ASN1_TIME_check(t))
- return NULL;
-
- ret = *out;
-
- /* If already GeneralizedTime just copy across */
- if (t->type == V_ASN1_GENERALIZEDTIME) {
- if (!ASN1_STRING_set(ret, t->data, t->length))
- return NULL;
- return ret;
- }
-
- /* grow the string */
- if (!ASN1_STRING_set(ret, NULL, t->length + 2))
- return NULL;
- /* ASN1_STRING_set() allocated 'len + 1' bytes. */
- newlen = t->length + 2 + 1;
- str = (char *)ret->data;
- /* XXX ASN1_TIME is not Y2050 compatible */
- i = snprintf(str, newlen, "%s%s", (t->data[0] >= '5') ? "19" : "20",
- (char *) t->data);
- if (i == -1 || i >= newlen) {
- ASN1_GENERALIZEDTIME_free(ret);
- *out = NULL;
- return NULL;
- }
- return ret;
-}
-
-ASN1_GENERALIZEDTIME *
-ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
-{
- ASN1_GENERALIZEDTIME *tmp = NULL, *ret;
-
- if (!out || !*out) {
- if (!(tmp = ASN1_GENERALIZEDTIME_new()))
- return NULL;
- if (out != NULL)
- *out = tmp;
- else
- out = &tmp;
- }
-
- ret = ASN1_TIME_to_generalizedtime_internal(t, out);
- if (ret == NULL && tmp != NULL)
- ASN1_GENERALIZEDTIME_free(tmp);
-
- return ret;
-}
-
-int
-ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
-{
- ASN1_TIME t;
-
- t.length = strlen(str);
- t.data = (unsigned char *)str;
- t.flags = 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;
-
- return 1;
-}
diff --git a/lib/libcrypto/asn1/a_time_tm.c b/lib/libcrypto/asn1/a_time_tm.c
index 53443fa965b..352b9159ee2 100644
--- a/lib/libcrypto/asn1/a_time_tm.c
+++ b/lib/libcrypto/asn1/a_time_tm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_time_tm.c,v 1.5 2015/10/08 02:26:31 beck Exp $ */
+/* $OpenBSD: a_time_tm.c,v 1.6 2015/10/19 16:32:37 beck Exp $ */
/*
* Copyright (c) 2015 Bob Beck <beck@openbsd.org>
*
@@ -14,7 +14,6 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
@@ -25,8 +24,41 @@
#include <openssl/err.h>
#include "o_time.h"
-#include "asn1_locl.h"
+#define RFC5280 0
+#define GENTIME_LENGTH 15
+#define UTCTIME_LENGTH 13
+
+int
+asn1_tm_cmp(struct tm *tm1, struct tm *tm2) {
+ if (tm1->tm_year < tm2->tm_year)
+ return (-1);
+ if (tm1->tm_year > tm2->tm_year)
+ return (1);
+ if (tm1->tm_mon < tm2->tm_mon)
+ return (-1);
+ if (tm1->tm_mon > tm2->tm_mon)
+ return (1);
+ if (tm1->tm_mday < tm2->tm_mday)
+ return (-1);
+ if (tm1->tm_mday > tm2->tm_mday)
+ return (1);
+ if (tm1->tm_hour < tm2->tm_hour)
+ return (-1);
+ if (tm1->tm_hour > tm2->tm_hour)
+ return (1);
+ if (tm1->tm_min < tm2->tm_min)
+ return (-1);
+ if (tm1->tm_min > tm2->tm_min)
+ return (1);
+ if (tm1->tm_sec < tm2->tm_sec)
+ return (-1);
+ if (tm1->tm_sec > tm2->tm_sec)
+ return (1);
+ return 0;
+}
+
+/* Format a time as an RFC 5280 format Generalized time */
char *
gentime_string_from_tm(struct tm *tm)
{
@@ -45,6 +77,7 @@ gentime_string_from_tm(struct tm *tm)
return (ret);
}
+/* Format a time as an RFC 5280 format UTC time */
char *
utctime_string_from_tm(struct tm *tm)
{
@@ -61,14 +94,32 @@ utctime_string_from_tm(struct tm *tm)
return (ret);
}
+/* Format a time correctly for an X509 object as per RFC 5280 */
+char *
+rfc5280_string_from_tm(struct tm *tm)
+{
+ char *ret = NULL;
+ int year;
+
+ year = tm->tm_year + 1900;
+ if (year < 1950 || year > 9999)
+ return (NULL);
+
+ if (year < 2050)
+ ret = utctime_string_from_tm(tm);
+ else
+ ret = gentime_string_from_tm(tm);
+
+ return (ret);
+}
+
/*
- * Parse an ASN.1 time string.
+ * Parse an RFC 5280 format 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 Generalized time.
+ * 0 if we expect to parse a time as specified in RFC 5280 from an X509 object.
+ * V_ASN1_UTCTIME if we wish to parse on RFC5280 format UTC time.
+ * V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
*
* Returns:
* -1 if the string was invalid.
@@ -77,141 +128,54 @@ utctime_string_from_tm(struct tm *tm)
*
* 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 = 0, noseconds = 0, type = 0, ret = -1;
+ int i, type = 0;
struct tm ltm;
struct tm *lt;
- size_t tlen;
- char tzc;
+ const char *p;
if (bytes == NULL)
- goto err;
-
- if (len > INT_MAX)
- goto err;
+ return (-1);
- /* Constrain the RFC5280 case within min/max valid lengths. */
- if (mode == RFC5280 && (len < 13 || len > 15))
- goto err;
-
- if ((buf = strndup(bytes, len)) == NULL)
- goto err;
+ /* Constrain to valid lengths. */
+ if (len != UTCTIME_LENGTH && len != GENTIME_LENGTH)
+ return (-1);
lt = tm;
if (lt == NULL) {
- time_t t = time(NULL);
- lt = gmtime_r(&t, &ltm);
- if (lt == NULL)
- goto err;
+ memset(&ltm, 0, sizeof(ltm));
+ lt = &ltm;
}
- /*
- * 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 && tz == 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;
- } else if (mode != RFC5280 && (tzc == '+' || tzc == '-') &&
- strlen(tz) == 4) {
- int hours = ATOI2(tz);
- int mins = ATOI2(tz);
-
- if (hours < 0 || hours > 12 || mins < 0 || mins > 59)
- goto err;
- offset = hours * 3600 + mins * 60;
- if (tzc == '-')
- offset = -offset;
- } else
- goto err;
-
- if (offset != 0) {
- /* XXX - yuck - OPENSSL_gmtime_adj should go away */
- if (!OPENSSL_gmtime_adj(lt, 0, offset))
- goto err;
- }
+ /* Timezone is required and must be GMT (Zulu). */
+ if (bytes[len - 1] != 'Z')
+ return (-1);
- /*
- * 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;
+ /* Make sure everything else is digits. */
+ for (i = 0; i < len - 1; i++) {
+ if (isdigit((unsigned char)bytes[i]))
+ continue;
+ return (-1);
}
/*
* Validate and convert the time
*/
- p = buf;
- tlen = strlen(buf);
- switch (tlen) {
- case 14:
+ p = bytes;
+ switch (len) {
+ case GENTIME_LENGTH:
+ if (mode == V_ASN1_UTCTIME)
+ return (-1);
lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */
- if (mode != RFC5280 && mode != V_ASN1_GENERALIZEDTIME)
- goto err;
type = V_ASN1_GENERALIZEDTIME;
/* 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:
+ case UTCTIME_LENGTH:
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)
- goto err;
- noseconds = 1;
- }
+ return (-1);
type = V_ASN1_UTCTIME;
}
lt->tm_year += ATOI2(p); /* yy */
@@ -221,40 +185,258 @@ asn1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
}
lt->tm_mon = ATOI2(p) - 1; /* mm */
if (lt->tm_mon < 0 || lt->tm_mon > 11)
- goto err;
+ return (-1);
lt->tm_mday = ATOI2(p); /* dd */
if (lt->tm_mday < 1 || lt->tm_mday > 31)
- goto err;
+ return (-1);
lt->tm_hour = ATOI2(p); /* HH */
if (lt->tm_hour < 0 || lt->tm_hour > 23)
- goto err;
+ return (-1);
lt->tm_min = ATOI2(p); /* MM */
- if (lt->tm_hour < 0 || lt->tm_min > 59)
- goto err;
- lt->tm_sec = 0; /* SS */
- if (noseconds)
- break;
- lt->tm_sec = ATOI2(p);
+ if (lt->tm_min < 0 || lt->tm_min > 59)
+ return (-1);
+ lt->tm_sec = ATOI2(p); /* SS */
/* Leap second 60 is not accepted. Reconsider later? */
- if (lt->tm_hour < 0 || lt->tm_sec > 59)
- goto err;
+ if (lt->tm_sec < 0 || lt->tm_sec > 59)
+ return (-1);
break;
default:
- goto err;
+ return (-1);
+ }
+
+ return (type);
+}
+
+/*
+ * ASN1_TIME generic functions.
+ */
+
+static int
+ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode)
+{
+ int type;
+ char *tmp;
+
+ if ((type = asn1_time_parse(str, strlen(str), NULL, mode)) == -1)
+ return (0);
+ if (mode != 0 && mode != type)
+ return (0);
+ if ((tmp = strdup(str)) == NULL)
+ return (0);
+ free(s->data);
+ s->data = tmp;
+ s->length = strlen(tmp);
+ s->type = type;
+ return (1);
+}
+
+static ASN1_TIME *
+ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
+ int mode)
+{
+ int allocated = 0;
+ struct tm tm;
+ size_t len;
+ char * p;
+
+ if (gmtime_r(&t, &tm) == NULL)
+ return (NULL);
+
+ if (offset_day || offset_sec) {
+ if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
+ return (NULL);
}
- /* RFC 5280 section 4.1.2.5 */
- if (mode == RFC5280) {
- if (lt->tm_year < 150 && type != V_ASN1_UTCTIME)
- goto err;
- if (lt->tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
- goto err;
+ switch (mode) {
+ case V_ASN1_UTCTIME:
+ p = utctime_string_from_tm(&tm);
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ p = gentime_string_from_tm(&tm);
+ break;
+ case RFC5280:
+ p = rfc5280_string_from_tm(&tm);
+ break;
+ default:
+ return (NULL);
+ }
+ if (p == NULL) {
+ ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ,
+ ASN1_R_ILLEGAL_TIME_VALUE);
+ return (NULL);
}
- ret = type;
+ if (s == NULL) {
+ if ((s = ASN1_TIME_new()) == NULL)
+ return (NULL);
+ allocated = 1;
+ }
-err:
- free(buf);
+ len = strlen(p);
+ switch (len) {
+ case GENTIME_LENGTH:
+ s->type = V_ASN1_GENERALIZEDTIME;
+ break;
+ case UTCTIME_LENGTH:
+ s->type = V_ASN1_UTCTIME;
+ break;
+ default:
+ if (allocated)
+ ASN1_TIME_free(s);
+ free(p);
+ return (NULL);
+ }
+ free(s->data);
+ s->data = p;
+ s->length = len;
+ return (s);
+}
- return (ret);
+ASN1_TIME *
+ASN1_TIME_set(ASN1_TIME *s, time_t t)
+{
+ return (ASN1_TIME_adj(s, t, 0, 0));
}
+
+ASN1_TIME *
+ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
+{
+ return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280));
+}
+
+int
+ASN1_TIME_check(ASN1_TIME *t)
+{
+ 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));
+}
+
+ASN1_GENERALIZEDTIME *
+ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
+{
+ ASN1_GENERALIZEDTIME *tmp = NULL;
+ struct tm tm;
+ char *str;
+
+ if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
+ return (NULL);
+
+ memset(&tm, 0, sizeof(tm));
+ if (t->type != asn1_time_parse(t->data, t->length, &tm, t->type))
+ return (NULL);
+ if ((str = gentime_string_from_tm(&tm)) == NULL)
+ return (NULL);
+
+ if (out != NULL)
+ tmp = *out;
+ if (tmp == NULL && (tmp = ASN1_GENERALIZEDTIME_new()) == NULL) {
+ free(str);
+ return (NULL);
+ }
+ if (out != NULL)
+ *out = tmp;
+
+ free(tmp->data);
+ tmp->data = str;
+ tmp->length = strlen(str);
+ return (tmp);
+}
+
+int
+ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
+{
+ return (ASN1_TIME_set_string_internal(s, str, 0));
+}
+
+/*
+ * ASN1_UTCTIME wrappers
+ */
+
+int
+ASN1_UTCTIME_check(ASN1_UTCTIME *d)
+{
+ if (d->type != V_ASN1_UTCTIME)
+ return (0);
+ return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
+}
+
+int
+ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
+{
+ if (s->type != V_ASN1_UTCTIME)
+ return (0);
+ return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME));
+}
+
+ASN1_UTCTIME *
+ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
+{
+ return (ASN1_UTCTIME_adj(s, t, 0, 0));
+}
+
+ASN1_UTCTIME *
+ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
+{
+ return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
+ V_ASN1_UTCTIME));
+}
+
+int
+ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t2)
+{
+ struct tm tm1, tm2;
+
+ /*
+ * This function has never handled failure conditions properly
+ * and should be deprecated. The OpenSSL version used to
+ * simply follow NULL pointers on failure. BoringSSL and
+ * OpenSSL now make it return -2 on failure.
+ *
+ * The danger is that users of this function will not
+ * differentiate the -2 failure case from t1 < t2.
+ */
+ if (asn1_time_parse(s->data, s->length, &tm1, V_ASN1_UTCTIME) == -1)
+ return (-2); /* XXX */
+
+ if (gmtime_r(&t2, &tm2) == NULL)
+ return (-2); /* XXX */
+
+ return asn1_tm_cmp(&tm1, &tm2);
+}
+
+/*
+ * ASN1_GENERALIZEDTIME wrappers
+ */
+
+int
+ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d)
+{
+ if (d->type != V_ASN1_GENERALIZEDTIME)
+ return (0);
+ return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
+}
+
+int
+ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
+{
+ if (s->type != V_ASN1_GENERALIZEDTIME)
+ return (0);
+ return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME));
+}
+
+ASN1_GENERALIZEDTIME *
+ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t)
+{
+ return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0));
+}
+
+ASN1_GENERALIZEDTIME *
+ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
+ long offset_sec)
+{
+ return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
+ V_ASN1_GENERALIZEDTIME));
+}
+
+
diff --git a/lib/libcrypto/asn1/a_utctm.c b/lib/libcrypto/asn1/a_utctm.c
deleted file mode 100644
index 495c497bc8d..00000000000
--- a/lib/libcrypto/asn1/a_utctm.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* $OpenBSD: a_utctm.c,v 1.32 2015/10/08 02:42:58 beck Exp $ */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-
-#include <openssl/asn1.h>
-#include <openssl/err.h>
-
-#include "o_time.h"
-#include "asn1_locl.h"
-
-int
-ASN1_UTCTIME_check(ASN1_UTCTIME *d)
-{
- if (d->type != V_ASN1_UTCTIME)
- return (0);
- return(d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
-}
-
-int
-ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
-{
- ASN1_UTCTIME t;
-
- t.type = V_ASN1_UTCTIME;
- t.length = strlen(str);
- t.data = (unsigned char *)str;
- if (ASN1_UTCTIME_check(&t)) {
- if (s != NULL) {
- if (!ASN1_STRING_set((ASN1_STRING *)s,
- (unsigned char *)str, t.length))
- return 0;
- s->type = V_ASN1_UTCTIME;
- }
- return (1);
- } else
- return (0);
-}
-
-ASN1_UTCTIME *
-ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
-{
- return ASN1_UTCTIME_adj(s, t, 0, 0);
-}
-
-static ASN1_UTCTIME *
-ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day,
- long offset_sec)
-{
- char *p;
- struct tm *ts;
- struct tm data;
-
- ts = gmtime_r(&t, &data);
- if (ts == NULL)
- return (NULL);
-
- if (offset_day || offset_sec) {
- if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
- return NULL;
- }
-
- if ((p = utctime_string_from_tm(ts)) == NULL) {
- ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
- return (NULL);
- }
- free(s->data);
- s->data = p;
- s->length = strlen(p);
-
- s->type = V_ASN1_UTCTIME;
- return (s);
-}
-
-ASN1_UTCTIME *
-ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
-{
- ASN1_UTCTIME *tmp = NULL, *ret;
-
- if (s == NULL) {
- tmp = ASN1_UTCTIME_new();
- if (tmp == NULL)
- return NULL;
- s = tmp;
- }
-
- ret = ASN1_UTCTIME_adj_internal(s, t, offset_day, offset_sec);
- if (ret == NULL && tmp != NULL)
- ASN1_UTCTIME_free(tmp);
-
- return ret;
-}
-
-int
-ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t2)
-{
- struct tm tm1;
- time_t t1;
-
- /*
- * This function has never handled failure conditions properly
- * and should be deprecated. BoringSSL makes it return -2 on
- * failures, the OpenSSL version follows NULL pointers instead.
- */
- if (asn1_time_parse(s->data, s->length, &tm1, V_ASN1_UTCTIME) == -1)
- return (-2); /* XXX */
-
- if ((t1 = timegm(&tm1)) == -1)
- return (-2); /* XXX */
-
- if (t1 < t2)
- return (-1);
- if (t1 > t2)
- return (1);
- return (0);
-}
diff --git a/lib/libcrypto/asn1/asn1_locl.h b/lib/libcrypto/asn1/asn1_locl.h
index d4994c7cee5..9b612c81832 100644
--- a/lib/libcrypto/asn1/asn1_locl.h
+++ b/lib/libcrypto/asn1/asn1_locl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: asn1_locl.h,v 1.6 2015/10/02 15:04:45 beck Exp $ */
+/* $OpenBSD: asn1_locl.h,v 1.7 2015/10/19 16:32:37 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@@ -58,10 +58,6 @@
/* 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/libcrypto/x509/x509_lcl.h b/lib/libcrypto/x509/x509_lcl.h
index 0c1c130d5c8..9ffdd01e61c 100644
--- a/lib/libcrypto/x509/x509_lcl.h
+++ b/lib/libcrypto/x509/x509_lcl.h
@@ -58,3 +58,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);
+int asn1_tm_cmp(struct tm *tm1, struct tm *tm2);
diff --git a/lib/libcrypto/x509/x509_vfy.c b/lib/libcrypto/x509/x509_vfy.c
index c48143f3517..159d60b0348 100644
--- a/lib/libcrypto/x509/x509_vfy.c
+++ b/lib/libcrypto/x509/x509_vfy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_vfy.c,v 1.46 2015/10/02 15:04:45 beck Exp $ */
+/* $OpenBSD: x509_vfy.c,v 1.47 2015/10/19 16:32:37 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -1648,8 +1648,9 @@ int
X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
{
time_t time1, time2;
- struct tm tm1;
+ struct tm tm1, tm2;
int ret = 0;
+ int type;
if (cmp_time == NULL)
time2 = time(NULL);
@@ -1658,9 +1659,15 @@ X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
memset(&tm1, 0, sizeof(tm1));
- if (asn1_time_parse(ctm->data, ctm->length, &tm1, 0) == -1)
+ if ((type = asn1_time_parse(ctm->data, ctm->length, &tm1, 0)) == -1)
goto out; /* invalid time */
+ /* RFC 5280 section 4.1.2.5 */
+ if (tm1.tm_year < 150 && type != V_ASN1_UTCTIME)
+ goto out;
+ if (tm1.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
+ goto out;
+
/*
* 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
@@ -1669,10 +1676,12 @@ X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
if ((time1 = timegm(&tm1)) == -1)
goto out;
- if (time1 <= time2)
- ret = -1;
- else
- ret = 1;
+ if (gmtime_r(&time2, &tm2) == NULL)
+ goto out;
+
+ ret = asn1_tm_cmp(&tm1, &tm2);
+ if (ret == 0)
+ ret = -1; /* 0 is used for error, so map same to less than */
out:
return (ret);
}
@@ -1684,28 +1693,20 @@ X509_gmtime_adj(ASN1_TIME *s, long adj)
}
ASN1_TIME *
-X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
+X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_time)
{
- return X509_time_adj_ex(s, 0, offset_sec, in_tm);
+ return X509_time_adj_ex(s, 0, offset_sec, in_time);
}
ASN1_TIME *
-X509_time_adj_ex(ASN1_TIME *s, int offset_day, long offset_sec, time_t *in_tm)
+X509_time_adj_ex(ASN1_TIME *s, int offset_day, long offset_sec, time_t *in_time)
{
time_t t;
-
- if (in_tm)
- t = *in_tm;
+ if (in_time == NULL)
+ t = time(NULL);
else
- time(&t);
-
- if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) {
- if (s->type == V_ASN1_UTCTIME)
- return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
- if (s->type == V_ASN1_GENERALIZEDTIME)
- return ASN1_GENERALIZEDTIME_adj(s, t, offset_day,
- offset_sec);
- }
+ t = *in_time;
+
return ASN1_TIME_adj(s, t, offset_day, offset_sec);
}