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