From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Library/BaseCryptLib/Pk/CryptAuthenticode.c | 192 +++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 roms/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c (limited to 'roms/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c') diff --git a/roms/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c b/roms/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c new file mode 100644 index 000000000..2772b1e2b --- /dev/null +++ b/roms/edk2/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c @@ -0,0 +1,192 @@ +/** @file + Authenticode Portable Executable Signature Verification over OpenSSL. + + Caution: This module requires additional review when modified. + This library will have external input - signature (e.g. PE/COFF Authenticode). + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + + AuthenticodeVerify() will get PE/COFF Authenticode and will do basic check for + data structure. + +Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include + +// +// OID ASN.1 Value for SPC_INDIRECT_DATA_OBJID +// +UINT8 mSpcIndirectOidValue[] = { + 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04 + }; + +/** + Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows + Authenticode Portable Executable Signature Format". + + If AuthData is NULL, then return FALSE. + If ImageHash is NULL, then return FALSE. + + Caution: This function may receive untrusted input. + PE/COFF Authenticode is external input, so this function will do basic check for + Authenticode data structure. + + @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed + PE/COFF image to be verified. + @param[in] DataSize Size of the Authenticode Signature in bytes. + @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which + is used for certificate chain verification. + @param[in] CertSize Size of the trusted certificate in bytes. + @param[in] ImageHash Pointer to the original image file hash value. The procedure + for calculating the image hash value is described in Authenticode + specification. + @param[in] HashSize Size of Image hash value in bytes. + + @retval TRUE The specified Authenticode Signature is valid. + @retval FALSE Invalid Authenticode Signature. + +**/ +BOOLEAN +EFIAPI +AuthenticodeVerify ( + IN CONST UINT8 *AuthData, + IN UINTN DataSize, + IN CONST UINT8 *TrustedCert, + IN UINTN CertSize, + IN CONST UINT8 *ImageHash, + IN UINTN HashSize + ) +{ + BOOLEAN Status; + PKCS7 *Pkcs7; + CONST UINT8 *Temp; + CONST UINT8 *OrigAuthData; + UINT8 *SpcIndirectDataContent; + UINT8 Asn1Byte; + UINTN ContentSize; + CONST UINT8 *SpcIndirectDataOid; + + // + // Check input parameters. + // + if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) { + return FALSE; + } + + if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) { + return FALSE; + } + + Status = FALSE; + Pkcs7 = NULL; + OrigAuthData = AuthData; + + // + // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature + // + Temp = AuthData; + Pkcs7 = d2i_PKCS7 (NULL, &Temp, (int)DataSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // Check if it's PKCS#7 Signed Data (for Authenticode Scenario) + // + if (!PKCS7_type_is_signed (Pkcs7)) { + goto _Exit; + } + + // + // NOTE: OpenSSL PKCS7 Decoder didn't work for Authenticode-format signed data due to + // some authenticode-specific structure. Use opaque ASN.1 string to retrieve + // PKCS#7 ContentInfo here. + // + SpcIndirectDataOid = OBJ_get0_data(Pkcs7->d.sign->contents->type); + if (OBJ_length(Pkcs7->d.sign->contents->type) != sizeof(mSpcIndirectOidValue) || + CompareMem ( + SpcIndirectDataOid, + mSpcIndirectOidValue, + sizeof (mSpcIndirectOidValue) + ) != 0) { + // + // Un-matched SPC_INDIRECT_DATA_OBJID. + // + goto _Exit; + } + + + SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data); + + // + // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent. + // + Asn1Byte = *(SpcIndirectDataContent + 1); + + if ((Asn1Byte & 0x80) == 0) { + // + // Short Form of Length Encoding (Length < 128) + // + ContentSize = (UINTN) (Asn1Byte & 0x7F); + // + // Skip the SEQUENCE Tag; + // + SpcIndirectDataContent += 2; + + } else if ((Asn1Byte & 0x81) == 0x81) { + // + // Long Form of Length Encoding (128 <= Length < 255, Single Octet) + // + ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2)); + // + // Skip the SEQUENCE Tag; + // + SpcIndirectDataContent += 3; + + } else if ((Asn1Byte & 0x82) == 0x82) { + // + // Long Form of Length Encoding (Length > 255, Two Octet) + // + ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2)); + ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3)); + // + // Skip the SEQUENCE Tag; + // + SpcIndirectDataContent += 4; + + } else { + goto _Exit; + } + + // + // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent + // defined in Authenticode + // NOTE: Need to double-check HashLength here! + // + if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) { + // + // Un-matched PE/COFF Hash Value + // + goto _Exit; + } + + // + // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature + // + Status = (BOOLEAN) Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize); + +_Exit: + // + // Release Resources + // + PKCS7_free (Pkcs7); + + return Status; +} -- cgit