summaryrefslogtreecommitdiffstats
path: root/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c
diff options
context:
space:
mode:
Diffstat (limited to 'CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c')
-rw-r--r--CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c524
1 files changed, 524 insertions, 0 deletions
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c
new file mode 100644
index 0000000000..b5ae4f6a89
--- /dev/null
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c
@@ -0,0 +1,524 @@
+/** @file -- Pkcs7EkuVerify.c
+ * Copyright (c) Microsoft Corporation.
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ This is an test code which verifies specified
+ Enhanced Key Usages (EKU)'s are present in the leaf signer
+ of a PKCS7 formatted signature.
+
+
+ A typical signing certificate chain looks like this: (Could be RSA or ECC).
+
+ ------------------------------------------
+ | | // Root of trust. ECDSA P521 curve
+ | TestEKUParsingRoot | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+ ------------------------------------------
+ ^
+ |
+ ------------------------------------------
+ | | // Policy CA. Issues subordinate CAs. ECC P384 curve.
+ | TestEKUParsingPolicyCA | // SHA 256 Key Usage:
+ | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+ ------------------------------------------
+ ^
+ |
+ ------------------------------------------
+ | | // Issues end-entity (leaf) signers. ECC P256 curve.
+ | TestEKUParsingIssuingCA | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ | | // Enhanced Key Usage:
+ ------------------------------------------ // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+ ^
+ |
+ --------------------------------------
+ / TestEKUParsingLeafSigner && / // Leaf signer, ECC P256 curve.
+ / TestEKUParsingLeafSignerPid12345 / // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ / / // Enhanced Key usages:
+ -------------------------------------- // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+ // 1.3.6.1.4.1.311.76.9.21.1.N, N == Product ID.
+
+
+
+
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+#include "Pkcs7EkuTestSignatures.h"
+
+EFI_STATUS
+EFIAPI
+VerifyEKUsInPkcs7Signature (
+ IN CONST UINT8 *Pkcs7Signature,
+ IN CONST UINT32 SignatureSize,
+ IN CONST CHAR8 *RequiredEKUs[],
+ IN CONST UINT32 RequiredEKUsSize,
+ IN BOOLEAN RequireAllPresent
+ );
+
+///================================================================================================
+///================================================================================================
+///
+/// TEST CASES
+///
+///================================================================================================
+///================================================================================================
+
+CONST CHAR8 FIRMWARE_SIGNER_EKU[] = "1.3.6.1.4.1.311.76.9.21.1";
+
+
+/**
+ TestVerifyEKUsInSignature()
+
+ Verify that "1.3.6.1.4.1.311.76.9.21.1" (Firmware signature) is in the
+ leaf signer certificate.
+
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(ProductionECCSignature,
+ ARRAY_SIZE(ProductionECCSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsInSignature()
+
+
+/**
+ TestVerifyEKUsWith3CertsInSignature()
+
+ This PKCS7 signature has 3 certificates in it. (Policy CA, Issuing CA
+ and leaf signer). It has one firmware signing EKU in it.
+ "1.3.6.1.4.1.311.76.9.21.1"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWith3CertsInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignEKUsWith3CertsInSignature,
+ ARRAY_SIZE(TestSignEKUsWith3CertsInSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWith3CertsInSignature()
+
+/**
+ TestVerifyEKUsWith2CertsInSignature()
+
+ This PKCS7 signature has 2 certificates in it. (Issuing CA and leaf signer).
+ It has one firmware signing EKU in it. "1.3.6.1.4.1.311.76.9.21.1"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWith2CertsInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignEKUsWith2CertsInSignature,
+ ARRAY_SIZE(TestSignEKUsWith2CertsInSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWith2CertsInSignature()
+
+
+/**
+ TestVerifyEKUsWith1CertInSignature()
+
+ This PKCS7 signature only has the leaf signer in it.
+ It has one firmware signing EKU in it. "1.3.6.1.4.1.311.76.9.21.1"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWith1CertInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignEKUsWith1CertInSignature,
+ ARRAY_SIZE(TestSignEKUsWith1CertInSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWith1CertInSignature()
+
+
+/**
+ TestVerifyEKUsWithMultipleEKUsInCert()
+
+
+ This signature has two EKU's in it:
+ "1.3.6.1.4.1.311.76.9.21.1"
+ "1.3.6.1.4.1.311.76.9.21.2"
+ We verify that both EKU's were present in the leaf signer.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWithMultipleEKUsInCert (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1",
+ "1.3.6.1.4.1.311.76.9.21.1.2" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithMultipleEKUsInCert,
+ ARRAY_SIZE(TestSignedWithMultipleEKUsInCert),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWithMultipleEKUsInCert()
+
+
+/**
+ TestEkusNotPresentInSignature()
+
+ This test verifies that if we send an EKU that is not in the signature,
+ that we get back an error.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestEkusNotPresentInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This EKU is not in the signature.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.3" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithMultipleEKUsInCert,
+ ARRAY_SIZE(TestSignedWithMultipleEKUsInCert),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestEkusNotPresentInSignature()
+
+/**
+ TestEkusNotPresentInSignature()
+
+ This test signature has two EKU's in it: (Product ID is 10001)
+ "1.3.6.1.4.1.311.76.9.21.1"
+ "1.3.6.1.4.1.311.76.9.21.1.10001"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestProductId10001PresentInSignature(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // These EKU's are present in the leaf signer certificate.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1",
+ "1.3.6.1.4.1.311.76.9.21.1.10001" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestProductId10001PresentInSignature()
+
+
+/**
+ TestOnlyOneEkuInListRequired()
+
+ This test will check the BOOLEAN RequireAllPresent parameter in the
+ call to VerifyEKUsInPkcs7Signature() behaves properly. The signature
+ has two EKU's in it:
+
+ "1.3.6.1.4.1.311.76.9.21.1"
+ "1.3.6.1.4.1.311.76.9.21.1.10001"
+
+ but we only pass in one of them, and set RequireAllPresent to FALSE.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestOnlyOneEkuInListRequired(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This will test the flag that specifies it is OK to succeed if
+ // any one of the EKU's passed in is found.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1.10001" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ FALSE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestOnlyOneEkuInListRequired()
+
+/**
+ TestNoEKUsInSignature()
+
+ This test uses a signature that was signed with a certificate that does
+ not contain any EKUs.
+
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestNoEKUsInSignature(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This EKU is not in the certificate, so it should fail.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignatureWithNoEKUsPresent,
+ ARRAY_SIZE(TestSignatureWithNoEKUsPresent),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestNoEKUsInSignature()
+
+
+/**
+ TestInvalidParameters()
+
+ Passes the API invalid parameters, and ensures that it does not succeed.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestInvalidParameters(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1" };
+
+ //
+ // Check bad signature.
+ //
+ Status = VerifyEKUsInPkcs7Signature(NULL,
+ 0,
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ //
+ // Check invalid EKU's
+ //
+ Status = VerifyEKUsInPkcs7Signature(TestSignatureWithNoEKUsPresent,
+ ARRAY_SIZE(TestSignatureWithNoEKUsPresent),
+ (CONST CHAR8**)NULL,
+ 0,
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ return UNIT_TEST_PASSED;
+}// TestInvalidParameters()
+
+
+/**
+ TestEKUSubStringFails()
+
+ Pass the API a sub set and super set of an EKU and ensure that they
+ don't pass.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestEKUSubsetSupersetFails(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This signature has an EKU of:
+ // "1.3.6.1.4.1.311.76.9.21.1.10001"
+ // so ensure that
+ // "1.3.6.1.4.1.311.76.9.21"
+ // does not pass.
+ //
+ CONST CHAR8* RequiredEKUs1[] = { "1.3.6.1.4.1.311.76.9.21" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs1,
+ ARRAY_SIZE(RequiredEKUs1),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ //
+ // This signature has an EKU of:
+ // "1.3.6.1.4.1.311.76.9.21.1.10001"
+ // so ensure that a super set
+ // "1.3.6.1.4.1.311.76.9.21.1.10001.1"
+ // does not pass.
+ //
+ CONST CHAR8* RequiredEKUs2[] = { "1.3.6.1.4.1.311.76.9.21.1.10001.1" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs2,
+ ARRAY_SIZE(RequiredEKUs2),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestEKUSubsetSupersetFails()
+
+TEST_DESC mPkcs7EkuTest[] = {
+ //
+ // -----Description--------------------------------Class----------------------------Function------------------------------Pre---Post--Context
+ //
+ {"TestVerifyEKUsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWith3CertsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWith3CertsInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWith2CertsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWith2CertsInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWith1CertInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWith1CertInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWithMultipleEKUsInCert()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWithMultipleEKUsInCert, NULL, NULL, NULL},
+ {"TestEkusNotPresentInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestEkusNotPresentInSignature, NULL, NULL, NULL},
+ {"TestProductId10001PresentInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestProductId10001PresentInSignature, NULL, NULL, NULL},
+ {"TestOnlyOneEkuInListRequired()", "CryptoPkg.BaseCryptLib.Eku", TestOnlyOneEkuInListRequired, NULL, NULL, NULL},
+ {"TestNoEKUsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestNoEKUsInSignature, NULL, NULL, NULL},
+ {"TestInvalidParameters()", "CryptoPkg.BaseCryptLib.Eku", TestInvalidParameters, NULL, NULL, NULL},
+ {"TestEKUSubsetSupersetFails()", "CryptoPkg.BaseCryptLib.Eku", TestEKUSubsetSupersetFails, NULL, NULL, NULL},
+};
+
+UINTN mPkcs7EkuTestNum = ARRAY_SIZE(mPkcs7EkuTest);