1 /* $OpenBSD: asn1time.c,v 1.8 2015/12/28 14:18:38 bcook Exp $ */
2 /*
3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include <openssl/asn1.h>
19
20 #include <err.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 struct asn1_time_test {
25 const char *str;
26 const char *data;
27 const unsigned char der[32];
28 time_t time;
29 };
30
31 struct asn1_time_test asn1_invtime_tests[] = {
32 {
33 .str = "",
34 },
35 {
36 .str = "2015",
37 },
38 {
39 .str = "201509",
40 },
41 {
42 .str = "20150923",
43 },
44 {
45 .str = "20150923032700",
46 },
47 {
48 .str = "20150923032700.Z",
49 },
50 {
51 .str = "20150923032700.123",
52 },
53 {
54 .str = "20150923032700+1.09",
55 },
56 {
57 .str = "20150923032700+1100Z",
58 },
59 {
60 .str = "20150923032700-11001",
61 },
62 {
63 /* UTC time cannot have fractional seconds. */
64 .str = "150923032700.123Z",
65 },
66 {
67 .str = "aaaaaaaaaaaaaaZ",
68 },
69 };
70
71 struct asn1_time_test asn1_gentime_tests[] = {
72 {
73 .str = "19700101000000Z",
74 .data = "19700101000000Z",
75 .time = 0,
76 .der = {
77 0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31,
78 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
79 0x5a,
80 },
81 },
82 {
83 .str = "20150923032700Z",
84 .data = "20150923032700Z",
85 .time = 1442978820,
86 .der = {
87 0x18, 0x0f, 0x32, 0x30, 0x31, 0x35, 0x30, 0x39,
88 0x32, 0x33, 0x30, 0x33, 0x32, 0x37, 0x30, 0x30,
89 0x5a,
90 },
91 },
92 };
93
94 struct asn1_time_test asn1_utctime_tests[] = {
95 {
96 .str = "700101000000Z",
97 .data = "700101000000Z",
98 .time = 0,
99 .der = {
100 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31,
101 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
102 },
103 },
104 {
105 .str = "150923032700Z",
106 .data = "150923032700Z",
107 .time = 1442978820,
108 .der = {
109 0x17, 0x0d, 0x31, 0x35, 0x30, 0x39, 0x32, 0x33,
110 0x30, 0x33, 0x32, 0x37, 0x30, 0x30, 0x5a,
111 },
112 },
113 {
114 .str = "140524144512Z",
115 .data = "140524144512Z",
116 .time = 1400942712,
117 .der = {
118 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x34,
119 0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a,
120 },
121 },
122 {
123 .str = "240401144512Z",
124 .data = "240401144512Z",
125 .time = 1711982712,
126 .der = {
127 0x17, 0x0d, 0x32, 0x34, 0x30, 0x34, 0x30, 0x31,
128 0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a
129 },
130 },
131 };
132
133 #define N_INVTIME_TESTS \
134 (sizeof(asn1_invtime_tests) / sizeof(*asn1_invtime_tests))
135 #define N_GENTIME_TESTS \
136 (sizeof(asn1_gentime_tests) / sizeof(*asn1_gentime_tests))
137 #define N_UTCTIME_TESTS \
138 (sizeof(asn1_utctime_tests) / sizeof(*asn1_utctime_tests))
139
140 static void
hexdump(const unsigned char * buf,size_t len)141 hexdump(const unsigned char *buf, size_t len)
142 {
143 size_t i;
144
145 for (i = 1; i <= len; i++)
146 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
147
148 fprintf(stderr, "\n");
149 }
150
151 static int
asn1_compare_bytes(int test_no,const unsigned char * d1,const unsigned char * d2,int len1,int len2)152 asn1_compare_bytes(int test_no, const unsigned char *d1,
153 const unsigned char *d2, int len1, int len2)
154 {
155 if (len1 != len2) {
156 fprintf(stderr, "FAIL: test %i - byte lengths differ "
157 "(%i != %i)\n", test_no, len1, len2);
158 return (1);
159 }
160 if (memcmp(d1, d2, len1) != 0) {
161 fprintf(stderr, "FAIL: test %i - bytes differ\n", test_no);
162 fprintf(stderr, "Got:\n");
163 hexdump(d1, len1);
164 fprintf(stderr, "Want:\n");
165 hexdump(d2, len2);
166 }
167 return (0);
168 }
169
170 static int
asn1_compare_str(int test_no,struct asn1_string_st * asn1str,const char * str)171 asn1_compare_str(int test_no, struct asn1_string_st *asn1str, const char *str)
172 {
173 int length = strlen(str);
174
175 if (asn1str->length != length) {
176 fprintf(stderr, "FAIL: test %i - string lengths differ "
177 "(%i != %i)\n", test_no, asn1str->length, length);
178 return (1);
179 }
180 if (strncmp(asn1str->data, str, length) != 0) {
181 fprintf(stderr, "FAIL: test %i - strings differ "
182 "('%s' != '%s')\n", test_no, asn1str->data, str);
183 return (1);
184 }
185
186 return (0);
187 }
188
189 static int
asn1_invtime_test(int test_no,struct asn1_time_test * att)190 asn1_invtime_test(int test_no, struct asn1_time_test *att)
191 {
192 ASN1_GENERALIZEDTIME *gt = NULL;
193 ASN1_UTCTIME *ut = NULL;
194 ASN1_TIME *t = NULL;
195 int failure = 1;
196
197 if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
198 goto done;
199 if ((ut = ASN1_UTCTIME_new()) == NULL)
200 goto done;
201 if ((t = ASN1_TIME_new()) == NULL)
202 goto done;
203
204 if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 0) {
205 fprintf(stderr, "FAIL: test %i - successfully set "
206 "GENERALIZEDTIME string '%s'\n", test_no, att->str);
207 goto done;
208 }
209 if (ASN1_UTCTIME_set_string(ut, att->str) != 0) {
210 fprintf(stderr, "FAIL: test %i - successfully set UTCTIME "
211 "string '%s'\n", test_no, att->str);
212 goto done;
213 }
214 if (ASN1_TIME_set_string(t, att->str) != 0) {
215 fprintf(stderr, "FAIL: test %i - successfully set TIME "
216 "string '%s'\n", test_no, att->str);
217 goto done;
218 }
219
220 failure = 0;
221
222 done:
223 ASN1_GENERALIZEDTIME_free(gt);
224 ASN1_UTCTIME_free(ut);
225 ASN1_TIME_free(t);
226
227 return (failure);
228 }
229
230 static int
asn1_gentime_test(int test_no,struct asn1_time_test * att)231 asn1_gentime_test(int test_no, struct asn1_time_test *att)
232 {
233 const unsigned char *der;
234 unsigned char *p = NULL;
235 ASN1_GENERALIZEDTIME *gt = NULL;
236 int failure = 1;
237 int len;
238
239 if (ASN1_GENERALIZEDTIME_set_string(NULL, att->str) != 1) {
240 fprintf(stderr, "FAIL: test %i - failed to set string '%s'\n",
241 test_no, att->str);
242 goto done;
243 }
244
245 if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
246 goto done;
247
248 if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 1) {
249 fprintf(stderr, "FAIL: test %i - failed to set string '%s'\n",
250 test_no, att->str);
251 goto done;
252 }
253 if (asn1_compare_str(test_no, gt, att->str) != 0)
254 goto done;
255
256 if ((len = i2d_ASN1_GENERALIZEDTIME(gt, &p)) <= 0) {
257 fprintf(stderr, "FAIL: test %i - i2d_ASN1_GENERALIZEDTIME "
258 "failed\n", test_no);
259 goto done;
260 }
261 der = att->der;
262 if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0)
263 goto done;
264
265 len = strlen(att->der);
266 if (d2i_ASN1_GENERALIZEDTIME(>, &der, len) == NULL) {
267 fprintf(stderr, "FAIL: test %i - d2i_ASN1_GENERALIZEDTIME "
268 "failed\n", test_no);
269 goto done;
270 }
271 if (asn1_compare_str(test_no, gt, att->str) != 0)
272 goto done;
273
274 ASN1_GENERALIZEDTIME_free(gt);
275
276 if ((gt = ASN1_GENERALIZEDTIME_set(NULL, att->time)) == NULL) {
277 fprintf(stderr, "FAIL: test %i - failed to set time %lli\n",
278 test_no, (long long)att->time);
279 goto done;
280 }
281 if (asn1_compare_str(test_no, gt, att->data) != 0)
282 goto done;
283
284 failure = 0;
285
286 done:
287 ASN1_GENERALIZEDTIME_free(gt);
288 free(p);
289
290 return (failure);
291 }
292
293 static int
asn1_utctime_test(int test_no,struct asn1_time_test * att)294 asn1_utctime_test(int test_no, struct asn1_time_test *att)
295 {
296 const unsigned char *der;
297 unsigned char *p = NULL;
298 ASN1_UTCTIME *ut = NULL;
299 int failure = 1;
300 int len;
301
302 if (ASN1_UTCTIME_set_string(NULL, att->str) != 1) {
303 fprintf(stderr, "FAIL: test %i - failed to set string '%s'\n",
304 test_no, att->str);
305 goto done;
306 }
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 %i - 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 ((len = i2d_ASN1_UTCTIME(ut, &p)) <= 0) {
320 fprintf(stderr, "FAIL: test %i - i2d_ASN1_UTCTIME failed\n",
321 test_no);
322 goto done;
323 }
324 der = att->der;
325 if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0)
326 goto done;
327
328 len = strlen(att->der);
329 if (d2i_ASN1_UTCTIME(&ut, &der, len) == NULL) {
330 fprintf(stderr, "FAIL: test %i - d2i_ASN1_UTCTIME failed\n",
331 test_no);
332 goto done;
333 }
334 if (asn1_compare_str(test_no, ut, att->str) != 0)
335 goto done;
336
337 ASN1_UTCTIME_free(ut);
338
339 if ((ut = ASN1_UTCTIME_set(NULL, att->time)) == NULL) {
340 fprintf(stderr, "FAIL: test %i - failed to set time %lli\n",
341 test_no, (long long)att->time);
342 goto done;
343 }
344 if (asn1_compare_str(test_no, ut, att->data) != 0)
345 goto done;
346
347 failure = 0;
348
349 done:
350 ASN1_UTCTIME_free(ut);
351 free(p);
352
353 return (failure);
354 }
355
356 static int
asn1_time_test(int test_no,struct asn1_time_test * att,int type)357 asn1_time_test(int test_no, struct asn1_time_test *att, int type)
358 {
359 ASN1_TIME *t = NULL;
360 int failure = 1;
361
362 if (ASN1_TIME_set_string(NULL, att->str) != 1) {
363 fprintf(stderr, "FAIL: test %i - failed to set string '%s'\n",
364 test_no, att->str);
365 goto done;
366 }
367
368 if ((t = ASN1_TIME_new()) == NULL)
369 goto done;
370
371 if (ASN1_TIME_set_string(t, att->str) != 1) {
372 fprintf(stderr, "FAIL: test %i - failed to set string '%s'\n",
373 test_no, att->str);
374 goto done;
375 }
376
377 if (t->type != type) {
378 fprintf(stderr, "FAIL: test %i - got type %i, want %i\n",
379 test_no, t->type, type);
380 goto done;
381 }
382
383 failure = 0;
384
385 done:
386
387 ASN1_TIME_free(t);
388
389 return (failure);
390 }
391
392 int
main(int argc,char ** argv)393 main(int argc, char **argv)
394 {
395 struct asn1_time_test *att;
396 int failed = 0;
397 size_t i;
398
399 fprintf(stderr, "Invalid time tests...\n");
400 for (i = 0; i < N_INVTIME_TESTS; i++) {
401 att = &asn1_invtime_tests[i];
402 failed |= asn1_invtime_test(i, att);
403 }
404
405 fprintf(stderr, "GENERALIZEDTIME tests...\n");
406 for (i = 0; i < N_GENTIME_TESTS; i++) {
407 att = &asn1_gentime_tests[i];
408 failed |= asn1_gentime_test(i, att);
409 }
410
411 fprintf(stderr, "UTCTIME tests...\n");
412 for (i = 0; i < N_UTCTIME_TESTS; i++) {
413 att = &asn1_utctime_tests[i];
414 failed |= asn1_utctime_test(i, att);
415 }
416
417 fprintf(stderr, "TIME tests...\n");
418 for (i = 0; i < N_UTCTIME_TESTS; i++) {
419 att = &asn1_utctime_tests[i];
420 failed |= asn1_time_test(i, att, V_ASN1_UTCTIME);
421 }
422 for (i = 0; i < N_GENTIME_TESTS; i++) {
423 att = &asn1_gentime_tests[i];
424 failed |= asn1_time_test(i, att, V_ASN1_GENERALIZEDTIME);
425 }
426
427 return (failed);
428 }
429