Skip to content

Commit

Permalink
Implement the CodeSign EKU check to fulfill the requirements of NIAP …
Browse files Browse the repository at this point in the history
…OS_PP.

Also modify the ModSign EKU check to use VerifyEKUsInPkcs7Signature() to
check the signer certificate instead of the certificate directly from the
key database.

This commit supersedes the PR#232 and PR#661 (Apply the EKU checks) so
that author's original codes can be quite independent of other modification.

To answer the question in PR#232, author also changed the conditional
statement to EFI_Status != EFI_SUCCESS right after VerifyEKUsInPkcs7Signature()
in Cryptlib/Pk/CryptPkcs7Verify.c

Signed-off-by: Dennis Tseng <[email protected]>
  • Loading branch information
lcp authored and dennis-tseng99 committed Jun 5, 2024
1 parent 0287c6b commit 6a9494c
Show file tree
Hide file tree
Showing 5 changed files with 599 additions and 0 deletions.
32 changes: 32 additions & 0 deletions Cryptlib/InternalCryptLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,37 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define OBJ_length(o) ((o)->length)
#endif

/**
Check input P7Data is a wrapped ContentInfo structure or not. If not construct
a new structure to wrap P7Data.
Caution: This function may receive untrusted input.
UEFI Authenticated Variable is external input, so this function will do basic
check for PKCS#7 data structure.
@param[in] P7Data Pointer to the PKCS#7 message to verify.
@param[in] P7Length Length of the PKCS#7 message in bytes.
@param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise
return FALSE.
@param[out] WrapData If return status of this function is TRUE:
1) when WrapFlag is TRUE, pointer to P7Data.
2) when WrapFlag is FALSE, pointer to a new ContentInfo
structure. It's caller's responsibility to free this
buffer.
@param[out] WrapDataSize Length of ContentInfo structure in bytes.
@retval TRUE The operation is finished successfully.
@retval FALSE The operation is failed due to lack of resources.
**/
BOOLEAN
WrapPkcs7Data (
IN CONST UINT8 *P7Data,
IN UINTN P7Length,
OUT BOOLEAN *WrapFlag,
OUT UINT8 **WrapData,
OUT UINTN *WrapDataSize
);

#endif

40 changes: 40 additions & 0 deletions Cryptlib/Library/BaseCryptLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -2403,6 +2403,46 @@ Pkcs7Verify (
IN UINTN DataLength
);

/**
This function receives a PKCS#7 formatted signature blob,
looks for the EKU SEQUENCE blob, and if found then looks
for all the required EKUs. This function was created so that
the Surface team can cut down on the number of Certificate
Authorities (CA's) by checking EKU's on leaf signers for
a specific product. This prevents one product's certificate
from signing another product's firmware or unlock blobs.
Note that this function does not validate the certificate chain.
That needs to be done before using this function.
@param[in] Pkcs7Signature The PKCS#7 signed information content block. An array
containing the content block with both the signature,
the signer's certificate, and any necessary intermediate
certificates.
@param[in] Pkcs7SignatureSize Number of bytes in Pkcs7Signature.
@param[in] RequiredEKUs Array of null-terminated strings listing OIDs of
required EKUs that must be present in the signature.
@param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array.
@param[in] RequireAllPresent If this is TRUE, then all of the specified EKU's
must be present in the leaf signer. If it is
FALSE, then we will succeed if we find any
of the specified EKU's.
@retval EFI_SUCCESS The required EKUs were found in the signature.
@retval EFI_INVALID_PARAMETER A parameter was invalid.
@retval EFI_NOT_FOUND One or more EKU's were not found in the signature.
**/
EFI_STATUS
EFIAPI
VerifyEKUsInPkcs7Signature (
IN CONST UINT8 *Pkcs7Signature,
IN CONST UINT32 SignatureSize,
IN CONST CHAR8 *RequiredEKUs[],
IN CONST UINT32 RequiredEKUsSize,
IN BOOLEAN RequireAllPresent
);

/**
Extracts the attached content from a PKCS#7 signed data if existed. The input signed
data could be wrapped in a ContentInfo structure.
Expand Down
1 change: 1 addition & 0 deletions Cryptlib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ OBJS = Hash/CryptMd4Null.o \
Pk/CryptRsaExtNull.o \
Pk/CryptPkcs7SignNull.o \
Pk/CryptPkcs7Verify.o \
Pk/CryptPkcs7VerifyEku.o \
Pk/CryptDhNull.o \
Pk/CryptTs.o \
Pk/CryptX509.o \
Expand Down
10 changes: 10 additions & 0 deletions Cryptlib/Pk/CryptPkcs7Verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <openssl/pkcs7.h>

UINT8 mOidValue[9] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 };
/* EKU CodeSign */
CHAR8 mOidCodeSign[] = "1.3.6.1.5.5.7.3.3";

#if 1
#if OPENSSL_VERSION_NUMBER < 0x10100000L
Expand Down Expand Up @@ -846,6 +848,8 @@ Pkcs7Verify (
CONST UINT8 *Temp;
UINTN SignedDataSize;
BOOLEAN Wrapped;
CONST CHAR8 *Ekus[1];
EFI_STATUS EFI_Status;

//
// Check input parameters.
Expand All @@ -859,6 +863,7 @@ Pkcs7Verify (
DataBio = NULL;
Cert = NULL;
CertStore = NULL;
Ekus[0] = mOidCodeSign;

//
// Register & Initialize necessary digest algorithms for PKCS#7 Handling
Expand Down Expand Up @@ -958,6 +963,11 @@ Pkcs7Verify (
//
X509_STORE_set_purpose (CertStore, X509_PURPOSE_ANY);

EFI_Status = VerifyEKUsInPkcs7Signature(P7Data, P7Length, Ekus, 1, TRUE);
if (EFI_Status != EFI_SUCCESS) {
goto _Exit;
}

//
// Verifies the PKCS#7 signedData structure
//
Expand Down
Loading

0 comments on commit 6a9494c

Please sign in to comment.