/** @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); |