xref: /openbsd-src/regress/lib/libcrypto/asn1/rfc5280time.c (revision 72c7c57a68e32c57ac752161b5a93464ad11e7e1)
1 /* $OpenBSD: rfc5280time.c,v 1.8 2024/04/08 19:57:40 beck Exp $ */
2 /*
3  * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4  * Copyright (c) 2015 Bob Beck <beck@opebsd.org>
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/x509.h>
21 
22 #include <err.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 struct rfc5280_time_test {
27 	const char *str;
28 	const char *data;
29 	time_t time;
30 };
31 
32 struct rfc5280_time_test rfc5280_invtime_tests[] = {
33 	{
34 		.str = "",
35 	},
36 	{
37 		.str = "2015",
38 	},
39 	{
40 		.str = "201509",
41 	},
42 	{
43 		.str = "20150923",
44 	},
45 	{
46 		.str = "20150923032700",
47 	},
48 	{
49 		/* UTC time must have seconds */
50 		.str = "7001010000Z",
51 	},
52 	{
53 		.str = "201509230327Z",
54 	},
55 	{
56 		.str = "20150923032700.Z",
57 	},
58 	{
59 		.str = "20150923032700.123",
60 	},
61 	{
62 		.str = "20150923032700+1100Z",
63 	},
64 	{
65 		.str = "20150923032700-11001",
66 	},
67 	{
68 		/* UTC time cannot have fractional seconds. */
69 		.str = "150923032700.123Z",
70 	},
71 	{
72 		/* Gen time cannot have +- TZ. */
73 		.str = "20150923032712+1115",
74 	},
75 	{
76 		/* Gen time cannot have fractional seconds */
77 		.str = "20150923032712.123Z",
78 	},
79 	{
80 		.str = "aaaaaaaaaaaaaaZ",
81 	},
82 	{
83 		/* Must be a UTC time per RFC 5280 */
84 		.str = "19700101000000Z",
85 		.data = "19700101000000Z",
86 		.time = 0,
87 	},
88 	{
89 		/* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */
90 		.str = "20150923032700Z",
91 		.data = "20150923032700Z",
92 		.time = 1442978820,
93 	},
94 	{
95 		/* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */
96 		.str = "00000101000000Z",
97 		.data = "00000101000000Z",
98 		.time = -62167219200LL,
99 	},
100 	{
101 		/* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */
102 		.str = "20491231235959Z",
103 		.data = "20491231235959Z",
104 		.time = 2524607999LL,
105 	},
106 	{
107 		/* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */
108 		.str = "19500101000000Z",
109 		.data = "19500101000000Z",
110 		.time = -631152000LL,
111 	},
112 };
113 
114 struct rfc5280_time_test rfc5280_gentime_tests[] = {
115 	{
116 		/* Biggest RFC 5280 time */
117 		.str = "99991231235959Z",
118 		.data = "99991231235959Z",
119 		.time = 253402300799LL,
120 	},
121 	{
122 		.str = "21600218104000Z",
123 		.data = "21600218104000Z",
124 		.time = 6000000000LL,
125 	},
126 	{
127 		/* Smallest RFC 5280 gen time */
128 		.str = "20500101000000Z",
129 		.data = "20500101000000Z",
130 		.time =  2524608000LL,
131 	},
132 };
133 struct rfc5280_time_test rfc5280_utctime_tests[] = {
134 	{
135 		.str = "500101000000Z",
136 		.data = "500101000000Z",
137 		.time = -631152000,
138 	},
139 	{
140 		.str = "540226230640Z",
141 		.data = "540226230640Z",
142 		.time = -500000000,
143 	},
144 	{
145 		.str = "491231235959Z",
146 		.data = "491231235959Z",
147 		.time = 2524607999LL,
148 	},
149 	{
150 		.str = "700101000000Z",
151 		.data = "700101000000Z",
152 		.time = 0,
153 	},
154 	{
155 		.str = "150923032700Z",
156 		.data = "150923032700Z",
157 		.time = 1442978820,
158 	},
159 	{
160 		.str = "150923102700Z",
161 		.data = "150923102700Z",
162 		.time = 1443004020,
163 	},
164 	{
165 		.str = "150922162712Z",
166 		.data = "150922162712Z",
167 		.time = 1442939232,
168 	},
169 	{
170 		.str = "140524144512Z",
171 		.data = "140524144512Z",
172 		.time = 1400942712,
173 	},
174 	{
175 		.str = "240401144512Z",
176 		.data = "240401144512Z",
177 		.time = 1711982712,
178 	},
179 };
180 
181 #define N_INVTIME_TESTS \
182     (sizeof(rfc5280_invtime_tests) / sizeof(*rfc5280_invtime_tests))
183 #define N_GENTIME_TESTS \
184     (sizeof(rfc5280_gentime_tests) / sizeof(*rfc5280_gentime_tests))
185 #define N_UTCTIME_TESTS \
186     (sizeof(rfc5280_utctime_tests) / sizeof(*rfc5280_utctime_tests))
187 
188 static int
asn1_compare_str(int test_no,struct asn1_string_st * asn1str,const char * str)189 asn1_compare_str(int test_no, struct asn1_string_st *asn1str, const char *str)
190 {
191 	int length = strlen(str);
192 
193 	if (asn1str->length != length) {
194 		fprintf(stderr, "FAIL: test %d - string lengths differ "
195 		    "(%d != %d)\n", test_no, asn1str->length, length);
196 		return (1);
197 	}
198 	if (strncmp(asn1str->data, str, length) != 0) {
199 		fprintf(stderr, "FAIL: test %d - strings differ "
200 		    "('%s' != '%s')\n", test_no, asn1str->data, str);
201 		return (1);
202 	}
203 
204 	return (0);
205 }
206 
207 static int
rfc5280_invtime_test(int test_no,struct rfc5280_time_test * att)208 rfc5280_invtime_test(int test_no, struct rfc5280_time_test *att)
209 {
210 	ASN1_GENERALIZEDTIME *gt = NULL;
211 	ASN1_UTCTIME *ut = NULL;
212 	ASN1_TIME *t = NULL;
213 	int failure = 1;
214 	time_t now = time(NULL);
215 
216 	if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
217 		goto done;
218 	if ((ut = ASN1_UTCTIME_new()) == NULL)
219 		goto done;
220 	if ((t = ASN1_TIME_new()) == NULL)
221 		goto done;
222 
223 	if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 0) {
224 		if (X509_cmp_time(gt, &now) != 0) {
225 			fprintf(stderr, "FAIL: test %d - successfully parsed as GENTIME "
226 			    "string '%s'\n", test_no, att->str);
227 			goto done;
228 		}
229 	}
230 	if (ASN1_UTCTIME_set_string(ut, att->str) != 0) {
231 		if (X509_cmp_time(ut, &now) != 0) {
232 			fprintf(stderr, "FAIL: test %d - successfully parsed as UTCTIME "
233 			    "string '%s'\n", test_no, att->str);
234 			goto done;
235 		}
236 	}
237 
238 	failure = 0;
239 
240  done:
241 	ASN1_GENERALIZEDTIME_free(gt);
242 	ASN1_UTCTIME_free(ut);
243 	ASN1_TIME_free(t);
244 
245 	return (failure);
246 }
247 
248 static int
rfc5280_gentime_test(int test_no,struct rfc5280_time_test * att)249 rfc5280_gentime_test(int test_no, struct rfc5280_time_test *att)
250 {
251 	unsigned char *p = NULL;
252 	ASN1_GENERALIZEDTIME *gt;
253 	int failure = 1;
254 	int i;
255 
256 	if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
257 		goto done;
258 
259 	if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 1) {
260 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
261 		    test_no, att->str);
262 		goto done;
263 	}
264 	if (asn1_compare_str(test_no, gt, att->str) != 0)
265 		goto done;
266 
267 	if ((i = X509_cmp_time(gt, &att->time)) != -1) {
268 		fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n",
269 		    test_no, i, (long long)att->time);
270 		goto done;
271 	}
272 
273 	att->time--;
274 	if ((i = X509_cmp_time(gt, &att->time)) != 1) {
275 		fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n",
276 		    test_no, i, (long long)att->time);
277 		goto done;
278 	}
279 	att->time++;
280 
281 	ASN1_GENERALIZEDTIME_free(gt);
282 
283 	if ((gt = ASN1_GENERALIZEDTIME_set(NULL, att->time)) == NULL) {
284 		fprintf(stderr, "FAIL: test %d - failed to set time %lld\n",
285 		    test_no, (long long)att->time);
286 		goto done;
287 	}
288 	if (asn1_compare_str(test_no, gt, att->data) != 0)
289 		goto done;
290 
291 	failure = 0;
292 
293  done:
294 	ASN1_GENERALIZEDTIME_free(gt);
295 	free(p);
296 
297 	return (failure);
298 }
299 
300 static int
rfc5280_utctime_test(int test_no,struct rfc5280_time_test * att)301 rfc5280_utctime_test(int test_no, struct rfc5280_time_test *att)
302 {
303 	unsigned char *p = NULL;
304 	ASN1_UTCTIME *ut;
305 	int failure = 1;
306 	int i;
307 
308 	if ((ut = ASN1_UTCTIME_new()) == NULL)
309 		goto done;
310 
311 	if (ASN1_UTCTIME_set_string(ut, att->str) != 1) {
312 		fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n",
313 		    test_no, att->str);
314 		goto done;
315 	}
316 	if (asn1_compare_str(test_no, ut, att->str) != 0)
317 		goto done;
318 
319 	if ((i = X509_cmp_time(ut, &att->time)) != -1) {
320 		fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n",
321 		    test_no, i, (long long)att->time);
322 		goto done;
323 	}
324 
325 	att->time--;
326 	if ((i = X509_cmp_time(ut, &att->time)) != 1) {
327 		fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n",
328 		    test_no, i, (long long)att->time);
329 		goto done;
330 	}
331 	att->time++;
332 
333 	ASN1_UTCTIME_free(ut);
334 
335 	if ((ut = ASN1_UTCTIME_set(NULL, att->time)) == NULL) {
336 		fprintf(stderr, "FAIL: test %d - failed to set time %lld\n",
337 		    test_no, (long long)att->time);
338 		goto done;
339 	}
340 	if (asn1_compare_str(test_no, ut, att->data) != 0)
341 		goto done;
342 
343 	failure = 0;
344 
345  done:
346 	ASN1_UTCTIME_free(ut);
347 	free(p);
348 
349 	return (failure);
350 }
351 
352 int
main(int argc,char ** argv)353 main(int argc, char **argv)
354 {
355 	struct rfc5280_time_test *att;
356 	int failed = 0;
357 	size_t i;
358 
359 	fprintf(stderr, "RFC5280 Invalid time tests...\n");
360 	for (i = 0; i < N_INVTIME_TESTS; i++) {
361 		att = &rfc5280_invtime_tests[i];
362 		failed |= rfc5280_invtime_test(i, att);
363 	}
364 
365 	fprintf(stderr, "RFC5280 GENERALIZEDTIME tests...\n");
366 	for (i = 0; i < N_GENTIME_TESTS; i++) {
367 		att = &rfc5280_gentime_tests[i];
368 		failed |= rfc5280_gentime_test(i, att);
369 	}
370 
371 	fprintf(stderr, "RFC5280 UTCTIME tests...\n");
372 	for (i = 0; i < N_UTCTIME_TESTS; i++) {
373 		att = &rfc5280_utctime_tests[i];
374 		failed |= rfc5280_utctime_test(i, att);
375 	}
376 	return (failed);
377 }
378