1 /* 2 * Copyright 2007-2026 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright Nokia 2007-2019 4 * Copyright Siemens AG 2015-2019 5 * 6 * Licensed under the Apache License 2.0 (the "License"). You may not use 7 * this file except in compliance with the License. You can obtain a copy 8 * in the file LICENSE in the source distribution or at 9 * https://www.openssl.org/source/license.html 10 */ 11 12 #include "helpers/cmp_testlib.h" 13 #include "../crypto/crmf/crmf_local.h" /* for manipulating POPO signature */ 14 15 static const char *server_f; 16 static const char *client_f; 17 static const char *endentity1_f; 18 static const char *endentity2_f; 19 static const char *root_f; 20 static const char *intermediate_f; 21 static const char *ir_protected_f; 22 static const char *ir_unprotected_f; 23 static const char *ir_rmprotection_f; 24 static const char *ip_waiting_f; 25 static const char *instacert_f; 26 static const char *instaca_f; 27 static const char *ir_protected_0_extracerts; 28 static const char *ir_protected_2_extracerts; 29 30 typedef struct test_fixture { 31 const char *test_case_name; 32 int expected; 33 OSSL_CMP_CTX *cmp_ctx; 34 OSSL_CMP_MSG *msg; 35 X509 *cert; 36 ossl_cmp_allow_unprotected_cb_t allow_unprotected_cb; 37 int additional_arg; 38 } CMP_VFY_TEST_FIXTURE; 39 40 static OSSL_LIB_CTX *libctx = NULL; 41 static OSSL_PROVIDER *default_null_provider = NULL, *provider = NULL; 42 43 static void tear_down(CMP_VFY_TEST_FIXTURE *fixture) 44 { 45 OSSL_CMP_MSG_free(fixture->msg); 46 OSSL_CMP_CTX_free(fixture->cmp_ctx); 47 OPENSSL_free(fixture); 48 } 49 50 static time_t test_time_valid = 0, test_time_after_expiration = 0; 51 52 static CMP_VFY_TEST_FIXTURE *set_up(const char *const test_case_name) 53 { 54 X509_STORE *ts; 55 CMP_VFY_TEST_FIXTURE *fixture; 56 57 if (!TEST_ptr(fixture = OPENSSL_zalloc(sizeof(*fixture)))) 58 return NULL; 59 60 ts = X509_STORE_new(); 61 fixture->test_case_name = test_case_name; 62 if (ts == NULL 63 || !TEST_ptr(fixture->cmp_ctx = OSSL_CMP_CTX_new(libctx, NULL)) 64 || !OSSL_CMP_CTX_set0_trusted(fixture->cmp_ctx, ts) 65 || !OSSL_CMP_CTX_set_log_cb(fixture->cmp_ctx, print_to_bio_out)) { 66 tear_down(fixture); 67 X509_STORE_free(ts); 68 return NULL; 69 } 70 X509_VERIFY_PARAM_set_time(X509_STORE_get0_param(ts), test_time_valid); 71 X509_STORE_set_verify_cb(ts, X509_STORE_CTX_print_verify_cb); 72 return fixture; 73 } 74 75 static X509 *srvcert = NULL; 76 static X509 *clcert = NULL; 77 /* chain */ 78 static X509 *endentity1 = NULL, *endentity2 = NULL, 79 *intermediate = NULL, *root = NULL; 80 /* INSTA chain */ 81 static X509 *insta_cert = NULL, *instaca_cert = NULL; 82 83 static unsigned char rand_data[OSSL_CMP_TRANSACTIONID_LENGTH]; 84 static OSSL_CMP_MSG *ir_unprotected, *ir_rmprotection; 85 86 /* secret value used for IP_waitingStatus_PBM.der */ 87 static const unsigned char sec_1[] = { 88 '9', 'p', 'p', '8', '-', 'b', '3', '5', 'i', '-', 'X', 'd', '3', 89 'Q', '-', 'u', 'd', 'N', 'R' 90 }; 91 92 static int flip_bit(ASN1_BIT_STRING *bitstr) 93 { 94 int bit_num = 7; 95 int bit = ASN1_BIT_STRING_get_bit(bitstr, bit_num); 96 97 return ASN1_BIT_STRING_set_bit(bitstr, bit_num, !bit); 98 } 99 100 static int execute_verify_popo_test(CMP_VFY_TEST_FIXTURE *fixture) 101 { 102 if ((fixture->msg = load_pkimsg(ir_protected_f, libctx)) == NULL) 103 return 0; 104 if (fixture->expected == 0) { 105 const OSSL_CRMF_MSGS *reqs = fixture->msg->body->value.ir; 106 const OSSL_CRMF_MSG *req = sk_OSSL_CRMF_MSG_value(reqs, 0); 107 108 if (req == NULL || !flip_bit(req->popo->value.signature->signature)) 109 return 0; 110 } 111 return TEST_int_eq(fixture->expected, 112 ossl_cmp_verify_popo(fixture->cmp_ctx, fixture->msg, 113 fixture->additional_arg)); 114 } 115 116 static int test_verify_popo(void) 117 { 118 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 119 fixture->expected = 1; 120 EXECUTE_TEST(execute_verify_popo_test, tear_down); 121 return result; 122 } 123 124 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 125 static int test_verify_popo_bad(void) 126 { 127 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 128 fixture->expected = 0; 129 EXECUTE_TEST(execute_verify_popo_test, tear_down); 130 return result; 131 } 132 #endif 133 134 /* indirectly checks also OSSL_CMP_validate_msg() */ 135 static int execute_validate_msg_test(CMP_VFY_TEST_FIXTURE *fixture) 136 { 137 int res = TEST_int_eq(fixture->expected, 138 ossl_cmp_msg_check_update(fixture->cmp_ctx, 139 fixture->msg, NULL, 0)); 140 X509 *validated = OSSL_CMP_CTX_get0_validatedSrvCert(fixture->cmp_ctx); 141 142 return res && (!fixture->expected || TEST_ptr_eq(validated, fixture->cert)); 143 } 144 145 static int execute_validate_cert_path_test(CMP_VFY_TEST_FIXTURE *fixture) 146 { 147 X509_STORE *ts = OSSL_CMP_CTX_get0_trusted(fixture->cmp_ctx); 148 int res = TEST_int_eq(fixture->expected, 149 OSSL_CMP_validate_cert_path(fixture->cmp_ctx, 150 ts, fixture->cert)); 151 152 OSSL_CMP_CTX_print_errors(fixture->cmp_ctx); 153 return res; 154 } 155 156 static int test_validate_msg_mac_alg_protection(int miss, int wrong) 157 { 158 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 159 fixture->cert = NULL; 160 161 fixture->expected = !miss && !wrong; 162 if (!TEST_true(miss ? OSSL_CMP_CTX_set0_trusted(fixture->cmp_ctx, NULL) 163 : OSSL_CMP_CTX_set1_secretValue(fixture->cmp_ctx, sec_1, 164 wrong ? 4 : sizeof(sec_1))) 165 || !TEST_ptr(fixture->msg = load_pkimsg(ip_waiting_f, libctx))) { 166 tear_down(fixture); 167 fixture = NULL; 168 } 169 EXECUTE_TEST(execute_validate_msg_test, tear_down); 170 return result; 171 } 172 173 static int test_validate_msg_mac_alg_protection_ok(void) 174 { 175 return test_validate_msg_mac_alg_protection(0, 0); 176 } 177 178 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 179 static int test_validate_msg_mac_alg_protection_missing(void) 180 { 181 return test_validate_msg_mac_alg_protection(1, 0); 182 } 183 184 static int test_validate_msg_mac_alg_protection_wrong(void) 185 { 186 return test_validate_msg_mac_alg_protection(0, 1); 187 } 188 189 static int test_validate_msg_mac_alg_protection_bad(void) 190 { 191 const unsigned char sec_bad[] = { 192 '9', 'p', 'p', '8', '-', 'b', '3', '5', 'i', '-', 'X', 'd', '3', 193 'Q', '-', 'u', 'd', 'N', 'r' 194 }; 195 196 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 197 fixture->cert = NULL; 198 fixture->expected = 0; 199 200 if (!TEST_true(OSSL_CMP_CTX_set1_secretValue(fixture->cmp_ctx, sec_bad, 201 sizeof(sec_bad))) 202 || !TEST_ptr(fixture->msg = load_pkimsg(ip_waiting_f, libctx))) { 203 tear_down(fixture); 204 fixture = NULL; 205 } 206 EXECUTE_TEST(execute_validate_msg_test, tear_down); 207 return result; 208 } 209 #endif 210 211 static int add_trusted(OSSL_CMP_CTX *ctx, X509 *cert) 212 { 213 return X509_STORE_add_cert(OSSL_CMP_CTX_get0_trusted(ctx), cert); 214 } 215 216 static int add_untrusted(OSSL_CMP_CTX *ctx, X509 *cert) 217 { 218 return X509_add_cert(OSSL_CMP_CTX_get0_untrusted(ctx), cert, 219 X509_ADD_FLAG_UP_REF); 220 } 221 222 static int test_validate_msg_signature_partial_chain(int expired) 223 { 224 X509_STORE *ts; 225 226 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 227 fixture->cert = srvcert; 228 229 ts = OSSL_CMP_CTX_get0_trusted(fixture->cmp_ctx); 230 fixture->expected = !expired; 231 if (ts == NULL 232 || !TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f, libctx)) 233 || !add_trusted(fixture->cmp_ctx, srvcert)) { 234 tear_down(fixture); 235 fixture = NULL; 236 } else { 237 X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts); 238 239 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); 240 if (expired) 241 X509_VERIFY_PARAM_set_time(vpm, test_time_after_expiration); 242 } 243 EXECUTE_TEST(execute_validate_msg_test, tear_down); 244 return result; 245 } 246 247 static int test_validate_msg_signature_trusted_ok(void) 248 { 249 return test_validate_msg_signature_partial_chain(0); 250 } 251 252 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 253 static int test_validate_msg_signature_trusted_expired(void) 254 { 255 return test_validate_msg_signature_partial_chain(1); 256 } 257 #endif 258 259 static int test_validate_msg_signature_srvcert(int bad_sig, int miss, int wrong) 260 { 261 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 262 fixture->cert = srvcert; 263 fixture->expected = !bad_sig && !wrong && !miss; 264 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f, libctx)) 265 || !TEST_true(miss ? OSSL_CMP_CTX_set1_secretValue(fixture->cmp_ctx, 266 sec_1, sizeof(sec_1)) 267 : OSSL_CMP_CTX_set1_srvCert(fixture->cmp_ctx, 268 wrong ? clcert : srvcert)) 269 || (bad_sig && !flip_bit(fixture->msg->protection))) { 270 tear_down(fixture); 271 fixture = NULL; 272 } 273 EXECUTE_TEST(execute_validate_msg_test, tear_down); 274 return result; 275 } 276 277 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 278 static int test_validate_msg_signature_srvcert_missing(void) 279 { 280 return test_validate_msg_signature_srvcert(0, 1, 0); 281 } 282 #endif 283 284 static int test_validate_msg_signature_srvcert_wrong(void) 285 { 286 return test_validate_msg_signature_srvcert(0, 0, 1); 287 } 288 289 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 290 static int test_validate_msg_signature_bad(void) 291 { 292 return test_validate_msg_signature_srvcert(1, 0, 0); 293 } 294 #endif 295 296 static int test_validate_msg_signature_sender_cert_srvcert(void) 297 { 298 return test_validate_msg_signature_srvcert(0, 0, 0); 299 } 300 301 static int test_validate_msg_signature_sender_cert_untrusted(void) 302 { 303 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 304 fixture->cert = insta_cert; 305 fixture->expected = 1; 306 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_0_extracerts, libctx)) 307 || !add_trusted(fixture->cmp_ctx, instaca_cert) 308 || !add_untrusted(fixture->cmp_ctx, insta_cert)) { 309 tear_down(fixture); 310 fixture = NULL; 311 } 312 EXECUTE_TEST(execute_validate_msg_test, tear_down); 313 return result; 314 } 315 316 static int test_validate_msg_signature_sender_cert_trusted(void) 317 { 318 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 319 fixture->cert = insta_cert; 320 fixture->expected = 1; 321 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_0_extracerts, libctx)) 322 || !add_trusted(fixture->cmp_ctx, instaca_cert) 323 || !add_trusted(fixture->cmp_ctx, insta_cert)) { 324 tear_down(fixture); 325 fixture = NULL; 326 } 327 EXECUTE_TEST(execute_validate_msg_test, tear_down); 328 return result; 329 } 330 331 static int test_validate_msg_signature_sender_cert_extracert(void) 332 { 333 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 334 fixture->expected = 1; 335 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_2_extracerts, libctx)) 336 || !add_trusted(fixture->cmp_ctx, instaca_cert)) { 337 tear_down(fixture); 338 fixture = NULL; 339 } else { 340 fixture->cert = sk_X509_value(fixture->msg->extraCerts, 1); /* Insta CA */ 341 } 342 EXECUTE_TEST(execute_validate_msg_test, tear_down); 343 return result; 344 } 345 346 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 347 static int test_validate_msg_signature_sender_cert_absent(void) 348 { 349 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 350 fixture->expected = 0; 351 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_0_extracerts, libctx))) { 352 tear_down(fixture); 353 fixture = NULL; 354 } 355 EXECUTE_TEST(execute_validate_msg_test, tear_down); 356 return result; 357 } 358 #endif 359 360 static int test_validate_with_sender(const X509_NAME *name, int expected) 361 { 362 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 363 fixture->cert = srvcert; 364 fixture->expected = expected; 365 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f, libctx)) 366 || !TEST_true(OSSL_CMP_CTX_set1_expected_sender(fixture->cmp_ctx, name)) 367 || !TEST_true(OSSL_CMP_CTX_set1_srvCert(fixture->cmp_ctx, srvcert))) { 368 tear_down(fixture); 369 fixture = NULL; 370 } 371 EXECUTE_TEST(execute_validate_msg_test, tear_down); 372 return result; 373 } 374 375 static int test_validate_msg_signature_expected_sender(void) 376 { 377 return test_validate_with_sender(X509_get_subject_name(srvcert), 1); 378 } 379 380 static int test_validate_msg_signature_unexpected_sender(void) 381 { 382 return test_validate_with_sender(X509_get_subject_name(root), 0); 383 } 384 385 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 386 static int test_validate_msg_unprotected_request(void) 387 { 388 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 389 fixture->expected = 0; 390 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_unprotected_f, libctx))) { 391 tear_down(fixture); 392 fixture = NULL; 393 } 394 EXECUTE_TEST(execute_validate_msg_test, tear_down); 395 return result; 396 } 397 #endif 398 399 static void setup_path(CMP_VFY_TEST_FIXTURE **fixture, X509 *wrong, int expired) 400 { 401 (*fixture)->cert = endentity2; 402 (*fixture)->expected = wrong == NULL && !expired; 403 if (expired) { 404 X509_STORE *ts = OSSL_CMP_CTX_get0_trusted((*fixture)->cmp_ctx); 405 X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts); 406 407 X509_VERIFY_PARAM_set_time(vpm, test_time_after_expiration); 408 } 409 if (!add_trusted((*fixture)->cmp_ctx, wrong == NULL ? root : wrong) 410 || !add_untrusted((*fixture)->cmp_ctx, endentity1) 411 || !add_untrusted((*fixture)->cmp_ctx, intermediate)) { 412 tear_down((*fixture)); 413 (*fixture) = NULL; 414 } 415 } 416 417 static int test_validate_cert_path_ok(void) 418 { 419 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 420 setup_path(&fixture, NULL, 0); 421 EXECUTE_TEST(execute_validate_cert_path_test, tear_down); 422 return result; 423 } 424 425 static int test_validate_cert_path_wrong_anchor(void) 426 { 427 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 428 setup_path(&fixture, srvcert /* wrong/non-root cert */, 0); 429 EXECUTE_TEST(execute_validate_cert_path_test, tear_down); 430 return result; 431 } 432 433 static int test_validate_cert_path_expired(void) 434 { 435 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 436 setup_path(&fixture, NULL, 1); 437 EXECUTE_TEST(execute_validate_cert_path_test, tear_down); 438 return result; 439 } 440 441 static int execute_msg_check_test(CMP_VFY_TEST_FIXTURE *fixture) 442 { 443 const OSSL_CMP_PKIHEADER *hdr = OSSL_CMP_MSG_get0_header(fixture->msg); 444 const ASN1_OCTET_STRING *tid = OSSL_CMP_HDR_get0_transactionID(hdr); 445 446 if (!TEST_int_eq(fixture->expected, 447 ossl_cmp_msg_check_update(fixture->cmp_ctx, 448 fixture->msg, 449 fixture->allow_unprotected_cb, 450 fixture->additional_arg))) 451 return 0; 452 453 if (fixture->expected == 0) /* error expected already during above check */ 454 return 1; 455 return TEST_int_eq(0, 456 ASN1_OCTET_STRING_cmp(ossl_cmp_hdr_get0_senderNonce(hdr), 457 fixture->cmp_ctx->recipNonce)) 458 && TEST_int_eq(0, 459 ASN1_OCTET_STRING_cmp(tid, 460 fixture->cmp_ctx->transactionID)); 461 } 462 463 static int allow_unprotected(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, 464 int invalid_protection, int allow) 465 { 466 return allow; 467 } 468 469 static void setup_check_update(CMP_VFY_TEST_FIXTURE **fixture, int expected, 470 ossl_cmp_allow_unprotected_cb_t cb, int arg, 471 const unsigned char *trid_data, 472 const unsigned char *nonce_data) 473 { 474 OSSL_CMP_CTX *ctx = (*fixture)->cmp_ctx; 475 int nonce_len = OSSL_CMP_SENDERNONCE_LENGTH; 476 477 (*fixture)->expected = expected; 478 (*fixture)->allow_unprotected_cb = cb; 479 (*fixture)->additional_arg = arg; 480 (*fixture)->msg = OSSL_CMP_MSG_dup(ir_rmprotection); 481 if ((*fixture)->msg == NULL 482 || (nonce_data != NULL 483 && !ossl_cmp_asn1_octet_string_set1_bytes(&ctx->senderNonce, 484 nonce_data, nonce_len))) { 485 tear_down((*fixture)); 486 (*fixture) = NULL; 487 } else if (trid_data != NULL) { 488 ASN1_OCTET_STRING *trid = ASN1_OCTET_STRING_new(); 489 490 if (trid == NULL 491 || !ASN1_OCTET_STRING_set(trid, trid_data, 492 OSSL_CMP_TRANSACTIONID_LENGTH) 493 || !OSSL_CMP_CTX_set1_transactionID(ctx, trid)) { 494 tear_down((*fixture)); 495 (*fixture) = NULL; 496 } 497 ASN1_OCTET_STRING_free(trid); 498 } 499 } 500 501 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 502 static int test_msg_check_no_protection_no_cb(void) 503 { 504 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 505 setup_check_update(&fixture, 0, NULL, 0, NULL, NULL); 506 EXECUTE_TEST(execute_msg_check_test, tear_down); 507 return result; 508 } 509 510 static int test_msg_check_no_protection_restrictive_cb(void) 511 { 512 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 513 setup_check_update(&fixture, 0, allow_unprotected, 0, NULL, NULL); 514 EXECUTE_TEST(execute_msg_check_test, tear_down); 515 return result; 516 } 517 #endif 518 519 static int test_msg_check_no_protection_permissive_cb(void) 520 { 521 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 522 setup_check_update(&fixture, 1, allow_unprotected, 1, NULL, NULL); 523 EXECUTE_TEST(execute_msg_check_test, tear_down); 524 return result; 525 } 526 527 static int test_msg_check_transaction_id(void) 528 { 529 /* Transaction id belonging to CMP_IR_rmprotection.der */ 530 const unsigned char trans_id[OSSL_CMP_TRANSACTIONID_LENGTH] = { 531 0x39, 0xB6, 0x90, 0x28, 0xC4, 0xBC, 0x7A, 0xF6, 532 0xBE, 0xC6, 0x4A, 0x88, 0x97, 0xA6, 0x95, 0x0B 533 }; 534 535 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 536 setup_check_update(&fixture, 1, allow_unprotected, 1, trans_id, NULL); 537 EXECUTE_TEST(execute_msg_check_test, tear_down); 538 return result; 539 } 540 541 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 542 static int test_msg_check_transaction_id_bad(void) 543 { 544 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 545 setup_check_update(&fixture, 0, allow_unprotected, 1, rand_data, NULL); 546 EXECUTE_TEST(execute_msg_check_test, tear_down); 547 return result; 548 } 549 #endif 550 551 static int test_msg_check_recipient_nonce(void) 552 { 553 /* Recipient nonce belonging to CMP_IP_ir_rmprotection.der */ 554 const unsigned char rec_nonce[OSSL_CMP_SENDERNONCE_LENGTH] = { 555 0x48, 0xF1, 0x71, 0x1F, 0xE5, 0xAF, 0x1C, 0x8B, 556 0x21, 0x97, 0x5C, 0x84, 0x74, 0x49, 0xBA, 0x32 557 }; 558 559 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 560 setup_check_update(&fixture, 1, allow_unprotected, 1, NULL, rec_nonce); 561 EXECUTE_TEST(execute_msg_check_test, tear_down); 562 return result; 563 } 564 565 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 566 static int test_msg_check_recipient_nonce_bad(void) 567 { 568 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 569 setup_check_update(&fixture, 0, allow_unprotected, 1, NULL, rand_data); 570 EXECUTE_TEST(execute_msg_check_test, tear_down); 571 return result; 572 } 573 574 /* Regression test for CVE-2026-63073 */ 575 static int execute_msg_check_update_malicious_sender(CMP_VFY_TEST_FIXTURE *fixture) 576 { 577 const char *data = NULL; 578 unsigned long err; 579 580 if (!TEST_int_eq(ossl_cmp_msg_check_update(fixture->cmp_ctx, fixture->msg, NULL, 0), 0) 581 || !TEST_int_ne((err = ERR_peek_last_error_all(NULL, NULL, NULL, &data, NULL)), 0) 582 || !TEST_int_eq(ERR_GET_LIB(err), ERR_LIB_CMP) 583 || !TEST_int_eq(ERR_GET_REASON(err), CMP_R_UNEXPECTED_SENDER) 584 || !TEST_ptr(data) 585 || !TEST_str_eq(data, "/CN=%n")) 586 return 0; 587 return 1; 588 } 589 590 static int test_msg_check_update_malicious_sender(void) 591 { 592 OSSL_CMP_PKIHEADER *hdr; 593 X509_NAME *expected = X509_NAME_new(); 594 X509_NAME *actual = X509_NAME_new(); 595 SETUP_TEST_FIXTURE(CMP_VFY_TEST_FIXTURE, set_up); 596 597 if (expected == NULL || actual == NULL) { 598 X509_NAME_free(expected); 599 return 0; 600 } 601 602 if (!TEST_ptr(fixture->msg = load_pkimsg(ir_protected_f, libctx)) 603 || !TEST_ptr(hdr = OSSL_CMP_MSG_get0_header(fixture->msg)) 604 || !TEST_int_eq(X509_NAME_add_entry_by_txt(expected, "CN", MBSTRING_ASC, 605 (unsigned char *)"%n", -1, -1, 0), 606 1) 607 || !TEST_int_eq(X509_NAME_add_entry_by_txt(actual, "CN", MBSTRING_ASC, 608 (unsigned char *)"actual", -1, -1, 0), 609 1) 610 || !TEST_int_eq(ossl_cmp_hdr_set1_sender(hdr, expected), 1) 611 || !TEST_int_eq(OSSL_CMP_CTX_set1_expected_sender(fixture->cmp_ctx, actual), 1)) { 612 X509_NAME_free(expected); 613 X509_NAME_free(actual); 614 tear_down(fixture); 615 return 0; 616 } 617 EXECUTE_TEST(execute_msg_check_update_malicious_sender, tear_down); 618 X509_NAME_free(expected); 619 X509_NAME_free(actual); 620 return result; 621 } 622 623 #endif 624 625 void cleanup_tests(void) 626 { 627 X509_free(srvcert); 628 X509_free(clcert); 629 X509_free(endentity1); 630 X509_free(endentity2); 631 X509_free(intermediate); 632 X509_free(root); 633 X509_free(insta_cert); 634 X509_free(instaca_cert); 635 OSSL_CMP_MSG_free(ir_unprotected); 636 OSSL_CMP_MSG_free(ir_rmprotection); 637 OSSL_PROVIDER_unload(default_null_provider); 638 OSSL_PROVIDER_unload(provider); 639 OSSL_LIB_CTX_free(libctx); 640 return; 641 } 642 643 #define USAGE "server.crt client.crt " \ 644 "EndEntity1.crt EndEntity2.crt " \ 645 "Root_CA.crt Intermediate_CA.crt " \ 646 "CMP_IR_protected.der CMP_IR_unprotected.der " \ 647 "IP_waitingStatus_PBM.der IR_rmprotection.der " \ 648 "insta.cert.pem insta_ca.cert.pem " \ 649 "IR_protected_0_extraCerts.der " \ 650 "IR_protected_2_extraCerts.der module_name [module_conf_file]\n" 651 OPT_TEST_DECLARE_USAGE(USAGE) 652 653 int setup_tests(void) 654 { 655 /* Set test time stamps */ 656 struct tm ts = { 0 }; 657 658 ts.tm_year = 2018 - 1900; /* 2018 */ 659 ts.tm_mon = 1; /* February */ 660 ts.tm_mday = 18; /* 18th */ 661 test_time_valid = mktime(&ts); /* February 18th 2018 */ 662 ts.tm_year += 10; /* February 18th 2028 */ 663 test_time_after_expiration = mktime(&ts); 664 665 if (!test_skip_common_options()) { 666 TEST_error("Error parsing test options\n"); 667 return 0; 668 } 669 670 RAND_bytes(rand_data, OSSL_CMP_TRANSACTIONID_LENGTH); 671 if (!TEST_ptr(server_f = test_get_argument(0)) 672 || !TEST_ptr(client_f = test_get_argument(1)) 673 || !TEST_ptr(endentity1_f = test_get_argument(2)) 674 || !TEST_ptr(endentity2_f = test_get_argument(3)) 675 || !TEST_ptr(root_f = test_get_argument(4)) 676 || !TEST_ptr(intermediate_f = test_get_argument(5)) 677 || !TEST_ptr(ir_protected_f = test_get_argument(6)) 678 || !TEST_ptr(ir_unprotected_f = test_get_argument(7)) 679 || !TEST_ptr(ip_waiting_f = test_get_argument(8)) 680 || !TEST_ptr(ir_rmprotection_f = test_get_argument(9)) 681 || !TEST_ptr(instacert_f = test_get_argument(10)) 682 || !TEST_ptr(instaca_f = test_get_argument(11)) 683 || !TEST_ptr(ir_protected_0_extracerts = test_get_argument(12)) 684 || !TEST_ptr(ir_protected_2_extracerts = test_get_argument(13))) { 685 TEST_error("usage: cmp_vfy_test %s", USAGE); 686 return 0; 687 } 688 689 if (!test_arg_libctx(&libctx, &default_null_provider, &provider, 14, USAGE)) 690 return 0; 691 692 /* Load certificates for cert chain */ 693 if (!TEST_ptr(endentity1 = load_cert_pem(endentity1_f, libctx)) 694 || !TEST_ptr(endentity2 = load_cert_pem(endentity2_f, libctx)) 695 || !TEST_ptr(root = load_cert_pem(root_f, NULL)) 696 || !TEST_ptr(intermediate = load_cert_pem(intermediate_f, libctx))) 697 goto err; 698 699 if (!TEST_ptr(insta_cert = load_cert_pem(instacert_f, libctx)) 700 || !TEST_ptr(instaca_cert = load_cert_pem(instaca_f, libctx))) 701 goto err; 702 703 /* Load certificates for message validation */ 704 if (!TEST_ptr(srvcert = load_cert_pem(server_f, libctx)) 705 || !TEST_ptr(clcert = load_cert_pem(client_f, libctx))) 706 goto err; 707 if (!TEST_int_eq(1, RAND_bytes(rand_data, OSSL_CMP_TRANSACTIONID_LENGTH))) 708 goto err; 709 if (!TEST_ptr(ir_unprotected = load_pkimsg(ir_unprotected_f, libctx)) 710 || !TEST_ptr(ir_rmprotection = load_pkimsg(ir_rmprotection_f, 711 libctx))) 712 goto err; 713 714 /* Message validation tests */ 715 ADD_TEST(test_verify_popo); 716 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 717 ADD_TEST(test_verify_popo_bad); 718 #endif 719 ADD_TEST(test_validate_msg_signature_trusted_ok); 720 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 721 ADD_TEST(test_validate_msg_signature_trusted_expired); 722 ADD_TEST(test_validate_msg_signature_srvcert_missing); 723 #endif 724 ADD_TEST(test_validate_msg_signature_srvcert_wrong); 725 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 726 ADD_TEST(test_validate_msg_signature_bad); 727 #endif 728 ADD_TEST(test_validate_msg_signature_sender_cert_srvcert); 729 ADD_TEST(test_validate_msg_signature_sender_cert_untrusted); 730 ADD_TEST(test_validate_msg_signature_sender_cert_trusted); 731 ADD_TEST(test_validate_msg_signature_sender_cert_extracert); 732 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 733 ADD_TEST(test_validate_msg_signature_sender_cert_absent); 734 #endif 735 ADD_TEST(test_validate_msg_signature_expected_sender); 736 ADD_TEST(test_validate_msg_signature_unexpected_sender); 737 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 738 ADD_TEST(test_validate_msg_unprotected_request); 739 #endif 740 ADD_TEST(test_validate_msg_mac_alg_protection_ok); 741 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 742 ADD_TEST(test_validate_msg_mac_alg_protection_missing); 743 ADD_TEST(test_validate_msg_mac_alg_protection_wrong); 744 ADD_TEST(test_validate_msg_mac_alg_protection_bad); 745 #endif 746 747 /* Cert path validation tests */ 748 ADD_TEST(test_validate_cert_path_ok); 749 ADD_TEST(test_validate_cert_path_expired); 750 ADD_TEST(test_validate_cert_path_wrong_anchor); 751 752 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 753 ADD_TEST(test_msg_check_no_protection_no_cb); 754 ADD_TEST(test_msg_check_no_protection_restrictive_cb); 755 #endif 756 ADD_TEST(test_msg_check_no_protection_permissive_cb); 757 ADD_TEST(test_msg_check_transaction_id); 758 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 759 ADD_TEST(test_msg_check_transaction_id_bad); 760 #endif 761 ADD_TEST(test_msg_check_recipient_nonce); 762 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 763 ADD_TEST(test_msg_check_recipient_nonce_bad); 764 ADD_TEST(test_msg_check_update_malicious_sender); 765 #endif 766 767 return 1; 768 769 err: 770 cleanup_tests(); 771 return 0; 772 } 773