Add CMS verification test coverage for OpenSSL CRL handling, including:
verification without CRL, revoked signer with PEM CRL, revoked signer
with DER CRL, and a non-revoked signer with an empty CRL.
Extend test fixture generation in test/Makefile to create CMS signature
artifacts and CRLs, and add test/data/.gitignore entries for generated
fixture files.
Co-developed-by: Franz Heger <
franz...@kuka.com>
Signed-off-by: Franz Heger <
franz...@kuka.com>
Signed-off-by: Daniel Braunwarth <
daniel.b...@kuka.com>
---
test/Makefile | 43 +++++++++++++++++
test/data/.gitignore | 5 ++
test/data/cms-test-ca/openssl.cnf | 31 +++++++++++++
test/test_verify.c | 76 +++++++++++++++++++++++++++++++
4 files changed, 155 insertions(+)
create mode 100644 test/data/.gitignore
create mode 100644 test/data/cms-test-ca/openssl.cnf
diff --git a/test/Makefile b/test/Makefile
index 7fa02dbd..ca66f7b0 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -25,6 +25,9 @@ tests-$(CONFIG_HASH_VERIFY) += test_hash
ifeq ($(CONFIG_SIGALG_RAWRSA),y)
tests-$(CONFIG_SIGNED_IMAGES) += test_verify
endif
+ifeq ($(CONFIG_SSL_IMPL_OPENSSL),y)
+tests-$(CONFIG_SIGALG_CMS) += test_verify
+endif
tests-$(CONFIG_SURICATTA_HAWKBIT) += test_json
tests-$(CONFIG_SURICATTA_HAWKBIT) += test_server_hawkbit
tests-$(CONFIG_MONGOOSE) += test_mongoose_upload
@@ -103,6 +106,12 @@ PREPARE_DATA:
$(obj)/test_verify.o: PREPARE_DATA $(DATADIR)/signature $(DATADIR)/signing-pubkey.pem
+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
+endif
+endif
+
.INTERMEDIATE: $(DATADIR)/signature
$(DATADIR)/signature: $(DATADIR)/to-be-signed $(DATADIR)/signing-secret.pem
$(if $(Q),@echo " SIGN $@")
@@ -118,6 +127,40 @@ $(DATADIR)/signing-secret.pem:
$(if $(Q),@echo " GEN $@")
$(Q)openssl genrsa -out $@ 2>/dev/null
+CMS_TEST_CA_DIR := $(DATADIR)/cms-test-ca
+CMS_TEST_CA_CONFIG := $(CMS_TEST_CA_DIR)/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
+ $(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)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
+ $(Q)touch $(CMS_TEST_CA_DIR)/index.txt
+ $(Q)openssl req -x509 -newkey rsa:2048 -nodes \
+ -keyout $(DATADIR)/cms-ca.key.pem -out $(DATADIR)/cms-ca.cert.pem \
+ -days 365 -sha256 -subj "/CN=SWUpdate Test CA" \
+ -addext "basicConstraints=critical,CA:true" \
+ -addext "keyUsage=critical,keyCertSign,cRLSign" > /dev/null 2>&1
+ $(Q)openssl req -new -newkey rsa:2048 -nodes \
+ -keyout $(DATADIR)/cms-signer.key.pem -out $(DATADIR)/cms-signer.csr.pem \
+ -subj "/CN=SWUpdate Test Signer" > /dev/null 2>&1
+ $(Q)openssl ca -batch -config $(CMS_TEST_CA_CONFIG) \
+ -in $(DATADIR)/cms-signer.csr.pem -out $(DATADIR)/cms-signer.cert.pem \
+ -days 365 > /dev/null 2>&1
+ $(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 ca -gencrl -config $(CMS_TEST_CA_CONFIG) \
+ -out $(DATADIR)/cms-ca.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
+
ifeq ($(CONFIG_PKCS11),y)
$(obj)/test_crypt_pkcs11.o: $(DATADIR)/softshm
diff --git a/test/data/.gitignore b/test/data/.gitignore
new file mode 100644
index 00000000..ae4bfdfc
--- /dev/null
+++ b/test/data/.gitignore
@@ -0,0 +1,5 @@
+*.pem
+*.der
+*.cms
+cms-test-ca/*
+!cms-test-ca/openssl.cnf
diff --git a/test/data/cms-test-ca/openssl.cnf b/test/data/cms-test-ca/openssl.cnf
new file mode 100644
index 00000000..0eb9d10f
--- /dev/null
+++ b/test/data/cms-test-ca/openssl.cnf
@@ -0,0 +1,31 @@
+# SPDX-FileCopyrightText: 2026 Daniel Braunwarth <
daniel.b...@kuka.com>
+#
+# SPDX-License-Identifier: CC0-1.0
+
+[ ca ]
+default_ca = swupdate_test_ca
+[ swupdate_test_ca ]
+dir = test/data/cms-test-ca
+database = $dir/index.txt
+new_certs_dir = $dir/newcerts
+certificate = test/data/cms-ca.cert.pem
+private_key = test/data/cms-ca.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/test_verify.c b/test/test_verify.c
index 1ed6793c..d72f3967 100644
--- a/test/test_verify.c
+++ b/test/test_verify.c
@@ -21,6 +21,7 @@
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
+#include <string.h>
#include <cmocka.h>
#include "swupdate_crypto.h"
@@ -44,11 +45,86 @@ static void test_verify_pkcs15(void **state)
assert_int_equal(error, 0);
}
+#if defined(CONFIG_SIGALG_CMS) && defined(CONFIG_SSL_IMPL_OPENSSL)
+static void test_verify_cms_without_crl(void **state)
+{
+ int error;
+ struct swupdate_cfg config;
+
+ (void)state;
+
+ memset(&config, 0, sizeof(config));
+ error = swupdate_dgst_init(&config, DATADIR "cms-ca.cert.pem");
+ assert_int_equal(error, 0);
+
+ error = swupdate_verify_file(config.dgst, DATADIR "signature.cms",
+ DATADIR "to-be-signed", NULL);
+ assert_int_equal(error, 0);
+}
+
+static void test_verify_cms_with_revoked_signer_crl(void **state)
+{
+ int error;
+ struct swupdate_cfg config;
+
+ (void)state;
+
+ memset(&config, 0, sizeof(config));
+ strlcpy(config.crlfname, DATADIR "cms-ca.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.cms",
+ DATADIR "to-be-signed", NULL);
+ assert_int_not_equal(error, 0);
+}
+
+static void test_verify_cms_with_revoked_signer_der_crl(void **state)
+{
+ int error;
+ struct swupdate_cfg config;
+
+ (void)state;
+
+ memset(&config, 0, sizeof(config));
+ strlcpy(config.crlfname, DATADIR "cms-ca.crl.der", 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.cms",
+ DATADIR "to-be-signed", NULL);
+ assert_int_not_equal(error, 0);
+}
+
+static void test_verify_cms_with_nonrevoked_crl(void **state)
+{
+ int error;
+ struct swupdate_cfg config;
+
+ (void)state;
+
+ memset(&config, 0, sizeof(config));
+ strlcpy(config.crlfname, DATADIR "cms-ca.crl.empty.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.cms",
+ DATADIR "to-be-signed", NULL);
+ assert_int_equal(error, 0);
+}
+#endif
+
int main(void)
{
swupdate_crypto_init();
static const struct CMUnitTest verify_tests[] = {
cmocka_unit_test(test_verify_pkcs15),
+#if defined(CONFIG_SIGALG_CMS) && defined(CONFIG_SSL_IMPL_OPENSSL)
+ cmocka_unit_test(test_verify_cms_without_crl),
+ 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),
+#endif
};
return cmocka_run_group_tests_name("verify", verify_tests, NULL, NULL);
}
--
2.43.0