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 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 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 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 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 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 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 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 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 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 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 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 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