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(>, &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(©, 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(©, &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(©, 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, ©, 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(©, 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(©, &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(©, 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, ©, 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(©, 0, valid_time_range)) {
758 fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
759 "failed\n");
760 goto err;
761 }
762 if (memcmp(©, &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(©, 0, -valid_time_range)) {
768 fprintf(stderr, "FAIL: OPENSSL_gmtime_adj by maximum range "
769 "failed\n");
770 goto err;
771 }
772 if (memcmp(©, &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(©, -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(©, &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(©, 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(©, &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(©, 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(©, 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