1 /* 2 * Copyright 2016 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 #include <ctype.h> 11 #include <math.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 16 #include <openssl/ct.h> 17 #include <openssl/err.h> 18 #include <openssl/pem.h> 19 #include <openssl/x509.h> 20 #include <openssl/x509v3.h> 21 #include "testutil.h" 22 23 #ifndef OPENSSL_NO_CT 24 25 /* Used when declaring buffers to read text files into */ 26 #define CT_TEST_MAX_FILE_SIZE 8096 27 28 static char *certs_dir = NULL; 29 static char *ct_dir = NULL; 30 31 typedef struct ct_test_fixture { 32 const char *test_case_name; 33 /* The current time in milliseconds */ 34 uint64_t epoch_time_in_ms; 35 /* The CT log store to use during tests */ 36 CTLOG_STORE* ctlog_store; 37 /* Set the following to test handling of SCTs in X509 certificates */ 38 const char *certs_dir; 39 char *certificate_file; 40 char *issuer_file; 41 /* Expected number of SCTs */ 42 int expected_sct_count; 43 /* Expected number of valid SCTS */ 44 int expected_valid_sct_count; 45 /* Set the following to test handling of SCTs in TLS format */ 46 const unsigned char *tls_sct_list; 47 size_t tls_sct_list_len; 48 STACK_OF(SCT) *sct_list; 49 /* 50 * A file to load the expected SCT text from. 51 * This text will be compared to the actual text output during the test. 52 * A maximum of |CT_TEST_MAX_FILE_SIZE| bytes will be read of this file. 53 */ 54 const char *sct_dir; 55 const char *sct_text_file; 56 /* Whether to test the validity of the SCT(s) */ 57 int test_validity; 58 } CT_TEST_FIXTURE; 59 60 static CT_TEST_FIXTURE set_up(const char *const test_case_name) 61 { 62 CT_TEST_FIXTURE fixture; 63 int setup_ok = 1; 64 65 memset(&fixture, 0, sizeof(fixture)); 66 67 fixture.test_case_name = test_case_name; 68 fixture.epoch_time_in_ms = 1473269626000; /* Sep 7 17:33:46 2016 GMT */ 69 fixture.ctlog_store = CTLOG_STORE_new(); 70 71 if (fixture.ctlog_store == NULL) { 72 setup_ok = 0; 73 fprintf(stderr, "Failed to create a new CT log store\n"); 74 goto end; 75 } 76 77 if (CTLOG_STORE_load_default_file(fixture.ctlog_store) != 1) { 78 setup_ok = 0; 79 fprintf(stderr, "Failed to load CT log list\n"); 80 goto end; 81 } 82 83 end: 84 if (!setup_ok) { 85 CTLOG_STORE_free(fixture.ctlog_store); 86 exit(EXIT_FAILURE); 87 } 88 return fixture; 89 } 90 91 static void tear_down(CT_TEST_FIXTURE fixture) 92 { 93 CTLOG_STORE_free(fixture.ctlog_store); 94 SCT_LIST_free(fixture.sct_list); 95 ERR_print_errors_fp(stderr); 96 } 97 98 static char *mk_file_path(const char *dir, const char *file) 99 { 100 char *full_file = NULL; 101 size_t full_file_l = 0; 102 const char *sep = ""; 103 #ifndef OPENSSL_SYS_VMS 104 sep = "/"; 105 #endif 106 107 full_file_l = strlen(dir) + strlen(sep) + strlen(file) + 1; 108 full_file = OPENSSL_zalloc(full_file_l); 109 if (full_file != NULL) { 110 OPENSSL_strlcpy(full_file, dir, full_file_l); 111 OPENSSL_strlcat(full_file, sep, full_file_l); 112 OPENSSL_strlcat(full_file, file, full_file_l); 113 } 114 115 return full_file; 116 } 117 118 static X509 *load_pem_cert(const char *dir, const char *file) 119 { 120 X509 *cert = NULL; 121 char *file_path = mk_file_path(dir, file); 122 123 if (file_path != NULL) { 124 BIO *cert_io = BIO_new_file(file_path, "r"); 125 OPENSSL_free(file_path); 126 127 if (cert_io != NULL) 128 cert = PEM_read_bio_X509(cert_io, NULL, NULL, NULL); 129 130 BIO_free(cert_io); 131 } 132 return cert; 133 } 134 135 static int read_text_file(const char *dir, const char *file, 136 char *buffer, int buffer_length) 137 { 138 int result = -1; 139 char *file_path = mk_file_path(dir, file); 140 141 if (file_path != NULL) { 142 BIO *file_io = BIO_new_file(file_path, "r"); 143 OPENSSL_free(file_path); 144 145 if (file_io != NULL) { 146 result = BIO_read(file_io, buffer, buffer_length); 147 BIO_free(file_io); 148 } 149 } 150 151 return result; 152 } 153 154 static int compare_sct_list_printout(STACK_OF(SCT) *sct, 155 const char *expected_output) 156 { 157 BIO *text_buffer = NULL; 158 char *actual_output = NULL; 159 int result = 1; 160 161 text_buffer = BIO_new(BIO_s_mem()); 162 if (text_buffer == NULL) { 163 fprintf(stderr, "Unable to allocate buffer\n"); 164 goto end; 165 } 166 167 SCT_LIST_print(sct, text_buffer, 0, "\n", NULL); 168 169 /* Append null terminator because we're about to use the buffer contents 170 * as a string. */ 171 if (BIO_write(text_buffer, "\0", 1) != 1) { 172 fprintf(stderr, "Failed to append null terminator to SCT text\n"); 173 goto end; 174 } 175 176 BIO_get_mem_data(text_buffer, &actual_output); 177 result = strcmp(actual_output, expected_output); 178 179 if (result != 0) { 180 fprintf(stderr, 181 "Expected SCT printout:\n%s\nActual SCT printout:\n%s\n", 182 expected_output, actual_output); 183 } 184 185 end: 186 BIO_free(text_buffer); 187 return result; 188 } 189 190 static int compare_extension_printout(X509_EXTENSION *extension, 191 const char *expected_output) 192 { 193 BIO *text_buffer = NULL; 194 char *actual_output = NULL; 195 int result = 1; 196 197 text_buffer = BIO_new(BIO_s_mem()); 198 if (text_buffer == NULL) { 199 fprintf(stderr, "Unable to allocate buffer\n"); 200 goto end; 201 } 202 203 if (!X509V3_EXT_print(text_buffer, extension, X509V3_EXT_DEFAULT, 0)) { 204 fprintf(stderr, "Failed to print extension\n"); 205 goto end; 206 } 207 208 /* Append null terminator because we're about to use the buffer contents 209 * as a string. */ 210 if (BIO_write(text_buffer, "\0", 1) != 1) { 211 fprintf(stderr, 212 "Failed to append null terminator to extension text\n"); 213 goto end; 214 } 215 216 BIO_get_mem_data(text_buffer, &actual_output); 217 result = strcmp(actual_output, expected_output); 218 219 if (result != 0) { 220 fprintf(stderr, 221 "Expected SCT printout:\n%s\nActual SCT printout:\n%s\n", 222 expected_output, actual_output); 223 } 224 225 end: 226 BIO_free(text_buffer); 227 return result; 228 } 229 230 static int assert_validity(CT_TEST_FIXTURE fixture, 231 STACK_OF(SCT) *scts, 232 CT_POLICY_EVAL_CTX *policy_ctx) { 233 int invalid_sct_count = 0; 234 int valid_sct_count = 0; 235 int i; 236 237 if (SCT_LIST_validate(scts, policy_ctx) < 0) { 238 fprintf(stderr, "Error verifying SCTs\n"); 239 return 0; 240 } 241 242 for (i = 0; i < sk_SCT_num(scts); ++i) { 243 SCT *sct_i = sk_SCT_value(scts, i); 244 switch (SCT_get_validation_status(sct_i)) { 245 case SCT_VALIDATION_STATUS_VALID: 246 ++valid_sct_count; 247 break; 248 case SCT_VALIDATION_STATUS_INVALID: 249 ++invalid_sct_count; 250 break; 251 default: 252 /* Ignore other validation statuses. */ 253 break; 254 } 255 } 256 257 if (valid_sct_count != fixture.expected_valid_sct_count) { 258 int unverified_sct_count = sk_SCT_num(scts) - 259 invalid_sct_count - valid_sct_count; 260 261 fprintf(stderr, 262 "%d SCTs failed verification\n" 263 "%d SCTs passed verification (%d expected)\n" 264 "%d SCTs were unverified\n", 265 invalid_sct_count, 266 valid_sct_count, 267 fixture.expected_valid_sct_count, 268 unverified_sct_count); 269 return 0; 270 } 271 272 return 1; 273 } 274 275 static int execute_cert_test(CT_TEST_FIXTURE fixture) 276 { 277 int success = 0; 278 X509 *cert = NULL, *issuer = NULL; 279 STACK_OF(SCT) *scts = NULL; 280 SCT *sct = NULL; 281 char expected_sct_text[CT_TEST_MAX_FILE_SIZE]; 282 int sct_text_len = 0; 283 unsigned char *tls_sct_list = NULL; 284 size_t tls_sct_list_len = 0; 285 CT_POLICY_EVAL_CTX *ct_policy_ctx = CT_POLICY_EVAL_CTX_new(); 286 287 if (fixture.sct_text_file != NULL) { 288 sct_text_len = read_text_file(fixture.sct_dir, fixture.sct_text_file, 289 expected_sct_text, 290 CT_TEST_MAX_FILE_SIZE - 1); 291 292 if (sct_text_len < 0) { 293 fprintf(stderr, "Test data file not found: %s\n", 294 fixture.sct_text_file); 295 goto end; 296 } 297 298 expected_sct_text[sct_text_len] = '\0'; 299 } 300 301 CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE( 302 ct_policy_ctx, fixture.ctlog_store); 303 304 CT_POLICY_EVAL_CTX_set_time(ct_policy_ctx, fixture.epoch_time_in_ms); 305 306 if (fixture.certificate_file != NULL) { 307 int sct_extension_index; 308 X509_EXTENSION *sct_extension = NULL; 309 cert = load_pem_cert(fixture.certs_dir, fixture.certificate_file); 310 311 if (cert == NULL) { 312 fprintf(stderr, "Unable to load certificate: %s\n", 313 fixture.certificate_file); 314 goto end; 315 } 316 317 CT_POLICY_EVAL_CTX_set1_cert(ct_policy_ctx, cert); 318 319 if (fixture.issuer_file != NULL) { 320 issuer = load_pem_cert(fixture.certs_dir, fixture.issuer_file); 321 322 if (issuer == NULL) { 323 fprintf(stderr, "Unable to load issuer certificate: %s\n", 324 fixture.issuer_file); 325 goto end; 326 } 327 328 CT_POLICY_EVAL_CTX_set1_issuer(ct_policy_ctx, issuer); 329 } 330 331 sct_extension_index = 332 X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1); 333 sct_extension = X509_get_ext(cert, sct_extension_index); 334 if (fixture.expected_sct_count > 0) { 335 if (sct_extension == NULL) { 336 fprintf(stderr, "SCT extension not found in: %s\n", 337 fixture.certificate_file); 338 goto end; 339 } 340 341 if (fixture.sct_text_file 342 && compare_extension_printout(sct_extension, 343 expected_sct_text)) { 344 goto end; 345 } 346 347 if (fixture.test_validity) { 348 int i; 349 350 scts = X509V3_EXT_d2i(sct_extension); 351 for (i = 0; i < sk_SCT_num(scts); ++i) { 352 SCT *sct_i = sk_SCT_value(scts, i); 353 354 if (!SCT_set_source(sct_i, SCT_SOURCE_X509V3_EXTENSION)) { 355 fprintf(stderr, 356 "Error setting SCT source to X509v3 extension\n"); 357 goto end; 358 } 359 } 360 361 if (!assert_validity(fixture, scts, ct_policy_ctx)) 362 goto end; 363 } 364 } else if (sct_extension != NULL) { 365 fprintf(stderr, 366 "Expected no SCTs, but found SCT extension in: %s\n", 367 fixture.certificate_file); 368 goto end; 369 } 370 } 371 372 if (fixture.tls_sct_list != NULL) { 373 const unsigned char *p = fixture.tls_sct_list; 374 if (o2i_SCT_LIST(&scts, &p, fixture.tls_sct_list_len) == NULL) { 375 fprintf(stderr, "Failed to decode SCTs from TLS format\n"); 376 goto end; 377 } 378 379 if (fixture.test_validity && cert != NULL) { 380 if (!assert_validity(fixture, scts, ct_policy_ctx)) 381 goto end; 382 } 383 384 if (fixture.sct_text_file 385 && compare_sct_list_printout(scts, expected_sct_text)) { 386 goto end; 387 } 388 389 tls_sct_list_len = i2o_SCT_LIST(scts, &tls_sct_list); 390 if (tls_sct_list_len != fixture.tls_sct_list_len || 391 memcmp(fixture.tls_sct_list, tls_sct_list, tls_sct_list_len) != 0) { 392 fprintf(stderr, 393 "Failed to encode SCTs into TLS format correctly\n"); 394 goto end; 395 } 396 } 397 success = 1; 398 399 end: 400 X509_free(cert); 401 X509_free(issuer); 402 SCT_LIST_free(scts); 403 SCT_free(sct); 404 CT_POLICY_EVAL_CTX_free(ct_policy_ctx); 405 OPENSSL_free(tls_sct_list); 406 return success; 407 } 408 409 #define SETUP_CT_TEST_FIXTURE() SETUP_TEST_FIXTURE(CT_TEST_FIXTURE, set_up) 410 #define EXECUTE_CT_TEST() EXECUTE_TEST(execute_cert_test, tear_down) 411 412 static int test_no_scts_in_certificate() 413 { 414 SETUP_CT_TEST_FIXTURE(); 415 fixture.certs_dir = certs_dir; 416 fixture.certificate_file = "leaf.pem"; 417 fixture.issuer_file = "subinterCA.pem"; 418 fixture.expected_sct_count = 0; 419 EXECUTE_CT_TEST(); 420 } 421 422 static int test_one_sct_in_certificate() 423 { 424 SETUP_CT_TEST_FIXTURE(); 425 fixture.certs_dir = certs_dir; 426 fixture.certificate_file = "embeddedSCTs1.pem"; 427 fixture.issuer_file = "embeddedSCTs1_issuer.pem"; 428 fixture.expected_sct_count = 1; 429 fixture.sct_dir = certs_dir; 430 fixture.sct_text_file = "embeddedSCTs1.sct"; 431 EXECUTE_CT_TEST(); 432 } 433 434 static int test_multiple_scts_in_certificate() 435 { 436 SETUP_CT_TEST_FIXTURE(); 437 fixture.certs_dir = certs_dir; 438 fixture.certificate_file = "embeddedSCTs3.pem"; 439 fixture.issuer_file = "embeddedSCTs3_issuer.pem"; 440 fixture.expected_sct_count = 3; 441 fixture.sct_dir = certs_dir; 442 fixture.sct_text_file = "embeddedSCTs3.sct"; 443 EXECUTE_CT_TEST(); 444 } 445 446 static int test_verify_one_sct() 447 { 448 SETUP_CT_TEST_FIXTURE(); 449 fixture.certs_dir = certs_dir; 450 fixture.certificate_file = "embeddedSCTs1.pem"; 451 fixture.issuer_file = "embeddedSCTs1_issuer.pem"; 452 fixture.expected_sct_count = fixture.expected_valid_sct_count = 1; 453 fixture.test_validity = 1; 454 EXECUTE_CT_TEST(); 455 } 456 457 static int test_verify_multiple_scts() 458 { 459 SETUP_CT_TEST_FIXTURE(); 460 fixture.certs_dir = certs_dir; 461 fixture.certificate_file = "embeddedSCTs3.pem"; 462 fixture.issuer_file = "embeddedSCTs3_issuer.pem"; 463 fixture.expected_sct_count = fixture.expected_valid_sct_count = 3; 464 fixture.test_validity = 1; 465 EXECUTE_CT_TEST(); 466 } 467 468 static int test_verify_fails_for_future_sct() 469 { 470 SETUP_CT_TEST_FIXTURE(); 471 fixture.epoch_time_in_ms = 1365094800000; /* Apr 4 17:00:00 2013 GMT */ 472 fixture.certs_dir = certs_dir; 473 fixture.certificate_file = "embeddedSCTs1.pem"; 474 fixture.issuer_file = "embeddedSCTs1_issuer.pem"; 475 fixture.expected_sct_count = 1; 476 fixture.expected_valid_sct_count = 0; 477 fixture.test_validity = 1; 478 EXECUTE_CT_TEST(); 479 } 480 481 static int test_decode_tls_sct() 482 { 483 const unsigned char tls_sct_list[] = "\x00\x78" /* length of list */ 484 "\x00\x76" 485 "\x00" /* version */ 486 /* log ID */ 487 "\xDF\x1C\x2E\xC1\x15\x00\x94\x52\x47\xA9\x61\x68\x32\x5D\xDC\x5C\x79" 488 "\x59\xE8\xF7\xC6\xD3\x88\xFC\x00\x2E\x0B\xBD\x3F\x74\xD7\x64" 489 "\x00\x00\x01\x3D\xDB\x27\xDF\x93" /* timestamp */ 490 "\x00\x00" /* extensions length */ 491 "" /* extensions */ 492 "\x04\x03" /* hash and signature algorithms */ 493 "\x00\x47" /* signature length */ 494 /* signature */ 495 "\x30\x45\x02\x20\x48\x2F\x67\x51\xAF\x35\xDB\xA6\x54\x36\xBE\x1F\xD6" 496 "\x64\x0F\x3D\xBF\x9A\x41\x42\x94\x95\x92\x45\x30\x28\x8F\xA3\xE5\xE2" 497 "\x3E\x06\x02\x21\x00\xE4\xED\xC0\xDB\x3A\xC5\x72\xB1\xE2\xF5\xE8\xAB" 498 "\x6A\x68\x06\x53\x98\x7D\xCF\x41\x02\x7D\xFE\xFF\xA1\x05\x51\x9D\x89" 499 "\xED\xBF\x08"; 500 501 SETUP_CT_TEST_FIXTURE(); 502 fixture.tls_sct_list = tls_sct_list; 503 fixture.tls_sct_list_len = 0x7a; 504 fixture.sct_dir = ct_dir; 505 fixture.sct_text_file = "tls1.sct"; 506 EXECUTE_CT_TEST(); 507 } 508 509 static int test_encode_tls_sct() 510 { 511 const char log_id[] = "3xwuwRUAlFJHqWFoMl3cXHlZ6PfG04j8AC4LvT9012Q="; 512 const uint64_t timestamp = 1; 513 const char extensions[] = ""; 514 const char signature[] = "BAMARzBAMiBIL2dRrzXbplQ2vh/WZA89v5pBQpSVkkUwKI+j5" 515 "eI+BgIhAOTtwNs6xXKx4vXoq2poBlOYfc9BAn3+/6EFUZ2J7b8I"; 516 SCT *sct = NULL; 517 518 SETUP_CT_TEST_FIXTURE(); 519 520 fixture.sct_list = sk_SCT_new_null(); 521 sct = SCT_new_from_base64(SCT_VERSION_V1, log_id, 522 CT_LOG_ENTRY_TYPE_X509, timestamp, 523 extensions, signature); 524 525 if (sct == NULL) { 526 tear_down(fixture); 527 fprintf(stderr, "Failed to create SCT from base64-encoded test data\n"); 528 return 0; 529 } 530 531 sk_SCT_push(fixture.sct_list, sct); 532 fixture.sct_dir = ct_dir; 533 fixture.sct_text_file = "tls1.sct"; 534 EXECUTE_CT_TEST(); 535 } 536 537 /* 538 * Tests that the CT_POLICY_EVAL_CTX default time is approximately now. 539 * Allow +-10 minutes, as it may compensate for clock skew. 540 */ 541 static int test_default_ct_policy_eval_ctx_time_is_now() 542 { 543 int success = 0; 544 CT_POLICY_EVAL_CTX *ct_policy_ctx = CT_POLICY_EVAL_CTX_new(); 545 const time_t default_time = CT_POLICY_EVAL_CTX_get_time(ct_policy_ctx) / 546 1000; 547 const time_t time_tolerance = 600; /* 10 minutes */ 548 549 if (fabs(difftime(time(NULL), default_time)) > time_tolerance) { 550 fprintf(stderr, 551 "Default CT_POLICY_EVAL_CTX time is not approximately now.\n"); 552 goto end; 553 } 554 555 success = 1; 556 end: 557 CT_POLICY_EVAL_CTX_free(ct_policy_ctx); 558 return success; 559 } 560 561 int main(int argc, char *argv[]) 562 { 563 int result = 0; 564 char *tmp_env = NULL; 565 566 tmp_env = getenv("OPENSSL_DEBUG_MEMORY"); 567 if (tmp_env != NULL && strcmp(tmp_env, "on") == 0) 568 CRYPTO_set_mem_debug(1); 569 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); 570 571 tmp_env = getenv("CT_DIR"); 572 ct_dir = OPENSSL_strdup(tmp_env != NULL ? tmp_env : "ct"); 573 tmp_env = getenv("CERTS_DIR"); 574 certs_dir = OPENSSL_strdup(tmp_env != NULL ? tmp_env : "certs"); 575 576 ADD_TEST(test_no_scts_in_certificate); 577 ADD_TEST(test_one_sct_in_certificate); 578 ADD_TEST(test_multiple_scts_in_certificate); 579 ADD_TEST(test_verify_one_sct); 580 ADD_TEST(test_verify_multiple_scts); 581 ADD_TEST(test_verify_fails_for_future_sct); 582 ADD_TEST(test_decode_tls_sct); 583 ADD_TEST(test_encode_tls_sct); 584 ADD_TEST(test_default_ct_policy_eval_ctx_time_is_now); 585 586 result = run_tests(argv[0]); 587 ERR_print_errors_fp(stderr); 588 589 OPENSSL_free(ct_dir); 590 OPENSSL_free(certs_dir); 591 592 #ifndef OPENSSL_NO_CRYPTO_MDEBUG 593 if (CRYPTO_mem_leaks_fp(stderr) <= 0) 594 result = 1; 595 #endif 596 597 return result; 598 } 599 600 #else /* OPENSSL_NO_CT */ 601 602 int main(int argc, char* argv[]) 603 { 604 return EXIT_SUCCESS; 605 } 606 607 #endif /* OPENSSL_NO_CT */ 608