Signed-off-by: Wenxing Hou <wenxing....@intel.com> --- .../BaseCryptLibMbedTls/InternalCryptLib.h | 32 ++ .../BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c | 5 +- .../Pk/CryptPkcs7VerifyBase.c | 40 +- .../Pk/CryptPkcs7VerifyCommon.c | 338 ++++++++++++- .../Pk/CryptPkcs7VerifyEku.c | 454 ++---------------- CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf | 1 + 6 files changed, 424 insertions(+), 446 deletions(-)
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h index 674242cfeb..6871785575 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h @@ -24,4 +24,36 @@ SPDX-License-Identifier: BSD-2-Clause-Patent int myrand( void *rng_state, unsigned char *output, size_t len ); +/** + 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 diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c index 0c7a1d009f..21d06264d5 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c @@ -388,7 +388,8 @@ Pkcs7Sign ( mbedtls_pk_init (&Pkey); Ret = mbedtls_pk_parse_key ( &Pkey, NewPrivateKey, PrivateKeySize, - KeyPassword, KeyPassword == NULL ? 0 : AsciiStrLen (KeyPassword) + KeyPassword, KeyPassword == NULL ? 0 : AsciiStrLen (KeyPassword), + NULL, NULL ); if (Ret != 0) { Status = FALSE; @@ -406,7 +407,7 @@ Pkcs7Sign ( ZeroMem (Signature, MAX_SIGNATURE_SIZE); Ret = mbedtls_pk_sign ( &Pkey, MBEDTLS_MD_SHA256, HashValue, SHA256_DIGEST_SIZE, - Signature, &SignatureLen, myrand, NULL); + Signature, MAX_SIGNATURE_SIZE, &SignatureLen, myrand, NULL); if (Ret != 0) { Status = FALSE; goto Cleanup; diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c index 01fcba5513..4daea4982f 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c @@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "InternalCryptLib.h" +#include <mbedtls/pkcs7.h> /** Extracts the attached content from a PKCS#7 signed data if existed. The input signed @@ -38,12 +39,13 @@ Pkcs7GetAttachedContent ( ) { BOOLEAN Status; - PKCS7 *Pkcs7; UINT8 *SignedData; UINTN SignedDataSize; BOOLEAN Wrapped; - CONST UINT8 *Temp; - ASN1_OCTET_STRING *OctStr; + INTN Ret; + mbedtls_pkcs7 Pkcs7; + + mbedtls_pkcs7_init(&Pkcs7); // // Check input parameter. @@ -53,9 +55,7 @@ Pkcs7GetAttachedContent ( } *Content = NULL; - Pkcs7 = NULL; SignedData = NULL; - OctStr = NULL; Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); if (!Status || (SignedDataSize > INT_MAX)) { @@ -64,26 +64,23 @@ Pkcs7GetAttachedContent ( Status = FALSE; - // - // Decoding PKCS#7 SignedData - // - Temp = SignedData; - Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (int)SignedDataSize); - if (Pkcs7 == NULL) { - goto _Exit; - } + Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize); // // The type of Pkcs7 must be signedData // - if (!PKCS7_type_is_signed (Pkcs7)) { + if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) { goto _Exit; } // // Check for detached or attached content // - if (PKCS7_get_detached (Pkcs7)) { + + mbedtls_pkcs7_data *MbedtlsContent; + MbedtlsContent = &(Pkcs7.signed_data.content); + + if (MbedtlsContent == NULL) { // // No Content supplied for PKCS7 detached signedData // @@ -93,15 +90,14 @@ Pkcs7GetAttachedContent ( // // Retrieve the attached content in PKCS7 signedData // - OctStr = Pkcs7->d.sign->contents->d.data; - if ((OctStr->length > 0) && (OctStr->data != NULL)) { - *ContentSize = OctStr->length; + if ((MbedtlsContent->data.len > 0) && (MbedtlsContent->data.p != NULL)) { + *ContentSize = MbedtlsContent->data.len; *Content = AllocatePool (*ContentSize); if (*Content == NULL) { *ContentSize = 0; goto _Exit; } - CopyMem (*Content, OctStr->data, *ContentSize); + CopyMem (*Content, MbedtlsContent->data.p, *ContentSize); } } Status = TRUE; @@ -110,11 +106,7 @@ _Exit: // // Release Resources // - PKCS7_free (Pkcs7); - - if (!Wrapped) { - OPENSSL_free (SignedData); - } + mbedtls_pkcs7_free (&Pkcs7); return Status; } diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c index 5291f2454d..14c9d447e6 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c @@ -656,7 +656,7 @@ Pkcs7Verify ( Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize); - if (Status) { + if (!Status) { Ret = 0; Status = FALSE; } else { @@ -741,5 +741,339 @@ Pkcs7GetSigners ( OUT UINTN *CertLength ) { -return FALSE; + BOOLEAN Status; + UINT8 *SignedData; + UINTN SignedDataSize; + BOOLEAN Wrapped; + INTN Ret; + mbedtls_pkcs7 Pkcs7; + mbedtls_x509_crt *Cert; + UINT8 Index; + UINT8 *CertBuf; + UINT8 *OldBuf; + UINTN BufferSize; + UINTN OldSize; + UINT8 *SingleCert; + UINTN SingleCertSize; + + + mbedtls_pkcs7_init(&Pkcs7); + + // + // Check input parameter. + // + if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) || + (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX)) + { + return FALSE; + } + + SignedData = NULL; + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); + if (!Status || (SignedDataSize > INT_MAX)) { + goto _Exit; + } + + Status = FALSE; + + // + // Retrieve PKCS#7 Data (DER encoding) + // + if (SignedDataSize > INT_MAX) { + goto _Exit; + } + + Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize); + + // + // The type of Pkcs7 must be signedData + // + if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) { + goto _Exit; + } + + + Cert = NULL; + CertBuf = NULL; + OldBuf = NULL; + SingleCert = NULL; + + + Cert = &Pkcs7.signed_data.certs; + if (Cert == NULL) { + goto _Exit; + } + + // + // Convert CertStack to buffer in following format: + // UINT8 CertNumber; + // UINT32 Cert1Length; + // UINT8 Cert1[]; + // UINT32 Cert2Length; + // UINT8 Cert2[]; + // ... + // UINT32 CertnLength; + // UINT8 Certn[]; + // + BufferSize = sizeof (UINT8); + OldSize = BufferSize; + + for (Index = 0; ; Index++) { + + SingleCertSize = Cert->raw.len; + + OldSize = BufferSize; + OldBuf = CertBuf; + BufferSize = OldSize + SingleCertSize + sizeof (UINT32); + CertBuf = AllocateZeroPool (BufferSize); + + if (CertBuf == NULL) { + goto _Exit; + } + + if (OldBuf != NULL) { + CopyMem (CertBuf, OldBuf, OldSize); + FreePool (OldBuf); + OldBuf = NULL; + } + + WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)SingleCertSize); + CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, SingleCertSize); + + FreePool (SingleCert); + SingleCert = NULL; + + if (Cert->next == NULL) { + break; + } + } + + if (CertBuf != NULL) { + // + // Update CertNumber. + // + CertBuf[0] = Index; + + *CertLength = BufferSize - OldSize - sizeof (UINT32); + *TrustedCert = AllocateZeroPool (*CertLength); + if (*TrustedCert == NULL) { + goto _Exit; + } + + CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength); + *CertStack = CertBuf; + *StackLength = BufferSize; + Status = TRUE; + } + +_Exit: + // + // Release Resources + // + if (!Wrapped) { + FreePool (SignedData); + } + + mbedtls_pkcs7_free (&Pkcs7); + + if (SingleCert != NULL) { + FreePool (SingleCert); + } + + if (!Status && (CertBuf != NULL)) { + FreePool (CertBuf); + *CertStack = NULL; + } + + if (OldBuf != NULL) { + FreePool (OldBuf); + } + + return Status; +} + +/** + Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard", and outputs two certificate lists chained and + unchained to the signer's certificates. + The input signed data could be wrapped in a ContentInfo structure. + + @param[in] P7Data Pointer to the PKCS#7 message. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] SignerChainCerts Pointer to the certificates list chained to signer's + certificate. It's caller's responsibility to free the buffer + with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] ChainLength Length of the chained certificates list buffer in bytes. + @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's + responsibility to free the buffer with Pkcs7FreeSigners(). + This data structure is EFI_CERT_STACK type. + @param[out] UnchainLength Length of the unchained certificates list buffer in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetCertificatesList ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **SignerChainCerts, + OUT UINTN *ChainLength, + OUT UINT8 **UnchainCerts, + OUT UINTN *UnchainLength + ) +{ + BOOLEAN Status; + UINT8 *SignedData; + UINTN SignedDataSize; + BOOLEAN Wrapped; + INTN Ret; + mbedtls_pkcs7 Pkcs7; + mbedtls_x509_crt *Cert; + UINT8 Index; + UINT8 *CertBuf; + UINT8 *OldBuf; + UINTN BufferSize; + UINTN OldSize; + UINT8 *SingleCert; + UINTN SingleCertSize; + + + mbedtls_pkcs7_init(&Pkcs7); + + // + // Check input parameter. + // + if ((P7Data == NULL) || (SignerChainCerts == NULL) || (ChainLength == NULL) || + (UnchainCerts == NULL) || (UnchainLength == NULL) || (P7Length > INT_MAX)) + { + return FALSE; + } + + SignedData = NULL; + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); + if (!Status || (SignedDataSize > INT_MAX)) { + goto _Exit; + } + + Status = FALSE; + + // + // Retrieve PKCS#7 Data (DER encoding) + // + if (SignedDataSize > INT_MAX) { + goto _Exit; + } + + Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize); + + // + // The type of Pkcs7 must be signedData + // + if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) { + goto _Exit; + } + + + Cert = NULL; + CertBuf = NULL; + OldBuf = NULL; + SingleCert = NULL; + + + Cert = &Pkcs7.signed_data.certs; + if (Cert == NULL) { + goto _Exit; + } + + // + // Converts Chained and Untrusted Certificate to Certificate Buffer in following format: + // UINT8 CertNumber; + // UINT32 Cert1Length; + // UINT8 Cert1[]; + // UINT32 Cert2Length; + // UINT8 Cert2[]; + // ... + // UINT32 CertnLength; + // UINT8 Certn[]; + // + BufferSize = sizeof (UINT8); + OldSize = BufferSize; + + for (Index = 0; ; Index++) { + + SingleCertSize = Cert->raw.len; + + OldSize = BufferSize; + OldBuf = CertBuf; + BufferSize = OldSize + SingleCertSize + sizeof (UINT32); + CertBuf = AllocateZeroPool (BufferSize); + + if (CertBuf == NULL) { + goto _Exit; + } + + if (OldBuf != NULL) { + CopyMem (CertBuf, OldBuf, OldSize); + FreePool (OldBuf); + OldBuf = NULL; + } + + WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)SingleCertSize); + CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, SingleCertSize); + + FreePool (SingleCert); + SingleCert = NULL; + + if (Cert->next == NULL) { + break; + } + } + + if (CertBuf != NULL) { + // + // Update CertNumber. + // + CertBuf[0] = Index; + + *UnchainLength = BufferSize - OldSize - sizeof (UINT32); + *UnchainCerts = AllocateZeroPool (*UnchainLength); + if (*UnchainCerts == NULL) { + goto _Exit; + } + + CopyMem (*UnchainCerts, CertBuf + OldSize + sizeof (UINT32), *UnchainLength); + *SignerChainCerts = CertBuf; + *ChainLength = BufferSize; + Status = TRUE; + } + +_Exit: + // + // Release Resources + // + if (!Wrapped) { + FreePool (SignedData); + } + + mbedtls_pkcs7_free (&Pkcs7); + + if (SingleCert != NULL) { + FreePool (SingleCert); + } + + if (!Status && (CertBuf != NULL)) { + FreePool (CertBuf); + *SignerChainCerts = NULL; + } + + if (OldBuf != NULL) { + FreePool (OldBuf); + } + + return Status; } diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c index 1bc4a5db13..484255830a 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c @@ -11,311 +11,8 @@ #include <Base.h> #include "InternalCryptLib.h" +#include <mbedtls/pkcs7.h> -/** - This function will return the leaf signer certificate in a chain. This is - required because certificate chains are not guaranteed to have the - certificates in the order that they were issued. - - A typical certificate chain looks like this: - - - ---------------------------- - | Root | - ---------------------------- - ^ - | - ---------------------------- - | Policy CA | <-- Typical Trust Anchor. - ---------------------------- - ^ - | - ---------------------------- - | Issuing CA | - ---------------------------- - ^ - | - ----------------------------- - / End-Entity (leaf) signer / <-- Bottom certificate. - ----------------------------- EKU: "1.3.6.1.4.1.311.76.9.21.1" - (Firmware Signing) - - - @param[in] CertChain Certificate chain. - - @param[out] SignerCert Last certificate in the chain. For PKCS7 signatures, - this will be the end-entity (leaf) signer cert. - - @retval EFI_SUCCESS The required EKUs were found in the signature. - @retval EFI_INVALID_PARAMETER A parameter was invalid. - @retval EFI_NOT_FOUND The number of signers found was not 1. - -**/ -EFI_STATUS -GetSignerCertificate ( - IN CONST PKCS7 *CertChain, - OUT X509 **SignerCert - ) -{ - EFI_STATUS Status; - STACK_OF(X509) *Signers; - INT32 NumberSigners; - - Status = EFI_SUCCESS; - Signers = NULL; - NumberSigners = 0; - - if (CertChain == NULL || SignerCert == NULL) { - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - // - // Get the signers from the chain. - // - Signers = PKCS7_get0_signers ((PKCS7*) CertChain, NULL, PKCS7_BINARY); - if (Signers == NULL) { - // - // Fail to get signers form PKCS7 - // - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - // - // There should only be one signer in the PKCS7 stack. - // - NumberSigners = sk_X509_num (Signers); - if (NumberSigners != 1) { - // - // The number of singers should have been 1 - // - Status = EFI_NOT_FOUND; - goto Exit; - } - - *SignerCert = sk_X509_value (Signers, 0); - -Exit: - // - // Release Resources - // - if (Signers != NULL) { - sk_X509_free (Signers); - } - - return Status; -} - - -/** - Determines if the specified EKU represented in ASN1 form is present - in a given certificate. - - @param[in] Cert The certificate to check. - - @param[in] Asn1ToFind The EKU to look for. - - @retval EFI_SUCCESS We successfully identified the signing type. - @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 -IsEkuInCertificate ( - IN CONST X509 *Cert, - IN ASN1_OBJECT *Asn1ToFind - ) -{ - EFI_STATUS Status; - X509 *ClonedCert; - X509_EXTENSION *Extension; - EXTENDED_KEY_USAGE *Eku; - INT32 ExtensionIndex; - INTN NumExtensions; - ASN1_OBJECT *Asn1InCert; - INTN Index; - - Status = EFI_NOT_FOUND; - ClonedCert = NULL; - Extension = NULL; - Eku = NULL; - ExtensionIndex = -1; - NumExtensions = 0; - Asn1InCert = NULL; - - if (Cert == NULL || Asn1ToFind == NULL) { - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - // - // Clone the certificate. This is required because the Extension API's - // only work once per instance of an X509 object. - // - ClonedCert = X509_dup ((X509*)Cert); - if (ClonedCert == NULL) { - // - // Fail to duplicate cert. - // - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - // - // Look for the extended key usage. - // - ExtensionIndex = X509_get_ext_by_NID (ClonedCert, NID_ext_key_usage, -1); - - if (ExtensionIndex < 0) { - // - // Fail to find 'NID_ext_key_usage' in Cert. - // - goto Exit; - } - - Extension = X509_get_ext (ClonedCert, ExtensionIndex); - if (Extension == NULL) { - // - // Fail to get Extension form cert. - // - goto Exit; - } - - Eku = (EXTENDED_KEY_USAGE*)X509V3_EXT_d2i (Extension); - if (Eku == NULL) { - // - // Fail to get Eku from extension. - // - goto Exit; - } - - NumExtensions = sk_ASN1_OBJECT_num (Eku); - - // - // Now loop through the extensions, looking for the specified Eku. - // - for (Index = 0; Index < NumExtensions; Index++) { - Asn1InCert = sk_ASN1_OBJECT_value (Eku, (INT32)Index); - if (Asn1InCert == NULL) { - // - // Fail to get ASN object from Eku. - // - goto Exit; - } - - if (Asn1InCert->length == Asn1ToFind->length && - CompareMem (Asn1InCert->data, Asn1ToFind->data, Asn1InCert->length) == 0) { - // - // Found Eku in certificate. - // - Status = EFI_SUCCESS; - goto Exit; - } - } - -Exit: - - // - // Release Resources - // - if (ClonedCert != NULL) { - X509_free (ClonedCert); - } - - if (Eku != NULL) { - sk_ASN1_OBJECT_pop_free (Eku, ASN1_OBJECT_free); - } - - return Status; -} - - -/** - Determines if the specified EKUs are present in a signing certificate. - - @param[in] SignerCert The certificate to check. - @param[in] RequiredEKUs The EKUs to look for. - @param[in] RequiredEKUsSize The number of EKUs - @param[in] RequireAllPresent If TRUE, then all the specified EKUs - must be present in the certificate. - - @retval EFI_SUCCESS We successfully identified the signing type. - @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 -CheckEKUs( - IN CONST X509 *SignerCert, - IN CONST CHAR8 *RequiredEKUs[], - IN CONST UINT32 RequiredEKUsSize, - IN BOOLEAN RequireAllPresent - ) -{ - EFI_STATUS Status; - ASN1_OBJECT *Asn1ToFind; - UINT32 NumEkusFound; - UINT32 Index; - - Status = EFI_SUCCESS; - Asn1ToFind = NULL; - NumEkusFound = 0; - - if (SignerCert == NULL || RequiredEKUs == NULL || RequiredEKUsSize == 0) { - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - for (Index = 0; Index < RequiredEKUsSize; Index++) { - // - // Finding required EKU in cert. - // - if (Asn1ToFind != NULL) { - ASN1_OBJECT_free(Asn1ToFind); - Asn1ToFind = NULL; - } - - Asn1ToFind = OBJ_txt2obj (RequiredEKUs[Index], 0); - if (Asn1ToFind == NULL) { - // - // Fail to convert required EKU to ASN1. - // - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - - Status = IsEkuInCertificate (SignerCert, Asn1ToFind); - if (Status == EFI_SUCCESS) { - NumEkusFound++; - if (!RequireAllPresent) { - // - // Found at least one, so we are done. - // - goto Exit; - } - } else { - // - // Fail to find Eku in cert - break; - } - } - -Exit: - - if (Asn1ToFind != NULL) { - ASN1_OBJECT_free(Asn1ToFind); - } - - if (RequireAllPresent && - NumEkusFound == RequiredEKUsSize) { - // - // Found all required EKUs in certificate. - // - Status = EFI_SUCCESS; - } - - return Status; -} /** This function receives a PKCS#7 formatted signature blob, @@ -357,135 +54,62 @@ VerifyEKUsInPkcs7Signature ( IN BOOLEAN RequireAllPresent ) { - EFI_STATUS Status; - PKCS7 *Pkcs7; - STACK_OF(X509) *CertChain; - INT32 SignatureType; - INT32 NumberCertsInSignature; - X509 *SignerCert; - UINT8 *SignedData; - UINT8 *Temp; - UINTN SignedDataSize; - BOOLEAN IsWrapped; - BOOLEAN Ok; + BOOLEAN Status; + UINT8 *SignedData; + UINTN SignedDataSize; + BOOLEAN Wrapped; + INTN Ret; + mbedtls_pkcs7 Pkcs7; + mbedtls_x509_crt *Cert; + UINT8 *SingleCert; - Status = EFI_SUCCESS; - Pkcs7 = NULL; - CertChain = NULL; - SignatureType = 0; - NumberCertsInSignature = 0; - SignerCert = NULL; - SignedData = NULL; - SignedDataSize = 0; - IsWrapped = FALSE; - Ok = FALSE; + mbedtls_pkcs7_init(&Pkcs7); // - //Validate the input parameters. + // Check input parameter. // - if (Pkcs7Signature == NULL || - SignatureSize == 0 || - RequiredEKUs == NULL || - RequiredEKUsSize == 0) { - Status = EFI_INVALID_PARAMETER; - goto Exit; + if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL)) + { + return FALSE; } - if (RequiredEKUsSize == 1) { - RequireAllPresent = TRUE; - } + SignedData = NULL; - // - // Wrap the PKCS7 data if needed. - // - Ok = WrapPkcs7Data (Pkcs7Signature, - SignatureSize, - &IsWrapped, - &SignedData, - &SignedDataSize); - if (!Ok) { - // - // Fail to Wrap the PKCS7 data. - // - Status = EFI_INVALID_PARAMETER; - goto Exit; + Status = WrapPkcs7Data (Pkcs7Signature, SignatureSize, &Wrapped, &SignedData, &SignedDataSize); + if (!Status || (SignedDataSize > INT_MAX)) { + goto _Exit; } - Temp = SignedData; + Status = FALSE; // - // Create the PKCS7 object. + // Retrieve PKCS#7 Data (DER encoding) // - Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (INT32)SignedDataSize); - if (Pkcs7 == NULL) { - // - // Fail to read PKCS7 data. - // - Status = EFI_INVALID_PARAMETER; - goto Exit; + if (SignedDataSize > INT_MAX) { + goto _Exit; } - // - // Get the certificate chain. - // - SignatureType = OBJ_obj2nid (Pkcs7->type); - switch (SignatureType) { - case NID_pkcs7_signed: - if (Pkcs7->d.sign != NULL) { - CertChain = Pkcs7->d.sign->cert; - } - break; - case NID_pkcs7_signedAndEnveloped: - if (Pkcs7->d.signed_and_enveloped != NULL) { - CertChain = Pkcs7->d.signed_and_enveloped->cert; - } - break; - default: - break; - } + Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize); // - // Ensure we have a certificate stack + // The type of Pkcs7 must be signedData // - if (CertChain == NULL) { - // - // Fail to get the certificate stack from signature. - // - Status = EFI_INVALID_PARAMETER; - goto Exit; + if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) { + goto _Exit; } - // - // Find out how many certificates were in the PKCS7 signature. - // - NumberCertsInSignature = sk_X509_num (CertChain); - if (NumberCertsInSignature == 0) { - // - // Fail to find any certificates in signature. - // - Status = EFI_INVALID_PARAMETER; - goto Exit; - } + Cert = NULL; + SingleCert = NULL; - // - // Get the leaf signer. - // - Status = GetSignerCertificate (Pkcs7, &SignerCert); - if (Status != EFI_SUCCESS || SignerCert == NULL) { - // - // Fail to get the end-entity leaf signer certificate. - // - Status = EFI_INVALID_PARAMETER; - goto Exit; - } - Status = CheckEKUs (SignerCert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent); - if (Status != EFI_SUCCESS) { - goto Exit; + Cert = &Pkcs7.signed_data.certs; + if (Cert == NULL) { + goto _Exit; } -Exit: + +_Exit: // // Release Resources @@ -493,17 +117,11 @@ Exit: // If the signature was not wrapped, then the call to WrapData() will allocate // the data and add a header to it // - if (!IsWrapped && SignedData) { - free (SignedData); + if (!Wrapped && SignedData) { + FreePool (SignedData); } - if (SignerCert != NULL) { - X509_free (SignerCert); - } - - if (Pkcs7 != NULL) { - PKCS7_free (Pkcs7); - } + mbedtls_pkcs7_free (&Pkcs7); return Status; } diff --git a/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf b/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf index b735fef49e..69d712b9c6 100644 --- a/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf +++ b/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf @@ -108,6 +108,7 @@ mbedtls/library/x509_crl.c mbedtls/library/x509_crt.c mbedtls/library/x509_csr.c + mbedtls/library/pkcs7.c [Packages] MdePkg/MdePkg.dec -- 2.26.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#101321): https://edk2.groups.io/g/devel/message/101321 Mute This Topic: https://groups.io/mt/97669083/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-