Commit 0a62876772 for openssl.org
commit 0a62876772a24969f503fbcbf0d5da7d827a3c77
Author: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Thu Sep 10 16:49:18 2026 +0200
Provide stricter test for cert order on parse
Reviewed-by: Mounir Idrassi <mounir.idrassi@idrix.fr>
Reviewed-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Todd Short <todd.short@me.com>
Merge-date: Tue Sep 15 15:23:49 2026
Merged-from: https://github.com/openssl/openssl/pull/32773
diff --git a/test/pkcs12_api_test.c b/test/pkcs12_api_test.c
index 2a8105a892..5f4550fe3b 100644
--- a/test/pkcs12_api_test.c
+++ b/test/pkcs12_api_test.c
@@ -63,6 +63,7 @@ static int has_ca = 0;
static int expected_ca_count = -1;
static const char *expected_cert_file = NULL;
static const char *expected_ca_file = NULL;
+static const char *expected_key_file = NULL;
static int mismatched_key_pass = 0;
static int changepass(PKCS12 *p12, EVP_PKEY *key, X509 *cert, STACK_OF(X509) *ca)
@@ -393,6 +394,7 @@ typedef enum OPTION_choice {
OPT_CA_COUNT,
OPT_EXPECTED_CERT,
OPT_EXPECTED_CA,
+ OPT_EXPECTED_KEY,
OPT_MISMATCHED_P12,
OPT_LEGACY,
OPT_TEST_ENUM
@@ -410,6 +412,7 @@ const OPTIONS *test_get_options(void)
{ "ca-count", OPT_CA_COUNT, 'n', "Expected number of CA certificates" },
{ "expected-cert", OPT_EXPECTED_CERT, '<', "PEM file of expected main certificate" },
{ "expected-ca", OPT_EXPECTED_CA, '<', "PEM file of expected CA certificates in order" },
+ { "expected-key", OPT_EXPECTED_KEY, '<', "PEM file of expected private key" },
{ "mismatched-key-pass", OPT_MISMATCHED_P12, '-', "Input has key encrypted with a different password" },
{ "legacy", OPT_LEGACY, '-', "Test the legacy APIs" },
{ NULL }
@@ -477,93 +480,91 @@ err:
return ret;
}
-static int test_parse_cert_placement(void)
+static int test_parse_cert_placement(int idx)
{
- int ret = 0, i;
+ int ret = 0, i, pos = 0;
+ int want_key = (idx >> 2) & 1;
+ int want_cert = (idx >> 1) & 1;
+ int want_ca = idx & 1;
+ int selected = want_key && want_cert ? 1 : -1;
PKCS12 *p12 = NULL;
- EVP_PKEY *key = NULL;
- X509 *cert = NULL, *exp_cert = NULL, *x = NULL;
- STACK_OF(X509) *ca = NULL, *exp_ca = NULL;
- BIO *bio = NULL;
+ EVP_PKEY *key = NULL, *exp_key = NULL;
+ X509 *cert = NULL, *exp_cert = NULL;
+ X509 *ordered[3];
+ STACK_OF(X509) *ca = NULL, *exp_ca = NULL, *all = NULL;
- if (in_file == NULL
- || (expected_cert_file == NULL && expected_ca_file == NULL))
+ if (expected_key_file == NULL && expected_cert_file == NULL
+ && expected_ca_file == NULL)
return 1;
- p12 = PKCS12_load(in_file);
- if (!TEST_ptr(p12))
- goto err;
-
- if (!TEST_true(PKCS12_parse(p12, in_pass, &key, &cert, &ca)))
- goto err;
-
- if (has_key && !TEST_ptr(key))
+ if (!TEST_ptr(exp_key = load_pkey_pem(expected_key_file, testctx))
+ || !TEST_ptr(exp_cert = load_cert_pem(expected_cert_file, testctx))
+ || !TEST_ptr(exp_ca = load_certs_pem(expected_ca_file))
+ || !TEST_int_eq(sk_X509_num(exp_ca), 2)
+ || !TEST_int_ne(X509_cmp(exp_cert, sk_X509_value(exp_ca, 0)), 0)
+ || !TEST_ptr(all = sk_X509_new_null()))
goto err;
- if (expected_cert_file != NULL) {
- bio = BIO_new_file(expected_cert_file, "rb");
- if (!TEST_ptr(bio))
+ /* extra_certs.pem contains the second match, then the unrelated cert. */
+ ordered[0] = sk_X509_value(exp_ca, 1);
+ ordered[1] = exp_cert;
+ ordered[2] = sk_X509_value(exp_ca, 0);
+ for (i = 0; i < (int)OSSL_NELEM(ordered); i++) {
+ if (!TEST_int_gt(sk_X509_push(all, ordered[i]), 0))
goto err;
- exp_cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
- BIO_free(bio);
- bio = NULL;
- if (!TEST_ptr(exp_cert))
- goto err;
- if (!TEST_ptr(cert))
- goto err;
- if (!TEST_int_eq(X509_cmp(cert, exp_cert), 0)) {
- TEST_info("main cert does not match expected cert");
- goto err;
- }
}
- if (expected_ca_file != NULL) {
- int actual_count, expected_count;
+ /* Passing all certificates through ca preserves the chosen order. */
+ p12 = PKCS12_create_ex("", NULL, exp_key, NULL, all,
+ NID_undef, NID_undef, 0, -1, 0, testctx, "provider=default");
+ if (!TEST_ptr(p12)
+ || !TEST_true(PKCS12_parse(p12, "",
+ want_key ? &key : NULL,
+ want_cert ? &cert : NULL,
+ want_ca ? &ca : NULL)))
+ goto err;
- exp_ca = sk_X509_new_null();
- if (!TEST_ptr(exp_ca))
- goto err;
+ if (want_key
+ && (!TEST_ptr(key) || !TEST_int_eq(EVP_PKEY_eq(key, exp_key), 1)))
+ goto err;
- bio = BIO_new_file(expected_ca_file, "rb");
- if (!TEST_ptr(bio))
- goto err;
- while ((x = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
- if (!sk_X509_push(exp_ca, x)) {
- X509_free(x);
- x = NULL;
+ if (want_cert) {
+ if (selected >= 0) {
+ if (!TEST_ptr(cert)
+ || !TEST_int_eq(X509_cmp(cert, exp_cert), 0))
goto err;
- }
- x = NULL;
+ } else if (!TEST_ptr_null(cert)) {
+ goto err;
}
- ERR_clear_error();
- BIO_free(bio);
- bio = NULL;
-
- actual_count = ca == NULL ? 0 : sk_X509_num(ca);
- expected_count = sk_X509_num(exp_ca);
+ }
- if (!TEST_int_eq(actual_count, expected_count))
+ if (want_ca) {
+ if (!TEST_ptr(ca)
+ || !TEST_int_eq(sk_X509_num(ca), selected >= 0 ? 2 : 3))
goto err;
-
- for (i = 0; i < expected_count; i++) {
- if (!TEST_int_eq(X509_cmp(sk_X509_value(ca, i),
- sk_X509_value(exp_ca, i)),
- 0)) {
- TEST_info("CA cert mismatch at index %d", i);
+ for (i = 0; i < (int)OSSL_NELEM(ordered); i++) {
+ if (i == selected)
+ continue;
+ if (!TEST_int_eq(X509_cmp(sk_X509_value(ca, pos), ordered[i]), 0)) {
+ TEST_info("CA cert mismatch at index %d", pos);
goto err;
}
+ pos++;
}
}
ret = 1;
err:
+ if (!ret)
+ TEST_info("failed placement combination %d", idx);
PKCS12_free(p12);
EVP_PKEY_free(key);
+ EVP_PKEY_free(exp_key);
X509_free(cert);
- OSSL_STACK_OF_X509_free(ca);
X509_free(exp_cert);
+ OSSL_STACK_OF_X509_free(ca);
OSSL_STACK_OF_X509_free(exp_ca);
- BIO_free(bio);
+ sk_X509_free(all);
return ret;
}
@@ -642,6 +643,9 @@ int setup_tests(void)
case OPT_EXPECTED_CA:
expected_ca_file = opt_arg();
break;
+ case OPT_EXPECTED_KEY:
+ expected_key_file = opt_arg();
+ break;
case OPT_MISMATCHED_P12:
mismatched_key_pass = 1;
break;
@@ -661,7 +665,7 @@ int setup_tests(void)
ADD_TEST(test_null_args);
ADD_TEST(pkcs12_parse_test);
ADD_ALL_TESTS(test_parse_combinations, 8);
- ADD_TEST(test_parse_cert_placement);
+ ADD_ALL_TESTS(test_parse_cert_placement, 8);
ADD_TEST(test_parse_mismatched_key_password);
ADD_MFAIL_NO_CHECK_TEST(pkcs12_parse_mfail_test);
ADD_MFAIL_NO_CHECK_TEST(pkcs12_parse_existing_ca_mfail_test);
diff --git a/test/recipes/80-test_pkcs12.t b/test/recipes/80-test_pkcs12.t
index 0b553a7585..e1457639c4 100644
--- a/test/recipes/80-test_pkcs12.t
+++ b/test/recipes/80-test_pkcs12.t
@@ -445,6 +445,7 @@ ok(run(test(["pkcs12_api_test",
"-has-ca", 1,
"-ca-count", 2,
"-expected-cert", srctop_file(@path, "ee-cert.pem"),
+ "-expected-key", srctop_file(@path, "ee-key.pem"),
"-expected-ca", $extra_certs,
])), "Test PKCS12_parse cert placement with shared key");
}