From: Wes Malone <
wesdm...@gmail.com>
Unit test cases to validate the X509_V_FLAG_CRL_CHECK_ALL behavior.
The test Makefile generates a multi-level CA hierarchy (root
CA -> intermediate CA -> signer).
Tests added (in test/test_verify.c):
- _with_revoked_intermediate_crl_default:
intermediate revoked, check_all=false → pass (current behavior)
- _with_revoked_intermediate_crl_check_all:
same scenario with check_all=true → rejected
The paired *_default / *_check_all tests show that without
CRL_CHECK_ALL, a revoked intermediate CA can issue a valid-looking new
leaf cert that passes verification.
test/Makefile | 33 +++++++++++++++--
.../data/cms-test-ca/intermediate-openssl.cnf | 31 ++++++++++++++++
test/data/cms-test-ca/openssl.cnf | 3 ++
test/test_verify.c | 37 +++++++++++++++++++
4 files changed, 101 insertions(+), 3 deletions(-)
create mode 100644 test/data/cms-test-ca/intermediate-openssl.cnf
diff --git a/test/Makefile b/test/Makefile
index ca66f7b0..ffe613ad 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -108,7 +108,7 @@ $(obj)/test_verify.o: PREPARE_DATA $(DATADIR)/signature $(DATADIR)/signing-pubke
ifeq ($(CONFIG_SSL_IMPL_OPENSSL),y)
ifeq ($(CONFIG_SIGALG_CMS),y)
-$(obj)/test_verify.o: $(DATADIR)/signature.cms $(DATADIR)/cms-ca.cert.pem $(DATADIR)/cms-ca.crl.pem $(DATADIR)/cms-ca.crl.der $(DATADIR)/cms-ca.crl.empty.pem
+$(obj)/test_verify.o: $(DATADIR)/signature.cms $(DATADIR)/cms-ca.cert.pem $(DATADIR)/cms-ca.crl.pem $(DATADIR)/cms-ca.crl.der $(DATADIR)/cms-ca.crl.empty.pem $(DATADIR)/signature-chain.cms $(DATADIR)/cms-chain.crl.pem
endif
endif
@@ -129,11 +129,12 @@ $(DATADIR)/signing-secret.pem:
CMS_TEST_CA_DIR := $(DATADIR)/cms-test-ca
CMS_TEST_CA_CONFIG := $(CMS_TEST_CA_DIR)/openssl.cnf
+CMS_TEST_INTERMEDIATE_CA_CONFIG := $(CMS_TEST_CA_DIR)/intermediate-openssl.cnf
-$(DATADIR)/signature.cms $(DATADIR)/cms-ca.cert.pem $(DATADIR)/cms-ca.crl.pem $(DATADIR)/cms-ca.crl.der $(DATADIR)/cms-ca.crl.empty.pem &: $(DATADIR)/to-be-signed $(CMS_TEST_CA_CONFIG) | PREPARE_DATA
+$(DATADIR)/signature.cms $(DATADIR)/cms-ca.cert.pem $(DATADIR)/cms-ca.crl.pem $(DATADIR)/cms-ca.crl.der $(DATADIR)/cms-ca.crl.empty.pem $(DATADIR)/signature-chain.cms $(DATADIR)/cms-chain.crl.pem &: $(DATADIR)/to-be-signed $(CMS_TEST_CA_CONFIG) $(CMS_TEST_INTERMEDIATE_CA_CONFIG) | PREPARE_DATA
$(if $(Q),@echo " GEN CMS/CRL test data")
$(Q)mkdir -p $(CMS_TEST_CA_DIR)
- $(Q)find $(CMS_TEST_CA_DIR) -mindepth 1 ! -name openssl.cnf -exec rm -rf {} +
+ $(Q)find $(CMS_TEST_CA_DIR) -mindepth 1 ! -name openssl.cnf ! -name intermediate-openssl.cnf -exec rm -rf {} +
$(Q)mkdir -p $(CMS_TEST_CA_DIR)/newcerts
$(Q)printf "1000\n" > $(CMS_TEST_CA_DIR)/serial
$(Q)printf "1000\n" > $(CMS_TEST_CA_DIR)/crlnumber
@@ -152,14 +153,40 @@ $(DATADIR)/signature.cms $(DATADIR)/cms-ca.cert.pem $(DATADIR)/cms-ca.crl.pem $(
$(Q)openssl cms -sign -in $(DATADIR)/to-be-signed -out $(DATADIR)/signature.cms \
-signer $(DATADIR)/cms-signer.cert.pem -inkey $(DATADIR)/cms-signer.key.pem \
-outform DER -nosmimecap -binary > /dev/null 2>&1
+ $(Q)openssl req -new -newkey rsa:2048 -nodes \
+ -keyout $(DATADIR)/cms-intermediate.key.pem -out $(DATADIR)/cms-intermediate.csr.pem \
+ -subj "/CN=SWUpdate Test Intermediate CA" > /dev/null 2>&1
+ $(Q)openssl ca -batch -config $(CMS_TEST_CA_CONFIG) -extensions intermediate_ca \
+ -in $(DATADIR)/cms-intermediate.csr.pem -out $(DATADIR)/cms-intermediate.cert.pem \
+ -days 365 > /dev/null 2>&1
+ $(Q)mkdir -p $(CMS_TEST_CA_DIR)/intermediate/newcerts
+ $(Q)printf "1000\n" > $(CMS_TEST_CA_DIR)/intermediate/serial
+ $(Q)printf "1000\n" > $(CMS_TEST_CA_DIR)/intermediate/crlnumber
+ $(Q)touch $(CMS_TEST_CA_DIR)/intermediate/index.txt
+ $(Q)openssl req -new -newkey rsa:2048 -nodes \
+ -keyout $(DATADIR)/cms-chain-signer.key.pem -out $(DATADIR)/cms-chain-signer.csr.pem \
+ -subj "/CN=SWUpdate Test Chain Signer" > /dev/null 2>&1
+ $(Q)openssl ca -batch -config $(CMS_TEST_INTERMEDIATE_CA_CONFIG) \
+ -in $(DATADIR)/cms-chain-signer.csr.pem -out $(DATADIR)/cms-chain-signer.cert.pem \
+ -days 365 > /dev/null 2>&1
+ $(Q)openssl cms -sign -in $(DATADIR)/to-be-signed -out $(DATADIR)/signature-chain.cms \
+ -signer $(DATADIR)/cms-chain-signer.cert.pem -inkey $(DATADIR)/cms-chain-signer.key.pem \
+ -certfile $(DATADIR)/cms-intermediate.cert.pem -outform DER -nosmimecap -binary > /dev/null 2>&1
$(Q)openssl ca -gencrl -config $(CMS_TEST_CA_CONFIG) \
-out $(DATADIR)/cms-ca.crl.empty.pem > /dev/null 2>&1
+ $(Q)openssl ca -gencrl -config $(CMS_TEST_INTERMEDIATE_CA_CONFIG) \
+ -out $(DATADIR)/cms-intermediate.crl.empty.pem > /dev/null 2>&1
$(Q)openssl ca -config $(CMS_TEST_CA_CONFIG) \
-revoke $(DATADIR)/cms-signer.cert.pem > /dev/null 2>&1
$(Q)openssl ca -gencrl -config $(CMS_TEST_CA_CONFIG) \
-out $(DATADIR)/cms-ca.crl.pem > /dev/null 2>&1
$(Q)openssl crl -in $(DATADIR)/cms-ca.crl.pem -out $(DATADIR)/cms-ca.crl.der \
-outform DER > /dev/null 2>&1
+ $(Q)openssl ca -config $(CMS_TEST_CA_CONFIG) \
+ -revoke $(DATADIR)/cms-intermediate.cert.pem > /dev/null 2>&1
+ $(Q)openssl ca -gencrl -config $(CMS_TEST_CA_CONFIG) \
+ -out $(DATADIR)/cms-root.crl.pem > /dev/null 2>&1
+ $(Q)cat $(DATADIR)/cms-root.crl.pem $(DATADIR)/cms-intermediate.crl.empty.pem > $(DATADIR)/cms-chain.crl.pem
ifeq ($(CONFIG_PKCS11),y)
$(obj)/test_crypt_pkcs11.o: $(DATADIR)/softshm
diff --git a/test/data/cms-test-ca/intermediate-openssl.cnf b/test/data/cms-test-ca/intermediate-openssl.cnf
new file mode 100644
index 00000000..9a5b346b
--- /dev/null
+++ b/test/data/cms-test-ca/intermediate-openssl.cnf
@@ -0,0 +1,31 @@
+# SPDX-FileCopyrightText: 2026 MTSI
+#
+# SPDX-License-Identifier: CC0-1.0
+
+[ ca ]
+default_ca = swupdate_test_intermediate_ca
+[ swupdate_test_intermediate_ca ]
+dir = test/data/cms-test-ca/intermediate
+database = $dir/index.txt
+new_certs_dir = $dir/newcerts
+certificate = test/data/cms-intermediate.cert.pem
+private_key = test/data/cms-intermediate.key.pem
+serial = $dir/serial
+crlnumber = $dir/crlnumber
+default_md = sha256
+policy = policy_any
+x509_extensions = usr_cert
+copy_extensions = copy
+default_crl_days = 365
+[ policy_any ]
+commonName = supplied
+organizationName = optional
+organizationalUnitName = optional
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+emailAddress = optional
+[ usr_cert ]
+basicConstraints = critical,CA:FALSE
+keyUsage = critical,digitalSignature
+extendedKeyUsage = emailProtection
diff --git a/test/data/cms-test-ca/openssl.cnf b/test/data/cms-test-ca/openssl.cnf
index 0eb9d10f..c6695ebf 100644
--- a/test/data/cms-test-ca/openssl.cnf
+++ b/test/data/cms-test-ca/openssl.cnf
@@ -29,3 +29,6 @@ emailAddress = optional
basicConstraints = critical,CA:FALSE
keyUsage = critical,digitalSignature
extendedKeyUsage = emailProtection
+[ intermediate_ca ]
+basicConstraints = critical,CA:true,pathlen:0
+keyUsage = critical,keyCertSign,cRLSign
diff --git a/test/test_verify.c b/test/test_verify.c
index d72f3967..a93f67f4 100644
--- a/test/test_verify.c
+++ b/test/test_verify.c
@@ -112,6 +112,41 @@ static void test_verify_cms_with_nonrevoked_crl(void **state)
DATADIR "to-be-signed", NULL);
assert_int_equal(error, 0);
}
+
+static void test_verify_cms_with_revoked_intermediate_crl_default(void **state)
+{
+ int error;
+ struct swupdate_cfg config;
+
+ (void)state;
+
+ memset(&config, 0, sizeof(config));
+ strlcpy(config.crlfname, DATADIR "cms-chain.crl.pem", sizeof(config.crlfname));
+ error = swupdate_dgst_init(&config, DATADIR "cms-ca.cert.pem");
+ assert_int_equal(error, 0);
+
+ error = swupdate_verify_file(config.dgst, DATADIR "signature-chain.cms",
+ DATADIR "to-be-signed", NULL);
+ assert_int_equal(error, 0);
+}
+
+static void test_verify_cms_with_revoked_intermediate_crl_check_all(void **state)
+{
+ int error;
+ struct swupdate_cfg config;
+
+ (void)state;
+
+ memset(&config, 0, sizeof(config));
+ strlcpy(config.crlfname, DATADIR "cms-chain.crl.pem", sizeof(config.crlfname));
+ config.crl_check_all = true;
+ error = swupdate_dgst_init(&config, DATADIR "cms-ca.cert.pem");
+ assert_int_equal(error, 0);
+
+ error = swupdate_verify_file(config.dgst, DATADIR "signature-chain.cms",
+ DATADIR "to-be-signed", NULL);
+ assert_int_not_equal(error, 0);
+}
#endif
int main(void)
@@ -124,6 +159,8 @@ int main(void)
cmocka_unit_test(test_verify_cms_with_revoked_signer_crl),
cmocka_unit_test(test_verify_cms_with_revoked_signer_der_crl),
cmocka_unit_test(test_verify_cms_with_nonrevoked_crl),
+ cmocka_unit_test(test_verify_cms_with_revoked_intermediate_crl_default),
+ cmocka_unit_test(test_verify_cms_with_revoked_intermediate_crl_check_all),
#endif
};
return cmocka_run_group_tests_name("verify", verify_tests, NULL, NULL);
--
2.43.0