diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c new file mode 100644 index 00000000..4e09c993 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/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); |