swtpm/tests/_test_tpm2_swtpm_cert
Stefan Berger 93f64a1a8e tests: Create certificates for ML-DSA and ML-KEM keys
Extend the swtpm_cert test cases to also have ML-DSA and ML-KEM keys
certified.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
2026-06-03 16:30:44 -04:00

395 lines
11 KiB
Bash
Executable File

#!/usr/bin/env bash
# For the license, see the LICENSE file in the root directory.
ROOT=${abs_top_builddir:-$(dirname "$0")/..}
TESTDIR=${abs_top_testdir:-$(dirname "$0")}
source "${TESTDIR}/common"
cert="$(mktemp)" || exit 1
trap "cleanup" SIGTERM EXIT
function cleanup()
{
rm -f "${cert}"
}
function check_cert_size()
{
local cert="$1"
local exp="$2"
local size lo hi
lo=$(cut -d"-" -f1 <<< "${exp}")
hi=$(cut -d"-" -f2 <<< "${exp}")
# Check size of DER cert
size=$(openssl x509 -in "${cert}" -outform der | wc -c)
if [ "${size}" -lt "${lo}" ] || [ "${size}" -gt "${hi}" ]; then
echo "Warning: DER Certificate has unexpected size."
echo " Expected: $exp; found: $size"
fi
}
function check_cert()
{
local cert="$1"
local size="$2"
shift 2
local txt msg
check_cert_size "${cert}" "${size}"
txt=$(openssl x509 -in "${cert}" -noout -text)
while [ $# -ne 0 ]; do
if ! grep -q "$1" <<< "${txt}"; then
echo "Could not find expected data in cert."
echo "expected: $1"
echo "${txt}"
exit 1
fi
shift
done
if ! msg=$(openssl verify \
-partial_chain \
-CAfile "${PARAM_ISSUERCERT}" \
"${cert}" 2>&1); then
echo "Could not verify the certificate."
echo "${msg}"
exit 1
fi
}
# shellcheck disable=2206
PARAM_CERT_SIZES=(${PARAM_CERT_SIZES})
COMMON=(
--tpm2
--signkey "${PARAM_SIGNKEY}"
--issuercert "${PARAM_ISSUERCERT}"
--out-cert "${cert}"
--days 3650
--pem
--tpm-manufacturer IBM --tpm-model swtpm-libtpms --tpm-version 2
--tpm-spec-family 2 --tpm-spec-revision 146 --tpm-spec-level 0
--subject "CN=swtpm,serialNumber=123,O=test,OU=test"
)
TC=0
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--modulus b9dda830729de58f9f5bed2b3b9394ad4ec5afb9c390b89a3337250cbc575cfc8f31f7ffd3f05f4155076f7d1605381cd281b7f147b801154e4f89ee529fe36eae50f79561850e5b63037edaacbb390ea3fcd037e674fb179e3c5afe31214d78a756ca44cc6cf25421b51420ede548310c92b08a513ccc62fd0ef45dcf6546f6e865be6a661d045d1c47b60b428d11dc97cb9f35ee7c385bb20320934b015f8014e8fb19851c2af307e1e64648c142175e40b60615dc494fdb09ea5d5a6f3273b65a241e3cf30cc449b9fb3f900d1ed4be967b32b16f95a1d732dbfa143eaa1c2017556117f70faee5d77f836705d05405361ad5871a32161fa5a1234cfab497 \
--decrypt \
--days -1;
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"Dec 31 23:59:59 9999 GMT" \
"Public-Key: (2048 bit)" \
"CA:FALSE" \
"Endorsement Key Certificate" \
"Key Encipherment" \
"DirName:/tcg-at-tpmManufacturer=IBM/tcg-at-tpmModel=swtpm-libtpms/tcg-at-tpmVersion=2"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (modulus)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--ecc-x 61eaf811ea582656ca2a835dd1b9cd63eb196d7ff62711d6e9b8f85e580a47ca \
--ecc-y a51efdc71fd6c791a24a75beb50526aa81b44cc598e65b2d5e116084aea4cb5b;
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"Public-Key: (256 bit)" \
"CA:FALSE" \
"Endorsement Key Certificate" \
"Key Agreement" \
"DirName:/tcg-at-tpmManufacturer=IBM/tcg-at-tpmModel=swtpm-libtpms/tcg-at-tpmVersion=2"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (ecc; coordinates)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--allow-signing \
--pubkey "${PARAM_RSAPUBKEY}";
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"Public-Key: (2432 bit)" \
"CA:FALSE" \
"Endorsement Key Certificate" \
"Digital Signature" \
"DirName:/tcg-at-tpmManufacturer=IBM/tcg-at-tpmModel=swtpm-libtpms/tcg-at-tpmVersion=2"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (allow signing)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--pubkey "${PARAM_ECPUBKEY}";
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"Public-Key: (256 bit)" \
"CA:FALSE" \
"Endorsement Key Certificate" \
"Key Encipherment" \
"DirName:/tcg-at-tpmManufacturer=IBM/tcg-at-tpmModel=swtpm-libtpms/tcg-at-tpmVersion=2"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (ecc)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--pubkey "${PARAM_MLKEM1024PUBKEY}";
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"ML-KEM-1024 Public-Key:" \
"CA:FALSE" \
"Endorsement Key Certificate" \
"Key Encipherment" \
"DirName:/tcg-at-tpmManufacturer=IBM/tcg-at-tpmModel=swtpm-libtpms/tcg-at-tpmVersion=2"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (ML-KEM-1024 key)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--public 16d75180b96183fc9ff96aa6b8d93793a0a645dc97589b62245955be3061719525ac90c3efb17308859038776d7eb88c8b55a8d9ebbeb8873f2b798d9888aff3f22358808b1c3c489d690d29ea9f6e1c1c301815686a0d39d1479f0979cfb07f7127c37c83c2f26a9c8c203d68c41ae6a690ce56bc4276082cec00c32a5b6515a41121a853d76e64e2a928aac333a4618af260ef7763b9f425d1737926e180ec50cbb87b334b085a638568455c2d14b8501056514e062365117a6603b007a70d1567290297b3998a7bc0cab0b43625a2fa94e58b88755cb3c5779aaff877ff11c1b380555bb05eae277f98808ebf590f6bc33c26353e8a55abdf838e7cb5ada53545dc3164e668494ef45441016f11b94c964b379c653f28111286f25987c0283189ba3dc34430f3c026b72870667dfe85038dec103ae08c511cc8dc292fd9091ac624575d78994ff54f3b20b985b62d76c6512c240c65024fba29a486b9c096ac9173c44583f94a1e6c5e1586ab35c3c93d667e5edb22393705eb9782666c76423954b818b346012851aa015af6cb9865ca45aa14e966a7882704d28049c66601615855acb604ced42bf743c1c1a37ead7bbd2284bf512086d6a6cde9f22e39a5abe321393b477f07ec76a5529cc81996c99777df184f41842f1722801d936becda48159c21e85bc5f39b6f17e537a18956eca7238e0336b196bc5a36b1c6e531b88b29a1b23ad9d0bfb6643c65092730e81410154faf1a429950aa3cf7a435a24d1ca00930bb354c207a5809958a505936224fcfcbb4f622ca5115113781b53f1225dda59b39bba4b82ca180f535ac3b7554a62187566a3a3c81dfc9cf7fd91648b36c0e19237dd2a067d86d627c366cacb716acaa3fd9c22bd0a1dd6256d42b2a460acb1a95ccf0070f62367096765d06dcb2f7959f0c7280874362c0f75473998240a91ac70528aec4b49ea974bf975f405180bd1393093555f015ca1dc81c8b22999466a674d440ee47bffd5193fae2c67ba6360e86c4d3a38c52a448f773b91094c25d56731ce83bdf515e6a345999186136f57a4bdb2d6c49aa185c81330e8ff4bdbd9321bb74c5e0c6c217c7b78a02783594a09dd7aeb9293b1e31fc \
--keyalgo ml-kem-512;
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"ML-KEM-512 Public-Key:" \
"CA:FALSE" \
"Endorsement Key Certificate" \
"Key Encipherment" \
"DirName:/tcg-at-tpmManufacturer=IBM/tcg-at-tpmModel=swtpm-libtpms/tcg-at-tpmVersion=2"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (ML-KEM-512 key)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--pubkey "${PARAM_MLDSA87PUBKEY}";
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"ML-DSA-87 Public-Key:" \
"CA:FALSE" \
"Endorsement Key Certificate" \
"Key Encipherment" \
"DirName:/tcg-at-tpmManufacturer=IBM/tcg-at-tpmModel=swtpm-libtpms/tcg-at-tpmVersion=2"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (ML-DSA-87 key)"
###################### Platform Certificate #####################
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--serial 123 \
--type platform \
--pubkey "${PARAM_RSAPUBKEY}" \
--platform-manufacturer Fedora \
--platform-model QEMU \
--platform-version 2.1;
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 123 (0x7b)" \
"Public-Key: (2432 bit)" \
"CA:FALSE" \
"Platform Attribute Certificate" \
"Key Encipherment" \
"DirName:/tcg-at-platformManufacturerStr=Fedora/tcg-at-platformModel=QEMU/tcg-at-platformVersion=2.1"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (platform cert)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--serial 12 \
--type platform \
--pubkey "${PARAM_ECPUBKEY}" \
--platform-manufacturer Fedora \
--platform-model QEMU \
--platform-version 2.1;
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 12 (0xc)" \
"Public-Key: (256 bit)" \
"CA:FALSE" \
"Platform Attribute Certificate" \
"Key Encipherment" \
"DirName:/tcg-at-platformManufacturerStr=Fedora/tcg-at-platformModel=QEMU/tcg-at-platformVersion=2.1"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (platform cert; ec key)"
###################### IAK Certificate #####################
serial=1234:5678
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--type iak \
--pubkey "${PARAM_RSAPUBKEY}" \
--subject "serialNumber=${serial}" \
--tpm-serial-num "${serial}";
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"Subject: serialNumber[[:space:]]*=[[:space:]]*${serial}" \
"Public-Key: (2432 bit)" \
"DirName:/id-on-hardwareModuleName=0.*${serial}" \
"CA:FALSE" \
"Digital Signature"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (IAK)"
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--type iak \
--pubkey "${PARAM_MLDSA87PUBKEY}" \
--subject "serialNumber=${serial}" \
--tpm-serial-num "${serial}";
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"ML-DSA-87 Public-Key:" \
"..${serial}" \
"CA:FALSE" \
"Digital Signature"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (ML-DSA-87 IAK)"
###################### IDevID Certificate #####################
serial=1234:5678
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--type idevid \
--pubkey "${PARAM_RSAPUBKEY}" \
--subject "serialNumber=${serial}" \
--tpm-serial-num "${serial}";
then
echo "Error: ${SWTPM_CERT} returned error code."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number: 1 (0x1)" \
"Subject: serialNumber[[:space:]]*=[[:space:]]*${serial}" \
"Public-Key: (2432 bit)" \
"DirName:/id-on-hardwareModuleName=0.*${serial}" \
"CA:FALSE" \
"Digital Signature"
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (IDevID)"
####################### max. serial number #####################
# max. serial number -- must pass
if ! ${SWTPM_CERT} \
"${COMMON[@]}" \
--pubkey "${PARAM_RSAPUBKEY}" \
--serial 1461501637330902918203684832716283019655932542975;
then
echo "Error: ${SWTPM_CERT} failed with max. serial number."
exit 1
fi
check_cert "${cert}" "${PARAM_CERT_SIZES[$((TC++))]}" \
"Serial Number:[[:space:]]*$" \
"ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff" \
"Public-Key: (2432 bit)" \
"CA:FALSE" \
"Key Encipherment"
# max. serial number + 1 -- must fail
if ${SWTPM_CERT} \
"${COMMON[@]}" \
--pubkey "${PARAM_RSAPUBKEY}" \
--serial 1461501637330902918203684832716283019655932542976;
then
echo "Error: ${SWTPM_CERT} should have failed with max. serial number + 1."
exit 1
fi
# truncate result file
echo -n > "${cert}"
echo "Test ${TC}: OK (failed as expected)"