Stop supporing "legcay" time formats that OpenSSL supports. Rewrite the
authorbeck <beck@openbsd.org>
Mon, 19 Oct 2015 16:32:37 +0000 (16:32 +0000)
committerbeck <beck@openbsd.org>
Mon, 19 Oct 2015 16:32:37 +0000 (16:32 +0000)
utctime and gentime wrappers accordingly. Along with some other cleanup.
this also removes the need for timegm.
ok bcook@ sthen@ jsing@

15 files changed:
lib/libcrypto/asn1/a_gentm.c [deleted file]
lib/libcrypto/asn1/a_time.c
lib/libcrypto/asn1/a_time_tm.c
lib/libcrypto/asn1/a_utctm.c [deleted file]
lib/libcrypto/asn1/asn1_locl.h
lib/libcrypto/crypto/Makefile
lib/libcrypto/x509/x509_lcl.h
lib/libcrypto/x509/x509_vfy.c
lib/libssl/src/crypto/asn1/a_gentm.c [deleted file]
lib/libssl/src/crypto/asn1/a_time.c
lib/libssl/src/crypto/asn1/a_time_tm.c
lib/libssl/src/crypto/asn1/a_utctm.c [deleted file]
lib/libssl/src/crypto/asn1/asn1_locl.h
lib/libssl/src/crypto/x509/x509_lcl.h
lib/libssl/src/crypto/x509/x509_vfy.c

diff --git a/lib/libcrypto/asn1/a_gentm.c b/lib/libcrypto/asn1/a_gentm.c
deleted file mode 100644 (file)
index 594eb63..0000000
+++ /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;
-
-}
index a6c7c8e..7a3742f 100644 (file)
@@ -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;
-}
index 53443fa..352b915 100644 (file)
@@ -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>
 #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 (file)
index 495c497..0000000
+++ /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);
-}
index d4994c7..9b612c8 100644 (file)
@@ -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.
  */
 
 /* 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 {
index 64ee774..d662aec 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.66 2015/10/02 15:04:45 beck Exp $
+# $OpenBSD: Makefile,v 1.67 2015/10/19 16:32:37 beck Exp $
 
 LIB=   crypto
 
@@ -35,7 +35,7 @@ SRCS+= aes_misc.c aes_ecb.c aes_cfb.c aes_ofb.c
 SRCS+= aes_ctr.c aes_ige.c aes_wrap.c
 
 # asn1/
-SRCS+= a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c
+SRCS+= a_object.c a_bitstr.c a_time.c a_int.c a_octet.c
 SRCS+= a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c
 SRCS+= a_enum.c a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c
 SRCS+= x_algor.c x_val.c x_pubkey.c x_sig.c x_req.c x_attrib.c x_bignum.c
index 0c1c130..9ffdd01 100644 (file)
@@ -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);
index c48143f..159d60b 100644 (file)
@@ -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);
 }
 
diff --git a/lib/libssl/src/crypto/asn1/a_gentm.c b/lib/libssl/src/crypto/asn1/a_gentm.c
deleted file mode 100644 (file)
index 594eb63..0000000
+++ /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;
-
-}
index a6c7c8e..7a3742f 100644 (file)
@@ -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;
-}
index 53443fa..352b915 100644 (file)
@@ -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>
 #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/libssl/src/crypto/asn1/a_utctm.c b/lib/libssl/src/crypto/asn1/a_utctm.c
deleted file mode 100644 (file)
index 495c497..0000000
+++ /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);
-}
index d4994c7..9b612c8 100644 (file)
@@ -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.
  */
 
 /* 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 {
index 0c1c130..9ffdd01 100644 (file)
@@ -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);
index c48143f..159d60b 100644 (file)
@@ -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);
 }