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