xref: /openbsd/regress/lib/libcrypto/asn1/asn1time.c (revision 4fb9ab68)
1 /* $OpenBSD: asn1time.c,v 1.30 2024/07/21 13:25:11 tb Exp $ */
2 /*
3  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4  * Copyright (c) 2024 Google Inc.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <openssl/asn1.h>
20 #include <openssl/posix_time.h>
21 
22 #include <err.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include "asn1_local.h"
28 
29 int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
30 
31 struct asn1_time_test {
32 	const char *str;
33 	const char *data;
34 	const unsigned char der[32];
35 	time_t time;
36 };
37 
38 static const struct asn1_time_test asn1_invtime_tests[] = {
39 	{
40 		.str = "",
41 	},
42 	{
43 		.str = "2015",
44 	},
45 	{
46 		.str = "201509",
47 	},
48 	{
49 		.str = "20150923",
50 	},
51 	{
52 		.str = "20150923032700",
53 	},
54 	{
55 		.str = "20150923032700.Z",
56 	},
57 	{
58 		.str = "20150923032700.123",
59 	},
60 	{
61 		.str = "20150923032700+1.09",
62 	},
63 	{
64 		.str = "20150923032700+1100Z",
65 	},
66 	{
67 		.str = "20150923032700-11001",
68 	},
69 	{
70 		/* UTC time cannot have fractional seconds. */
71 		.str = "150923032700.123Z",
72 	},
73 	{
74 		.str = "aaaaaaaaaaaaaaZ",
75 	},
76 	/* utc time with omitted seconds, should fail */
77 	{
78 		.str = "1609082343Z",
79 	},
80 };
81 
82 static const struct asn1_time_test asn1_invgentime_tests[] = {
83 	/* Generalized time with omitted seconds, should fail */
84 	{
85 		.str = "201612081934Z",
86 	},
87 	/* Valid UTC time, should fail as a generalized time */
88 	{
89 		.str = "160908234300Z",
90 	},
91 };
92 
93 static const struct asn1_time_test asn1_gentime_tests[] = {
94 	{
95 		.str = "20161208193400Z",
96 		.data = "20161208193400Z",
97 		.time = 1481225640,
98 		.der = {
99 			0x18, 0x0f, 0x32, 0x30, 0x31, 0x36, 0x31, 0x32,
100 			0x30, 0x38, 0x31, 0x39, 0x33, 0x34, 0x30, 0x30,
101 			0x5a,
102 		},
103 	},
104 	{
105 		.str = "19700101000000Z",
106 		.data = "19700101000000Z",
107 		.time = 0,
108 		.der = {
109 			0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31,
110 			0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
111 			0x5a,
112 		},
113 	},
114 	{
115 		.str = "20150923032700Z",
116 		.data = "20150923032700Z",
117 		.time = 1442978820,
118 		.der = {
119 			0x18, 0x0f, 0x32, 0x30, 0x31, 0x35, 0x30, 0x39,
120 			0x32, 0x33, 0x30, 0x33, 0x32, 0x37, 0x30, 0x30,
121 			0x5a,
122 		},
123 	},
124 	{
125 		/* 1 second after the 32-bit epoch wraps. */
126 		.str = "20380119031408Z",
127 		.data = "20380119031408Z",
128 		.time = 2147483648LL,
129 		.der = {
130 			0x18, 0x0f, 0x32, 0x30, 0x33, 0x38, 0x30, 0x31,
131 			0x31, 0x39, 0x30, 0x33, 0x31, 0x34, 0x30, 0x38,
132 			0x5a,
133 		},
134 
135 	},
136 };
137 
138 static const struct asn1_time_test asn1_utctime_tests[] = {
139 	{
140 		.str = "700101000000Z",
141 		.data = "700101000000Z",
142 		.time = 0,
143 		.der = {
144 			0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31,
145 			0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
146 		},
147 	},
148 	{
149 		.str = "150923032700Z",
150 		.data = "150923032700Z",
151 		.time = 1442978820,
152 		.der = {
153 			0x17, 0x0d, 0x31, 0x35, 0x30, 0x39, 0x32, 0x33,
154 			0x30, 0x33, 0x32, 0x37, 0x30, 0x30, 0x5a,
155 		},
156 	},
157 	{
158 		.str = "140524144512Z",
159 		.data = "140524144512Z",
160 		.time = 1400942712,
161 		.der = {
162 			0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x34,
163 			0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a,
164 		},
165 	},
166 	{
167 		.str = "240401144512Z",
168 		.data = "240401144512Z",
169 		.time = 1711982712,
170 		.der = {
171 			0x17, 0x0d, 0x32, 0x34, 0x30, 0x34, 0x30, 0x31,
172 			0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a
173 		},
174 	},
175 };
176 
177 #define N_INVTIME_TESTS \
178     (sizeof(asn1_invtime_tests) / sizeof(*asn1_invtime_tests))
179 #define N_INVGENTIME_TESTS \
180     (sizeof(asn1_invgentime_tests) / sizeof(*asn1_invgentime_tests))
181 #define N_GENTIME_TESTS \
182     (sizeof(asn1_gentime_tests) / sizeof(*asn1_gentime_tests))
183 #define N_UTCTIME_TESTS \
184     (sizeof(asn1_utctime_tests) / sizeof(*asn1_utctime_tests))
185 
186 static void
hexdump(const unsigned char * buf,size_t len)187 hexdump(const unsigned char *buf, size_t len)
188 {
189 	size_t i;
190 
191 	for (i = 1; i <= len; i++)
192 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
193 
194 	fprintf(stderr, "\n");
195 }
196 
197 static int
asn1_compare_bytes(int test_no,const unsigned char * d1,const unsigned char * d2,int len1,int len2)198 asn1_compare_bytes(int test_no, const unsigned char *d1,
199     const unsigned char *d2, int len1, int len2)
200 {
201 	if (len1 != len2) {
202 		fprintf(stderr, "FAIL: test %d - byte lengths differ "
203 		    "(%d != %d)\n", test_no, len1, len2);
204 		return (1);
205 	}
206 	if (memcmp(d1, d2, len1) != 0) {
207 		fprintf(stderr, "FAIL: test %d - bytes differ\n", test_no);
208 		fprintf(stderr, "Got:\n");
209 		hexdump(d1, len1);
210 		fprintf(stderr, "Want:\n");
211 		hexdump(d2, len2);
212 		return (1);
213 	}
214 	return (0);
215 }
216 
217 static int
asn1_compare_str(int test_no,const struct asn1_string_st * asn1str,const char * str)218 asn1_compare_str(int test_no, const struct asn1_string_st *asn1str,
219     const char *str)
220 {
221 	int length = strlen(str);
222 
223 	if (asn1str->length != length) {
224 		fprintf(stderr, "FAIL: test %d - string lengths differ "
225 		    "(%d != %d)\n", test_no, asn1str->length, length);
226 		return (1);
227 	}
228 	if (strncmp(asn1str->data, str, length) != 0) {
229 		fprintf(stderr, "FAIL: test %d - strings differ "
230 		    "('%s' != '%s')\n", test_no, asn1str->data, str);
231 		return (1);
232 	}
233 
234 	return (0);
235 }
236 
237 static int
asn1_invtime_test(int test_no,const struct asn1_time_test * att,int gen)238 asn1_invtime_test(int test_no, const struct asn1_time_test *att, int gen)
239 {
240 	ASN1_GENERALIZEDTIME *gt = NULL;
241 	ASN1_UTCTIME *ut = NULL;
242 	ASN1_TIME *t = NULL;
243 	int failure = 1;
244 
245 	if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
246 		goto done;
247 	if ((ut = ASN1_UTCTIME_new()) == NULL)
248 		goto done;
249 	if ((t = ASN1_TIME_new()) == NULL)
250 		goto done;
251 
252 	if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 0) {
253 		fprintf(stderr, "FAIL: test %d - successfully set "
254 		    "GENERALIZEDTIME string '%s'\n", test_no, att->str);
255 		goto done;
256 	}
257 
258 	if (gen)  {
259 		failure = 0;
260 		goto done;
261 	}
262 
263 	if (ASN1_UTCTIME_set_string(ut, att->str) != 0) {
264 		fprintf(stderr, "FAIL: test %d - successfully set UTCTIME "
265 		    "string '%s'\n", test_no, att->str);
266 		goto done;
267 	}
268 	if (ASN1_TIME_set_string(t, att->str) != 0) {
269 		fprintf(stderr, "FAIL: test %d - successfully set TIME "
270 		    "string '%s'\n", test_no, att->str);
271 		goto done;
272 	}
273 	if (ASN1_TIME_set_string_X509(t, att->str) != 0) {
274 		fprintf(stderr, "FAIL: test %d - successfully set x509 TIME "
275 		    "string '%s'\n", test_no, att->str);
276 		goto done;
277 	}
278 
279 	failure = 0;
280 
281  done:
282 	ASN1_GENERALIZEDTIME_free(gt);
283 	ASN1_UTCTIME_free(ut);
284 	ASN1_TIME_free(t);
285 
286 	return (failure);
287 }
288 
289 static int
asn1_gentime_test(int test_no,const struct asn1_time_test * att)290 asn1_gentime_test(int test_no, const struct asn1_time_test *att)
291 {
292 	const unsigned char *der;
293 	unsigned char *p = NULL;
294 	ASN1_GENERALIZEDTIME *gt = NULL;
295 	time_t t;
296 	int failure = 1;
297 	int len;
298 	struct tm tm;
299 
300 	if (ASN1_GENERALIZEDTIME_set_string(NULL, att->str) != 1) {
301 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
302 		    test_no, att->str);
303 		goto done;
304 	}
305 
306 	if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
307 		goto done;
308 
309 	if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 1) {
310 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
311 		    test_no, att->str);
312 		goto done;
313 	}
314 	if (asn1_compare_str(test_no, gt, att->str) != 0)
315 		goto done;
316 
317 	if (ASN1_TIME_to_tm(gt, &tm) == 0)  {
318 		fprintf(stderr, "FAIL: test %d - ASN1_time_to_tm failed '%s'\n",
319 		    test_no, att->str);
320 		goto done;
321 	}
322 
323 	if (!OPENSSL_timegm(&tm, &t)) {
324 		/* things with crappy time_t should die in fire */
325 		fprintf(stderr, "FAIL: test %d - OPENSSL_timegm failed\n",
326 		    test_no);
327 	}
328 
329 	if (t != att->time) {
330 		/* things with crappy time_t should die in fire */
331 		int64_t a = t, b = att->time;
332 
333 		fprintf(stderr, "FAIL: test %d - times don't match, "
334 		    "expected %lld got %lld\n",
335 		    test_no, (long long)b, (long long)a);
336 		goto done;
337 	}
338 
339 	if ((len = i2d_ASN1_GENERALIZEDTIME(gt, &p)) <= 0) {
340 		fprintf(stderr, "FAIL: test %d - i2d_ASN1_GENERALIZEDTIME "
341 		    "failed\n", test_no);
342 		goto done;
343 	}
344 	der = att->der;
345 	if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0)
346 		goto done;
347 
348 	len = strlen(att->der);
349 	if (d2i_ASN1_GENERALIZEDTIME(&gt, &der, len) == NULL) {
350 		fprintf(stderr, "FAIL: test %d - d2i_ASN1_GENERALIZEDTIME "
351 		    "failed\n", test_no);
352 		goto done;
353 	}
354 	if (asn1_compare_str(test_no, gt, att->str) != 0)
355 		goto done;
356 
357 	ASN1_GENERALIZEDTIME_free(gt);
358 
359 	if ((gt = ASN1_GENERALIZEDTIME_set(NULL, att->time)) == NULL) {
360 		fprintf(stderr, "FAIL: test %d - failed to set time %lld\n",
361 		    test_no, (long long)att->time);
362 		goto done;
363 	}
364 	if (asn1_compare_str(test_no, gt, att->data) != 0)
365 		goto done;
366 
367 	failure = 0;
368 
369  done:
370 	ASN1_GENERALIZEDTIME_free(gt);
371 	free(p);
372 
373 	return (failure);
374 }
375 
376 static int
asn1_utctime_test(int test_no,const struct asn1_time_test * att)377 asn1_utctime_test(int test_no, const struct asn1_time_test *att)
378 {
379 	const unsigned char *der;
380 	unsigned char *p = NULL;
381 	ASN1_UTCTIME *ut = NULL;
382 	int failure = 1;
383 	int len;
384 
385 	if (ASN1_UTCTIME_set_string(NULL, att->str) != 1) {
386 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
387 		    test_no, att->str);
388 		goto done;
389 	}
390 
391 	if ((ut = ASN1_UTCTIME_new()) == NULL)
392 		goto done;
393 
394 	if (ASN1_UTCTIME_set_string(ut, att->str) != 1) {
395 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
396 		    test_no, att->str);
397 		goto done;
398 	}
399 	if (asn1_compare_str(test_no, ut, att->str) != 0)
400 		goto done;
401 
402 	if ((len = i2d_ASN1_UTCTIME(ut, &p)) <= 0) {
403 		fprintf(stderr, "FAIL: test %d - i2d_ASN1_UTCTIME failed\n",
404 		    test_no);
405 		goto done;
406 	}
407 	der = att->der;
408 	if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0)
409 		goto done;
410 
411 	len = strlen(att->der);
412 	if (d2i_ASN1_UTCTIME(&ut, &der, len) == NULL) {
413 		fprintf(stderr, "FAIL: test %d - d2i_ASN1_UTCTIME failed\n",
414 		    test_no);
415 		goto done;
416 	}
417 	if (asn1_compare_str(test_no, ut, att->str) != 0)
418 		goto done;
419 
420 	ASN1_UTCTIME_free(ut);
421 
422 	if ((ut = ASN1_UTCTIME_set(NULL, att->time)) == NULL) {
423 		fprintf(stderr, "FAIL: test %d - failed to set time %lld\n",
424 		    test_no, (long long)att->time);
425 		goto done;
426 	}
427 	if (asn1_compare_str(test_no, ut, att->data) != 0)
428 		goto done;
429 
430 	failure = 0;
431 
432  done:
433 	ASN1_UTCTIME_free(ut);
434 	free(p);
435 
436 	return (failure);
437 }
438 
439 static int
asn1_time_test(int test_no,const struct asn1_time_test * att,int type)440 asn1_time_test(int test_no, const struct asn1_time_test *att, int type)
441 {
442 	ASN1_TIME *t = NULL, *tx509 = NULL;
443 	char *parsed_time = NULL;
444 	int failure = 1;
445 
446 	if (ASN1_TIME_set_string(NULL, att->str) != 1) {
447 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
448 		    test_no, att->str);
449 		goto done;
450 	}
451 
452 	if ((t = ASN1_TIME_new()) == NULL)
453 		goto done;
454 
455 	if ((tx509 = ASN1_TIME_new()) == NULL)
456 		goto done;
457 
458 	switch (strlen(att->str)) {
459 	case 13:
460 		t->type = V_ASN1_UTCTIME;
461 		if (ASN1_UTCTIME_set_string(t, att->str) != 1) {
462 			fprintf(stderr, "FAIL: test %d - failed to set utc "
463 			    "string '%s'\n",
464 			    test_no, att->str);
465 			goto done;
466 		}
467 		break;
468 	case 15:
469 		t->type = V_ASN1_GENERALIZEDTIME;
470 		if (ASN1_GENERALIZEDTIME_set_string(t, att->str) != 1) {
471 			fprintf(stderr, "FAIL: test %d - failed to set gen "
472 			    "string '%s'\n",
473 			    test_no, att->str);
474 			goto done;
475 		}
476 		break;
477 	default:
478 		fprintf(stderr, "FAIL: unknown type\n");
479 		goto done;
480 	}
481 
482 	if (t->type != type) {
483 		fprintf(stderr, "FAIL: test %d - got type %d, want %d\n",
484 		    test_no, t->type, type);
485 		goto done;
486 	}
487 
488 	if ((parsed_time = strdup(t->data)) == NULL)
489 		goto done;
490 
491 	if (ASN1_TIME_normalize(t) != 1) {
492 		fprintf(stderr, "FAIL: test %d - failed to set normalize '%s'\n",
493 		    test_no, att->str);
494 		goto done;
495 	}
496 
497 	if (ASN1_TIME_set_string_X509(tx509, parsed_time) != 1) {
498 		fprintf(stderr, "FAIL: test %d - failed to set string X509 '%s'\n",
499 		    test_no, t->data);
500 		goto done;
501 	}
502 
503 	if (t->type != tx509->type) {
504 		fprintf(stderr, "FAIL: test %d - type %d, different from %d\n",
505 		    test_no, t->type, tx509->type);
506 		goto done;
507 	}
508 
509 	if (ASN1_TIME_compare(t, tx509) != 0) {
510 		fprintf(stderr, "FAIL: ASN1_TIME values differ!\n");
511 		goto done;
512 	}
513 
514 	if (ASN1_TIME_set_string(tx509, parsed_time) != 1) {
515 		fprintf(stderr, "FAIL: test %d - failed to set string X509 '%s'\n",
516 		    test_no, t->data);
517 		goto done;
518 	}
519 
520 	if (t->type != tx509->type) {
521 		fprintf(stderr, "FAIL: test %d - type %d, different from %d\n",
522 		    test_no, t->type, tx509->type);
523 		goto done;
524 	}
525 
526 	if (ASN1_TIME_compare(t, tx509) != 0) {
527 		fprintf(stderr, "FAIL: ASN1_TIME values differ!\n");
528 		goto done;
529 	}
530 
531 
532 	failure = 0;
533 
534  done:
535 
536 	ASN1_TIME_free(t);
537 	ASN1_TIME_free(tx509);
538 	free(parsed_time);
539 
540 	return (failure);
541 }
542 
543 static int
time_t_cmp(time_t t1,time_t t2)544 time_t_cmp(time_t t1, time_t t2)
545 {
546 	if (t1 < t2)
547 		return -1;
548 	if (t2 < t1)
549 		return 1;
550 	return 0;
551 }
552 
553 static int
asn1_time_compare_families(const struct asn1_time_test * fam1,size_t fam1_size,const struct asn1_time_test * fam2,size_t fam2_size)554 asn1_time_compare_families(const struct asn1_time_test *fam1, size_t fam1_size,
555     const struct asn1_time_test *fam2, size_t fam2_size)
556 {
557 	const struct asn1_time_test *att1, *att2;
558 	ASN1_TIME *t1 = NULL, *t2 = NULL;
559 	size_t i, j;
560 	int asn1_cmp, time_cmp;
561 	int comparison_failure = 0;
562 	int failure = 1;
563 
564 	if ((t1 = ASN1_TIME_new()) == NULL)
565 		goto done;
566 	if ((t2 = ASN1_TIME_new()) == NULL)
567 		goto done;
568 
569 	for (i = 0; i < fam1_size; i++) {
570 		att1 = &fam1[i];
571 
572 		if (!ASN1_TIME_set_string(t1, att1->str))
573 			goto done;
574 		for (j = 0; j < fam2_size; j++) {
575 			att2 = &fam2[j];
576 
577 			if (!ASN1_TIME_set_string(t2, att2->str))
578 				goto done;
579 
580 			time_cmp = time_t_cmp(att1->time, att2->time);
581 			asn1_cmp = ASN1_TIME_compare(t1, t2);
582 
583 			if (time_cmp != asn1_cmp) {
584 				fprintf(stderr, "ASN1_TIME_compare - %s vs. %s: "
585 				    "want %d, got %d\n",
586 				    att1->str, att2->str, time_cmp, asn1_cmp);
587 				comparison_failure |= 1;
588 			}
589 
590 			time_cmp = ASN1_TIME_cmp_time_t(t1, att2->time);
591 			if (time_cmp != asn1_cmp) {
592 				fprintf(stderr, "ASN1_TIME_cmp_time_t - %s vs. %lld: "
593 				    "want %d, got %d\n",
594 				    att1->str, (long long)att2->time,
595 				    asn1_cmp, time_cmp);
596 				comparison_failure |= 1;
597 			}
598 
599 			time_cmp = ASN1_UTCTIME_cmp_time_t(t1, att2->time);
600 			if (t1->type != V_ASN1_UTCTIME)
601 				asn1_cmp = -2;
602 			if (time_cmp != asn1_cmp) {
603 				fprintf(stderr, "ASN1_UTCTIME_cmp_time_t - %s vs. %lld: "
604 				    "want %d, got %d\n",
605 				    att1->str, (long long)att2->time,
606 				    asn1_cmp, time_cmp);
607 				comparison_failure |= 1;
608 			}
609 		}
610 	}
611 
612 	failure = comparison_failure;
613 
614  done:
615 	ASN1_TIME_free(t1);
616 	ASN1_TIME_free(t2);
617 
618 	return failure;
619 }
620 
621 static int
asn1_time_compare_test(void)622 asn1_time_compare_test(void)
623 {
624 	const struct asn1_time_test *gen = asn1_gentime_tests;
625 	size_t gen_size = N_GENTIME_TESTS;
626 	const struct asn1_time_test *utc = asn1_utctime_tests;
627 	size_t utc_size = N_UTCTIME_TESTS;
628 	int failed = 0;
629 
630 	failed |= asn1_time_compare_families(gen, gen_size, gen, gen_size);
631 	failed |= asn1_time_compare_families(gen, gen_size, utc, utc_size);
632 	failed |= asn1_time_compare_families(utc, utc_size, gen, gen_size);
633 	failed |= asn1_time_compare_families(utc, utc_size, utc, utc_size);
634 
635 	return failed;
636 }
637 
638 static int
asn1_time_overflow(void)639 asn1_time_overflow(void)
640 {
641 	struct tm overflow_year = {0}, overflow_month = {0};
642 	struct tm copy, max_time = {0}, min_time = {0}, zero = {0};
643 	int64_t valid_time_range = INT64_C(315569519999);
644 	int64_t posix_u64;
645 	time_t posix_time;
646 	int days, secs;
647 	int failed = 1;
648 
649 	overflow_year.tm_year = INT_MAX - 1899;
650 	overflow_year.tm_mday = 1;
651 
652 	overflow_month.tm_mon = INT_MAX;
653 	overflow_month.tm_mday = 1;
654 
655 	if (OPENSSL_tm_to_posix(&overflow_year, &posix_u64)) {
656 		fprintf(stderr, "FAIL: OPENSSL_tm_to_posix didn't fail on "
657 		    "overflow of years\n");
658 		goto err;
659 	}
660 	if (OPENSSL_tm_to_posix(&overflow_month, &posix_u64)) {
661 		fprintf(stderr, "FAIL: OPENSSL_tm_to_posix didn't fail on "
662 		    "overflow of months\n");
663 		goto err;
664 	}
665 	if (OPENSSL_timegm(&overflow_year, &posix_time)) {
666 		fprintf(stderr, "FAIL: OPENSSL_timegm didn't fail on "
667 		    "overflow of years\n");
668 		goto err;
669 	}
670 	if (OPENSSL_timegm(&overflow_month, &posix_time)) {
671 		fprintf(stderr, "FAIL: OPENSSL_timegm didn't fail on "
672 		    "overflow of months\n");
673 		goto err;
674 	}
675 	if (OPENSSL_gmtime_adj(&overflow_year, 0, 0)) {
676 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj didn't fail on "
677 		    "overflow of years\n");
678 		goto err;
679 	}
680 	if (OPENSSL_gmtime_adj(&overflow_month, 0, 0)) {
681 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj didn't fail on "
682 		    "overflow of months\n");
683 		goto err;
684 	}
685 	if (OPENSSL_gmtime_diff(&days, &secs, &overflow_year, &overflow_year)) {
686 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff didn't fail on "
687 		    "overflow of years\n");
688 		goto err;
689 	}
690 	if (OPENSSL_gmtime_diff(&days, &secs, &overflow_month, &overflow_month)) {
691 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff didn't fail on "
692 		    "overflow of months\n");
693 		goto err;
694 	}
695 
696 	/* Input time is in range but adding one second puts it out of range. */
697 	max_time.tm_year = 9999 - 1900;
698 	max_time.tm_mon = 12 - 1;
699 	max_time.tm_mday = 31;
700 	max_time.tm_hour = 23;
701 	max_time.tm_min = 59;
702 	max_time.tm_sec = 59;
703 
704 	copy = max_time;
705 	if (!OPENSSL_gmtime_adj(&copy, 0, 0)) {
706 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
707 		    "succeed for maximum time\n");
708 		goto err;
709 	}
710 	if (memcmp(&copy, &max_time, sizeof(max_time)) != 0) {
711 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
712 		    "leave copy of max_time unmodified\n");
713 		goto err;
714 	}
715 	if (OPENSSL_gmtime_adj(&copy, 0, 1)) {
716 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 1 sec didn't "
717 		    "fail for maximum time\n");
718 		goto err;
719 	}
720 	if (memcmp(&zero, &copy, sizeof(copy)) != 0) {
721 		fprintf(stderr, "FAIL: failing OPENSSL_gmtime_adj didn't "
722 		    "zero out max_time\n");
723 		goto err;
724 	}
725 
726 	min_time.tm_year = 0 - 1900;
727 	min_time.tm_mon = 1 - 1;
728 	min_time.tm_mday = 1;
729 	min_time.tm_hour = 0;
730 	min_time.tm_min = 0;
731 	min_time.tm_sec = 0;
732 
733 	copy = min_time;
734 	if (!OPENSSL_gmtime_adj(&copy, 0, 0)) {
735 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
736 		    "succeed for minimum time\n");
737 		goto err;
738 	}
739 	if (memcmp(&copy, &min_time, sizeof(min_time)) != 0) {
740 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 0 sec didn't "
741 		    "leave copy of min_time unmodified\n");
742 		goto err;
743 	}
744 	if (OPENSSL_gmtime_adj(&copy, 0, -1)) {
745 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by 1 sec didn't "
746 		    "fail for minimum time\n");
747 		goto err;
748 	}
749 	if (memcmp(&zero, &copy, sizeof(copy)) != 0) {
750 		fprintf(stderr, "FAIL: failing OPENSSL_gmtime_adj didn't "
751 		    "zero out max_time\n");
752 		goto err;
753 	}
754 
755 	copy = min_time;
756 	/* Test that we can offset by the valid minimum and maximum times. */
757 	if (!OPENSSL_gmtime_adj(&copy, 0, valid_time_range)) {
758 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
759 		    "failed\n");
760 		goto err;
761 	}
762 	if (memcmp(&copy, &max_time, sizeof(max_time)) != 0) {
763 		fprintf(stderr, "FAIL: maximally adjusted copy didn't match "
764 		    "max_time\n");
765 		goto err;
766 	}
767 	if (!OPENSSL_gmtime_adj(&copy, 0, -valid_time_range)) {
768 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
769 		    "failed\n");
770 		goto err;
771 	}
772 	if (memcmp(&copy, &min_time, sizeof(min_time)) != 0) {
773 		fprintf(stderr, "FAIL: maximally adjusted copy didn't match "
774 		    "min_time\n");
775 		goto err;
776 	}
777 
778 	/*
779 	 * The second offset may even exceed the valid_time_range if it is
780 	 * cancelled out by offset_day.
781 	 */
782 	if (!OPENSSL_gmtime_adj(&copy, -1, valid_time_range + 24 * 3600)) {
783 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
784 		    "failed\n");
785 		goto err;
786 	}
787 	if (memcmp(&copy, &max_time, sizeof(max_time)) != 0) {
788 		fprintf(stderr, "FAIL: excess maximally adjusted copy didn't "
789 		    "match max_time\n");
790 		goto err;
791 	}
792 	if (!OPENSSL_gmtime_adj(&copy, 1, -valid_time_range - 24 * 3600)) {
793 		fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
794 		    "failed\n");
795 		goto err;
796 	}
797 	if (memcmp(&copy, &min_time, sizeof(min_time)) != 0) {
798 		fprintf(stderr, "FAIL: excess maximally adjusted copy didn't "
799 		    "match min_time\n");
800 		goto err;
801 	}
802 
803 	copy = max_time;
804 	if (OPENSSL_gmtime_adj(&copy, INT_MAX, INT64_MAX)) {
805 		fprintf(stderr, "FAIL: maximal adjustments in OPENSSL_gmtime_adj"
806 		    "didn't fail\n");
807 		goto err;
808 	}
809 	copy = min_time;
810 	if (OPENSSL_gmtime_adj(&copy, INT_MIN, INT64_MIN)) {
811 		fprintf(stderr, "FAIL: minimal adjustments in OPENSSL_gmtime_adj"
812 		    "didn't fail\n");
813 		goto err;
814 	}
815 
816 	/* Test we can diff between maximum time and minimum time. */
817 	if (!OPENSSL_gmtime_diff(&days, &secs, &max_time, &min_time)) {
818 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff between maximum and "
819 		    "minimum time failed\n");
820 		goto err;
821 	}
822 	if (!OPENSSL_gmtime_diff(&days, &secs, &min_time, &max_time)) {
823 		fprintf(stderr, "FAIL: OPENSSL_gmtime_diff between minimum and "
824 		    "maximum time failed\n");
825 		goto err;
826 	}
827 
828 
829 	failed = 0;
830 
831  err:
832 	return failed;
833 }
834 
835 int
main(int argc,char ** argv)836 main(int argc, char **argv)
837 {
838 	const struct asn1_time_test *att;
839 	int failed = 0;
840 	size_t i;
841 
842 	fprintf(stderr, "Invalid time tests...\n");
843 	for (i = 0; i < N_INVTIME_TESTS; i++) {
844 		att = &asn1_invtime_tests[i];
845 		failed |= asn1_invtime_test(i, att, 0);
846 	}
847 
848 	fprintf(stderr, "Invalid generalized time tests...\n");
849 	for (i = 0; i < N_INVGENTIME_TESTS; i++) {
850 		att = &asn1_invgentime_tests[i];
851 		failed |= asn1_invtime_test(i, att, 1);
852 	}
853 
854 	fprintf(stderr, "GENERALIZEDTIME tests...\n");
855 	for (i = 0; i < N_GENTIME_TESTS; i++) {
856 		att = &asn1_gentime_tests[i];
857 		failed |= asn1_gentime_test(i, att);
858 	}
859 
860 	fprintf(stderr, "UTCTIME tests...\n");
861 	for (i = 0; i < N_UTCTIME_TESTS; i++) {
862 		att = &asn1_utctime_tests[i];
863 		failed |= asn1_utctime_test(i, att);
864 	}
865 
866 	fprintf(stderr, "TIME tests...\n");
867 	for (i = 0; i < N_UTCTIME_TESTS; i++) {
868 		att = &asn1_utctime_tests[i];
869 		failed |= asn1_time_test(i, att, V_ASN1_UTCTIME);
870 	}
871 	for (i = 0; i < N_GENTIME_TESTS; i++) {
872 		att = &asn1_gentime_tests[i];
873 		failed |= asn1_time_test(i, att, V_ASN1_GENERALIZEDTIME);
874 	}
875 
876 	fprintf(stderr, "ASN1_TIME_compare tests...\n");
877 	failed |= asn1_time_compare_test();
878 
879 	/* Check for a leak in ASN1_TIME_normalize(). */
880 	failed |= ASN1_TIME_normalize(NULL) != 0;
881 
882 	fprintf(stderr, "Time overflow tests...\n");
883 	failed |= asn1_time_overflow();
884 
885 	return (failed);
886 }
887