Add new time manipulation funcitons that OpenSSL has exposed that
authorbeck <beck@openbsd.org>
Mon, 27 Jun 2022 13:54:57 +0000 (13:54 +0000)
committerbeck <beck@openbsd.org>
Mon, 27 Jun 2022 13:54:57 +0000 (13:54 +0000)
the world seems to be using.

Symbols.list changes and exposure to wait for minor bump

ok jsing@ jca@

lib/libcrypto/asn1/a_time.c
lib/libcrypto/asn1/a_time_tm.c
lib/libcrypto/asn1/asn1.h
regress/lib/libcrypto/asn1/asn1time.c

index cd6a790..03311e1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_time.c,v 1.33 2021/12/25 07:48:09 jsing Exp $ */
+/* $OpenBSD: a_time.c,v 1.34 2022/06/27 13:54:57 beck Exp $ */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
  *
@@ -92,8 +92,7 @@ ASN1_TIME_free(ASN1_TIME *a)
        ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it);
 }
 
-/* Public API in OpenSSL. Kept internal for now. */
-static int
+int
 ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
 {
        time_t now;
index 0e040ae..23e2ce4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_time_tm.c,v 1.20 2022/04/28 17:31:29 tb Exp $ */
+/* $OpenBSD: a_time_tm.c,v 1.21 2022/06/27 13:54:57 beck Exp $ */
 /*
  * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
  *
@@ -379,6 +379,61 @@ ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
        return (ASN1_TIME_set_string_internal(s, str, 0));
 }
 
+static int
+ASN1_TIME_cmp_time_t_internal(const ASN1_TIME *s, time_t t2, int mode)
+{
+       struct tm tm1, tm2;
+
+       /*
+        * This function has never handled failure conditions properly
+        * 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 s < t2. Callers must be careful. Sadly this is
+        * one of those pervasive things from OpenSSL we must continue with.
+        */
+
+       if (ASN1_time_parse(s->data, s->length, &tm1, mode) == -1)
+               return -2;
+
+       if (gmtime_r(&t2, &tm2) == NULL)
+               return -2;
+
+       return ASN1_time_tm_cmp(&tm1, &tm2);
+}
+
+int
+ASN1_TIME_compare(const ASN1_TIME *t1, const ASN1_TIME *t2)
+{
+       struct tm tm1, tm2;
+
+       if (t1->type != V_ASN1_UTCTIME && t1->type != V_ASN1_GENERALIZEDTIME)
+               return -2;
+
+       if (t2->type != V_ASN1_UTCTIME && t2->type != V_ASN1_GENERALIZEDTIME)
+               return -2;
+
+       if (ASN1_time_parse(t1->data, t1->length, &tm1, t1->type) == -1)
+               return -2;
+
+       if (ASN1_time_parse(t1->data, t2->length, &tm2, t2->type) == -1)
+               return -2;
+
+       return ASN1_time_tm_cmp(&tm1, &tm2);
+}
+
+int
+ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
+{
+       if (s->type == V_ASN1_UTCTIME)
+               return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
+       if (s->type == V_ASN1_GENERALIZEDTIME)
+               return ASN1_TIME_cmp_time_t_internal(s, t,
+                   V_ASN1_GENERALIZEDTIME);
+       return -2;
+}
+
 /*
  * ASN1_UTCTIME wrappers
  */
@@ -413,26 +468,11 @@ ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
 }
 
 int
-ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t2)
+ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
 {
-       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_time_tm_cmp(&tm1, &tm2);
+       if (s->type == V_ASN1_UTCTIME)
+               return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
+       return -2;
 }
 
 /*
@@ -468,3 +508,19 @@ ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
        return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
            V_ASN1_GENERALIZEDTIME));
 }
+
+int
+ASN1_TIME_normalize(ASN1_TIME *t)
+{
+       struct tm tm;
+
+       if (!ASN1_TIME_to_tm(t, &tm))
+               return 0;
+       return tm_to_rfc5280_time(&tm, t) != NULL;
+}
+
+int
+ASN1_TIME_set_string_x509(ASN1_TIME *s, const char *str)
+{
+       return ASN1_TIME_set_string_internal(s, str, RFC5280);
+}
index 0db0b1d..3ff3f51 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: asn1.h,v 1.64 2022/06/25 16:15:18 jsing Exp $ */
+/* $OpenBSD: asn1.h,v 1.65 2022/06/27 13:54:57 beck Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -719,6 +719,13 @@ ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **a, const unsigned char **in, long len);
 int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **out);
 extern const ASN1_ITEM ASN1_TIME_it;
 
+#ifdef LIBRESSL_INTERNAL
+int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
+int ASN1_TIME_compare(const ASN1_TIME *t1, const ASN1_TIME *t2);
+int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t2);
+int ASN1_TIME_normalize(ASN1_TIME *t);
+int ASN1_TIME_set_string_x509(ASN1_TIME *time, const char *str);
+#endif
 int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from,
     const ASN1_TIME *to);
 
index 6bbbf39..d392792 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: asn1time.c,v 1.9 2021/12/09 16:31:33 jsing Exp $ */
+/* $OpenBSD: asn1time.c,v 1.10 2022/06/27 13:54:58 beck Exp $ */
 /*
  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
  *
@@ -217,6 +217,11 @@ asn1_invtime_test(int test_no, struct asn1_time_test *att)
                    "string '%s'\n", test_no, att->str);
                goto done;
        }
+       if (ASN1_TIME_set_string_x509(t, att->str) != 0) {
+               fprintf(stderr, "FAIL: test %i - successfully set x509 TIME "
+                   "string '%s'\n", test_no, att->str);
+               goto done;
+       }
 
        failure = 0;
 
@@ -357,7 +362,7 @@ asn1_utctime_test(int test_no, struct asn1_time_test *att)
 static int
 asn1_time_test(int test_no, struct asn1_time_test *att, int type)
 {
-       ASN1_TIME *t = NULL;
+       ASN1_TIME *t = NULL, *tx509 = NULL;
        int failure = 1;
 
        if (ASN1_TIME_set_string(NULL, att->str) != 1) {
@@ -369,6 +374,9 @@ asn1_time_test(int test_no, struct asn1_time_test *att, int type)
        if ((t = ASN1_TIME_new()) == NULL)
                goto done;
 
+       if ((tx509 = ASN1_TIME_new()) == NULL)
+               goto done;
+
        if (ASN1_TIME_set_string(t, att->str) != 1) {
                fprintf(stderr, "FAIL: test %i - failed to set string '%s'\n",
                    test_no, att->str);
@@ -381,11 +389,36 @@ asn1_time_test(int test_no, struct asn1_time_test *att, int type)
                goto done;
        }
 
+       if (ASN1_TIME_normalize(t) != 1) {
+               fprintf(stderr, "FAIL: test %i - failed to set normalize '%s'\n",
+                   test_no, att->str);
+               goto done;
+       }
+
+       if (ASN1_TIME_set_string_x509(tx509, t->data) != 1) {
+               fprintf(stderr, "FAIL: test %i - failed to set string X509 '%s'\n",
+                   test_no, t->data);
+               goto done;
+       }
+
+       if (t->type != tx509->type) {
+               fprintf(stderr, "FAIL: test %i - type %d, different from %d\n",
+                   test_no, t->type, tx509->type);
+               goto done;
+       }
+
+       if (ASN1_TIME_compare(t, tx509) != 0) {
+               fprintf(stderr, "FAIL: ASN1_TIME values differ!\n");
+               goto done;
+       }
+
+
        failure = 0;
 
  done:
 
        ASN1_TIME_free(t);
+       ASN1_TIME_free(tx509);
 
        return (failure);
 }