Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply EKU check with compile option #664

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion Cryptlib/InternalCryptLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,38 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define OBJ_length(o) ((o)->length)
#endif

#endif
#if defined(ENABLE_CODESIGN_EKU)
/**
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
#endif
42 changes: 42 additions & 0 deletions Cryptlib/Library/BaseCryptLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -2403,6 +2403,48 @@ Pkcs7Verify (
IN UINTN DataLength
);

#if defined(ENABLE_CODESIGN_EKU)
/**
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
);
#endif

/**
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
7 changes: 7 additions & 0 deletions Cryptlib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ endif
ifeq ($(ARCH),arm)
DEFINES += -DMDE_CPU_ARM
endif
ifeq ($(ENABLE_CODESIGN_EKU),1)
DEFINES += -DENABLE_CODESIGN_EKU
endif

LDFLAGS = -nostdlib -znocombreloc

Expand Down Expand Up @@ -67,6 +70,10 @@ OBJS = Hash/CryptMd4Null.o \
SysCall/BaseMemAllocation.o \
SysCall/BaseStrings.o

ifeq ($(ENABLE_CODESIGN_EKU),1)
OBJS += Pk/CryptPkcs7VerifyEku.o
endif

all: $(TARGET)

libcryptlib.a: $(OBJS)
Expand Down
18 changes: 18 additions & 0 deletions Cryptlib/Pk/CryptPkcs7Verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ 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 };
#if defined(ENABLE_CODESIGN_EKU)
/* EKU CodeSign */
CHAR8 mOidCodeSign[] = "1.3.6.1.5.5.7.3.3";
#endif

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

//
// Check input parameters.
Expand All @@ -859,6 +867,9 @@ Pkcs7Verify (
DataBio = NULL;
Cert = NULL;
CertStore = NULL;
#if defined(ENABLE_CODESIGN_EKU)
Ekus[0] = mOidCodeSign;
#endif

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

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

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