xref: /openbsd-src/regress/lib/libcrypto/asn1/asn1time.c (revision 4fb9ab680e2b4d2af177cf6cbecece075cda4341)
1*4fb9ab68Stb /* $OpenBSD: asn1time.c,v 1.30 2024/07/21 13:25:11 tb Exp $ */
2ad33c0b7Sjsing /*
3ad33c0b7Sjsing  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4261a77c2Stb  * Copyright (c) 2024 Google Inc.
5ad33c0b7Sjsing  *
6ad33c0b7Sjsing  * Permission to use, copy, modify, and distribute this software for any
7ad33c0b7Sjsing  * purpose with or without fee is hereby granted, provided that the above
8ad33c0b7Sjsing  * copyright notice and this permission notice appear in all copies.
9ad33c0b7Sjsing  *
10ad33c0b7Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11ad33c0b7Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12ad33c0b7Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13ad33c0b7Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14ad33c0b7Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15ad33c0b7Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16ad33c0b7Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17ad33c0b7Sjsing  */
18ad33c0b7Sjsing 
19ad33c0b7Sjsing #include <openssl/asn1.h>
20261a77c2Stb #include <openssl/posix_time.h>
21ad33c0b7Sjsing 
22ad33c0b7Sjsing #include <err.h>
23261a77c2Stb #include <limits.h>
24ad33c0b7Sjsing #include <stdio.h>
25ad33c0b7Sjsing #include <string.h>
26ad33c0b7Sjsing 
27261a77c2Stb #include "asn1_local.h"
28261a77c2Stb 
294048fd87Stb int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
304048fd87Stb 
31ad33c0b7Sjsing struct asn1_time_test {
32ad33c0b7Sjsing 	const char *str;
33ad33c0b7Sjsing 	const char *data;
3448917c78Sjsing 	const unsigned char der[32];
35ad33c0b7Sjsing 	time_t time;
36ad33c0b7Sjsing };
37ad33c0b7Sjsing 
3806baaab8Stb static const struct asn1_time_test asn1_invtime_tests[] = {
39ad33c0b7Sjsing 	{
40ad33c0b7Sjsing 		.str = "",
41ad33c0b7Sjsing 	},
42ad33c0b7Sjsing 	{
43ad33c0b7Sjsing 		.str = "2015",
44ad33c0b7Sjsing 	},
45ad33c0b7Sjsing 	{
46ad33c0b7Sjsing 		.str = "201509",
47ad33c0b7Sjsing 	},
48ad33c0b7Sjsing 	{
49ad33c0b7Sjsing 		.str = "20150923",
50ad33c0b7Sjsing 	},
51ad33c0b7Sjsing 	{
52ad33c0b7Sjsing 		.str = "20150923032700",
53ad33c0b7Sjsing 	},
54ad33c0b7Sjsing 	{
55ad33c0b7Sjsing 		.str = "20150923032700.Z",
56ad33c0b7Sjsing 	},
57ad33c0b7Sjsing 	{
58ad33c0b7Sjsing 		.str = "20150923032700.123",
59ad33c0b7Sjsing 	},
60ad33c0b7Sjsing 	{
616055f875Sjsing 		.str = "20150923032700+1.09",
626055f875Sjsing 	},
636055f875Sjsing 	{
64ad33c0b7Sjsing 		.str = "20150923032700+1100Z",
65ad33c0b7Sjsing 	},
66ad33c0b7Sjsing 	{
67ad33c0b7Sjsing 		.str = "20150923032700-11001",
68ad33c0b7Sjsing 	},
69ad33c0b7Sjsing 	{
70ad33c0b7Sjsing 		/* UTC time cannot have fractional seconds. */
71ad33c0b7Sjsing 		.str = "150923032700.123Z",
72ad33c0b7Sjsing 	},
73ad33c0b7Sjsing 	{
74ad33c0b7Sjsing 		.str = "aaaaaaaaaaaaaaZ",
75ad33c0b7Sjsing 	},
7625b449edSbeck 	/* utc time with omitted seconds, should fail */
7725b449edSbeck 	{
7825b449edSbeck 		.str = "1609082343Z",
7925b449edSbeck 	},
8025b449edSbeck };
8125b449edSbeck 
8206baaab8Stb static const struct asn1_time_test asn1_invgentime_tests[] = {
8325b449edSbeck 	/* Generalized time with omitted seconds, should fail */
8425b449edSbeck 	{
8525b449edSbeck 		.str = "201612081934Z",
8625b449edSbeck 	},
8731c2cd2bSbeck 	/* Valid UTC time, should fail as a generalized time */
8831c2cd2bSbeck 	{
8931c2cd2bSbeck 		.str = "160908234300Z",
9031c2cd2bSbeck 	},
9125b449edSbeck };
9225b449edSbeck 
9306baaab8Stb static const struct asn1_time_test asn1_gentime_tests[] = {
94ad33c0b7Sjsing 	{
9599ec6bffSbeck 		.str = "20161208193400Z",
9699ec6bffSbeck 		.data = "20161208193400Z",
9799ec6bffSbeck 		.time = 1481225640,
9899ec6bffSbeck 		.der = {
9999ec6bffSbeck 			0x18, 0x0f, 0x32, 0x30, 0x31, 0x36, 0x31, 0x32,
10099ec6bffSbeck 			0x30, 0x38, 0x31, 0x39, 0x33, 0x34, 0x30, 0x30,
10199ec6bffSbeck 			0x5a,
10299ec6bffSbeck 		},
10399ec6bffSbeck 	},
10499ec6bffSbeck 	{
105ad33c0b7Sjsing 		.str = "19700101000000Z",
106ad33c0b7Sjsing 		.data = "19700101000000Z",
107ad33c0b7Sjsing 		.time = 0,
10848917c78Sjsing 		.der = {
10948917c78Sjsing 			0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31,
11048917c78Sjsing 			0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
11148917c78Sjsing 			0x5a,
11248917c78Sjsing 		},
113ad33c0b7Sjsing 	},
114ad33c0b7Sjsing 	{
115ad33c0b7Sjsing 		.str = "20150923032700Z",
116ad33c0b7Sjsing 		.data = "20150923032700Z",
117ad33c0b7Sjsing 		.time = 1442978820,
11848917c78Sjsing 		.der = {
11948917c78Sjsing 			0x18, 0x0f, 0x32, 0x30, 0x31, 0x35, 0x30, 0x39,
12048917c78Sjsing 			0x32, 0x33, 0x30, 0x33, 0x32, 0x37, 0x30, 0x30,
12148917c78Sjsing 			0x5a,
12248917c78Sjsing 		},
123ad33c0b7Sjsing 	},
124b0131f08Stb 	{
125b0131f08Stb 		/* 1 second after the 32-bit epoch wraps. */
126b0131f08Stb 		.str = "20380119031408Z",
127b0131f08Stb 		.data = "20380119031408Z",
128b0131f08Stb 		.time = 2147483648LL,
129b0131f08Stb 		.der = {
130b0131f08Stb 			0x18, 0x0f, 0x32, 0x30, 0x33, 0x38, 0x30, 0x31,
131b0131f08Stb 			0x31, 0x39, 0x30, 0x33, 0x31, 0x34, 0x30, 0x38,
132b0131f08Stb 			0x5a,
133b0131f08Stb 		},
134b0131f08Stb 
135b0131f08Stb 	},
136ad33c0b7Sjsing };
137ad33c0b7Sjsing 
13806baaab8Stb static const struct asn1_time_test asn1_utctime_tests[] = {
139ad33c0b7Sjsing 	{
1406c4452d7Sbeck 		.str = "700101000000Z",
141ad33c0b7Sjsing 		.data = "700101000000Z",
142ad33c0b7Sjsing 		.time = 0,
14348917c78Sjsing 		.der = {
1446c4452d7Sbeck 			0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31,
1456c4452d7Sbeck 			0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
14648917c78Sjsing 		},
147ad33c0b7Sjsing 	},
148ad33c0b7Sjsing 	{
149ad33c0b7Sjsing 		.str = "150923032700Z",
150ad33c0b7Sjsing 		.data = "150923032700Z",
151ad33c0b7Sjsing 		.time = 1442978820,
15248917c78Sjsing 		.der = {
15348917c78Sjsing 			0x17, 0x0d, 0x31, 0x35, 0x30, 0x39, 0x32, 0x33,
15448917c78Sjsing 			0x30, 0x33, 0x32, 0x37, 0x30, 0x30, 0x5a,
15548917c78Sjsing 		},
156ad33c0b7Sjsing 	},
157ad33c0b7Sjsing 	{
15848917c78Sjsing 		.str = "140524144512Z",
15948917c78Sjsing 		.data = "140524144512Z",
16048917c78Sjsing 		.time = 1400942712,
16148917c78Sjsing 		.der = {
16248917c78Sjsing 			0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x34,
16348917c78Sjsing 			0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a,
16448917c78Sjsing 		},
16548917c78Sjsing 	},
16648917c78Sjsing 	{
16748917c78Sjsing 		.str = "240401144512Z",
16848917c78Sjsing 		.data = "240401144512Z",
16948917c78Sjsing 		.time = 1711982712,
17048917c78Sjsing 		.der = {
17148917c78Sjsing 			0x17, 0x0d, 0x32, 0x34, 0x30, 0x34, 0x30, 0x31,
17248917c78Sjsing 			0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a
17348917c78Sjsing 		},
174ad33c0b7Sjsing 	},
175ad33c0b7Sjsing };
176ad33c0b7Sjsing 
177ad33c0b7Sjsing #define N_INVTIME_TESTS \
178ad33c0b7Sjsing     (sizeof(asn1_invtime_tests) / sizeof(*asn1_invtime_tests))
17925b449edSbeck #define N_INVGENTIME_TESTS \
18025b449edSbeck     (sizeof(asn1_invgentime_tests) / sizeof(*asn1_invgentime_tests))
181ad33c0b7Sjsing #define N_GENTIME_TESTS \
182ad33c0b7Sjsing     (sizeof(asn1_gentime_tests) / sizeof(*asn1_gentime_tests))
183ad33c0b7Sjsing #define N_UTCTIME_TESTS \
184ad33c0b7Sjsing     (sizeof(asn1_utctime_tests) / sizeof(*asn1_utctime_tests))
185ad33c0b7Sjsing 
18648917c78Sjsing static void
18748917c78Sjsing hexdump(const unsigned char *buf, size_t len)
18848917c78Sjsing {
18948917c78Sjsing 	size_t i;
19048917c78Sjsing 
19148917c78Sjsing 	for (i = 1; i <= len; i++)
19248917c78Sjsing 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
19348917c78Sjsing 
19448917c78Sjsing 	fprintf(stderr, "\n");
19548917c78Sjsing }
19648917c78Sjsing 
19748917c78Sjsing static int
19848917c78Sjsing asn1_compare_bytes(int test_no, const unsigned char *d1,
19948917c78Sjsing     const unsigned char *d2, int len1, int len2)
20048917c78Sjsing {
20148917c78Sjsing 	if (len1 != len2) {
2027bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - byte lengths differ "
2037bb1a6cfStb 		    "(%d != %d)\n", test_no, len1, len2);
20448917c78Sjsing 		return (1);
20548917c78Sjsing 	}
20648917c78Sjsing 	if (memcmp(d1, d2, len1) != 0) {
2077bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - bytes differ\n", test_no);
20848917c78Sjsing 		fprintf(stderr, "Got:\n");
20948917c78Sjsing 		hexdump(d1, len1);
21048917c78Sjsing 		fprintf(stderr, "Want:\n");
21148917c78Sjsing 		hexdump(d2, len2);
212e85f2c97Sjsing 		return (1);
21348917c78Sjsing 	}
21448917c78Sjsing 	return (0);
21548917c78Sjsing }
21648917c78Sjsing 
21748917c78Sjsing static int
21806baaab8Stb asn1_compare_str(int test_no, const struct asn1_string_st *asn1str,
21906baaab8Stb     const char *str)
22048917c78Sjsing {
22148917c78Sjsing 	int length = strlen(str);
22248917c78Sjsing 
22348917c78Sjsing 	if (asn1str->length != length) {
2247bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - string lengths differ "
2257bb1a6cfStb 		    "(%d != %d)\n", test_no, asn1str->length, length);
22648917c78Sjsing 		return (1);
22748917c78Sjsing 	}
22848917c78Sjsing 	if (strncmp(asn1str->data, str, length) != 0) {
2297bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - strings differ "
23048917c78Sjsing 		    "('%s' != '%s')\n", test_no, asn1str->data, str);
23148917c78Sjsing 		return (1);
23248917c78Sjsing 	}
23348917c78Sjsing 
23448917c78Sjsing 	return (0);
23548917c78Sjsing }
23648917c78Sjsing 
237ad33c0b7Sjsing static int
23806baaab8Stb asn1_invtime_test(int test_no, const struct asn1_time_test *att, int gen)
239ad33c0b7Sjsing {
240ad33c0b7Sjsing 	ASN1_GENERALIZEDTIME *gt = NULL;
241ad33c0b7Sjsing 	ASN1_UTCTIME *ut = NULL;
242ad33c0b7Sjsing 	ASN1_TIME *t = NULL;
243ad33c0b7Sjsing 	int failure = 1;
244ad33c0b7Sjsing 
245ad33c0b7Sjsing 	if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
246ad33c0b7Sjsing 		goto done;
247ad33c0b7Sjsing 	if ((ut = ASN1_UTCTIME_new()) == NULL)
248ad33c0b7Sjsing 		goto done;
249ad33c0b7Sjsing 	if ((t = ASN1_TIME_new()) == NULL)
250ad33c0b7Sjsing 		goto done;
251ad33c0b7Sjsing 
252ad33c0b7Sjsing 	if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 0) {
2537bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - successfully set "
254ad33c0b7Sjsing 		    "GENERALIZEDTIME string '%s'\n", test_no, att->str);
255ad33c0b7Sjsing 		goto done;
256ad33c0b7Sjsing 	}
25725b449edSbeck 
25825b449edSbeck 	if (gen)  {
25925b449edSbeck 		failure = 0;
26025b449edSbeck 		goto done;
26125b449edSbeck 	}
26225b449edSbeck 
263ad33c0b7Sjsing 	if (ASN1_UTCTIME_set_string(ut, att->str) != 0) {
2647bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - successfully set UTCTIME "
265ad33c0b7Sjsing 		    "string '%s'\n", test_no, att->str);
266ad33c0b7Sjsing 		goto done;
267ad33c0b7Sjsing 	}
2687265076cSjsing 	if (ASN1_TIME_set_string(t, att->str) != 0) {
2697bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - successfully set TIME "
270ad33c0b7Sjsing 		    "string '%s'\n", test_no, att->str);
271ad33c0b7Sjsing 		goto done;
272ad33c0b7Sjsing 	}
27398f696c2Santon 	if (ASN1_TIME_set_string_X509(t, att->str) != 0) {
2747bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - successfully set x509 TIME "
275b680683fSbeck 		    "string '%s'\n", test_no, att->str);
276b680683fSbeck 		goto done;
277b680683fSbeck 	}
278ad33c0b7Sjsing 
279ad33c0b7Sjsing 	failure = 0;
280ad33c0b7Sjsing 
281ad33c0b7Sjsing  done:
282ad33c0b7Sjsing 	ASN1_GENERALIZEDTIME_free(gt);
283ad33c0b7Sjsing 	ASN1_UTCTIME_free(ut);
284ad33c0b7Sjsing 	ASN1_TIME_free(t);
285ad33c0b7Sjsing 
286ad33c0b7Sjsing 	return (failure);
287ad33c0b7Sjsing }
288ad33c0b7Sjsing 
289ad33c0b7Sjsing static int
29006baaab8Stb asn1_gentime_test(int test_no, const struct asn1_time_test *att)
291ad33c0b7Sjsing {
29248917c78Sjsing 	const unsigned char *der;
29348917c78Sjsing 	unsigned char *p = NULL;
2943f55748cSbcook 	ASN1_GENERALIZEDTIME *gt = NULL;
295b0131f08Stb 	time_t t;
296ad33c0b7Sjsing 	int failure = 1;
29748917c78Sjsing 	int len;
29899ec6bffSbeck 	struct tm tm;
299ad33c0b7Sjsing 
300986aa51eSjsing 	if (ASN1_GENERALIZEDTIME_set_string(NULL, att->str) != 1) {
3017bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
302986aa51eSjsing 		    test_no, att->str);
303986aa51eSjsing 		goto done;
304986aa51eSjsing 	}
305986aa51eSjsing 
306ad33c0b7Sjsing 	if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
307ad33c0b7Sjsing 		goto done;
308ad33c0b7Sjsing 
309ad33c0b7Sjsing 	if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 1) {
3107bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
311ad33c0b7Sjsing 		    test_no, att->str);
312ad33c0b7Sjsing 		goto done;
313ad33c0b7Sjsing 	}
31448917c78Sjsing 	if (asn1_compare_str(test_no, gt, att->str) != 0)
31548917c78Sjsing 		goto done;
316ad33c0b7Sjsing 
31799ec6bffSbeck 	if (ASN1_TIME_to_tm(gt, &tm) == 0)  {
3187bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - ASN1_time_to_tm failed '%s'\n",
31999ec6bffSbeck 		    test_no, att->str);
32099ec6bffSbeck 		goto done;
32199ec6bffSbeck 	}
32299ec6bffSbeck 
323b0131f08Stb 	if (!OPENSSL_timegm(&tm, &t)) {
32499ec6bffSbeck 		/* things with crappy time_t should die in fire */
325b0131f08Stb 		fprintf(stderr, "FAIL: test %d - OPENSSL_timegm failed\n",
326b0131f08Stb 		    test_no);
327b0131f08Stb 	}
328b0131f08Stb 
329b0131f08Stb 	if (t != att->time) {
330b0131f08Stb 		/* things with crappy time_t should die in fire */
331b0131f08Stb 		int64_t a = t, b = att->time;
332b0131f08Stb 
333b0131f08Stb 		fprintf(stderr, "FAIL: test %d - times don't match, "
334b0131f08Stb 		    "expected %lld got %lld\n",
335ff076c1bStb 		    test_no, (long long)b, (long long)a);
33699ec6bffSbeck 		goto done;
33799ec6bffSbeck 	}
33899ec6bffSbeck 
33948917c78Sjsing 	if ((len = i2d_ASN1_GENERALIZEDTIME(gt, &p)) <= 0) {
3407bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - i2d_ASN1_GENERALIZEDTIME "
34148917c78Sjsing 		    "failed\n", test_no);
342ad33c0b7Sjsing 		goto done;
343ad33c0b7Sjsing 	}
34448917c78Sjsing 	der = att->der;
34548917c78Sjsing 	if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0)
34648917c78Sjsing 		goto done;
34748917c78Sjsing 
34848917c78Sjsing 	len = strlen(att->der);
34948917c78Sjsing 	if (d2i_ASN1_GENERALIZEDTIME(&gt, &der, len) == NULL) {
3507bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - d2i_ASN1_GENERALIZEDTIME "
35148917c78Sjsing 		    "failed\n", test_no);
352ad33c0b7Sjsing 		goto done;
353ad33c0b7Sjsing 	}
35448917c78Sjsing 	if (asn1_compare_str(test_no, gt, att->str) != 0)
35548917c78Sjsing 		goto done;
356ad33c0b7Sjsing 
357ad33c0b7Sjsing 	ASN1_GENERALIZEDTIME_free(gt);
358ad33c0b7Sjsing 
359ad33c0b7Sjsing 	if ((gt = ASN1_GENERALIZEDTIME_set(NULL, att->time)) == NULL) {
3607bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set time %lld\n",
361ad33c0b7Sjsing 		    test_no, (long long)att->time);
362ad33c0b7Sjsing 		goto done;
363ad33c0b7Sjsing 	}
36448917c78Sjsing 	if (asn1_compare_str(test_no, gt, att->data) != 0)
365ad33c0b7Sjsing 		goto done;
366ad33c0b7Sjsing 
367ad33c0b7Sjsing 	failure = 0;
368ad33c0b7Sjsing 
369ad33c0b7Sjsing  done:
370ad33c0b7Sjsing 	ASN1_GENERALIZEDTIME_free(gt);
37148917c78Sjsing 	free(p);
372ad33c0b7Sjsing 
373ad33c0b7Sjsing 	return (failure);
374ad33c0b7Sjsing }
375ad33c0b7Sjsing 
376ad33c0b7Sjsing static int
37706baaab8Stb asn1_utctime_test(int test_no, const struct asn1_time_test *att)
378ad33c0b7Sjsing {
37948917c78Sjsing 	const unsigned char *der;
38048917c78Sjsing 	unsigned char *p = NULL;
381c1eeab68Smiod 	ASN1_UTCTIME *ut = NULL;
382ad33c0b7Sjsing 	int failure = 1;
38348917c78Sjsing 	int len;
384ad33c0b7Sjsing 
385986aa51eSjsing 	if (ASN1_UTCTIME_set_string(NULL, att->str) != 1) {
3867bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
387986aa51eSjsing 		    test_no, att->str);
388986aa51eSjsing 		goto done;
389986aa51eSjsing 	}
390986aa51eSjsing 
391ad33c0b7Sjsing 	if ((ut = ASN1_UTCTIME_new()) == NULL)
392ad33c0b7Sjsing 		goto done;
393ad33c0b7Sjsing 
394ad33c0b7Sjsing 	if (ASN1_UTCTIME_set_string(ut, att->str) != 1) {
3957bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
396ad33c0b7Sjsing 		    test_no, att->str);
397ad33c0b7Sjsing 		goto done;
398ad33c0b7Sjsing 	}
39948917c78Sjsing 	if (asn1_compare_str(test_no, ut, att->str) != 0)
40048917c78Sjsing 		goto done;
401ad33c0b7Sjsing 
40248917c78Sjsing 	if ((len = i2d_ASN1_UTCTIME(ut, &p)) <= 0) {
4037bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - i2d_ASN1_UTCTIME failed\n",
40448917c78Sjsing 		    test_no);
405ad33c0b7Sjsing 		goto done;
406ad33c0b7Sjsing 	}
40748917c78Sjsing 	der = att->der;
40848917c78Sjsing 	if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0)
40948917c78Sjsing 		goto done;
41048917c78Sjsing 
41148917c78Sjsing 	len = strlen(att->der);
41248917c78Sjsing 	if (d2i_ASN1_UTCTIME(&ut, &der, len) == NULL) {
4137bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - d2i_ASN1_UTCTIME failed\n",
41448917c78Sjsing 		    test_no);
415ad33c0b7Sjsing 		goto done;
416ad33c0b7Sjsing 	}
41748917c78Sjsing 	if (asn1_compare_str(test_no, ut, att->str) != 0)
41848917c78Sjsing 		goto done;
419ad33c0b7Sjsing 
420ad33c0b7Sjsing 	ASN1_UTCTIME_free(ut);
421ad33c0b7Sjsing 
422ad33c0b7Sjsing 	if ((ut = ASN1_UTCTIME_set(NULL, att->time)) == NULL) {
4237bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set time %lld\n",
424ad33c0b7Sjsing 		    test_no, (long long)att->time);
425ad33c0b7Sjsing 		goto done;
426ad33c0b7Sjsing 	}
42748917c78Sjsing 	if (asn1_compare_str(test_no, ut, att->data) != 0)
428ad33c0b7Sjsing 		goto done;
429ad33c0b7Sjsing 
430ad33c0b7Sjsing 	failure = 0;
431ad33c0b7Sjsing 
432ad33c0b7Sjsing  done:
433ad33c0b7Sjsing 	ASN1_UTCTIME_free(ut);
43448917c78Sjsing 	free(p);
435ad33c0b7Sjsing 
436ad33c0b7Sjsing 	return (failure);
437ad33c0b7Sjsing }
438ad33c0b7Sjsing 
439ad33c0b7Sjsing static int
44006baaab8Stb asn1_time_test(int test_no, const struct asn1_time_test *att, int type)
441ad33c0b7Sjsing {
442b680683fSbeck 	ASN1_TIME *t = NULL, *tx509 = NULL;
44372c7c57aSbeck 	char *parsed_time = NULL;
444ad33c0b7Sjsing 	int failure = 1;
445ad33c0b7Sjsing 
446986aa51eSjsing 	if (ASN1_TIME_set_string(NULL, att->str) != 1) {
4477bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
448986aa51eSjsing 		    test_no, att->str);
449986aa51eSjsing 		goto done;
450986aa51eSjsing 	}
451986aa51eSjsing 
452ad33c0b7Sjsing 	if ((t = ASN1_TIME_new()) == NULL)
453ad33c0b7Sjsing 		goto done;
454ad33c0b7Sjsing 
455b680683fSbeck 	if ((tx509 = ASN1_TIME_new()) == NULL)
456b680683fSbeck 		goto done;
457b680683fSbeck 
45872c7c57aSbeck 	switch (strlen(att->str)) {
45972c7c57aSbeck 	case 13:
46072c7c57aSbeck 		t->type = V_ASN1_UTCTIME;
46172c7c57aSbeck 		if (ASN1_UTCTIME_set_string(t, att->str) != 1) {
46272c7c57aSbeck 			fprintf(stderr, "FAIL: test %d - failed to set utc "
46372c7c57aSbeck 			    "string '%s'\n",
464ad33c0b7Sjsing 			    test_no, att->str);
465ad33c0b7Sjsing 			goto done;
466ad33c0b7Sjsing 		}
46772c7c57aSbeck 		break;
46872c7c57aSbeck 	case 15:
46972c7c57aSbeck 		t->type = V_ASN1_GENERALIZEDTIME;
47072c7c57aSbeck 		if (ASN1_GENERALIZEDTIME_set_string(t, att->str) != 1) {
47172c7c57aSbeck 			fprintf(stderr, "FAIL: test %d - failed to set gen "
47272c7c57aSbeck 			    "string '%s'\n",
47372c7c57aSbeck 			    test_no, att->str);
47472c7c57aSbeck 			goto done;
47572c7c57aSbeck 		}
47672c7c57aSbeck 		break;
47772c7c57aSbeck 	default:
47872c7c57aSbeck 		fprintf(stderr, "FAIL: unknown type\n");
47972c7c57aSbeck 		goto done;
48072c7c57aSbeck 	}
481ad33c0b7Sjsing 
482ad33c0b7Sjsing 	if (t->type != type) {
4837bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - got type %d, want %d\n",
484ad33c0b7Sjsing 		    test_no, t->type, type);
485ad33c0b7Sjsing 		goto done;
486ad33c0b7Sjsing 	}
487ad33c0b7Sjsing 
48872c7c57aSbeck 	if ((parsed_time = strdup(t->data)) == NULL)
48972c7c57aSbeck 		goto done;
49072c7c57aSbeck 
491b680683fSbeck 	if (ASN1_TIME_normalize(t) != 1) {
4927bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set normalize '%s'\n",
493b680683fSbeck 		    test_no, att->str);
494b680683fSbeck 		goto done;
495b680683fSbeck 	}
496b680683fSbeck 
49772c7c57aSbeck 	if (ASN1_TIME_set_string_X509(tx509, parsed_time) != 1) {
49872c7c57aSbeck 		fprintf(stderr, "FAIL: test %d - failed to set string X509 '%s'\n",
49972c7c57aSbeck 		    test_no, t->data);
50072c7c57aSbeck 		goto done;
50172c7c57aSbeck 	}
50272c7c57aSbeck 
50372c7c57aSbeck 	if (t->type != tx509->type) {
50472c7c57aSbeck 		fprintf(stderr, "FAIL: test %d - type %d, different from %d\n",
50572c7c57aSbeck 		    test_no, t->type, tx509->type);
50672c7c57aSbeck 		goto done;
50772c7c57aSbeck 	}
50872c7c57aSbeck 
50972c7c57aSbeck 	if (ASN1_TIME_compare(t, tx509) != 0) {
51072c7c57aSbeck 		fprintf(stderr, "FAIL: ASN1_TIME values differ!\n");
51172c7c57aSbeck 		goto done;
51272c7c57aSbeck 	}
51372c7c57aSbeck 
51472c7c57aSbeck 	if (ASN1_TIME_set_string(tx509, parsed_time) != 1) {
5157bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - failed to set string X509 '%s'\n",
516b680683fSbeck 		    test_no, t->data);
517b680683fSbeck 		goto done;
518b680683fSbeck 	}
519b680683fSbeck 
520b680683fSbeck 	if (t->type != tx509->type) {
5217bb1a6cfStb 		fprintf(stderr, "FAIL: test %d - type %d, different from %d\n",
522b680683fSbeck 		    test_no, t->type, tx509->type);
523b680683fSbeck 		goto done;
524b680683fSbeck 	}
525b680683fSbeck 
526b680683fSbeck 	if (ASN1_TIME_compare(t, tx509) != 0) {
527b680683fSbeck 		fprintf(stderr, "FAIL: ASN1_TIME values differ!\n");
528b680683fSbeck 		goto done;
529b680683fSbeck 	}
530b680683fSbeck 
531b680683fSbeck 
532ad33c0b7Sjsing 	failure = 0;
533ad33c0b7Sjsing 
534ad33c0b7Sjsing  done:
535ad33c0b7Sjsing 
536ad33c0b7Sjsing 	ASN1_TIME_free(t);
537b680683fSbeck 	ASN1_TIME_free(tx509);
53872c7c57aSbeck 	free(parsed_time);
539ad33c0b7Sjsing 
540ad33c0b7Sjsing 	return (failure);
541ad33c0b7Sjsing }
542ad33c0b7Sjsing 
54319426056Stb static int
54419426056Stb time_t_cmp(time_t t1, time_t t2)
54519426056Stb {
54619426056Stb 	if (t1 < t2)
54719426056Stb 		return -1;
54819426056Stb 	if (t2 < t1)
54919426056Stb 		return 1;
55019426056Stb 	return 0;
55119426056Stb }
55219426056Stb 
55319426056Stb static int
55419426056Stb asn1_time_compare_families(const struct asn1_time_test *fam1, size_t fam1_size,
55519426056Stb     const struct asn1_time_test *fam2, size_t fam2_size)
55619426056Stb {
55719426056Stb 	const struct asn1_time_test *att1, *att2;
55819426056Stb 	ASN1_TIME *t1 = NULL, *t2 = NULL;
55919426056Stb 	size_t i, j;
56019426056Stb 	int asn1_cmp, time_cmp;
56119426056Stb 	int comparison_failure = 0;
56219426056Stb 	int failure = 1;
56319426056Stb 
56419426056Stb 	if ((t1 = ASN1_TIME_new()) == NULL)
56519426056Stb 		goto done;
56619426056Stb 	if ((t2 = ASN1_TIME_new()) == NULL)
56719426056Stb 		goto done;
56819426056Stb 
56919426056Stb 	for (i = 0; i < fam1_size; i++) {
57019426056Stb 		att1 = &fam1[i];
57119426056Stb 
57219426056Stb 		if (!ASN1_TIME_set_string(t1, att1->str))
57319426056Stb 			goto done;
57419426056Stb 		for (j = 0; j < fam2_size; j++) {
57519426056Stb 			att2 = &fam2[j];
57619426056Stb 
57719426056Stb 			if (!ASN1_TIME_set_string(t2, att2->str))
57819426056Stb 				goto done;
57919426056Stb 
58019426056Stb 			time_cmp = time_t_cmp(att1->time, att2->time);
58119426056Stb 			asn1_cmp = ASN1_TIME_compare(t1, t2);
58219426056Stb 
58319426056Stb 			if (time_cmp != asn1_cmp) {
584*4fb9ab68Stb 				fprintf(stderr, "ASN1_TIME_compare - %s vs. %s: "
585*4fb9ab68Stb 				    "want %d, got %d\n",
58619426056Stb 				    att1->str, att2->str, time_cmp, asn1_cmp);
58719426056Stb 				comparison_failure |= 1;
58819426056Stb 			}
589a1d6a9e3Stb 
590a1d6a9e3Stb 			time_cmp = ASN1_TIME_cmp_time_t(t1, att2->time);
591a1d6a9e3Stb 			if (time_cmp != asn1_cmp) {
592*4fb9ab68Stb 				fprintf(stderr, "ASN1_TIME_cmp_time_t - %s vs. %lld: "
593*4fb9ab68Stb 				    "want %d, got %d\n",
594a1d6a9e3Stb 				    att1->str, (long long)att2->time,
595a1d6a9e3Stb 				    asn1_cmp, time_cmp);
596a1d6a9e3Stb 				comparison_failure |= 1;
597a1d6a9e3Stb 			}
598a1d6a9e3Stb 
5994048fd87Stb 			time_cmp = ASN1_UTCTIME_cmp_time_t(t1, att2->time);
6004048fd87Stb 			if (t1->type != V_ASN1_UTCTIME)
6014048fd87Stb 				asn1_cmp = -2;
6024048fd87Stb 			if (time_cmp != asn1_cmp) {
603*4fb9ab68Stb 				fprintf(stderr, "ASN1_UTCTIME_cmp_time_t - %s vs. %lld: "
604*4fb9ab68Stb 				    "want %d, got %d\n",
6054048fd87Stb 				    att1->str, (long long)att2->time,
6064048fd87Stb 				    asn1_cmp, time_cmp);
6074048fd87Stb 				comparison_failure |= 1;
6084048fd87Stb 			}
60919426056Stb 		}
61019426056Stb 	}
61119426056Stb 
61219426056Stb 	failure = comparison_failure;
61319426056Stb 
61419426056Stb  done:
61519426056Stb 	ASN1_TIME_free(t1);
61619426056Stb 	ASN1_TIME_free(t2);
61719426056Stb 
61819426056Stb 	return failure;
61919426056Stb }
62019426056Stb 
62119426056Stb static int
62219426056Stb asn1_time_compare_test(void)
62319426056Stb {
62419426056Stb 	const struct asn1_time_test *gen = asn1_gentime_tests;
62519426056Stb 	size_t gen_size = N_GENTIME_TESTS;
62619426056Stb 	const struct asn1_time_test *utc = asn1_utctime_tests;
62719426056Stb 	size_t utc_size = N_UTCTIME_TESTS;
62819426056Stb 	int failed = 0;
62919426056Stb 
63019426056Stb 	failed |= asn1_time_compare_families(gen, gen_size, gen, gen_size);
63119426056Stb 	failed |= asn1_time_compare_families(gen, gen_size, utc, utc_size);
63219426056Stb 	failed |= asn1_time_compare_families(utc, utc_size, gen, gen_size);
63319426056Stb 	failed |= asn1_time_compare_families(utc, utc_size, utc, utc_size);
63419426056Stb 
63519426056Stb 	return failed;
63619426056Stb }
63719426056Stb 
638261a77c2Stb static int
639261a77c2Stb asn1_time_overflow(void)
640261a77c2Stb {
641261a77c2Stb 	struct tm overflow_year = {0}, overflow_month = {0};
642357c6b75Stb 	struct tm copy, max_time = {0}, min_time = {0}, zero = {0};
643261a77c2Stb 	int64_t valid_time_range = INT64_C(315569519999);
644261a77c2Stb 	int64_t posix_u64;
645261a77c2Stb 	time_t posix_time;
646261a77c2Stb 	int days, secs;
647261a77c2Stb 	int failed = 1;
648261a77c2Stb 
649261a77c2Stb 	overflow_year.tm_year = INT_MAX - 1899;
650261a77c2Stb 	overflow_year.tm_mday = 1;
651261a77c2Stb 
652261a77c2Stb 	overflow_month.tm_mon = INT_MAX;
653261a77c2Stb 	overflow_month.tm_mday = 1;
654261a77c2Stb 
655261a77c2Stb 	if (OPENSSL_tm_to_posix(&overflow_year, &posix_u64)) {
656261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_tm_to_posix didn't fail on "
657261a77c2Stb 		    "overflow of years\n");
658261a77c2Stb 		goto err;
659261a77c2Stb 	}
660261a77c2Stb 	if (OPENSSL_tm_to_posix(&overflow_month, &posix_u64)) {
661261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_tm_to_posix didn't fail on "
662261a77c2Stb 		    "overflow of months\n");
663261a77c2Stb 		goto err;
664261a77c2Stb 	}
665261a77c2Stb 	if (OPENSSL_timegm(&overflow_year, &posix_time)) {
666261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_timegm didn't fail on "
667261a77c2Stb 		    "overflow of years\n");
668261a77c2Stb 		goto err;
669261a77c2Stb 	}
670261a77c2Stb 	if (OPENSSL_timegm(&overflow_month, &posix_time)) {
671261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_timegm didn't fail on "
672261a77c2Stb 		    "overflow of months\n");
673261a77c2Stb 		goto err;
674261a77c2Stb 	}
675261a77c2Stb 	if (OPENSSL_gmtime_adj(&overflow_year, 0, 0)) {
676261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj didn't fail on "
677261a77c2Stb 		    "overflow of years\n");
678261a77c2Stb 		goto err;
679261a77c2Stb 	}
680261a77c2Stb 	if (OPENSSL_gmtime_adj(&overflow_month, 0, 0)) {
681261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj didn't fail on "
682261a77c2Stb 		    "overflow of months\n");
683261a77c2Stb 		goto err;
684261a77c2Stb 	}
685261a77c2Stb 	if (OPENSSL_gmtime_diff(&days, &secs, &overflow_year, &overflow_year)) {
686261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff didn't fail on "
687261a77c2Stb 		    "overflow of years\n");
688261a77c2Stb 		goto err;
689261a77c2Stb 	}
690261a77c2Stb 	if (OPENSSL_gmtime_diff(&days, &secs, &overflow_month, &overflow_month)) {
691261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff didn't fail on "
692261a77c2Stb 		    "overflow of months\n");
693261a77c2Stb 		goto err;
694261a77c2Stb 	}
695261a77c2Stb 
696261a77c2Stb 	/* Input time is in range but adding one second puts it out of range. */
697261a77c2Stb 	max_time.tm_year = 9999 - 1900;
698261a77c2Stb 	max_time.tm_mon = 12 - 1;
699261a77c2Stb 	max_time.tm_mday = 31;
700261a77c2Stb 	max_time.tm_hour = 23;
701261a77c2Stb 	max_time.tm_min = 59;
702261a77c2Stb 	max_time.tm_sec = 59;
703261a77c2Stb 
704261a77c2Stb 	copy = max_time;
705261a77c2Stb 	if (!OPENSSL_gmtime_adj(&copy, 0, 0)) {
706261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
707261a77c2Stb 		    "succeed for maximum time\n");
708261a77c2Stb 		goto err;
709261a77c2Stb 	}
710261a77c2Stb 	if (memcmp(&copy, &max_time, sizeof(max_time)) != 0) {
711261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
712261a77c2Stb 		    "leave copy of max_time unmodified\n");
713261a77c2Stb 		goto err;
714261a77c2Stb 	}
7159639cda1Stb 	if (OPENSSL_gmtime_adj(&copy, 0, 1)) {
716261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 1 sec didn't "
717261a77c2Stb 		    "fail for maximum time\n");
718261a77c2Stb 		goto err;
719261a77c2Stb 	}
7209639cda1Stb 	if (memcmp(&zero, &copy, sizeof(copy)) != 0) {
721357c6b75Stb 		fprintf(stderr, "FAIL: failing OPENSSL_gmtime_adj didn't "
722357c6b75Stb 		    "zero out max_time\n");
723357c6b75Stb 		goto err;
724357c6b75Stb 	}
725261a77c2Stb 
726261a77c2Stb 	min_time.tm_year = 0 - 1900;
727261a77c2Stb 	min_time.tm_mon = 1 - 1;
728261a77c2Stb 	min_time.tm_mday = 1;
729261a77c2Stb 	min_time.tm_hour = 0;
730261a77c2Stb 	min_time.tm_min = 0;
731261a77c2Stb 	min_time.tm_sec = 0;
732261a77c2Stb 
733261a77c2Stb 	copy = min_time;
734261a77c2Stb 	if (!OPENSSL_gmtime_adj(&copy, 0, 0)) {
735261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
736261a77c2Stb 		    "succeed for minimum time\n");
737261a77c2Stb 		goto err;
738261a77c2Stb 	}
739261a77c2Stb 	if (memcmp(&copy, &min_time, sizeof(min_time)) != 0) {
740261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
741261a77c2Stb 		    "leave copy of min_time unmodified\n");
742261a77c2Stb 		goto err;
743261a77c2Stb 	}
7449639cda1Stb 	if (OPENSSL_gmtime_adj(&copy, 0, -1)) {
745261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 1 sec didn't "
746261a77c2Stb 		    "fail for minimum time\n");
747261a77c2Stb 		goto err;
748261a77c2Stb 	}
7499639cda1Stb 	if (memcmp(&zero, &copy, sizeof(copy)) != 0) {
750357c6b75Stb 		fprintf(stderr, "FAIL: failing OPENSSL_gmtime_adj didn't "
751357c6b75Stb 		    "zero out max_time\n");
752357c6b75Stb 		goto err;
753357c6b75Stb 	}
754261a77c2Stb 
7559639cda1Stb 	copy = min_time;
756261a77c2Stb 	/* Test that we can offset by the valid minimum and maximum times. */
757261a77c2Stb 	if (!OPENSSL_gmtime_adj(&copy, 0, valid_time_range)) {
758261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
759261a77c2Stb 		    "failed\n");
760261a77c2Stb 		goto err;
761261a77c2Stb 	}
762261a77c2Stb 	if (memcmp(&copy, &max_time, sizeof(max_time)) != 0) {
763261a77c2Stb 		fprintf(stderr, "FAIL: maximally adjusted copy didn't match "
764261a77c2Stb 		    "max_time\n");
765261a77c2Stb 		goto err;
766261a77c2Stb 	}
767261a77c2Stb 	if (!OPENSSL_gmtime_adj(&copy, 0, -valid_time_range)) {
768261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
769261a77c2Stb 		    "failed\n");
770261a77c2Stb 		goto err;
771261a77c2Stb 	}
772261a77c2Stb 	if (memcmp(&copy, &min_time, sizeof(min_time)) != 0) {
773261a77c2Stb 		fprintf(stderr, "FAIL: maximally adjusted copy didn't match "
774261a77c2Stb 		    "min_time\n");
775261a77c2Stb 		goto err;
776261a77c2Stb 	}
777261a77c2Stb 
778261a77c2Stb 	/*
779261a77c2Stb 	 * The second offset may even exceed the valid_time_range if it is
780261a77c2Stb 	 * cancelled out by offset_day.
781261a77c2Stb 	 */
782261a77c2Stb 	if (!OPENSSL_gmtime_adj(&copy, -1, valid_time_range + 24 * 3600)) {
783261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
784261a77c2Stb 		    "failed\n");
785261a77c2Stb 		goto err;
786261a77c2Stb 	}
787261a77c2Stb 	if (memcmp(&copy, &max_time, sizeof(max_time)) != 0) {
788261a77c2Stb 		fprintf(stderr, "FAIL: excess maximally adjusted copy didn't "
789261a77c2Stb 		    "match max_time\n");
790261a77c2Stb 		goto err;
791261a77c2Stb 	}
792261a77c2Stb 	if (!OPENSSL_gmtime_adj(&copy, 1, -valid_time_range - 24 * 3600)) {
793261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
794261a77c2Stb 		    "failed\n");
795261a77c2Stb 		goto err;
796261a77c2Stb 	}
797261a77c2Stb 	if (memcmp(&copy, &min_time, sizeof(min_time)) != 0) {
798261a77c2Stb 		fprintf(stderr, "FAIL: excess maximally adjusted copy didn't "
799261a77c2Stb 		    "match min_time\n");
800261a77c2Stb 		goto err;
801261a77c2Stb 	}
802261a77c2Stb 
803261a77c2Stb 	copy = max_time;
804261a77c2Stb 	if (OPENSSL_gmtime_adj(&copy, INT_MAX, INT64_MAX)) {
805261a77c2Stb 		fprintf(stderr, "FAIL: maximal adjustments in OPENSSL_gmtime_adj"
806261a77c2Stb 		    "didn't fail\n");
807261a77c2Stb 		goto err;
808261a77c2Stb 	}
809261a77c2Stb 	copy = min_time;
810261a77c2Stb 	if (OPENSSL_gmtime_adj(&copy, INT_MIN, INT64_MIN)) {
811261a77c2Stb 		fprintf(stderr, "FAIL: minimal adjustments in OPENSSL_gmtime_adj"
812261a77c2Stb 		    "didn't fail\n");
813261a77c2Stb 		goto err;
814261a77c2Stb 	}
815261a77c2Stb 
816261a77c2Stb 	/* Test we can diff between maximum time and minimum time. */
817261a77c2Stb 	if (!OPENSSL_gmtime_diff(&days, &secs, &max_time, &min_time)) {
818261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff between maximum and "
819261a77c2Stb 		    "minimum time failed\n");
820261a77c2Stb 		goto err;
821261a77c2Stb 	}
822261a77c2Stb 	if (!OPENSSL_gmtime_diff(&days, &secs, &min_time, &max_time)) {
823261a77c2Stb 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff between minimum and "
824261a77c2Stb 		    "maximum time failed\n");
825261a77c2Stb 		goto err;
826261a77c2Stb 	}
827261a77c2Stb 
828261a77c2Stb 
829261a77c2Stb 	failed = 0;
830261a77c2Stb 
831261a77c2Stb  err:
832261a77c2Stb 	return failed;
833261a77c2Stb }
834261a77c2Stb 
835ad33c0b7Sjsing int
836ad33c0b7Sjsing main(int argc, char **argv)
837ad33c0b7Sjsing {
83806baaab8Stb 	const struct asn1_time_test *att;
839ad33c0b7Sjsing 	int failed = 0;
840ad33c0b7Sjsing 	size_t i;
841ad33c0b7Sjsing 
842ad33c0b7Sjsing 	fprintf(stderr, "Invalid time tests...\n");
843ad33c0b7Sjsing 	for (i = 0; i < N_INVTIME_TESTS; i++) {
844ad33c0b7Sjsing 		att = &asn1_invtime_tests[i];
84525b449edSbeck 		failed |= asn1_invtime_test(i, att, 0);
84625b449edSbeck 	}
84725b449edSbeck 
84825b449edSbeck 	fprintf(stderr, "Invalid generalized time tests...\n");
84925b449edSbeck 	for (i = 0; i < N_INVGENTIME_TESTS; i++) {
85025b449edSbeck 		att = &asn1_invgentime_tests[i];
85131c2cd2bSbeck 		failed |= asn1_invtime_test(i, att, 1);
852ad33c0b7Sjsing 	}
853ad33c0b7Sjsing 
854ad33c0b7Sjsing 	fprintf(stderr, "GENERALIZEDTIME tests...\n");
855ad33c0b7Sjsing 	for (i = 0; i < N_GENTIME_TESTS; i++) {
856ad33c0b7Sjsing 		att = &asn1_gentime_tests[i];
857ad33c0b7Sjsing 		failed |= asn1_gentime_test(i, att);
858ad33c0b7Sjsing 	}
859ad33c0b7Sjsing 
860ad33c0b7Sjsing 	fprintf(stderr, "UTCTIME tests...\n");
861ad33c0b7Sjsing 	for (i = 0; i < N_UTCTIME_TESTS; i++) {
862ad33c0b7Sjsing 		att = &asn1_utctime_tests[i];
863ad33c0b7Sjsing 		failed |= asn1_utctime_test(i, att);
864ad33c0b7Sjsing 	}
865ad33c0b7Sjsing 
866ad33c0b7Sjsing 	fprintf(stderr, "TIME tests...\n");
867ad33c0b7Sjsing 	for (i = 0; i < N_UTCTIME_TESTS; i++) {
868ad33c0b7Sjsing 		att = &asn1_utctime_tests[i];
869ad33c0b7Sjsing 		failed |= asn1_time_test(i, att, V_ASN1_UTCTIME);
870ad33c0b7Sjsing 	}
871ad33c0b7Sjsing 	for (i = 0; i < N_GENTIME_TESTS; i++) {
872ad33c0b7Sjsing 		att = &asn1_gentime_tests[i];
873ad33c0b7Sjsing 		failed |= asn1_time_test(i, att, V_ASN1_GENERALIZEDTIME);
874ad33c0b7Sjsing 	}
875ad33c0b7Sjsing 
87619426056Stb 	fprintf(stderr, "ASN1_TIME_compare tests...\n");
87719426056Stb 	failed |= asn1_time_compare_test();
87819426056Stb 
8794ee6c374Sjob 	/* Check for a leak in ASN1_TIME_normalize(). */
8804ee6c374Sjob 	failed |= ASN1_TIME_normalize(NULL) != 0;
8814ee6c374Sjob 
882261a77c2Stb 	fprintf(stderr, "Time overflow tests...\n");
883261a77c2Stb 	failed |= asn1_time_overflow();
884261a77c2Stb 
885ad33c0b7Sjsing 	return (failed);
886ad33c0b7Sjsing }
887