Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2017-2024 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 /* Tests for X509 time functions */
     11 
     12 #include <string.h>
     13 #include <time.h>
     14 
     15 #include <openssl/asn1.h>
     16 #include <openssl/x509.h>
     17 #include "testutil.h"
     18 #include "internal/nelem.h"
     19 
     20 typedef struct {
     21     const char *data;
     22     int type;
     23     time_t cmp_time;
     24     /* -1 if asn1_time <= cmp_time, 1 if asn1_time > cmp_time, 0 if error. */
     25     int expected;
     26 } TESTDATA;
     27 
     28 typedef struct {
     29     const char *data;
     30     /* 0 for check-only mode, 1 for set-string mode */
     31     int set_string;
     32     /* 0 for error, 1 if succeed */
     33     int expected;
     34     /*
     35      * The following 2 fields are ignored if set_string field is set to '0'
     36      * (in check only mode).
     37      *
     38      * But they can still be ignored explicitly in set-string mode by:
     39      * setting -1 to expected_type and setting NULL to expected_string.
     40      *
     41      * It's useful in a case of set-string mode but the expected result
     42      * is a 'parsing error'.
     43      */
     44     int expected_type;
     45     const char *expected_string;
     46 } TESTDATA_FORMAT;
     47 
     48 /*
     49  * Actually, the "loose" mode has been tested in
     50  * those time-compare-cases, so we may not test it again.
     51  */
     52 static TESTDATA_FORMAT x509_format_tests[] = {
     53     /* GeneralizedTime */
     54     {
     55         /* good format, check only */
     56         "20170217180105Z",
     57         0,
     58         1,
     59         -1,
     60         NULL,
     61     },
     62     {
     63         /* not leap year, check only */
     64         "20170229180105Z",
     65         0,
     66         0,
     67         -1,
     68         NULL,
     69     },
     70     {
     71         /* leap year, check only */
     72         "20160229180105Z",
     73         0,
     74         1,
     75         -1,
     76         NULL,
     77     },
     78     {
     79         /* SS is missing, check only */
     80         "201702171801Z",
     81         0,
     82         0,
     83         -1,
     84         NULL,
     85     },
     86     {
     87         /* fractional seconds, check only */
     88         "20170217180105.001Z",
     89         0,
     90         0,
     91         -1,
     92         NULL,
     93     },
     94     {
     95         /* timezone, check only */
     96         "20170217180105+0800",
     97         0,
     98         0,
     99         -1,
    100         NULL,
    101     },
    102     {
    103         /* SS is missing, set string */
    104         "201702171801Z",
    105         1,
    106         0,
    107         -1,
    108         NULL,
    109     },
    110     {
    111         /* fractional seconds, set string */
    112         "20170217180105.001Z",
    113         1,
    114         0,
    115         -1,
    116         NULL,
    117     },
    118     {
    119         /* timezone, set string */
    120         "20170217180105+0800",
    121         1,
    122         0,
    123         -1,
    124         NULL,
    125     },
    126     {
    127         /* good format, check returned 'turned' string */
    128         "20170217180154Z",
    129         1,
    130         1,
    131         V_ASN1_UTCTIME,
    132         "170217180154Z",
    133     },
    134     {
    135         /* good format, check returned string */
    136         "20510217180154Z",
    137         1,
    138         1,
    139         V_ASN1_GENERALIZEDTIME,
    140         "20510217180154Z",
    141     },
    142     {
    143         /* good format but out of UTC range, check returned string */
    144         "19230419180154Z",
    145         1,
    146         1,
    147         V_ASN1_GENERALIZEDTIME,
    148         "19230419180154Z",
    149     },
    150     /* UTC */
    151     {
    152         /* SS is missing, check only */
    153         "1702171801Z",
    154         0,
    155         0,
    156         -1,
    157         NULL,
    158     },
    159     {
    160         /* not leap year, check only */
    161         "050229180101Z",
    162         0,
    163         0,
    164         -1,
    165         NULL,
    166     },
    167     {
    168         /* leap year, check only */
    169         "040229180101Z",
    170         0,
    171         1,
    172         -1,
    173         NULL,
    174     },
    175     {
    176         /* timezone, check only */
    177         "170217180154+0800",
    178         0,
    179         0,
    180         -1,
    181         NULL,
    182     },
    183     {
    184         /* SS is missing, set string */
    185         "1702171801Z",
    186         1,
    187         0,
    188         -1,
    189         NULL,
    190     },
    191     {
    192         /* timezone, set string */
    193         "170217180154+0800",
    194         1,
    195         0,
    196         -1,
    197         NULL,
    198     },
    199     {
    200         /* 2017, good format, check returned string */
    201         "170217180154Z",
    202         1,
    203         1,
    204         V_ASN1_UTCTIME,
    205         "170217180154Z",
    206     },
    207     {
    208         /* 1998, good format, check returned string */
    209         "981223180154Z",
    210         1,
    211         1,
    212         V_ASN1_UTCTIME,
    213         "981223180154Z",
    214     },
    215 };
    216 
    217 static TESTDATA x509_cmp_tests[] = {
    218     {
    219         "20170217180154Z",
    220         V_ASN1_GENERALIZEDTIME,
    221         /* The same in seconds since epoch. */
    222         1487354514,
    223         -1,
    224     },
    225     {
    226         "20170217180154Z",
    227         V_ASN1_GENERALIZEDTIME,
    228         /* One second more. */
    229         1487354515,
    230         -1,
    231     },
    232     {
    233         "20170217180154Z",
    234         V_ASN1_GENERALIZEDTIME,
    235         /* One second less. */
    236         1487354513,
    237         1,
    238     },
    239     /* Same as UTC time. */
    240     {
    241         "170217180154Z",
    242         V_ASN1_UTCTIME,
    243         /* The same in seconds since epoch. */
    244         1487354514,
    245         -1,
    246     },
    247     {
    248         "170217180154Z",
    249         V_ASN1_UTCTIME,
    250         /* One second more. */
    251         1487354515,
    252         -1,
    253     },
    254     {
    255         "170217180154Z",
    256         V_ASN1_UTCTIME,
    257         /* One second less. */
    258         1487354513,
    259         1,
    260     },
    261     /* UTCTime from the 20th century. */
    262     {
    263         "990217180154Z",
    264         V_ASN1_UTCTIME,
    265         /* The same in seconds since epoch. */
    266         919274514,
    267         -1,
    268     },
    269     {
    270         "990217180154Z",
    271         V_ASN1_UTCTIME,
    272         /* One second more. */
    273         919274515,
    274         -1,
    275     },
    276     {
    277         "990217180154Z",
    278         V_ASN1_UTCTIME,
    279         /* One second less. */
    280         919274513,
    281         1,
    282     },
    283     /* Various invalid formats. */
    284     {
    285         /* No trailing Z. */
    286         "20170217180154",
    287         V_ASN1_GENERALIZEDTIME,
    288         0,
    289         0,
    290     },
    291     {
    292         /* No trailing Z, UTCTime. */
    293         "170217180154",
    294         V_ASN1_UTCTIME,
    295         0,
    296         0,
    297     },
    298     {
    299         /* No seconds. */
    300         "201702171801Z",
    301         V_ASN1_GENERALIZEDTIME,
    302         0,
    303         0,
    304     },
    305     {
    306         /* No seconds, UTCTime. */
    307         "1702171801Z",
    308         V_ASN1_UTCTIME,
    309         0,
    310         0,
    311     },
    312     {
    313         /* Fractional seconds. */
    314         "20170217180154.001Z",
    315         V_ASN1_GENERALIZEDTIME,
    316         0,
    317         0,
    318     },
    319     {
    320         /* Fractional seconds, UTCTime. */
    321         "170217180154.001Z",
    322         V_ASN1_UTCTIME,
    323         0,
    324         0,
    325     },
    326     {
    327         /* Timezone offset. */
    328         "20170217180154+0100",
    329         V_ASN1_GENERALIZEDTIME,
    330         0,
    331         0,
    332     },
    333     {
    334         /* Timezone offset, UTCTime. */
    335         "170217180154+0100",
    336         V_ASN1_UTCTIME,
    337         0,
    338         0,
    339     },
    340     {
    341         /* Extra digits. */
    342         "2017021718015400Z",
    343         V_ASN1_GENERALIZEDTIME,
    344         0,
    345         0,
    346     },
    347     {
    348         /* Extra digits, UTCTime. */
    349         "17021718015400Z",
    350         V_ASN1_UTCTIME,
    351         0,
    352         0,
    353     },
    354     {
    355         /* Non-digits. */
    356         "2017021718015aZ",
    357         V_ASN1_GENERALIZEDTIME,
    358         0,
    359         0,
    360     },
    361     {
    362         /* Non-digits, UTCTime. */
    363         "17021718015aZ",
    364         V_ASN1_UTCTIME,
    365         0,
    366         0,
    367     },
    368     {
    369         /* Trailing garbage. */
    370         "20170217180154Zlongtrailinggarbage",
    371         V_ASN1_GENERALIZEDTIME,
    372         0,
    373         0,
    374     },
    375     {
    376         /* Trailing garbage, UTCTime. */
    377         "170217180154Zlongtrailinggarbage",
    378         V_ASN1_UTCTIME,
    379         0,
    380         0,
    381     },
    382     {
    383         /* Swapped type. */
    384         "20170217180154Z",
    385         V_ASN1_UTCTIME,
    386         0,
    387         0,
    388     },
    389     {
    390         /* Swapped type. */
    391         "170217180154Z",
    392         V_ASN1_GENERALIZEDTIME,
    393         0,
    394         0,
    395     },
    396     {
    397         /* Bad type. */
    398         "20170217180154Z",
    399         V_ASN1_OCTET_STRING,
    400         0,
    401         0,
    402     },
    403 };
    404 
    405 static int test_x509_cmp_time(int idx)
    406 {
    407     ASN1_TIME t;
    408     int result;
    409 
    410     memset(&t, 0, sizeof(t));
    411     t.type = x509_cmp_tests[idx].type;
    412     t.data = (unsigned char *)(x509_cmp_tests[idx].data);
    413     t.length = strlen(x509_cmp_tests[idx].data);
    414     t.flags = 0;
    415 
    416     result = X509_cmp_time(&t, &x509_cmp_tests[idx].cmp_time);
    417     if (!TEST_int_eq(result, x509_cmp_tests[idx].expected)) {
    418         TEST_info("test_x509_cmp_time(%d) failed: expected %d, got %d\n",
    419             idx, x509_cmp_tests[idx].expected, result);
    420         return 0;
    421     }
    422     return 1;
    423 }
    424 
    425 static int test_x509_cmp_time_current(void)
    426 {
    427     time_t now = time(NULL);
    428     /* Pick a day earlier and later, relative to any system clock. */
    429     ASN1_TIME *asn1_before = NULL, *asn1_after = NULL;
    430     int cmp_result, failed = 0;
    431 
    432     asn1_before = ASN1_TIME_adj(NULL, now, -1, 0);
    433     asn1_after = ASN1_TIME_adj(NULL, now, 1, 0);
    434 
    435     cmp_result = X509_cmp_time(asn1_before, NULL);
    436     if (!TEST_int_eq(cmp_result, -1))
    437         failed = 1;
    438 
    439     cmp_result = X509_cmp_time(asn1_after, NULL);
    440     if (!TEST_int_eq(cmp_result, 1))
    441         failed = 1;
    442 
    443     ASN1_TIME_free(asn1_before);
    444     ASN1_TIME_free(asn1_after);
    445 
    446     return failed == 0;
    447 }
    448 
    449 static int test_X509_cmp_timeframe_vpm(const X509_VERIFY_PARAM *vpm,
    450     ASN1_TIME *asn1_before,
    451     ASN1_TIME *asn1_mid,
    452     ASN1_TIME *asn1_after)
    453 {
    454     int always_0 = vpm != NULL
    455         && (X509_VERIFY_PARAM_get_flags(vpm) & X509_V_FLAG_USE_CHECK_TIME) == 0
    456         && (X509_VERIFY_PARAM_get_flags(vpm) & X509_V_FLAG_NO_CHECK_TIME) != 0;
    457 
    458     return asn1_before != NULL && asn1_mid != NULL && asn1_after != NULL
    459         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_before, asn1_after), 0)
    460         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_before, NULL), 0)
    461         && TEST_int_eq(X509_cmp_timeframe(vpm, NULL, asn1_after), 0)
    462         && TEST_int_eq(X509_cmp_timeframe(vpm, NULL, NULL), 0)
    463         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_after, asn1_after),
    464             always_0 ? 0 : -1)
    465         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_before, asn1_before),
    466             always_0 ? 0 : 1)
    467         && TEST_int_eq(X509_cmp_timeframe(vpm, asn1_after, asn1_before),
    468             always_0 ? 0 : 1);
    469 }
    470 
    471 static int test_X509_cmp_timeframe(void)
    472 {
    473     time_t now = time(NULL);
    474     ASN1_TIME *asn1_mid = ASN1_TIME_adj(NULL, now, 0, 0);
    475     /* Pick a day earlier and later, relative to any system clock. */
    476     ASN1_TIME *asn1_before = ASN1_TIME_adj(NULL, now, -1, 0);
    477     ASN1_TIME *asn1_after = ASN1_TIME_adj(NULL, now, 1, 0);
    478     X509_VERIFY_PARAM *vpm = X509_VERIFY_PARAM_new();
    479     int res = 0;
    480 
    481     if (vpm == NULL)
    482         goto finish;
    483     res = test_X509_cmp_timeframe_vpm(NULL, asn1_before, asn1_mid, asn1_after)
    484         && test_X509_cmp_timeframe_vpm(vpm, asn1_before, asn1_mid, asn1_after);
    485 
    486     X509_VERIFY_PARAM_set_time(vpm, now);
    487     res = res
    488         && test_X509_cmp_timeframe_vpm(vpm, asn1_before, asn1_mid, asn1_after)
    489         && X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME)
    490         && test_X509_cmp_timeframe_vpm(vpm, asn1_before, asn1_mid, asn1_after);
    491 
    492     X509_VERIFY_PARAM_free(vpm);
    493 finish:
    494     ASN1_TIME_free(asn1_mid);
    495     ASN1_TIME_free(asn1_before);
    496     ASN1_TIME_free(asn1_after);
    497 
    498     return res;
    499 }
    500 
    501 static int test_x509_time(int idx)
    502 {
    503     ASN1_TIME *t = NULL;
    504     int result, rv = 0;
    505 
    506     if (x509_format_tests[idx].set_string) {
    507         /* set-string mode */
    508         t = ASN1_TIME_new();
    509         if (t == NULL) {
    510             TEST_info("test_x509_time(%d) failed: internal error\n", idx);
    511             return 0;
    512         }
    513     }
    514 
    515     result = ASN1_TIME_set_string_X509(t, x509_format_tests[idx].data);
    516     /* time string parsing result is always checked against what's expected */
    517     if (!TEST_int_eq(result, x509_format_tests[idx].expected)) {
    518         TEST_info("test_x509_time(%d) failed: expected %d, got %d\n",
    519             idx, x509_format_tests[idx].expected, result);
    520         goto out;
    521     }
    522 
    523     /* if t is not NULL but expected_type is ignored(-1), it is an 'OK' case */
    524     if (t != NULL && x509_format_tests[idx].expected_type != -1) {
    525         if (!TEST_int_eq(t->type, x509_format_tests[idx].expected_type)) {
    526             TEST_info("test_x509_time(%d) failed: expected_type %d, got %d\n",
    527                 idx, x509_format_tests[idx].expected_type, t->type);
    528             goto out;
    529         }
    530     }
    531 
    532     /* if t is not NULL but expected_string is NULL, it is an 'OK' case too */
    533     if (t != NULL && x509_format_tests[idx].expected_string) {
    534         if (!TEST_mem_eq((const char *)t->data, t->length,
    535                 x509_format_tests[idx].expected_string,
    536                 strlen(x509_format_tests[idx].expected_string))) {
    537             TEST_info("test_x509_time(%d) failed: expected_string %s, got %.*s\n",
    538                 idx, x509_format_tests[idx].expected_string, t->length,
    539                 t->data);
    540             goto out;
    541         }
    542     }
    543 
    544     rv = 1;
    545 out:
    546     if (t != NULL)
    547         ASN1_TIME_free(t);
    548     return rv;
    549 }
    550 
    551 static const struct {
    552     int y, m, d;
    553     int yd, wd;
    554 } day_of_week_tests[] = {
    555     /*YYYY  MM  DD  DoY  DoW */
    556     { 1900, 1, 1, 0, 1 },
    557     { 1900, 2, 28, 58, 3 },
    558     { 1900, 3, 1, 59, 4 },
    559     { 1900, 12, 31, 364, 1 },
    560     { 1901, 1, 1, 0, 2 },
    561     { 1970, 1, 1, 0, 4 },
    562     { 1999, 1, 10, 9, 0 },
    563     { 1999, 12, 31, 364, 5 },
    564     { 2000, 1, 1, 0, 6 },
    565     { 2000, 2, 28, 58, 1 },
    566     { 2000, 2, 29, 59, 2 },
    567     { 2000, 3, 1, 60, 3 },
    568     { 2000, 12, 31, 365, 0 },
    569     { 2001, 1, 1, 0, 1 },
    570     { 2008, 1, 1, 0, 2 },
    571     { 2008, 2, 28, 58, 4 },
    572     { 2008, 2, 29, 59, 5 },
    573     { 2008, 3, 1, 60, 6 },
    574     { 2008, 12, 31, 365, 3 },
    575     { 2009, 1, 1, 0, 4 },
    576     { 2011, 1, 1, 0, 6 },
    577     { 2011, 2, 28, 58, 1 },
    578     { 2011, 3, 1, 59, 2 },
    579     { 2011, 12, 31, 364, 6 },
    580     { 2012, 1, 1, 0, 0 },
    581     { 2019, 1, 2, 1, 3 },
    582     { 2019, 2, 2, 32, 6 },
    583     { 2019, 3, 2, 60, 6 },
    584     { 2019, 4, 2, 91, 2 },
    585     { 2019, 5, 2, 121, 4 },
    586     { 2019, 6, 2, 152, 0 },
    587     { 2019, 7, 2, 182, 2 },
    588     { 2019, 8, 2, 213, 5 },
    589     { 2019, 9, 2, 244, 1 },
    590     { 2019, 10, 2, 274, 3 },
    591     { 2019, 11, 2, 305, 6 },
    592     { 2019, 12, 2, 335, 1 },
    593     { 2020, 1, 2, 1, 4 },
    594     { 2020, 2, 2, 32, 0 },
    595     { 2020, 3, 2, 61, 1 },
    596     { 2020, 4, 2, 92, 4 },
    597     { 2020, 5, 2, 122, 6 },
    598     { 2020, 6, 2, 153, 2 },
    599     { 2020, 7, 2, 183, 4 },
    600     { 2020, 8, 2, 214, 0 },
    601     { 2020, 9, 2, 245, 3 },
    602     { 2020, 10, 2, 275, 5 },
    603     { 2020, 11, 2, 306, 1 },
    604     { 2020, 12, 2, 336, 3 }
    605 };
    606 
    607 static int test_days(int n)
    608 {
    609     char d[16];
    610     ASN1_TIME *a = NULL;
    611     struct tm t;
    612     int r;
    613 
    614     BIO_snprintf(d, sizeof(d), "%04d%02d%02d050505Z",
    615         day_of_week_tests[n].y, day_of_week_tests[n].m,
    616         day_of_week_tests[n].d);
    617 
    618     if (!TEST_ptr(a = ASN1_TIME_new()))
    619         return 0;
    620 
    621     r = TEST_true(ASN1_TIME_set_string(a, d))
    622         && TEST_true(ASN1_TIME_to_tm(a, &t))
    623         && TEST_int_eq(t.tm_yday, day_of_week_tests[n].yd)
    624         && TEST_int_eq(t.tm_wday, day_of_week_tests[n].wd);
    625 
    626     ASN1_TIME_free(a);
    627     return r;
    628 }
    629 
    630 #define construct_asn1_time(s, t, e) \
    631     { { sizeof(s) - 1, t, (unsigned char *)s, 0 }, e }
    632 
    633 static const struct {
    634     ASN1_TIME asn1;
    635     const char *readable;
    636 } x509_print_tests_rfc_822[] = {
    637     /* Generalized Time */
    638     construct_asn1_time("20170731222050Z", V_ASN1_GENERALIZEDTIME,
    639         "Jul 31 22:20:50 2017 GMT"),
    640     /* Generalized Time, no seconds */
    641     construct_asn1_time("201707312220Z", V_ASN1_GENERALIZEDTIME,
    642         "Bad time value"),
    643     /* Generalized Time, fractional seconds (3 digits) */
    644     construct_asn1_time("20170731222050.123Z", V_ASN1_GENERALIZEDTIME,
    645         "Jul 31 22:20:50.123 2017 GMT"),
    646     /* Generalized Time, fractional seconds (1 digit) */
    647     construct_asn1_time("20170731222050.1Z", V_ASN1_GENERALIZEDTIME,
    648         "Jul 31 22:20:50.1 2017 GMT"),
    649     /* Generalized Time, fractional seconds (0 digit) */
    650     construct_asn1_time("20170731222050.Z", V_ASN1_GENERALIZEDTIME,
    651         "Bad time value"),
    652     /* UTC Time */
    653     construct_asn1_time("170731222050Z", V_ASN1_UTCTIME,
    654         "Jul 31 22:20:50 2017 GMT"),
    655     /* UTC Time, no seconds */
    656     construct_asn1_time("1707312220Z", V_ASN1_UTCTIME,
    657         "Bad time value"),
    658 };
    659 
    660 static const struct {
    661     ASN1_TIME asn1;
    662     const char *readable;
    663 } x509_print_tests_iso_8601[] = {
    664     /* Generalized Time */
    665     construct_asn1_time("20170731222050Z", V_ASN1_GENERALIZEDTIME,
    666         "2017-07-31 22:20:50Z"),
    667     /* Generalized Time, no seconds */
    668     construct_asn1_time("201707312220Z", V_ASN1_GENERALIZEDTIME,
    669         "Bad time value"),
    670     /* Generalized Time, fractional seconds (3 digits) */
    671     construct_asn1_time("20170731222050.123Z", V_ASN1_GENERALIZEDTIME,
    672         "2017-07-31 22:20:50.123Z"),
    673     /* Generalized Time, fractional seconds (1 digit) */
    674     construct_asn1_time("20170731222050.1Z", V_ASN1_GENERALIZEDTIME,
    675         "2017-07-31 22:20:50.1Z"),
    676     /* Generalized Time, fractional seconds (0 digit) */
    677     construct_asn1_time("20170731222050.Z", V_ASN1_GENERALIZEDTIME,
    678         "Bad time value"),
    679     /* UTC Time */
    680     construct_asn1_time("170731222050Z", V_ASN1_UTCTIME,
    681         "2017-07-31 22:20:50Z"),
    682     /* UTC Time, no seconds */
    683     construct_asn1_time("1707312220Z", V_ASN1_UTCTIME,
    684         "Bad time value"),
    685 };
    686 
    687 static int test_x509_time_print_rfc_822(int idx)
    688 {
    689     BIO *m;
    690     int ret = 0, rv;
    691     char *pp;
    692     const char *readable;
    693 
    694     if (!TEST_ptr(m = BIO_new(BIO_s_mem())))
    695         goto err;
    696 
    697     rv = ASN1_TIME_print_ex(m, &x509_print_tests_rfc_822[idx].asn1, ASN1_DTFLGS_RFC822);
    698     readable = x509_print_tests_rfc_822[idx].readable;
    699 
    700     if (rv == 0 && !TEST_str_eq(readable, "Bad time value")) {
    701         /* only if the test case intends to fail... */
    702         goto err;
    703     }
    704     if (!TEST_int_ne(rv = BIO_get_mem_data(m, &pp), 0)
    705         || !TEST_int_eq(rv, (int)strlen(readable))
    706         || !TEST_strn_eq(pp, readable, rv))
    707         goto err;
    708 
    709     ret = 1;
    710 err:
    711     BIO_free(m);
    712     return ret;
    713 }
    714 
    715 static int test_x509_time_print_iso_8601(int idx)
    716 {
    717     BIO *m;
    718     int ret = 0, rv;
    719     char *pp;
    720     const char *readable;
    721 
    722     if (!TEST_ptr(m = BIO_new(BIO_s_mem())))
    723         goto err;
    724 
    725     rv = ASN1_TIME_print_ex(m, &x509_print_tests_iso_8601[idx].asn1, ASN1_DTFLGS_ISO8601);
    726     readable = x509_print_tests_iso_8601[idx].readable;
    727 
    728     if (rv == 0 && !TEST_str_eq(readable, "Bad time value")) {
    729         /* only if the test case intends to fail... */
    730         goto err;
    731     }
    732     if (!TEST_int_ne(rv = BIO_get_mem_data(m, &pp), 0)
    733         || !TEST_int_eq(rv, (int)strlen(readable))
    734         || !TEST_strn_eq(pp, readable, rv))
    735         goto err;
    736 
    737     ret = 1;
    738 err:
    739     BIO_free(m);
    740     return ret;
    741 }
    742 
    743 int setup_tests(void)
    744 {
    745     ADD_TEST(test_x509_cmp_time_current);
    746     ADD_TEST(test_X509_cmp_timeframe);
    747     ADD_ALL_TESTS(test_x509_cmp_time, OSSL_NELEM(x509_cmp_tests));
    748     ADD_ALL_TESTS(test_x509_time, OSSL_NELEM(x509_format_tests));
    749     ADD_ALL_TESTS(test_days, OSSL_NELEM(day_of_week_tests));
    750     ADD_ALL_TESTS(test_x509_time_print_rfc_822, OSSL_NELEM(x509_print_tests_rfc_822));
    751     ADD_ALL_TESTS(test_x509_time_print_iso_8601, OSSL_NELEM(x509_print_tests_iso_8601));
    752     return 1;
    753 }
    754