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 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 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 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 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 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 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 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 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