6812805847f93d01eb3d3fa76aca20ff0ad6fab2
[openssl.git] / test / x509_time_test.c
1 /*
2  * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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 "e_os.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", 0, 1, -1, NULL,
57     },
58     {
59         /* SS is missing, check only */
60         "201702171801Z", 0, 0, -1, NULL,
61     },
62     {
63         /* fractional seconds, check only */
64         "20170217180105.001Z", 0, 0, -1, NULL,
65     },
66     {
67         /* time zone, check only */
68         "20170217180105+0800", 0, 0, -1, NULL,
69     },
70     {
71         /* SS is missing, set string */
72         "201702171801Z", 1, 0, -1, NULL,
73     },
74     {
75         /* fractional seconds, set string */
76         "20170217180105.001Z", 1, 0, -1, NULL,
77     },
78     {
79         /* time zone, set string */
80         "20170217180105+0800", 1, 0, -1, NULL,
81     },
82     {
83         /* good format, check returned 'turned' string */
84         "20170217180154Z", 1, 1, V_ASN1_UTCTIME, "170217180154Z",
85     },
86     {
87         /* good format, check returned string */
88         "20510217180154Z", 1, 1, V_ASN1_GENERALIZEDTIME, "20510217180154Z",
89     },
90     {
91         /* good format but out of UTC range, check returned string */
92         "19230419180154Z", 1, 1, V_ASN1_GENERALIZEDTIME, "19230419180154Z",
93     },
94     /* UTC */
95     {
96         /* SS is missing, check only */
97         "1702171801Z", 0, 0, -1, NULL,
98     },
99     {
100         /* time zone, check only */
101         "170217180154+0800", 0, 0, -1, NULL,
102     },
103     {
104         /* SS is missing, set string */
105         "1702171801Z", 1, 0, -1, NULL,
106     },
107     {
108         /* time zone, set string */
109         "170217180154+0800", 1, 0, -1, NULL,
110     },
111     {
112         /* 2017, good format, check returned string */
113         "170217180154Z", 1, 1, V_ASN1_UTCTIME, "170217180154Z",
114     },
115     {
116         /* 1998, good format, check returned string */
117         "981223180154Z", 1, 1, V_ASN1_UTCTIME, "981223180154Z",
118     },
119 };
120
121 static TESTDATA x509_cmp_tests[] = {
122     {
123         "20170217180154Z", V_ASN1_GENERALIZEDTIME,
124         /* The same in seconds since epoch. */
125         1487354514, -1,
126     },
127     {
128         "20170217180154Z", V_ASN1_GENERALIZEDTIME,
129         /* One second more. */
130         1487354515, -1,
131     },
132     {
133         "20170217180154Z", V_ASN1_GENERALIZEDTIME,
134         /* One second less. */
135         1487354513, 1,
136     },
137     /* Same as UTC time. */
138     {
139         "170217180154Z", V_ASN1_UTCTIME,
140         /* The same in seconds since epoch. */
141         1487354514, -1,
142     },
143     {
144         "170217180154Z", V_ASN1_UTCTIME,
145         /* One second more. */
146         1487354515, -1,
147     },
148     {
149         "170217180154Z", V_ASN1_UTCTIME,
150         /* One second less. */
151         1487354513, 1,
152     },
153     /* UTCTime from the 20th century. */
154     {
155         "990217180154Z", V_ASN1_UTCTIME,
156         /* The same in seconds since epoch. */
157         919274514, -1,
158     },
159     {
160         "990217180154Z", V_ASN1_UTCTIME,
161         /* One second more. */
162         919274515, -1,
163     },
164     {
165         "990217180154Z", V_ASN1_UTCTIME,
166         /* One second less. */
167         919274513, 1,
168     },
169     /* Various invalid formats. */
170     {
171         /* No trailing Z. */
172         "20170217180154", V_ASN1_GENERALIZEDTIME, 0, 0,
173     },
174     {
175         /* No trailing Z, UTCTime. */
176         "170217180154", V_ASN1_UTCTIME, 0, 0,
177     },
178     {
179         /* No seconds. */
180         "201702171801Z", V_ASN1_GENERALIZEDTIME, 0, 0,
181     },
182     {
183         /* No seconds, UTCTime. */
184         "1702171801Z", V_ASN1_UTCTIME, 0, 0,
185     },
186     {
187         /* Fractional seconds. */
188         "20170217180154.001Z", V_ASN1_GENERALIZEDTIME, 0, 0,
189     },
190     {
191         /* Fractional seconds, UTCTime. */
192         "170217180154.001Z", V_ASN1_UTCTIME, 0, 0,
193     },
194     {
195         /* Timezone offset. */
196         "20170217180154+0100", V_ASN1_GENERALIZEDTIME, 0, 0,
197     },
198     {
199         /* Timezone offset, UTCTime. */
200         "170217180154+0100", V_ASN1_UTCTIME, 0, 0,
201     },
202     {
203         /* Extra digits. */
204         "2017021718015400Z", V_ASN1_GENERALIZEDTIME, 0, 0,
205     },
206     {
207         /* Extra digits, UTCTime. */
208         "17021718015400Z", V_ASN1_UTCTIME, 0, 0,
209     },
210     {
211         /* Non-digits. */
212         "2017021718015aZ", V_ASN1_GENERALIZEDTIME, 0, 0,
213     },
214     {
215         /* Non-digits, UTCTime. */
216         "17021718015aZ", V_ASN1_UTCTIME, 0, 0,
217     },
218     {
219         /* Trailing garbage. */
220         "20170217180154Zlongtrailinggarbage", V_ASN1_GENERALIZEDTIME, 0, 0,
221     },
222     {
223         /* Trailing garbage, UTCTime. */
224         "170217180154Zlongtrailinggarbage", V_ASN1_UTCTIME, 0, 0,
225     },
226     {
227          /* Swapped type. */
228         "20170217180154Z", V_ASN1_UTCTIME, 0, 0,
229     },
230     {
231         /* Swapped type. */
232         "170217180154Z", V_ASN1_GENERALIZEDTIME, 0, 0,
233     },
234     {
235         /* Bad type. */
236         "20170217180154Z", V_ASN1_OCTET_STRING, 0, 0,
237     },
238 };
239
240 static int test_x509_cmp_time(int idx)
241 {
242     ASN1_TIME t;
243     int result;
244
245     memset(&t, 0, sizeof(t));
246     t.type = x509_cmp_tests[idx].type;
247     t.data = (unsigned char*)(x509_cmp_tests[idx].data);
248     t.length = strlen(x509_cmp_tests[idx].data);
249     t.flags = 0;
250
251     result = X509_cmp_time(&t, &x509_cmp_tests[idx].cmp_time);
252     if (!TEST_int_eq(result, x509_cmp_tests[idx].expected)) {
253         TEST_info("test_x509_cmp_time(%d) failed: expected %d, got %d\n",
254                 idx, x509_cmp_tests[idx].expected, result);
255         return 0;
256     }
257     return 1;
258 }
259
260 static int test_x509_cmp_time_current()
261 {
262     time_t now = time(NULL);
263     /* Pick a day earlier and later, relative to any system clock. */
264     ASN1_TIME *asn1_before = NULL, *asn1_after = NULL;
265     int cmp_result, failed = 0;
266
267     asn1_before = ASN1_TIME_adj(NULL, now, -1, 0);
268     asn1_after = ASN1_TIME_adj(NULL, now, 1, 0);
269
270     cmp_result  = X509_cmp_time(asn1_before, NULL);
271     if (!TEST_int_eq(cmp_result, -1))
272         failed = 1;
273
274     cmp_result = X509_cmp_time(asn1_after, NULL);
275     if (!TEST_int_eq(cmp_result, 1))
276         failed = 1;
277
278     ASN1_TIME_free(asn1_before);
279     ASN1_TIME_free(asn1_after);
280
281     return failed == 0;
282 }
283
284 static int test_x509_time(int idx)
285 {
286     ASN1_TIME *t = NULL;
287     int result, rv = 0;
288
289     if (x509_format_tests[idx].set_string) {
290         /* set-string mode */
291         t = ASN1_TIME_new();
292         if (t == NULL) {
293             TEST_info("test_x509_time(%d) failed: internal error\n", idx);
294             return 0;
295         }
296     }
297
298     result = ASN1_TIME_set_string_X509(t, x509_format_tests[idx].data);
299     /* time string parsing result is always checked against what's expected */
300     if (!TEST_int_eq(result, x509_format_tests[idx].expected)) {
301         TEST_info("test_x509_time(%d) failed: expected %d, got %d\n",
302                 idx, x509_format_tests[idx].expected, result);
303         goto out;
304     }
305
306     /* if t is not NULL but expected_type is ignored(-1), it is an 'OK' case */
307     if (t != NULL && x509_format_tests[idx].expected_type != -1) {
308         if (!TEST_int_eq(t->type, x509_format_tests[idx].expected_type)) {
309             TEST_info("test_x509_time(%d) failed: expected_type %d, got %d\n",
310                     idx, x509_format_tests[idx].expected_type, t->type);
311             goto out;
312         }
313     }
314
315     /* if t is not NULL but expected_string is NULL, it is an 'OK' case too */
316     if (t != NULL && x509_format_tests[idx].expected_string) {
317         if (!TEST_str_eq((const char *)t->data,
318                     x509_format_tests[idx].expected_string)) {
319             TEST_info("test_x509_time(%d) failed: expected_string %s, got %s\n",
320                     idx, x509_format_tests[idx].expected_string, t->data);
321             goto out;
322         }
323     }
324
325     rv = 1;
326 out:
327     if (t != NULL)
328         ASN1_TIME_free(t);
329     return rv;
330 }
331
332 void register_tests()
333 {
334     ADD_TEST(test_x509_cmp_time_current);
335     ADD_ALL_TESTS(test_x509_cmp_time, OSSL_NELEM(x509_cmp_tests));
336     ADD_ALL_TESTS(test_x509_time, OSSL_NELEM(x509_format_tests));
337 }