From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id 7449A74003E for ; Fri, 17 May 2024 10:26:57 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=W2gdKBM/1O+MPWjG7E44AVyxSFXO5ikwdbBvOWZPC3Y=; c=relaxed/simple; d=groups.io; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding; s=20240206; t=1715941616; v=1; b=BAvs6jm5ceQ97R2wZTBmdIxc44nfOX4zTzE9uudW2PC/iiFja/Pcvejc7ZBDi6k81Jr7MucE Ne72JNunIhU6pGENzXI2AzVj/j6sNTK/P6NWGpLUSx3aQDCbn0ZytP7xREj3d9yvQBDlZHFXSz/ Ic4oeTE3xnHhcNTyzVYzZndLpymzsXTGXt38vGMYDrDWfGUeQ5842yZ4HLsTMaUPH+3w+Fgu8Cy vgEI56RbdZ3Pt7n2NJTpzEZcTCu2t5JqbEQdOn9UBw2dDRnXnlpw0kCARXvcjN1ik16gZzm6crD zFm5CpCpqLJ8gtVrXtYMMjeSL+L2qITa4PfhYmjceRk2g== X-Received: by 127.0.0.2 with SMTP id j3mcYY7687511xyPX1WyV9Cf; Fri, 17 May 2024 03:26:56 -0700 X-Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.7]) by mx.groups.io with SMTP id smtpd.web10.36833.1715941605520178194 for ; Fri, 17 May 2024 03:26:55 -0700 X-CSE-ConnectionGUID: l0giSiXKTMC+v+sjGaB9SA== X-CSE-MsgGUID: HeLCQzz7TwO/IzWLLFMeoQ== X-IronPort-AV: E=McAfee;i="6600,9927,11074"; a="37488626" X-IronPort-AV: E=Sophos;i="6.08,167,1712646000"; d="scan'208";a="37488626" X-Received: from orviesa006.jf.intel.com ([10.64.159.146]) by fmvoesa101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 May 2024 03:26:55 -0700 X-CSE-ConnectionGUID: Sdk7Az4BSDi7LBycMY5okA== X-CSE-MsgGUID: ys/3npb5TdKAsktpFTdDiw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.08,167,1712646000"; d="scan'208";a="32171523" X-Received: from shwdejointd777.ccr.corp.intel.com ([10.239.58.116]) by orviesa006.jf.intel.com with ESMTP; 17 May 2024 03:26:53 -0700 From: "Wenxing Hou" To: devel@edk2.groups.io Cc: Jiewen Yao , Yi Li , Jiewen Yao Subject: [edk2-devel] [PATCH v4 05/11] CryptoPkg: Add Pkcs7 related functions based on Mbedtls Date: Fri, 17 May 2024 18:26:35 +0800 Message-Id: <20240517102641.4586-6-wenxing.hou@intel.com> In-Reply-To: <20240517102641.4586-1-wenxing.hou@intel.com> References: <20240517102641.4586-1-wenxing.hou@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Fri, 17 May 2024 03:26:55 -0700 Resent-From: wenxing.hou@intel.com Reply-To: devel@edk2.groups.io,wenxing.hou@intel.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: Oc5ezAMIX8XP4siYjZNxGOkHx7686176AA= Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=BAvs6jm5; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=intel.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D4177 Because the current Mbedlts pkcs7 library doesn't support authenticatedAttributes and only support 0 or 1 certificates in Signed data, the patch implement Pkcs7 by low Mbedtls Api. And the implementation has pass unit_tes and integration test. Cc: Jiewen Yao Cc: Yi Li Signed-off-by: Wenxing Hou Reviewed-by: Yi Li Acked-by: Jiewen Yao --- CryptoPkg/Include/Library/BaseCryptLib.h | 2 + .../BaseCryptLibMbedTls/InternalCryptLib.h | 33 + .../Pk/CryptPkcs7Internal.h | 29 +- .../BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c | 635 ++++++++ .../Pk/CryptPkcs7VerifyBase.c | 113 ++ .../Pk/CryptPkcs7VerifyCommon.c | 1354 +++++++++++++++++ .../Pk/CryptPkcs7VerifyEku.c | 689 +++++++++ 7 files changed, 2843 insertions(+), 12 deletions(-) create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign= .c create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Veri= fyBase.c create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Veri= fyCommon.c create mode 100644 CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Veri= fyEku.c diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/L= ibrary/BaseCryptLib.h index 111df8e78b..ac5841f1d9 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -2351,6 +2351,8 @@ Pkcs7FreeSigners ( unchained to the signer's certificates.=0D The input signed data could be wrapped in a ContentInfo structure.=0D =0D + Pkcs7GetCertificatesList has not been implemented in BaseCryptoLibMbedTl= s.=0D +=0D @param[in] P7Data Pointer to the PKCS#7 message.=0D @param[in] P7Length Length of the PKCS#7 message in bytes.=0D @param[out] SignerChainCerts Pointer to the certificates list chained t= o signer's=0D diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/Cry= ptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h index a30666cef4..c9f19dd0cd 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h @@ -38,4 +38,37 @@ MbedtlsRand ( UINT8 *Output,=0D UINTN Len=0D );=0D +=0D +/**=0D + Check input P7Data is a wrapped ContentInfo structure or not. If not con= struct=0D + a new structure to wrap P7Data.=0D +=0D + Caution: This function may receive untrusted input.=0D + UEFI Authenticated Variable is external input, so this function will do = basic=0D + check for PKCS#7 data structure.=0D +=0D + @param[in] P7Data Pointer to the PKCS#7 message to verify.=0D + @param[in] P7Length Length of the PKCS#7 message in bytes.=0D + @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, othe= rwise=0D + return FALSE.=0D + @param[out] WrapData If return status of this function is TRUE:=0D + 1) when WrapFlag is TRUE, pointer to P7Data.=0D + 2) when WrapFlag is FALSE, pointer to a new Con= tentInfo=0D + structure. It's caller's responsibility to free= this=0D + buffer.=0D + @param[out] WrapDataSize Length of ContentInfo structure in bytes.=0D +=0D + @retval TRUE The operation is finished successfully.=0D + @retval FALSE The operation is failed due to lack of resource= s.=0D +=0D +**/=0D +BOOLEAN=0D +WrapPkcs7Data (=0D + IN CONST UINT8 *P7Data,=0D + IN UINTN P7Length,=0D + OUT BOOLEAN *WrapFlag,=0D + OUT UINT8 **WrapData,=0D + OUT UINTN *WrapDataSize=0D + );=0D +=0D #endif=0D diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h = b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h index 207f493cbb..cbdd1dc530 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h @@ -4,7 +4,7 @@ =0D RFC 2315 - PKCS #7: Cryptographic Message Syntax Version 1.5=0D =0D -Copyright (c) 2023, Intel Corporation. All rights reserved.
=0D +Copyright (c) 2023-2024, Intel Corporation. All rights reserved.
=0D SPDX-License-Identifier: BSD-2-Clause-Patent=0D =0D **/=0D @@ -31,10 +31,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x= 05"=0D #define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x= 06"=0D =0D -typedef mbedtls_asn1_buf MBEDTLSPKCS7BUF;=0D -typedef mbedtls_asn1_named_data MBEDTLSPKCS7NAME;=0D -typedef mbedtls_asn1_sequence MBEDTLSPKCS7SEQUENCE;=0D -=0D ///=0D /// PKCS7 SignerInfo type=0D /// https://tools.ietf.org/html/rfc2315#section-9.2=0D @@ -48,8 +44,8 @@ typedef struct MbedtlsPkcs7SignerInfo { mbedtls_x509_buf SigAlgIdentifier;=0D mbedtls_x509_buf AuthAttr;=0D mbedtls_x509_buf Sig;=0D - struct MBEDTLSPKCS7SIGNERINFO *Next;=0D -} MBEDTLSPKCS7SIGNERINFO;=0D + struct MbedtlsPkcs7SignerInfo *Next;=0D +} MbedtlsPkcs7SignerInfo;=0D =0D ///=0D /// PKCS7 signed data attached data format=0D @@ -57,7 +53,7 @@ typedef struct MbedtlsPkcs7SignerInfo { typedef struct MbedtlsPkcs7Data {=0D mbedtls_asn1_buf Oid;=0D mbedtls_asn1_buf Data;=0D -} MBEDTLSPKCS7DATA;=0D +} MbedtlsPkcs7Data;=0D =0D ///=0D /// Signed Data=0D @@ -66,18 +62,27 @@ typedef struct MbedtlsPkcs7Data { typedef struct MbedtlsPkcs7SignedData {=0D INT32 Version;=0D mbedtls_asn1_buf DigestAlgorithms;=0D - struct MBEDTLSPKCS7DATA ContentInfo;=0D + struct MbedtlsPkcs7Data ContentInfo;=0D mbedtls_x509_crt Certificates;=0D mbedtls_x509_crl Crls;=0D struct MbedtlsPkcs7SignerInfo SignerInfos;=0D -} MBEDTLSPKCS7SIGNEDDATA;=0D +} MbedtlsPkcs7SignedData;=0D =0D ///=0D /// PKCS7 struct, only support SignedData=0D ///=0D typedef struct MbedtlsPkcs7 {=0D mbedtls_asn1_buf ContentTypeOid;=0D - struct MBEDTLSPKCS7SIGNEDDATA SignedData;=0D -} MBEDTLSPKCS7;=0D + struct MbedtlsPkcs7SignedData SignedData;=0D +} MbedtlsPkcs7;=0D +=0D +#define EDKII_ASN1_CHK_ADD(g, f) \=0D + do \=0D + { \=0D + if( ( Ret =3D (f) ) < 0 ) \=0D + return( Ret ); \=0D + else \=0D + (g) +=3D Ret; \=0D + } while( 0 )=0D =0D #endif=0D diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c b/Cr= yptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c new file mode 100644 index 0000000000..e3283dad48 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c @@ -0,0 +1,635 @@ +/** @file=0D + PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrappe= r=0D + Implementation over mbedtls.=0D +=0D + RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites=0D + FIPS 186-4 - Digital Signature Standard (DSS)=0D +=0D +Copyright (c) 2024, Intel Corporation. All rights reserved.
=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "CryptPkcs7Internal.h"=0D +#include =0D +=0D +///=0D +/// Enough to store any signature generated by PKCS7=0D +///=0D +#define MAX_SIGNATURE_SIZE 1024=0D +=0D +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidDigestAlgSha256[] =3D MBEDT= LS_OID_DIGEST_ALG_SHA256;=0D +GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidPkcs1Rsa[] =3D MBEDT= LS_OID_PKCS1_RSA;=0D +=0D +/**=0D + Write DigestAlgorithmIdentifier.=0D +=0D + @param[in, out] Ptr The reference to the current position poi= nter.=0D + @param[in] Start The start of the buffer, for bounds-checkin= g.=0D + @param[in] DigestType Digest Type=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteDigestAlgorithm (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + mbedtls_md_type_t DigestType=0D + )=0D +{=0D + UINT8 *OidPtr;=0D + UINTN OidLen;=0D + INT32 Ret;=0D +=0D + Ret =3D mbedtls_oid_get_oid_by_md (DigestType, (CONST CHAR8 **)&OidPtr, = &OidLen);=0D + if (Ret =3D=3D 0) {=0D + return mbedtls_asn1_write_oid (Ptr, (CONST UINT8 *)Start, (CONST CHAR8= *)OidPtr, OidLen);=0D + }=0D +=0D + return 0;=0D +}=0D +=0D +/**=0D + DigestAlgorithmIdentifiers ::=3D=0D + SET OF DigestAlgorithmIdentifier.=0D +=0D + @param[in, out] Ptr The reference to the current position poi= nter.=0D + @param[in] Start The start of the buffer, for bounds-checkin= g.=0D + @param[in] DigestTypes Digest Type array.=0D + @param[in] Count The index for Digest Type.=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteDigestAlgorithmSet (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + mbedtls_md_type_t *DigestTypes,=0D + INTN Count=0D + )=0D +{=0D + INTN Idx;=0D + INT32 Len;=0D + INT32 Ret;=0D +=0D + Len =3D 0;=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_null (Ptr, Start));=0D +=0D + for (Idx =3D 0; Idx < Count; Idx++) {=0D + EDKII_ASN1_CHK_ADD (=0D + Len,=0D + MbedTlsPkcs7WriteDigestAlgorithm (Ptr, Start, DigestTypes[Idx])=0D + );=0D + }=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len)= );=0D +=0D + EDKII_ASN1_CHK_ADD (=0D + Len,=0D + mbedtls_asn1_write_tag (=0D + Ptr,=0D + Start,=0D + (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)=0D + )=0D + );=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len)= );=0D +=0D + EDKII_ASN1_CHK_ADD (=0D + Len,=0D + mbedtls_asn1_write_tag (=0D + Ptr,=0D + Start,=0D + (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)=0D + )=0D + );=0D +=0D + return Len;=0D +}=0D +=0D +/**=0D + ContentInfo ::=3D SEQUENCE {=0D + contentType ContentType,=0D + content=0D + [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.=0D +=0D + @param[in, out] Ptr The reference to the current position poi= nter.=0D + @param[in] Start The start of the buffer, for bounds-checkin= g.=0D + @param[in] Content ContentInfo.=0D + @param[in] ContentLen Size of ContentInfo.=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteContentInfo (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + UINT8 *Content,=0D + INTN ContentLen=0D + )=0D +{=0D + INT32 Ret;=0D + INT32 Len;=0D +=0D + Len =3D 0;=0D + if (Content !=3D NULL) {=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, = Content, ContentLen));=0D + }=0D +=0D + EDKII_ASN1_CHK_ADD (=0D + Len,=0D + mbedtls_asn1_write_oid (=0D + Ptr,=0D + Start,=0D + MBEDTLS_OID_PKCS7_DATA,=0D + sizeof (MBEDTLS_OID_PKCS7_DATA) - 1=0D + )=0D + );=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN= 1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));=0D +=0D + return Len;=0D +}=0D +=0D +/**=0D + certificates :: SET OF ExtendedCertificateOrCertificate,=0D + ExtendedCertificateOrCertificate ::=3D CHOICE {=0D + certificate Certificate -- x509,=0D + extendedCertificate[0] IMPLICIT ExtendedCertificate }.=0D +=0D + @param[in, out] Ptr The reference to the current position poi= nter.=0D + @param[in] Start The start of the buffer, for bounds-checkin= g.=0D + @param[in] Cert Certificate.=0D + @param[in] OtherCerts Ohter Certificate.=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteCertificates (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + mbedtls_x509_crt *Cert,=0D + mbedtls_x509_crt *OtherCerts=0D + )=0D +{=0D + INT32 Ret;=0D + INT32 Len;=0D + mbedtls_x509_crt *TmpCert;=0D +=0D + Len =3D 0;=0D +=0D + /// Write OtherCerts=0D + TmpCert =3D OtherCerts;=0D + while (TmpCert !=3D NULL) {=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, Tm= pCert->raw.p, TmpCert->raw.len));=0D + TmpCert =3D TmpCert->next;=0D + }=0D +=0D + /// Write Cert=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, Cert= ->raw.p, Cert->raw.len));=0D +=0D + /// Write NextContext=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN= 1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));=0D + return Len;=0D +}=0D +=0D +/**=0D + write Pkcs7 Int.=0D +=0D + @param[in, out] Ptr The reference to the current position po= inter.=0D + @param[in] Start The start of the buffer, for bounds-checki= ng.=0D + @param[in] SerialRaw SerialRaw.=0D + @param[in] SerialRawLen Size of SerialRaw.=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteInt (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + UINT8 *SerialRaw,=0D + INTN SerialRawLen=0D + )=0D +{=0D + INT32 Ret;=0D + UINT8 *Pt;=0D + INT32 Len;=0D +=0D + Len =3D 0;=0D + Pt =3D SerialRaw + SerialRawLen;=0D + while (Pt > SerialRaw) {=0D + *--(*Ptr) =3D *--Pt;=0D + Len++;=0D + }=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN= 1_INTEGER));=0D +=0D + return Len;=0D +}=0D +=0D +/**=0D + write Pkcs7 Issuer And SerialNumber.=0D +=0D + @param[in, out] Ptr The reference to the current position po= inter.=0D + @param[in] Start The start of the buffer, for bounds-checki= ng.=0D + @param[in] Serial Serial.=0D + @param[in] SerialLen Size of Serial.=0D + @param[in] IssuerRaw IssuerRawLen.=0D + @param[in] IssuerRawLen Size of IssuerRawLen.=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteIssuerAndSerialNumber (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + UINT8 *Serial,=0D + INTN SerialLen,=0D + UINT8 *IssuerRaw,=0D + INTN IssuerRawLen=0D + )=0D +{=0D + INT32 Ret;=0D + INT32 Len;=0D +=0D + Len =3D 0;=0D + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteInt (Ptr, Start, Serial, Seria= lLen));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, Issu= erRaw, IssuerRawLen));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN= 1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));=0D +=0D + return Len;=0D +}=0D +=0D +/**=0D + SignerInfo ::=3D SEQUENCE {=0D + version Version;=0D + issuerAndSerialNumber IssuerAndSerialNumber,=0D + digestAlgorithm DigestAlgorithmIdentifier,=0D + authenticatedAttributes=0D + [0] IMPLICIT Attributes OPTIONAL,=0D + digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,=0D + encryptedDigest EncryptedDigest,=0D + unauthenticatedAttributes=0D + [1] IMPLICIT Attributes OPTIONAL.=0D +=0D + @param[in, out] Ptr The reference to the current position po= inter.=0D + @param[in] Start The start of the buffer, for bounds-checki= ng.=0D + @param[in] SignerInfo SignerInfo.=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteSignerInfo (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + MbedtlsPkcs7SignerInfo *SignerInfo=0D + )=0D +{=0D + INT32 Ret;=0D + INT32 Len;=0D +=0D + Len =3D 0;=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, Si= gnerInfo->Sig.p, SignerInfo->Sig.len));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, S= tart, (CONST CHAR8 *)SignerInfo->SigAlgIdentifier.p, SignerInfo->SigAlgIden= tifier.len, 0));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, S= tart, (CONST CHAR8 *)SignerInfo->AlgIdentifier.p, SignerInfo->AlgIdentifier= .len, 0));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteIssuerAndSerialNumber (Ptr, St= art, SignerInfo->Serial.p, SignerInfo->Serial.len, SignerInfo->IssuerRaw.p,= SignerInfo->IssuerRaw.len));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, SignerInfo-= >Version));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN= 1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));=0D +=0D + return Len;=0D +}=0D +=0D +/**=0D + write Pkcs7 Signers Info Set.=0D +=0D + @param[in, out] Ptr The reference to the current position po= inter.=0D + @param[in] Start The start of the buffer, for bounds-checki= ng.=0D + @param[in] SignersSet SignerInfo Set.=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteSignersInfoSet (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + MbedtlsPkcs7SignerInfo *SignersSet=0D + )=0D +{=0D + MbedtlsPkcs7SignerInfo *SignerInfo;=0D + INT32 Ret;=0D + INT32 Len;=0D +=0D + SignerInfo =3D SignersSet;=0D + Len =3D 0;=0D +=0D + while (SignerInfo !=3D NULL) {=0D + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignerInfo (Ptr, Start, Sign= erInfo));=0D + // move to next=0D + SignerInfo =3D SignerInfo->Next;=0D + }=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN= 1_CONSTRUCTED | MBEDTLS_ASN1_SET));=0D +=0D + return Len;=0D +}=0D +=0D +/**=0D + Signed Data Type=0D + SignedData ::=3D SEQUENCE {=0D + version Version,=0D + digestAlgorithms DigestAlgorithmIdentifiers,=0D + contentInfo ContentInfo,=0D + certificates=0D + [0] IMPLICIT ExtendedCertificatesAndCertificates=0D + OPTIONAL,=0D + crls=0D + [1] IMPLICIT CertificateRevocationLists OPTIONAL,=0D + signerInfos SignerInfos }=0D +=0D + DigestAlgorithmIdentifiers ::=3D=0D + SET OF DigestAlgorithmIdentifier=0D +=0D + SignerInfos ::=3D SET OF SignerInfo.=0D +=0D + @param[in, out] Ptr The reference to the current position po= inter.=0D + @param[in] Start The start of the buffer, for bounds-checki= ng.=0D + @param[in] Pkcs7 MbedtlsPkcs7=0D +=0D + @retval number The number of bytes written to p on success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.= =0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7WriteDer (=0D + UINT8 **Ptr,=0D + UINT8 *Start,=0D + MbedtlsPkcs7 *Pkcs7=0D + )=0D +{=0D + INT32 Ret;=0D + INT32 Len;=0D + mbedtls_md_type_t DigestAlg[1];=0D +=0D + DigestAlg[0] =3D MBEDTLS_MD_SHA256;=0D + Len =3D 0;=0D +=0D + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignersInfoSet (Ptr, Start, &(= Pkcs7->SignedData.SignerInfos)));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteCertificates (Ptr, Start, &(Pk= cs7->SignedData.Certificates), Pkcs7->SignedData.Certificates.next));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteContentInfo (Ptr, Start, NULL,= 0));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteDigestAlgorithmSet (Ptr, Start= , DigestAlg, 1));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, Pkcs7->Sign= edData.Version));=0D +=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));=0D + EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN= 1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));=0D +=0D + return Len;=0D +}=0D +=0D +/**=0D + Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Mess= age=0D + Syntax Standard, version 1.5". This interface is only intended to be use= d for=0D + application to perform PKCS#7 functionality validation.=0D +=0D + If this interface is not supported, then return FALSE.=0D +=0D + @param[in] PrivateKey Pointer to the PEM-formatted private key da= ta for=0D + data signing.=0D + @param[in] PrivateKeySize Size of the PEM private key data in bytes.= =0D + @param[in] KeyPassword NULL-terminated passphrase used for encrypt= ed PEM=0D + key data.=0D + @param[in] InData Pointer to the content to be signed.=0D + @param[in] InDataSize Size of InData in bytes.=0D + @param[in] SignCert Pointer to signer's DER-encoded certificate= to sign with.=0D + @param[in] OtherCerts Pointer to an optional additional set of ce= rtificates to=0D + include in the PKCS#7 signedData (e.g. any = intermediate=0D + CAs in the chain).=0D + @param[out] SignedData Pointer to output PKCS#7 signedData. It's c= aller's=0D + responsibility to free the buffer with Free= Pool().=0D + @param[out] SignedDataSize Size of SignedData in bytes.=0D +=0D + @retval TRUE PKCS#7 data signing succeeded.=0D + @retval FALSE PKCS#7 data signing failed.=0D + @retval FALSE This interface is not supported.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +Pkcs7Sign (=0D + IN CONST UINT8 *PrivateKey,=0D + IN UINTN PrivateKeySize,=0D + IN CONST UINT8 *KeyPassword,=0D + IN UINT8 *InData,=0D + IN UINTN InDataSize,=0D + IN UINT8 *SignCert,=0D + IN UINT8 *OtherCerts OPTIONAL,=0D + OUT UINT8 **SignedData,=0D + OUT UINTN *SignedDataSize=0D + )=0D +{=0D + BOOLEAN Status;=0D + INT32 Ret;=0D + mbedtls_pk_context Pkey;=0D + UINT8 HashValue[SHA256_DIGEST_SIZE];=0D + UINT8 Signature[MAX_SIGNATURE_SIZE];=0D + UINTN SignatureLen;=0D + UINT8 *NewPrivateKey;=0D + mbedtls_x509_crt *Crt;=0D +=0D + MbedtlsPkcs7 Pkcs7;=0D + MbedtlsPkcs7SignerInfo SignerInfo;=0D + UINT8 *Buffer;=0D + INTN BufferSize;=0D + UINT8 *Ptr;=0D + INT32 Len;=0D +=0D + //=0D + // Check input parameters.=0D + //=0D + if ((PrivateKey =3D=3D NULL) || (KeyPassword =3D=3D NULL) || (InData =3D= =3D NULL) ||=0D + (SignCert =3D=3D NULL) || (SignedData =3D=3D NULL) || (SignedDataSiz= e =3D=3D NULL) || (InDataSize > INT_MAX))=0D + {=0D + return FALSE;=0D + }=0D +=0D + BufferSize =3D 4096;=0D +=0D + SignatureLen =3D MAX_SIGNATURE_SIZE;=0D + Crt =3D (mbedtls_x509_crt *)SignCert;=0D +=0D + NewPrivateKey =3D NULL;=0D + if (PrivateKey[PrivateKeySize - 1] !=3D 0) {=0D + NewPrivateKey =3D AllocateZeroPool (PrivateKeySize + 1);=0D + if (NewPrivateKey =3D=3D NULL) {=0D + return FALSE;=0D + }=0D +=0D + CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);=0D + NewPrivateKey[PrivateKeySize] =3D 0;=0D + PrivateKeySize++;=0D + } else {=0D + NewPrivateKey =3D AllocateZeroPool (PrivateKeySize);=0D + if (NewPrivateKey =3D=3D NULL) {=0D + return FALSE;=0D + }=0D +=0D + CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);=0D + }=0D +=0D + mbedtls_pk_init (&Pkey);=0D + Ret =3D mbedtls_pk_parse_key (=0D + &Pkey,=0D + NewPrivateKey,=0D + PrivateKeySize,=0D + KeyPassword,=0D + KeyPassword =3D=3D NULL ? 0 : AsciiStrLen ((CONST CHAR8 *)KeyPas= sword),=0D + NULL,=0D + NULL=0D + );=0D + if (Ret !=3D 0) {=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D +=0D + /// Calculate InData Digest=0D + ZeroMem (HashValue, SHA256_DIGEST_SIZE);=0D + Status =3D Sha256HashAll (InData, InDataSize, HashValue);=0D + if (!Status) {=0D + goto Cleanup;=0D + }=0D +=0D + /// Pk Sign=0D + ZeroMem (Signature, MAX_SIGNATURE_SIZE);=0D + Ret =3D mbedtls_pk_sign (=0D + &Pkey,=0D + MBEDTLS_MD_SHA256,=0D + HashValue,=0D + SHA256_DIGEST_SIZE,=0D + Signature,=0D + MAX_SIGNATURE_SIZE,=0D + &SignatureLen,=0D + MbedtlsRand,=0D + NULL=0D + );=0D + if (Ret !=3D 0) {=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D +=0D + ZeroMem (&Pkcs7, sizeof (MbedtlsPkcs7));=0D + Pkcs7.SignedData.Version =3D 1;=0D +=0D + Crt->next =3D (mbedtls_x509_crt *)OtherCerts;=0D + Pkcs7.SignedData.Certificates =3D *Crt;=0D +=0D + SignerInfo.Next =3D NULL;=0D + SignerInfo.Sig.p =3D Signature;=0D + SignerInfo.Sig.len =3D SignatureLen;=0D + SignerInfo.Version =3D 1;=0D + SignerInfo.AlgIdentifier.p =3D MbedtlsOidDigestAlgSha256;=0D + SignerInfo.AlgIdentifier.len =3D sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) = - 1;=0D + if (mbedtls_pk_get_type (&Pkey) =3D=3D MBEDTLS_PK_RSA) {=0D + SignerInfo.SigAlgIdentifier.p =3D MbedtlsOidPkcs1Rsa;=0D + SignerInfo.SigAlgIdentifier.len =3D sizeof (MBEDTLS_OID_PKCS1_RSA) - 1= ;=0D + } else {=0D + Ret =3D mbedtls_oid_get_oid_by_sig_alg (MBEDTLS_PK_ECDSA, MBEDTLS_MD_S= HA256, (CONST CHAR8 **)&SignerInfo.SigAlgIdentifier.p, &SignerInfo.SigAlgId= entifier.len);=0D + if (Ret !=3D 0) {=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D + }=0D +=0D + SignerInfo.Serial =3D ((mbedtls_x509_crt *)SignCert)->serial;= =0D + SignerInfo.IssuerRaw =3D ((mbedtls_x509_crt *)SignCert)->issuer_= raw;=0D + Pkcs7.SignedData.SignerInfos =3D SignerInfo;=0D +=0D + Buffer =3D AllocateZeroPool (BufferSize);=0D + if (Buffer =3D=3D NULL) {=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D +=0D + Ptr =3D Buffer + BufferSize;=0D + Len =3D MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7);=0D +=0D + /// Enlarge buffer if buffer is too small=0D + while (Len =3D=3D MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {=0D + BufferSize =3D BufferSize * 2;=0D + Ptr =3D Buffer + BufferSize;=0D + FreePool (Buffer);=0D + Buffer =3D AllocateZeroPool (BufferSize);=0D + if (Buffer =3D=3D NULL) {=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D +=0D + Ptr =3D Buffer + BufferSize;=0D + Len =3D MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7);=0D + }=0D +=0D + if (Len <=3D 0) {=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D +=0D + *SignedData =3D AllocateZeroPool (Len);=0D + if (*SignedData =3D=3D NULL) {=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D +=0D + *SignedDataSize =3D Len;=0D + CopyMem (*SignedData, Ptr, Len);=0D + Status =3D TRUE;=0D +=0D +Cleanup:=0D + if (&Pkey !=3D NULL) {=0D + mbedtls_pk_free (&Pkey);=0D + }=0D +=0D + if (NewPrivateKey !=3D NULL) {=0D + memset (NewPrivateKey, 0, PrivateKeySize);=0D + FreePool (NewPrivateKey);=0D + }=0D +=0D + if (Buffer !=3D NULL) {=0D + memset (Buffer, 0, BufferSize);=0D + FreePool (Buffer);=0D + }=0D +=0D + return Status;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.= c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c new file mode 100644 index 0000000000..6b62ee2618 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c @@ -0,0 +1,113 @@ +/** @file=0D + Non-runtime specific implementation of PKCS#7 SignedData Verification Wr= apper.=0D +=0D +Copyright (c) 2024, Intel Corporation. All rights reserved.
=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "InternalCryptLib.h"=0D +#include =0D +=0D +/**=0D + Extracts the attached content from a PKCS#7 signed data if existed. The = input signed=0D + data could be wrapped in a ContentInfo structure.=0D +=0D + If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Leng= th overflow,=0D + then return FALSE. If the P7Data is not correctly formatted, then return= FALSE.=0D +=0D + Caution: This function may receive untrusted input. So this function wil= l do=0D + basic check for PKCS#7 data structure.=0D +=0D + @param[in] P7Data Pointer to the PKCS#7 signed data to process.= =0D + @param[in] P7Length Length of the PKCS#7 signed data in bytes.=0D + @param[out] Content Pointer to the extracted content from the PKCS= #7 signedData.=0D + It's caller's responsibility to free the buffe= r with FreePool().=0D + @param[out] ContentSize The size of the extracted content in bytes.=0D +=0D + @retval TRUE The P7Data was correctly formatted for process= ing.=0D + @retval FALSE The P7Data was not correctly formatted for pro= cessing.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +Pkcs7GetAttachedContent (=0D + IN CONST UINT8 *P7Data,=0D + IN UINTN P7Length,=0D + OUT VOID **Content,=0D + OUT UINTN *ContentSize=0D + )=0D +{=0D + BOOLEAN Status;=0D + UINT8 *SignedData;=0D + UINTN SignedDataSize;=0D + BOOLEAN Wrapped;=0D + INTN Ret;=0D + mbedtls_pkcs7 Pkcs7;=0D + mbedtls_pkcs7_data *MbedtlsContent;=0D +=0D + mbedtls_pkcs7_init (&Pkcs7);=0D +=0D + //=0D + // Check input parameter.=0D + //=0D + if ((P7Data =3D=3D NULL) || (P7Length > INT_MAX) || (Content =3D=3D NULL= ) || (ContentSize =3D=3D NULL)) {=0D + return FALSE;=0D + }=0D +=0D + *Content =3D NULL;=0D + SignedData =3D NULL;=0D +=0D + Status =3D WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &Sign= edDataSize);=0D + if (!Status || (SignedDataSize > INT_MAX)) {=0D + goto _Exit;=0D + }=0D +=0D + Status =3D FALSE;=0D +=0D + Ret =3D mbedtls_pkcs7_parse_der (&Pkcs7, SignedData, (INT32)SignedDataSi= ze);=0D +=0D + //=0D + // The type of Pkcs7 must be signedData=0D + //=0D + if (Ret !=3D MBEDTLS_PKCS7_SIGNED_DATA) {=0D + goto _Exit;=0D + }=0D +=0D + //=0D + // Check for detached or attached content=0D + //=0D + MbedtlsContent =3D &(Pkcs7.signed_data.content);=0D +=0D + if (MbedtlsContent =3D=3D NULL) {=0D + //=0D + // No Content supplied for PKCS7 detached signedData=0D + //=0D + *Content =3D NULL;=0D + *ContentSize =3D 0;=0D + } else {=0D + //=0D + // Retrieve the attached content in PKCS7 signedData=0D + //=0D + if ((MbedtlsContent->data.len > 0) && (MbedtlsContent->data.p !=3D NUL= L)) {=0D + *ContentSize =3D MbedtlsContent->data.len;=0D + *Content =3D AllocateZeroPool (*ContentSize);=0D + if (*Content =3D=3D NULL) {=0D + *ContentSize =3D 0;=0D + goto _Exit;=0D + }=0D +=0D + CopyMem (*Content, MbedtlsContent->data.p, *ContentSize);=0D + }=0D + }=0D +=0D + Status =3D TRUE;=0D +=0D +_Exit:=0D + //=0D + // Release Resources=0D + //=0D + mbedtls_pkcs7_free (&Pkcs7);=0D +=0D + return Status;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommo= n.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c new file mode 100644 index 0000000000..e9f1b0efdd --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c @@ -0,0 +1,1354 @@ +/** @file=0D + PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrappe= r=0D + Implementation over mbedtls.=0D +=0D + RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites=0D + FIPS 186-4 - Digital Signature Standard (DSS)=0D +=0D +Copyright (c) 2024, Intel Corporation. All rights reserved.
=0D +SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "CryptPkcs7Internal.h"=0D +#include =0D +=0D +/* Profile for backward compatibility. Allows RSA 1024, unlike the default= =0D + profile. */=0D +STATIC mbedtls_x509_crt_profile gCompatProfile =3D=0D +{=0D + /* Hashes from SHA-256 and above. Note that this selection=0D + * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */=0D +=0D + #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA1) |=0D + #endif=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) |=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) |=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512),=0D + 0xFFFFFFF, /* Any PK alg */=0D +=0D + /* Curves at or above 128-bit security level. Note that this selection=0D + * should be aligned with ssl_preset_default_curves in ssl_tls.c. */=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) |=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) |=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) |=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) |=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) |=0D + MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) |=0D + 0,=0D + 1024,=0D +};=0D +=0D +/**=0D + Init MbedtlsPkcs7.=0D +=0D + @param[in] Pkcs7 MbedtlsPkcs7.=0D +**/=0D +STATIC=0D +VOID=0D +MbedTlsPkcs7Init (=0D + MbedtlsPkcs7 *Pkcs7=0D + )=0D +{=0D + ZeroMem (Pkcs7, sizeof (MbedtlsPkcs7));=0D +}=0D +=0D +/**=0D + Get Pkcs7 Next Content Len.=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] End The end of the buffer.=0D + @param[out] Len MbedtlsPkcs7 Content Len.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7GetNextContentLen (=0D + UINT8 **Ptr,=0D + UINT8 *End,=0D + UINTN *Len=0D + )=0D +{=0D + INT32 Ret;=0D +=0D + Ret =3D mbedtls_asn1_get_tag (Ptr, End, Len, MBEDTLS_ASN1_CONSTRUCTED | = MBEDTLS_ASN1_CONTEXT_SPECIFIC);=0D + return Ret;=0D +}=0D +=0D +/**=0D + Get Pkcs7 Version..=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] End The end of the buffer.=0D + @param[out] Ver MbedtlsPkcs7 Version.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7GetVersion (=0D + UINT8 **Ptr,=0D + UINT8 *End,=0D + INT32 *Ver=0D + )=0D +{=0D + INT32 Ret;=0D +=0D + Ret =3D mbedtls_asn1_get_int (Ptr, End, Ver);=0D + return Ret;=0D +}=0D +=0D +/**=0D + ContentInfo ::=3D SEQUENCE {=0D + contentType ContentType,=0D + content=0D + [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] End The end of the buffer.=0D + @param[out] Pkcs7 MbedtlsPkcs7.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +Pkcs7GetContentInfoType (=0D + UINT8 **Ptr,=0D + UINT8 *End,=0D + mbedtls_asn1_buf *Pkcs7=0D + )=0D +{=0D + UINTN Len;=0D + int Ret;=0D +=0D + Len =3D 0;=0D + Ret =3D mbedtls_asn1_get_tag (=0D + Ptr,=0D + End,=0D + &Len,=0D + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE=0D + );=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OID);=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Pkcs7->tag =3D MBEDTLS_ASN1_OID;=0D + Pkcs7->len =3D Len;=0D + Pkcs7->p =3D *Ptr;=0D + }=0D +=0D + return Ret;=0D +}=0D +=0D +/**=0D + DigestAlgorithmIdentifier ::=3D AlgorithmIdentifier.=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] End The end of the buffer.=0D + @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7GetDigestAlgorithm (=0D + UINT8 **Ptr,=0D + UINT8 *End,=0D + mbedtls_x509_buf *Alg=0D + )=0D +{=0D + INT32 Ret;=0D +=0D + Ret =3D mbedtls_asn1_get_alg_null (Ptr, End, Alg);=0D + return Ret;=0D +}=0D +=0D +/**=0D + DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier.=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] End The end of the buffer.=0D + @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7GetDigestAlgorithmSet (=0D + UINT8 **Ptr,=0D + UINT8 *End,=0D + mbedtls_x509_buf *Alg=0D + )=0D +{=0D + UINTN Len;=0D + INT32 Ret;=0D +=0D + Len =3D 0;=0D + Ret =3D mbedtls_asn1_get_tag (=0D + Ptr,=0D + End,=0D + &Len,=0D + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET=0D + );=0D +=0D + if (Ret =3D=3D 0) {=0D + End =3D *Ptr + Len;=0D + // assume only one digest algorithm=0D + Ret =3D mbedtls_asn1_get_alg_null (Ptr, End, Alg);=0D + }=0D +=0D + return Ret;=0D +}=0D +=0D +/**=0D + certificates :: SET OF ExtendedCertificateOrCertificate,=0D + ExtendedCertificateOrCertificate ::=3D CHOICE {=0D + certificate Certificate -- x509,=0D + extendedCertificate[0] IMPLICIT ExtendedCertificate }.=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] Plen The buffer len.=0D + @param[out] Certs mbedtls_x509_crt cert.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7GetCertificates (=0D + UINT8 **Ptr,=0D + INTN Plen,=0D + mbedtls_x509_crt *Certs=0D + )=0D +{=0D + INT32 Ret;=0D +=0D + Ret =3D mbedtls_x509_crt_parse (Certs, *Ptr, Plen);=0D + return Ret;=0D +}=0D +=0D +/**=0D + EncryptedDigest ::=3D OCTET STRING.=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] End The end of the buffer.=0D + @param[out] Signature Signature.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +Pkcs7GetSignature (=0D + UINT8 **Ptr,=0D + UINT8 *End,=0D + mbedtls_asn1_buf *Signature=0D + )=0D +{=0D + INT32 Ret;=0D + UINTN Len;=0D +=0D + Len =3D 0;=0D + Ret =3D mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OCTET_STRING)= ;=0D + if (Ret =3D=3D 0) {=0D + Signature->tag =3D MBEDTLS_ASN1_OCTET_STRING;=0D + Signature->len =3D Len;=0D + Signature->p =3D *Ptr;=0D + }=0D +=0D + return Ret;=0D +}=0D +=0D +/**=0D + SignerInfo ::=3D SEQUENCE {=0D + version Version;=0D + issuerAndSerialNumber IssuerAndSerialNumber,=0D + digestAlgorithm DigestAlgorithmIdentifier,=0D + authenticatedAttributes=0D + [0] IMPLICIT Attributes OPTIONAL,=0D + digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,=0D + encryptedDigest EncryptedDigest,=0D + unauthenticatedAttributes=0D + [1] IMPLICIT Attributes OPTIONAL.=0D +=0D + @param[in] Ptr The start of the buffer.=0D + @param[in] End The end of the buffer.=0D + @param[out] SignersSet MbedtlsPkcs7SignerInfo.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedTlsPkcs7GetSignersInfoSet (=0D + UINT8 **Ptr,=0D + UINT8 *End,=0D + MbedtlsPkcs7SignerInfo *SignersSet=0D + )=0D +{=0D + UINT8 *EndSet;=0D + INT32 Ret;=0D + UINTN Len;=0D + UINT8 *TempP;=0D +=0D + Len =3D 0;=0D +=0D + Ret =3D mbedtls_asn1_get_tag (=0D + Ptr,=0D + End,=0D + &Len,=0D + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET=0D + );=0D +=0D + if (Ret =3D=3D 0) {=0D + EndSet =3D *Ptr + Len;=0D +=0D + Ret =3D mbedtls_asn1_get_tag (=0D + Ptr,=0D + EndSet,=0D + &Len,=0D + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE=0D + );=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D mbedtls_asn1_get_int (Ptr, EndSet, &SignersSet->Version);=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D mbedtls_asn1_get_tag (=0D + Ptr,=0D + EndSet,=0D + &Len,=0D + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE=0D + );=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + SignersSet->IssuerRaw.p =3D *Ptr;=0D + Ret =3D mbedtls_asn1_get_tag (=0D + Ptr,=0D + EndSet,=0D + &Len,=0D + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SE= QUENCE=0D + );=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D mbedtls_x509_get_name (Ptr, *Ptr + Len, &SignersSet->Issuer);= =0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + SignersSet->IssuerRaw.len =3D *Ptr - SignersSet->IssuerRaw.p;=0D +=0D + Ret =3D mbedtls_x509_get_serial (Ptr, EndSet, &SignersSet->Serial);=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->AlgI= dentifier);=0D + }=0D +=0D + // OPTIONAL AuthenticatedAttributes=0D + if (Ret =3D=3D 0) {=0D + TempP =3D *Ptr;=0D + if (mbedtls_asn1_get_tag (&TempP, EndSet, &Len, MBEDTLS_ASN1_CONSTRUCT= ED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) =3D=3D 0) {=0D + SignersSet->AuthAttr.len =3D Len + (TempP - *Ptr);=0D + SignersSet->AuthAttr.p =3D *Ptr;=0D + *Ptr =3D TempP + Len;=0D + } else {=0D + SignersSet->AuthAttr.p =3D NULL;=0D + }=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->SigA= lgIdentifier);=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D Pkcs7GetSignature (Ptr, End, &SignersSet->Sig);=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + SignersSet->Next =3D NULL;=0D + }=0D +=0D + return Ret;=0D +}=0D +=0D +/**=0D + SignedData ::=3D SEQUENCE {=0D + version Version,=0D + digestAlgorithms DigestAlgorithmIdentifiers,=0D + contentInfo ContentInfo,=0D + certificates=0D + [0] IMPLICIT ExtendedCertificatesAndCertificates=0D + OPTIONAL,=0D + crls=0D + [0] IMPLICIT CertificateRevocationLists OPTIONAL,=0D + signerInfos SignerInfos }.=0D +=0D + @param[in] Buffer The start of the buffer.=0D + @param[in] BufferLen The len the buffer.=0D + @param[out] SignedData MbedtlsPkcs7SignedData.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +Pkcs7GetSignedData (=0D + UINT8 *Buffer,=0D + INTN BufferLen,=0D + MbedtlsPkcs7SignedData *SignedData=0D + )=0D +{=0D + UINT8 *Ptr;=0D + UINT8 *End;=0D + UINTN Len;=0D + INT32 Ret;=0D + UINT8 *CertP;=0D + UINTN CertLen;=0D + UINT8 *OldCertP;=0D + UINTN TotalCertLen;=0D + mbedtls_x509_crt *MoreCert;=0D + UINT8 CertNum;=0D + mbedtls_x509_crt *LastCert;=0D + mbedtls_x509_crt *TempCrt;=0D +=0D + Len =3D 0;=0D + Ptr =3D Buffer;=0D + End =3D Buffer + BufferLen;=0D + MoreCert =3D NULL;=0D +=0D + Ret =3D mbedtls_asn1_get_tag (=0D + &Ptr,=0D + End,=0D + &Len,=0D + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE=0D + );=0D +=0D + if (Ret =3D=3D 0) {=0D + // version=0D + Ret =3D MbedTlsPkcs7GetVersion (&Ptr, End, &SignedData->Version);=0D + }=0D +=0D + if ((Ret =3D=3D 0) && (SignedData->Version !=3D 1)) {=0D + Ret =3D -1;=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + // digest algorithm=0D + Ret =3D MbedTlsPkcs7GetDigestAlgorithmSet (=0D + &Ptr,=0D + End,=0D + &SignedData->DigestAlgorithms=0D + );=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + if (=0D + #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES=0D + ((SignedData->DigestAlgorithms.len =3D=3D sizeof (MBEDTLS_OID_DIGE= ST_ALG_SHA1) - 1) &&=0D + (CompareMem (=0D + SignedData->DigestAlgorithms.p,=0D + MBEDTLS_OID_DIGEST_ALG_SHA1,=0D + SignedData->DigestAlgorithms.len=0D + ) =3D=3D 0)) ||=0D + #endif=0D + ((SignedData->DigestAlgorithms.len =3D=3D sizeof (MBEDTLS_OID_DIGE= ST_ALG_SHA256) - 1) &&=0D + (CompareMem (=0D + SignedData->DigestAlgorithms.p,=0D + MBEDTLS_OID_DIGEST_ALG_SHA256,=0D + SignedData->DigestAlgorithms.len=0D + ) =3D=3D 0)) ||=0D + ((SignedData->DigestAlgorithms.len =3D=3D sizeof (MBEDTLS_OID_DIGE= ST_ALG_SHA384) - 1) &&=0D + (CompareMem (=0D + SignedData->DigestAlgorithms.p,=0D + MBEDTLS_OID_DIGEST_ALG_SHA384,=0D + SignedData->DigestAlgorithms.len=0D + ) =3D=3D 0)) ||=0D + ((SignedData->DigestAlgorithms.len =3D=3D sizeof (MBEDTLS_OID_DIGE= ST_ALG_SHA512) - 1) &&=0D + (CompareMem (=0D + SignedData->DigestAlgorithms.p,=0D + MBEDTLS_OID_DIGEST_ALG_SHA512,=0D + SignedData->DigestAlgorithms.len=0D + ) =3D=3D 0)))=0D + {=0D + Ret =3D 0;=0D + } else {=0D + Ret =3D -1;=0D + }=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + Ret =3D Pkcs7GetContentInfoType (&Ptr, End, &SignedData->ContentInfo.O= id);=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + // move to next=0D + Ptr =3D Ptr + SignedData->ContentInfo.Oid.len;=0D + Ret =3D MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len);=0D + CertP =3D Ptr + Len;=0D +=0D + // move to actual cert, if there are more [0]=0D + if (MbedTlsPkcs7GetNextContentLen (&CertP, End, &CertLen) =3D=3D 0) {= =0D + Len =3D CertLen;=0D + Ptr =3D CertP;=0D + }=0D + }=0D +=0D + // certificates: may have many certs=0D + CertP =3D Ptr;=0D +=0D + TotalCertLen =3D 0;=0D +=0D + MoreCert =3D &SignedData->Certificates;=0D + CertNum =3D 0;=0D +=0D + while (TotalCertLen < Len) {=0D + OldCertP =3D CertP;=0D +=0D + Ret =3D mbedtls_asn1_get_tag (&CertP, End, &CertLen, MBEDTLS_ASN1_CONS= TRUCTED | MBEDTLS_ASN1_SEQUENCE);=0D + if (Ret !=3D 0) {=0D + goto Out;=0D + }=0D +=0D + // cert total len=0D + CertLen =3D CertLen + (CertP - OldCertP);=0D +=0D + // move to next cert=0D + CertP =3D OldCertP + CertLen;=0D +=0D + // change TotalCertLen=0D + TotalCertLen +=3D CertLen;=0D +=0D + mbedtls_x509_crt_init (MoreCert);=0D + Ret =3D MbedTlsPkcs7GetCertificates (&OldCertP, CertLen, MoreCert);=0D + if (Ret !=3D 0) {=0D + goto Out;=0D + }=0D +=0D + CertNum++;=0D + MoreCert->next =3D mbedtls_calloc (1, sizeof (mbedtls_x509_crt));=0D + MoreCert =3D MoreCert->next;=0D + }=0D +=0D + if (TotalCertLen !=3D Len) {=0D + Ret =3D -1;=0D + goto Out;=0D + }=0D +=0D + LastCert =3D &(SignedData->Certificates);=0D +=0D + while (CertNum--) {=0D + if (CertNum =3D=3D 0) {=0D + LastCert->next =3D NULL;=0D + break;=0D + } else {=0D + LastCert =3D LastCert->next;=0D + }=0D + }=0D +=0D + // signers info=0D + if (Ret =3D=3D 0) {=0D + Ptr =3D Ptr + Len;=0D + Ret =3D MbedTlsPkcs7GetSignersInfoSet (&Ptr, End, &SignedData->SignerI= nfos);=0D + }=0D +=0D +Out:=0D + if (Ret =3D=3D 0) {=0D + if (MoreCert !=3D NULL) {=0D + mbedtls_x509_crt_free (MoreCert);=0D + MoreCert =3D NULL;=0D + }=0D + } else {=0D + if (SignedData->Certificates.next !=3D NULL) {=0D + TempCrt =3D SignedData->Certificates.next;=0D + mbedtls_x509_crt_free (TempCrt);=0D + }=0D + }=0D +=0D + return Ret;=0D +}=0D +=0D +/**=0D + Parse MbedtlsPkcs7 to Der format.=0D + @param[in] Buffer The start of the buffer.=0D + @param[in] BufferLen The len the buffer.=0D + @param[out] Pkcs7 MbedtlsPkcs7.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedtlsPkcs7ParseDer (=0D + CONST UINT8 *Buffer,=0D + INTN BufferLen,=0D + MbedtlsPkcs7 *Pkcs7=0D + )=0D +{=0D + UINT8 *Ptr;=0D + UINT8 *End;=0D + UINTN Len;=0D + INT32 Ret;=0D +=0D + if (Pkcs7 =3D=3D NULL) {=0D + return -1;=0D + }=0D +=0D + Len =3D 0;=0D + Ptr =3D (UINT8 *)Buffer;=0D + End =3D Ptr + BufferLen;=0D +=0D + Ret =3D Pkcs7GetContentInfoType (&Ptr, End, &Pkcs7->ContentTypeOid);=0D + if (Ret !=3D 0) {=0D + goto Out;=0D + }=0D +=0D + if ((CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DATA, Pkcs7-= >ContentTypeOid.len) =3D=3D 0) ||=0D + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DA= TA, Pkcs7->ContentTypeOid.len) =3D=3D 0) ||=0D + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DA= TA, Pkcs7->ContentTypeOid.len) =3D=3D 0) ||=0D + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_E= NVELOPED_DATA, Pkcs7->ContentTypeOid.len) =3D=3D 0) ||=0D + (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DIGESTED_DAT= A, Pkcs7->ContentTypeOid.len) =3D=3D 0))=0D + {=0D + // Invalid PKCS7 data type;=0D + Ret =3D -1;=0D + goto Out;=0D + }=0D +=0D + if (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA, = Pkcs7->ContentTypeOid.len) !=3D 0) {=0D + // Invalid PKCS7 data type;=0D + Ret =3D -1;=0D + goto Out;=0D + }=0D +=0D + // Content type is SignedData=0D + Ptr =3D Ptr + Pkcs7->ContentTypeOid.len;=0D +=0D + Ret =3D MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len);=0D + if (Ret !=3D 0) {=0D + goto Out;=0D + }=0D +=0D + Ret =3D Pkcs7GetSignedData (Ptr, Len, &Pkcs7->SignedData);=0D + if (Ret !=3D 0) {=0D + goto Out;=0D + }=0D +=0D +Out:=0D + return Ret;=0D +}=0D +=0D +/**=0D + MbedtlsPkcs7 verify MbedtlsPkcs7SignerInfo.=0D + @param[in] SignerInfo MbedtlsPkcs7 SignerInfo.=0D + @param[in] Cert cert.=0D + @param[in] Data Pointer for data.=0D + @param[in] DataLen The len the buffer.=0D +=0D + @retval 0 Success.=0D + @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on f= ailure.=0D +**/=0D +STATIC=0D +INT32=0D +MbedtlsPkcs7SignedDataVerifySigners (=0D + MbedtlsPkcs7SignerInfo *SignerInfo,=0D + mbedtls_x509_crt *Cert,=0D + CONST UINT8 *Data,=0D + INTN DataLen=0D + )=0D +{=0D + INT32 Ret;=0D + UINT8 Hash[MBEDTLS_MD_MAX_SIZE];=0D + mbedtls_pk_context Pk;=0D + CONST mbedtls_md_info_t *MdInfo;=0D + INTN HashLen;=0D + UINT8 TempAuthAttr;=0D +=0D + Pk =3D Cert->pk;=0D + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);=0D +=0D + // all the hash algo=0D + #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES=0D + MdInfo =3D mbedtls_md_info_from_type (MBEDTLS_MD_SHA1);=0D + HashLen =3D mbedtls_md_get_size (MdInfo);=0D + mbedtls_md (MdInfo, Data, DataLen, Hash);=0D + if (SignerInfo->AuthAttr.p !=3D NULL) {=0D + TempAuthAttr =3D *(SignerInfo->AuthAttr.p);=0D + *(SignerInfo->AuthAttr.p) =3D MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_= SET;=0D + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, = Hash);=0D + // Restore content=0D + *(SignerInfo->AuthAttr.p) =3D TempAuthAttr;=0D + }=0D +=0D + Ret =3D mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA1, Hash, HashLen, SignerIn= fo->Sig.p, SignerInfo->Sig.len);=0D +=0D + if (Ret =3D=3D 0) {=0D + return Ret;=0D + }=0D +=0D + #endif=0D +=0D + MdInfo =3D mbedtls_md_info_from_type (MBEDTLS_MD_SHA256);=0D + HashLen =3D mbedtls_md_get_size (MdInfo);=0D + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);=0D + mbedtls_md (MdInfo, Data, DataLen, Hash);=0D + if (SignerInfo->AuthAttr.p !=3D NULL) {=0D + TempAuthAttr =3D *(SignerInfo->AuthAttr.p);=0D + *(SignerInfo->AuthAttr.p) =3D MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_= SET;=0D + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, = Hash);=0D + // Restore content=0D + *(SignerInfo->AuthAttr.p) =3D TempAuthAttr;=0D + }=0D +=0D + Ret =3D mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA256, Hash, HashLen, Signer= Info->Sig.p, SignerInfo->Sig.len);=0D + if (Ret =3D=3D 0) {=0D + return Ret;=0D + }=0D +=0D + MdInfo =3D mbedtls_md_info_from_type (MBEDTLS_MD_SHA384);=0D + HashLen =3D mbedtls_md_get_size (MdInfo);=0D + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);=0D + mbedtls_md (MdInfo, Data, DataLen, Hash);=0D + if (SignerInfo->AuthAttr.p !=3D NULL) {=0D + TempAuthAttr =3D *(SignerInfo->AuthAttr.p);=0D + *(SignerInfo->AuthAttr.p) =3D MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_= SET;=0D + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, = Hash);=0D + // Restore content=0D + *(SignerInfo->AuthAttr.p) =3D TempAuthAttr;=0D + }=0D +=0D + Ret =3D mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA384, Hash, HashLen, Signer= Info->Sig.p, SignerInfo->Sig.len);=0D + if (Ret =3D=3D 0) {=0D + return Ret;=0D + }=0D +=0D + MdInfo =3D mbedtls_md_info_from_type (MBEDTLS_MD_SHA512);=0D + HashLen =3D mbedtls_md_get_size (MdInfo);=0D + ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);=0D + mbedtls_md (MdInfo, Data, DataLen, Hash);=0D + if (SignerInfo->AuthAttr.p !=3D NULL) {=0D + TempAuthAttr =3D *(SignerInfo->AuthAttr.p);=0D + *(SignerInfo->AuthAttr.p) =3D MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_= SET;=0D + mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, = Hash);=0D + // Restore content=0D + *(SignerInfo->AuthAttr.p) =3D TempAuthAttr;=0D + }=0D +=0D + Ret =3D mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA512, Hash, HashLen, Signer= Info->Sig.p, SignerInfo->Sig.len);=0D + if (Ret =3D=3D 0) {=0D + return Ret;=0D + }=0D +=0D + return Ret;=0D +}=0D +=0D +/**=0D + Find signer cert in MbedtlsPkcs7SignerInfo.=0D +=0D + @param[in] SignerInfo MbedtlsPkcs7 SignerInfo.=0D + @param[in] Certs MbedtlsPkcs7 SignerInfo certs.=0D +=0D + @retval cert Signer Cert.=0D +**/=0D +STATIC=0D +mbedtls_x509_crt *=0D +MbedTlsPkcs7FindSignerCert (=0D + MbedtlsPkcs7SignerInfo *SignerInfo,=0D + mbedtls_x509_crt *Certs=0D + )=0D +{=0D + mbedtls_x509_crt *Cert;=0D +=0D + Cert =3D Certs;=0D + while (Cert !=3D NULL) {=0D + if ((Cert->serial.p =3D=3D NULL) || (Cert->issuer_raw.p =3D=3D NULL)) = {=0D + return NULL;=0D + }=0D +=0D + if ((Cert->issuer_raw.len =3D=3D SignerInfo->IssuerRaw.len) &&=0D + (CompareMem (Cert->issuer_raw.p, SignerInfo->IssuerRaw.p, Cert->is= suer_raw.len) =3D=3D 0) &&=0D + (Cert->serial.len =3D=3D SignerInfo->Serial.len) &&=0D + (CompareMem (Cert->serial.p, SignerInfo->Serial.p, Cert->serial.le= n) =3D=3D 0))=0D + {=0D + break;=0D + }=0D +=0D + Cert =3D Cert->next;=0D + }=0D +=0D + return Cert;=0D +}=0D +=0D +/**=0D + verify cert.=0D +=0D + @param[in] Ca CA cert.=0D + @param[in] CaCrl CRL.=0D + @param[in] End Cert which need be verified.=0D +=0D + @retval TRUE Verify successfully.=0D + @retval FALSE Verify failed.=0D +**/=0D +STATIC=0D +BOOLEAN=0D +MbedTlsPkcs7VerifyCert (=0D + mbedtls_x509_crt *Ca,=0D + mbedtls_x509_crl *CaCrl,=0D + mbedtls_x509_crt *End=0D + )=0D +{=0D + INT32 Ret;=0D + UINT32 VFlag;=0D + mbedtls_x509_crt_profile Profile;=0D +=0D + VFlag =3D 0;=0D + CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile));= =0D +=0D + Ret =3D mbedtls_x509_crt_verify_with_profile (End, Ca, CaCrl, &Profile, = NULL, &VFlag, NULL, NULL);=0D +=0D + return Ret =3D=3D 0;=0D +}=0D +=0D +/**=0D + verify cert chain.=0D +=0D + @param[in] Pkcs7 MbedtlsPkcs7.=0D + @param[in] Ca CA cert.=0D + @param[in] End Cert which need be verified.=0D +=0D + @retval TRUE Verify successfully.=0D + @retval FALSE Verify failed.=0D +**/=0D +STATIC=0D +BOOLEAN=0D +MbedTlsPkcs7VerifyCertChain (=0D + MbedtlsPkcs7 *Pkcs7,=0D + mbedtls_x509_crt *Ca,=0D + mbedtls_x509_crt *End=0D + )=0D +{=0D + mbedtls_x509_crt *AllCert;=0D + mbedtls_x509_crt *InterCert;=0D +=0D + AllCert =3D &(Pkcs7->SignedData.Certificates);=0D + InterCert =3D NULL;=0D +=0D + while (AllCert !=3D NULL) {=0D + if ((AllCert->next =3D=3D End) && (MbedTlsPkcs7VerifyCert (AllCert, NU= LL, End))) {=0D + InterCert =3D AllCert;=0D + break;=0D + }=0D +=0D + AllCert =3D AllCert->next;=0D + }=0D +=0D + if (InterCert =3D=3D NULL) {=0D + return FALSE;=0D + }=0D +=0D + if (MbedTlsPkcs7VerifyCert (Ca, &(Pkcs7->SignedData.Crls), InterCert)) {= =0D + return TRUE;=0D + } else {=0D + return MbedTlsPkcs7VerifyCertChain (Pkcs7, Ca, InterCert);=0D + }=0D +}=0D +=0D +/**=0D + MbedTlsPkcs7 Verify SignedData.=0D +=0D + @param[in] Pkcs7 MbedtlsPkcs7.=0D + @param[in] TrustCert CA cert.=0D + @param[in] Data Pointer for data.=0D + @param[in] DataLen The len the buffer.=0D +=0D + @retval TRUE Verify successfully.=0D + @retval FALSE Verify failed.=0D +**/=0D +STATIC=0D +BOOLEAN=0D +MbedTlsPkcs7SignedDataVerify (=0D + MbedtlsPkcs7 *Pkcs7,=0D + mbedtls_x509_crt *TrustCert,=0D + CONST UINT8 *Data,=0D + INTN DataLen=0D + )=0D +{=0D + MbedtlsPkcs7SignerInfo *SignerInfo;=0D + mbedtls_x509_crt *Cert;=0D + mbedtls_x509_crt *AllCert;=0D + BOOLEAN Result;=0D +=0D + SignerInfo =3D &(Pkcs7->SignedData.SignerInfos);=0D + Result =3D TRUE;=0D +=0D + //=0D + // Traverse signers and verify each signers=0D + //=0D + while (SignerInfo !=3D NULL) {=0D + Result =3D FALSE;=0D + // 1. Find signers cert=0D + Cert =3D MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7->SignedData.C= ertificates));=0D + if (Cert !=3D NULL) {=0D + // 2. Check signer cert is trusted by trustCert=0D + if (MbedTlsPkcs7VerifyCert (TrustCert, &(Pkcs7->SignedData.Crls), Ce= rt)) {=0D + // root cert verify pass=0D + Result =3D TRUE;=0D + } else {=0D + if (MbedTlsPkcs7VerifyCertChain (Pkcs7, TrustCert, Cert)) {=0D + Result =3D TRUE;=0D + } else {=0D + Result =3D FALSE;=0D + }=0D + }=0D +=0D + if (Result =3D=3D TRUE) {=0D + // 3. Check signed data=0D + AllCert =3D &(Pkcs7->SignedData.Certificates);=0D + while (AllCert !=3D NULL) {=0D + if (MbedtlsPkcs7SignedDataVerifySigners (SignerInfo, AllCert, Da= ta, DataLen) =3D=3D 0) {=0D + return TRUE;=0D + }=0D +=0D + AllCert =3D AllCert->next;=0D + }=0D +=0D + Result =3D FALSE;=0D + }=0D + }=0D +=0D + // move to next=0D + SignerInfo =3D SignerInfo->Next;=0D + }=0D +=0D + return Result;=0D +}=0D +=0D +/**=0D + Check input P7Data is a wrapped ContentInfo structure or not. If not con= struct=0D + a new structure to wrap P7Data.=0D +=0D + Caution: This function may receive untrusted input.=0D + UEFI Authenticated Variable is external input, so this function will do = basic=0D + check for PKCS#7 data structure.=0D +=0D + @param[in] P7Data Pointer to the PKCS#7 message to verify.=0D + @param[in] P7Length Length of the PKCS#7 message in bytes.=0D + @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, othe= rwise=0D + return FALSE.=0D + @param[out] WrapData If return status of this function is TRUE:=0D + 1) when WrapFlag is TRUE, pointer to P7Data.=0D + 2) when WrapFlag is FALSE, pointer to a new Con= tentInfo=0D + structure. It's caller's responsibility to free= this=0D + buffer.=0D + @param[out] WrapDataSize Length of ContentInfo structure in bytes.=0D +=0D + @retval TRUE The operation is finished successfully.=0D + @retval FALSE The operation is failed due to lack of resource= s.=0D +=0D +**/=0D +BOOLEAN=0D +WrapPkcs7Data (=0D + IN CONST UINT8 *P7Data,=0D + IN UINTN P7Length,=0D + OUT BOOLEAN *WrapFlag,=0D + OUT UINT8 **WrapData,=0D + OUT UINTN *WrapDataSize=0D + )=0D +{=0D + BOOLEAN Wrapped;=0D + UINT8 *SignedData;=0D +=0D + //=0D + // Check whether input P7Data is a wrapped ContentInfo structure or not.= =0D + //=0D + Wrapped =3D FALSE;=0D + if ((P7Data[4] =3D=3D MBEDTLS_ASN1_OID) && (P7Data[5] =3D=3D sizeof (MBE= DTLS_OID_PKCS7_SIGNED_DATA) - 1)) {=0D + if (CompareMem (P7Data + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBE= DTLS_OID_PKCS7_SIGNED_DATA) - 1) =3D=3D 0) {=0D + if ((P7Data[15] =3D=3D (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONT= EXT_SPECIFIC)) && (P7Data[16] =3D=3D 0x82)) {=0D + Wrapped =3D TRUE;=0D + }=0D + }=0D + }=0D +=0D + if (Wrapped) {=0D + *WrapData =3D (UINT8 *)P7Data;=0D + *WrapDataSize =3D P7Length;=0D + } else {=0D + //=0D + // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in= 19 bytes.=0D + //=0D + *WrapDataSize =3D P7Length + 19;=0D + *WrapData =3D AllocateZeroPool (*WrapDataSize);=0D + if (*WrapData =3D=3D NULL) {=0D + *WrapFlag =3D Wrapped;=0D + return FALSE;=0D + }=0D +=0D + SignedData =3D *WrapData;=0D +=0D + //=0D + // Part1: 0x30, 0x82.=0D + //=0D + SignedData[0] =3D MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE;=0D + SignedData[1] =3D 0x82;=0D +=0D + //=0D + // Part2: Length1 =3D P7Length + 19 - 4, in big endian.=0D + //=0D + SignedData[2] =3D (UINT8)(((UINT16)(*WrapDataSize - 4)) >> 8);=0D + SignedData[3] =3D (UINT8)(((UINT16)(*WrapDataSize - 4)) & 0xff);=0D +=0D + //=0D + // Part3: 0x06, 0x09.=0D + //=0D + SignedData[4] =3D MBEDTLS_ASN1_OID;=0D + SignedData[5] =3D sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1;=0D +=0D + //=0D + // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02.=0D + //=0D + CopyMem (SignedData + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTL= S_OID_PKCS7_SIGNED_DATA) - 1);=0D +=0D + //=0D + // Part5: 0xA0, 0x82.=0D + //=0D + SignedData[15] =3D MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPE= CIFIC;=0D + SignedData[16] =3D 0x82;=0D +=0D + //=0D + // Part6: Length2 =3D P7Length, in big endian.=0D + //=0D + SignedData[17] =3D (UINT8)(((UINT16)P7Length) >> 8);=0D + SignedData[18] =3D (UINT8)(((UINT16)P7Length) & 0xff);=0D +=0D + //=0D + // Part7: P7Data.=0D + //=0D + CopyMem (SignedData + 19, P7Data, P7Length);=0D + }=0D +=0D + *WrapFlag =3D Wrapped;=0D + return TRUE;=0D +}=0D +=0D +/**=0D + Verifies the validity of a PKCS#7 signed data as described in "PKCS #7:= =0D + Cryptographic Message Syntax Standard". The input signed data could be w= rapped=0D + in a ContentInfo structure.=0D +=0D + If P7Data, TrustedCert or InData is NULL, then return FALSE.=0D + If P7Length, CertLength or DataLength overflow, then return FALSE.=0D + If this interface is not supported, then return FALSE.=0D +=0D + @param[in] P7Data Pointer to the PKCS#7 message to verify.=0D + @param[in] P7Length Length of the PKCS#7 message in bytes.=0D + @param[in] TrustedCert Pointer to a trusted/root certificate encoded i= n DER, which=0D + is used for certificate chain verification.=0D + @param[in] CertLength Length of the trusted certificate in bytes.=0D + @param[in] InData Pointer to the content to be verified.=0D + @param[in] DataLength Length of InData in bytes.=0D +=0D + @retval TRUE The specified PKCS#7 signed data is valid.=0D + @retval FALSE Invalid PKCS#7 signed data.=0D + @retval FALSE This interface is not supported.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +Pkcs7Verify (=0D + IN CONST UINT8 *P7Data,=0D + IN UINTN P7Length,=0D + IN CONST UINT8 *TrustedCert,=0D + IN UINTN CertLength,=0D + IN CONST UINT8 *InData,=0D + IN UINTN DataLength=0D + )=0D +{=0D + BOOLEAN Status;=0D + UINT8 *WrapData;=0D + UINTN WrapDataSize;=0D + BOOLEAN Wrapped;=0D + MbedtlsPkcs7 Pkcs7;=0D + INT32 Ret;=0D + mbedtls_x509_crt Crt;=0D + mbedtls_x509_crt *TempCrt;=0D +=0D + //=0D + // Check input parameters.=0D + //=0D + if ((P7Data =3D=3D NULL) || (TrustedCert =3D=3D NULL) || (InData =3D=3D = NULL) ||=0D + (P7Length > INT_MAX) || (CertLength > INT_MAX) || (DataLength > INT_= MAX))=0D + {=0D + return FALSE;=0D + }=0D +=0D + Status =3D WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDa= taSize);=0D +=0D + if (!Status) {=0D + return FALSE;=0D + }=0D +=0D + Status =3D FALSE;=0D + MbedTlsPkcs7Init (&Pkcs7);=0D + mbedtls_x509_crt_init (&Crt);=0D +=0D + Ret =3D MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7);=0D + if (Ret !=3D 0) {=0D + goto Cleanup;=0D + }=0D +=0D + Ret =3D mbedtls_x509_crt_parse_der (&Crt, TrustedCert, CertLength);=0D + if (Ret !=3D 0) {=0D + goto Cleanup;=0D + }=0D +=0D + Status =3D MbedTlsPkcs7SignedDataVerify (&Pkcs7, &Crt, InData, (INT32)Da= taLength);=0D +=0D +Cleanup:=0D + if (&Crt !=3D NULL) {=0D + mbedtls_x509_crt_free (&Crt);=0D + }=0D +=0D + if (Pkcs7.SignedData.Certificates.next !=3D NULL) {=0D + TempCrt =3D Pkcs7.SignedData.Certificates.next;=0D + mbedtls_x509_crt_free (TempCrt);=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Wrap function to use free() to free allocated memory for certificates.=0D +=0D + @param[in] Certs Pointer to the certificates to be freed.=0D +=0D +**/=0D +VOID=0D +EFIAPI=0D +Pkcs7FreeSigners (=0D + IN UINT8 *Certs=0D + )=0D +{=0D + if (Certs =3D=3D NULL) {=0D + return;=0D + }=0D +=0D + FreePool (Certs);=0D +}=0D +=0D +/**=0D + Get the signer's certificates from PKCS#7 signed data as described in "P= KCS #7:=0D + Cryptographic Message Syntax Standard". The input signed data could be w= rapped=0D + in a ContentInfo structure.=0D +=0D + If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, th= en=0D + return FALSE. If P7Length overflow, then return FALSE.=0D +=0D + Caution: This function may receive untrusted input.=0D + UEFI Authenticated Variable is external input, so this function will do = basic=0D + check for PKCS#7 data structure.=0D +=0D + @param[in] P7Data Pointer to the PKCS#7 message to verify.=0D + @param[in] P7Length Length of the PKCS#7 message in bytes.=0D + @param[out] CertStack Pointer to Signer's certificates retrieved from= P7Data.=0D + It's caller's responsibility to free the buffer= with=0D + Pkcs7FreeSigners().=0D + This data structure is EFI_CERT_STACK type.=0D + @param[out] StackLength Length of signer's certificates in bytes.=0D + @param[out] TrustedCert Pointer to a trusted certificate from Signer's = certificates.=0D + It's caller's responsibility to free the buffer= with=0D + Pkcs7FreeSigners().=0D + @param[out] CertLength Length of the trusted certificate in bytes.=0D +=0D + @retval TRUE The operation is finished successfully.=0D + @retval FALSE Error occurs during the operation.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +Pkcs7GetSigners (=0D + IN CONST UINT8 *P7Data,=0D + IN UINTN P7Length,=0D + OUT UINT8 **CertStack,=0D + OUT UINTN *StackLength,=0D + OUT UINT8 **TrustedCert,=0D + OUT UINTN *CertLength=0D + )=0D +{=0D + MbedtlsPkcs7SignerInfo *SignerInfo;=0D + mbedtls_x509_crt *Cert;=0D + MbedtlsPkcs7 Pkcs7;=0D + BOOLEAN Status;=0D + UINT8 *WrapData;=0D + UINTN WrapDataSize;=0D + BOOLEAN Wrapped;=0D + mbedtls_x509_crt *TempCrt;=0D +=0D + UINTN CertSize;=0D + UINT8 Index;=0D + UINT8 *CertBuf;=0D + UINT8 *OldBuf;=0D + UINTN BufferSize;=0D + UINTN OldSize;=0D +=0D + if ((P7Data =3D=3D NULL) || (CertStack =3D=3D NULL) || (StackLength =3D= =3D NULL) ||=0D + (TrustedCert =3D=3D NULL) || (CertLength =3D=3D NULL) || (P7Length >= INT_MAX))=0D + {=0D + return FALSE;=0D + }=0D +=0D + Status =3D WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDa= taSize);=0D +=0D + if (!Status) {=0D + return FALSE;=0D + }=0D +=0D + Status =3D FALSE;=0D + CertBuf =3D NULL;=0D + OldBuf =3D NULL;=0D + Cert =3D NULL;=0D +=0D + MbedTlsPkcs7Init (&Pkcs7);=0D + if (MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7) !=3D 0)= {=0D + goto _Exit;=0D + }=0D +=0D + SignerInfo =3D &(Pkcs7.SignedData.SignerInfos);=0D +=0D + //=0D + // Traverse each signers=0D + //=0D + // Convert CertStack to buffer in following format:=0D + // UINT8 CertNumber;=0D + // UINT32 Cert1Length;=0D + // UINT8 Cert1[];=0D + // UINT32 Cert2Length;=0D + // UINT8 Cert2[];=0D + // ...=0D + // UINT32 CertnLength;=0D + // UINT8 Certn[];=0D + //=0D + BufferSize =3D sizeof (UINT8);=0D + OldSize =3D BufferSize;=0D + Index =3D 0;=0D +=0D + while (SignerInfo !=3D NULL) {=0D + // Find signers cert=0D + Cert =3D MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7.SignedData.Ce= rtificates));=0D + if (Cert =3D=3D NULL) {=0D + goto _Exit;=0D + }=0D +=0D + CertSize =3D Cert->raw.len;=0D + OldSize =3D BufferSize;=0D + OldBuf =3D CertBuf;=0D + BufferSize =3D OldSize + CertSize + sizeof (UINT32);=0D +=0D + CertBuf =3D AllocateZeroPool (BufferSize);=0D + if (CertBuf =3D=3D NULL) {=0D + goto _Exit;=0D + }=0D +=0D + if (OldBuf !=3D NULL) {=0D + CopyMem (CertBuf, OldBuf, OldSize);=0D + FreePool (OldBuf);=0D + OldBuf =3D NULL;=0D + }=0D +=0D + WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)CertSize);=0D + CopyMem (CertBuf + OldSize + sizeof (UINT32), Cert->raw.p, CertSize);= =0D +=0D + Index++;=0D +=0D + // move to next=0D + SignerInfo =3D SignerInfo->Next;=0D + }=0D +=0D + if (CertBuf !=3D NULL) {=0D + //=0D + // Update CertNumber.=0D + //=0D + CertBuf[0] =3D Index;=0D +=0D + *CertLength =3D BufferSize - OldSize - sizeof (UINT32);=0D + *TrustedCert =3D AllocateZeroPool (*CertLength);=0D + if (*TrustedCert =3D=3D NULL) {=0D + goto _Exit;=0D + }=0D +=0D + CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLengt= h);=0D + *CertStack =3D CertBuf;=0D + *StackLength =3D BufferSize;=0D + Status =3D TRUE;=0D + }=0D +=0D +_Exit:=0D + //=0D + // Release Resources=0D + //=0D + if (!Status && (CertBuf !=3D NULL)) {=0D + FreePool (CertBuf);=0D + *CertStack =3D NULL;=0D + }=0D +=0D + if (Status) {=0D + if (Pkcs7.SignedData.Certificates.next !=3D NULL) {=0D + TempCrt =3D Pkcs7.SignedData.Certificates.next;=0D + mbedtls_x509_crt_free (TempCrt);=0D + }=0D + }=0D +=0D + if (OldBuf !=3D NULL) {=0D + FreePool (OldBuf);=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Retrieves all embedded certificates from PKCS#7 signed data as described= in "PKCS #7:=0D + Cryptographic Message Syntax Standard", and outputs two certificate list= s chained and=0D + unchained to the signer's certificates.=0D + The input signed data could be wrapped in a ContentInfo structure.=0D +=0D + @param[in] P7Data Pointer to the PKCS#7 message.=0D + @param[in] P7Length Length of the PKCS#7 message in bytes.=0D + @param[out] SignerChainCerts Pointer to the certificates list chained t= o signer's=0D + certificate. It's caller's responsibility = to free the buffer=0D + with Pkcs7FreeSigners().=0D + This data structure is EFI_CERT_STACK type= .=0D + @param[out] ChainLength Length of the chained certificates list bu= ffer in bytes.=0D + @param[out] UnchainCerts Pointer to the unchained certificates list= s. It's caller's=0D + responsibility to free the buffer with Pkc= s7FreeSigners().=0D + This data structure is EFI_CERT_STACK type= .=0D + @param[out] UnchainLength Length of the unchained certificates list = buffer in bytes.=0D +=0D + @retval TRUE The operation is finished successfully.=0D + @retval FALSE Error occurs during the operation.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +Pkcs7GetCertificatesList (=0D + IN CONST UINT8 *P7Data,=0D + IN UINTN P7Length,=0D + OUT UINT8 **SignerChainCerts,=0D + OUT UINTN *ChainLength,=0D + OUT UINT8 **UnchainCerts,=0D + OUT UINTN *UnchainLength=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c= b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c new file mode 100644 index 0000000000..47a8230cf6 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c @@ -0,0 +1,689 @@ +/** @file=0D + This module verifies that Enhanced Key Usages (EKU's) are present within= =0D + a PKCS7 signature blob using MbedTLS.=0D +=0D + Copyright (C) Microsoft Corporation. All Rights Reserved.=0D + Copyright (c) 2024, Intel Corporation. All rights reserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include =0D +#include "InternalCryptLib.h"=0D +#include =0D +#include =0D +=0D +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 EkuOID[] =3D { 0x55, 0x1D, 0x25= };=0D +=0D +/*leaf Cert basic_constraints case1: CA: false and CA object is excluded *= /=0D +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase1[] =3D { = 0x30, 0x00 };=0D +=0D +/*leaf Cert basic_constraints case2: CA: false */=0D +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase2[] =3D { = 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 };=0D +=0D +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gOidBasicConstraints[] =3D { 0x= 55, 0x1D, 0x13 };=0D +=0D +/**=0D + Find first Extension data match with given OID=0D +=0D + @param[in] Start Pointer to the DER-encoded extensions = data=0D + @param[in] End extensions data size in bytes=0D + @param[in ] Oid OID for match=0D + @param[in ] OidSize OID size in bytes=0D + @param[out] FindExtensionData output matched extension data.=0D + @param[out] FindExtensionDataLen matched extension data size.=0D +=0D +**/=0D +STATIC=0D +BOOLEAN=0D +InternalX509FindExtensionData (=0D + UINT8 *Start,=0D + UINT8 *End,=0D + CONST UINT8 *Oid,=0D + UINTN OidSize,=0D + UINT8 **FindExtensionData,=0D + UINTN *FindExtensionDataLen=0D + )=0D +{=0D + UINT8 *Ptr;=0D + UINT8 *ExtensionPtr;=0D + UINTN ObjLen;=0D + INT32 Ret;=0D + BOOLEAN Status;=0D + UINTN FindExtensionLen;=0D + UINTN HeaderLen;=0D +=0D + /*If no Extension entry match Oid*/=0D + Status =3D FALSE;=0D + Ptr =3D Start;=0D +=0D + Ret =3D 0;=0D +=0D + while (TRUE) {=0D + //=0D + // Extension ::=3D SEQUENCE {=0D + // extnID OBJECT IDENTIFIER,=0D + // critical BOOLEAN DEFAULT FALSE,=0D + // extnValue OCTET STRING }=0D + //=0D + ExtensionPtr =3D Ptr;=0D + Ret =3D mbedtls_asn1_get_tag (=0D + &Ptr,=0D + End,=0D + &ObjLen,=0D + MBEDTLS_ASN1_CONSTRUCTED |=0D + MBEDTLS_ASN1_SEQUENCE=0D + );=0D + if (Ret =3D=3D 0) {=0D + HeaderLen =3D (UINTN)(Ptr - ExtensionPtr);=0D + FindExtensionLen =3D ObjLen;=0D + /* Get Object Identifier*/=0D + Ret =3D mbedtls_asn1_get_tag (=0D + &Ptr,=0D + End,=0D + &ObjLen,=0D + MBEDTLS_ASN1_OID=0D + );=0D + } else {=0D + break;=0D + }=0D +=0D + if ((Ret =3D=3D 0) && !CompareMem (Ptr, Oid, OidSize)) {=0D + Ptr +=3D ObjLen;=0D +=0D + Ret =3D mbedtls_asn1_get_tag (=0D + &Ptr,=0D + End,=0D + &ObjLen,=0D + MBEDTLS_ASN1_BOOLEAN=0D + );=0D + if (Ret =3D=3D 0) {=0D + Ptr +=3D ObjLen;=0D + }=0D +=0D + Ret =3D mbedtls_asn1_get_tag (=0D + &Ptr,=0D + End,=0D + &ObjLen,=0D + MBEDTLS_ASN1_OCTET_STRING=0D + );=0D + } else {=0D + Ret =3D 1;=0D + }=0D +=0D + if (Ret =3D=3D 0) {=0D + *FindExtensionData =3D Ptr;=0D + *FindExtensionDataLen =3D ObjLen;=0D + Status =3D TRUE;=0D + break;=0D + }=0D +=0D + /* move to next*/=0D + Ptr =3D ExtensionPtr + HeaderLen + FindExtensionLen;=0D + Ret =3D 0;=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Retrieve Extension data from one X.509 certificate.=0D +=0D + @param[in] Cert Pointer to the X509 certificate.=0D + @param[in] Oid Object identifier buffer=0D + @param[in] OidSize Object identifier buffer size=0D + @param[out] ExtensionData Extension bytes.=0D + @param[in, out] ExtensionDataSize Extension bytes size.=0D +=0D + @retval RETURN_SUCCESS The certificate Extension data retrieve= d successfully.=0D + @retval RETURN_INVALID_PARAMETER If Cert is NULL.=0D + If ExtensionDataSize is NULL.=0D + If ExtensionData is not NULL and *Extens= ionDataSize is 0.=0D + If Certificate is invalid.=0D + @retval RETURN_NOT_FOUND If no Extension entry match Oid.=0D + @retval RETURN_BUFFER_TOO_SMALL If the ExtensionData is NULL. The requi= red buffer size=0D + is returned in the ExtensionDataSize par= ameter.=0D + @retval RETURN_UNSUPPORTED The operation is not supported.=0D +**/=0D +STATIC=0D +BOOLEAN=0D +GetExtensionData (=0D + CONST mbedtls_x509_crt *Cert,=0D + CONST UINT8 *Oid,=0D + UINTN OidSize,=0D + UINT8 *ExtensionData,=0D + UINTN *ExtensionDataSize=0D + )=0D +{=0D + CONST mbedtls_x509_crt *Crt;=0D + INT32 Ret;=0D + BOOLEAN Status;=0D + UINT8 *Ptr;=0D + UINT8 *End;=0D + UINTN ObjLen;=0D +=0D + Ptr =3D NULL;=0D + End =3D NULL;=0D + ObjLen =3D 0;=0D +=0D + if ((Cert =3D=3D NULL) || (Oid =3D=3D NULL) || (OidSize =3D=3D 0) ||=0D + (ExtensionDataSize =3D=3D NULL))=0D + {=0D + return FALSE;=0D + }=0D +=0D + Status =3D FALSE;=0D +=0D + Crt =3D Cert;=0D +=0D + Ptr =3D Crt->v3_ext.p;=0D + End =3D Crt->v3_ext.p + Crt->v3_ext.len;=0D + Ret =3D mbedtls_asn1_get_tag (=0D + &Ptr,=0D + End,=0D + &ObjLen,=0D + MBEDTLS_ASN1_CONSTRUCTED |=0D + MBEDTLS_ASN1_SEQUENCE=0D + );=0D +=0D + if (Ret =3D=3D 0) {=0D + Status =3D InternalX509FindExtensionData (=0D + Ptr,=0D + End,=0D + Oid,=0D + OidSize,=0D + &Ptr,=0D + &ObjLen=0D + );=0D + }=0D +=0D + if (Status) {=0D + if (*ExtensionDataSize < ObjLen) {=0D + *ExtensionDataSize =3D ObjLen;=0D + Status =3D FALSE;=0D + goto Cleanup;=0D + }=0D +=0D + if (Oid !=3D NULL) {=0D + if (ExtensionData =3D=3D NULL) {=0D + return FALSE;=0D + }=0D +=0D + CopyMem (ExtensionData, Ptr, ObjLen);=0D + }=0D +=0D + *ExtensionDataSize =3D ObjLen;=0D + } else {=0D + *ExtensionDataSize =3D 0;=0D + }=0D +=0D +Cleanup:=0D + return Status;=0D +}=0D +=0D +/**=0D + Determines if the specified EKU represented in ASN1 form is present=0D + in a given certificate.=0D +=0D + @param[in] Cert The certificate to check.=0D + @param[in] EKU The EKU to look for.=0D + @param[in] EkuLen The size of EKU.=0D +=0D + @retval EFI_SUCCESS We successfully identified the signing= type.=0D + @retval EFI_INVALID_PARAMETER A parameter was invalid.=0D + @retval EFI_NOT_FOUND One or more EKU's were not found in th= e signature.=0D +=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +IsEkuInCertificate (=0D + IN CONST mbedtls_x509_crt *Cert,=0D + IN UINT8 *EKU,=0D + IN UINTN EkuLen=0D + )=0D +{=0D + EFI_STATUS Status;=0D + BOOLEAN Ret;=0D + UINT8 *Buffer;=0D + UINTN Index;=0D + UINTN Len;=0D +=0D + if ((Cert =3D=3D NULL) || (EKU =3D=3D NULL)) {=0D + Status =3D EFI_INVALID_PARAMETER;=0D + return Status;=0D + }=0D +=0D + Len =3D 0;=0D + Buffer =3D NULL;=0D + Ret =3D GetExtensionData (=0D + Cert,=0D + (CONST UINT8 *)EkuOID,=0D + sizeof (EkuOID),=0D + NULL,=0D + &Len=0D + );=0D + if (Len =3D=3D 0) {=0D + Status =3D EFI_NOT_FOUND;=0D + goto Exit;=0D + }=0D +=0D + Buffer =3D AllocateZeroPool (Len);=0D + if (Buffer =3D=3D NULL) {=0D + Status =3D EFI_NOT_FOUND;=0D + goto Exit;=0D + }=0D +=0D + Ret =3D GetExtensionData (=0D + Cert,=0D + (CONST UINT8 *)EkuOID,=0D + sizeof (EkuOID),=0D + Buffer,=0D + &Len=0D + );=0D +=0D + if ((Len =3D=3D 0) || (!Ret)) {=0D + Status =3D EFI_NOT_FOUND;=0D + goto Exit;=0D + }=0D +=0D + Status =3D EFI_NOT_FOUND;=0D + /*find the spdm hardware identity OID*/=0D + for (Index =3D 0; Index <=3D Len - EkuLen; Index++) {=0D + if (!CompareMem (Buffer + Index, EKU, EkuLen)) {=0D + // check sub EKU=0D + if (Index =3D=3D Len - EkuLen) {=0D + Status =3D EFI_SUCCESS;=0D + break;=0D + // Ensure that the OID is complete=0D + } else if (Buffer[Index + EkuLen] =3D=3D 0x06) {=0D + Status =3D EFI_SUCCESS;=0D + break;=0D + } else {=0D + break;=0D + }=0D + }=0D + }=0D +=0D +Exit:=0D + if (Buffer !=3D NULL) {=0D + FreePool (Buffer);=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Get OID from txt.=0D +=0D + @param[in] RequiredEKUs Array of null-terminated strings listin= g OIDs of=0D + required EKUs that must be present in t= he signature.=0D + @param[in] RequiredEKUsSize Number of elements in the RequiredEKUs = string array.=0D + @param[in,out] CheckOid OID.=0D + @param[out] OidLen The size of OID.=0D +=0D +**/=0D +VOID=0D +GetOidFromTxt (=0D + IN CONST CHAR8 *RequiredEKUs,=0D + IN UINTN RequiredEKUsSize,=0D + IN OUT UINT8 *CheckOid,=0D + OUT UINT8 *OidLen=0D + )=0D +{=0D + UINT8 *Ptr;=0D + UINT16 Index;=0D + UINT32 Data;=0D + UINT8 OidIndex;=0D + UINTN EKUsSize;=0D +=0D + EKUsSize =3D RequiredEKUsSize;=0D + // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-o= bject-identifier?redirectedfrom=3DMSDN=0D + CheckOid[0] =3D (UINT8)((RequiredEKUs[0] - '0') * 40 + (RequiredEKUs[2] = - '0'));=0D +=0D + EKUsSize =3D EKUsSize - 4;=0D + Ptr =3D (UINT8 *)(RequiredEKUs + 4);=0D +=0D + OidIndex =3D 1;=0D +=0D + while (EKUsSize) {=0D + Index =3D 0;=0D + Data =3D 0;=0D +=0D + while ((*Ptr !=3D '.') && (*Ptr !=3D '\0')) {=0D + Index++;=0D + Ptr++;=0D + EKUsSize--;=0D + }=0D +=0D + while (Index) {=0D + Data =3D 10 * Data + (*(Ptr - Index) - '0');=0D + Index--;=0D + }=0D +=0D + if (EKUsSize !=3D 0) {=0D + Ptr++;=0D + EKUsSize--;=0D + }=0D +=0D + if (Data < 128) {=0D + CheckOid[OidIndex] =3D (UINT8)Data;=0D + OidIndex++;=0D + } else {=0D + CheckOid[OidIndex + 1] =3D (UINT8)(Data & 0xFF);=0D + CheckOid[OidIndex] =3D (UINT8)(((((Data & 0xFF00) << 1) | 0x8000= ) >> 8) & 0xFF);=0D + OidIndex =3D OidIndex + 2;=0D + }=0D + }=0D +=0D + *OidLen =3D OidIndex;=0D +}=0D +=0D +/**=0D + Verify the Cert is signer cert=0D +=0D + @param[in] Start Pointer to the DER-encoded certificate data Sta= rt.=0D + @param[in] End Pointer to the DER-encoded certificate data End= .=0D +=0D + @retval true verify pass=0D + @retval false verify fail=0D +**/=0D +STATIC=0D +BOOLEAN=0D +IsCertSignerCert (=0D + UINT8 *Start,=0D + UINT8 *End=0D + )=0D +{=0D + BOOLEAN Status;=0D + UINT8 *Buffer;=0D + UINTN Len;=0D + mbedtls_x509_crt Cert;=0D + UINTN ObjLen;=0D +=0D + mbedtls_x509_crt_init (&Cert);=0D +=0D + ObjLen =3D End - Start;=0D +=0D + if (mbedtls_x509_crt_parse_der (&Cert, Start, ObjLen) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + Len =3D 0;=0D + Buffer =3D NULL;=0D + Status =3D GetExtensionData (=0D + &Cert,=0D + (CONST UINT8 *)gOidBasicConstraints,=0D + sizeof (gOidBasicConstraints),=0D + NULL,=0D + &Len=0D + );=0D + if (Len =3D=3D 0) {=0D + /* basic constraints is not present in Cert */=0D + return TRUE;=0D + }=0D +=0D + Buffer =3D AllocateZeroPool (Len);=0D + if (Buffer =3D=3D NULL) {=0D + return FALSE;=0D + }=0D +=0D + Status =3D GetExtensionData (=0D + &Cert,=0D + (CONST UINT8 *)gOidBasicConstraints,=0D + sizeof (gOidBasicConstraints),=0D + Buffer,=0D + &Len=0D + );=0D +=0D + if (Len =3D=3D 0) {=0D + /* basic constraints is not present in Cert */=0D + Status =3D TRUE;=0D + goto Exit;=0D + } else if (!Status) {=0D + Status =3D FALSE;=0D + goto Exit;=0D + }=0D +=0D + if ((Len =3D=3D sizeof (gBasicConstraintsCase1)) &&=0D + (!CompareMem (Buffer, gBasicConstraintsCase1, sizeof (gBasicConstrai= ntsCase1))))=0D + {=0D + Status =3D TRUE;=0D + goto Exit;=0D + }=0D +=0D + if ((Len =3D=3D sizeof (gBasicConstraintsCase2)) &&=0D + (!CompareMem (Buffer, gBasicConstraintsCase2, sizeof (gBasicConstrai= ntsCase2))))=0D + {=0D + Status =3D TRUE;=0D + goto Exit;=0D + }=0D +=0D + Status =3D FALSE;=0D +=0D +Exit:=0D + mbedtls_x509_crt_free (&Cert);=0D +=0D + if (Buffer !=3D NULL) {=0D + FreePool (Buffer);=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + Determines if the specified EKUs are present in a signing certificate.=0D +=0D + @param[in] SignerCert The certificate to check.=0D + @param[in] RequiredEKUs The EKUs to look for.=0D + @param[in] RequiredEKUsSize The number of EKUs=0D + @param[in] RequireAllPresent If TRUE, then all the specified EKUs=0D + must be present in the certificate.=0D +=0D + @retval EFI_SUCCESS We successfully identified the signing= type.=0D + @retval EFI_INVALID_PARAMETER A parameter was invalid.=0D + @retval EFI_NOT_FOUND One or more EKU's were not found in th= e signature.=0D +**/=0D +STATIC=0D +EFI_STATUS=0D +CheckEKUs (=0D + IN CONST mbedtls_x509_crt *SignerCert,=0D + IN CONST CHAR8 *RequiredEKUs[],=0D + IN CONST UINT32 RequiredEKUsSize,=0D + IN BOOLEAN RequireAllPresent=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINT32 NumEkusFound;=0D + UINT32 Index;=0D + UINT8 *EKU;=0D + UINTN EkuLen;=0D + UINT8 CheckOid[20];=0D + UINT8 OidLen;=0D +=0D + Status =3D EFI_SUCCESS;=0D + NumEkusFound =3D 0;=0D +=0D + if ((SignerCert =3D=3D NULL) || (RequiredEKUs =3D=3D NULL) || (RequiredE= KUsSize =3D=3D 0)) {=0D + Status =3D EFI_INVALID_PARAMETER;=0D + goto Exit;=0D + }=0D +=0D + for (Index =3D 0; Index < RequiredEKUsSize; Index++) {=0D + //=0D + // Finding required EKU in Cert.=0D + //=0D + GetOidFromTxt (RequiredEKUs[Index], strlen (RequiredEKUs[Index]), Chec= kOid, &OidLen);=0D +=0D + EKU =3D CheckOid;=0D + EkuLen =3D OidLen;=0D +=0D + Status =3D IsEkuInCertificate (SignerCert, EKU, EkuLen);=0D + if (Status =3D=3D EFI_SUCCESS) {=0D + NumEkusFound++;=0D + if (!RequireAllPresent) {=0D + //=0D + // Found at least one, so we are done.=0D + //=0D + goto Exit;=0D + }=0D + } else {=0D + //=0D + // Fail to find Eku in Cert=0D + break;=0D + }=0D + }=0D +=0D +Exit:=0D + if (RequireAllPresent &&=0D + (NumEkusFound =3D=3D RequiredEKUsSize))=0D + {=0D + //=0D + // Found all required EKUs in certificate.=0D + //=0D + Status =3D EFI_SUCCESS;=0D + }=0D +=0D + return Status;=0D +}=0D +=0D +/**=0D + This function receives a PKCS#7 formatted signature blob,=0D + looks for the EKU SEQUENCE blob, and if found then looks=0D + for all the required EKUs. This function was created so that=0D + the Surface team can cut down on the number of Certificate=0D + Authorities (CA's) by checking EKU's on leaf signers for=0D + a specific product. This prevents one product's certificate=0D + from signing another product's firmware or unlock blobs.=0D +=0D + Note that this function does not validate the certificate chain.=0D + That needs to be done before using this function.=0D +=0D + @param[in] Pkcs7Signature The PKCS#7 signed information content b= lock. An array=0D + containing the content block with both = the signature,=0D + the signer's certificate, and any neces= sary intermediate=0D + certificates.=0D + @param[in] Pkcs7SignatureSize Number of bytes in Pkcs7Signature.=0D + @param[in] RequiredEKUs Array of null-terminated strings listin= g OIDs of=0D + required EKUs that must be present in t= he signature.=0D + @param[in] RequiredEKUsSize Number of elements in the RequiredEKUs = string array.=0D + @param[in] RequireAllPresent If this is TRUE, then all of the specif= ied EKU's=0D + must be present in the leaf signer. If= it is=0D + FALSE, then we will succeed if we find = any=0D + of the specified EKU's.=0D +=0D + @retval EFI_SUCCESS The required EKUs were found in the sig= nature.=0D + @retval EFI_INVALID_PARAMETER A parameter was invalid.=0D + @retval EFI_NOT_FOUND One or more EKU's were not found in the= signature.=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +VerifyEKUsInPkcs7Signature (=0D + IN CONST UINT8 *Pkcs7Signature,=0D + IN CONST UINT32 SignatureSize,=0D + IN CONST CHAR8 *RequiredEKUs[],=0D + IN CONST UINT32 RequiredEKUsSize,=0D + IN BOOLEAN RequireAllPresent=0D + )=0D +{=0D + EFI_STATUS Status;=0D + mbedtls_x509_crt Cert;=0D + UINT8 *Ptr;=0D + UINT8 *End;=0D + INT32 Len;=0D + UINTN ObjLen;=0D + UINT8 *OldEnd;=0D +=0D + //=0D + // Check input parameter.=0D + //=0D + if ((RequiredEKUs =3D=3D NULL) || (Pkcs7Signature =3D=3D NULL)) {=0D + Status =3D EFI_INVALID_PARAMETER;=0D + return Status;=0D + }=0D +=0D + mbedtls_x509_crt_init (&Cert);=0D +=0D + Ptr =3D (UINT8 *)(UINTN)Pkcs7Signature;=0D + Len =3D (UINT32)SignatureSize;=0D + End =3D Ptr + Len;=0D +=0D + // Cert=0D + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED |= MBEDTLS_ASN1_SEQUENCE) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + // tbscert=0D + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) !=3D= 0) {=0D + return FALSE;=0D + }=0D +=0D + Ptr +=3D ObjLen;=0D + // signature algo=0D + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED |= MBEDTLS_ASN1_SET) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + Ptr +=3D ObjLen;=0D + // signature=0D + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED |= MBEDTLS_ASN1_SEQUENCE) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + Ptr +=3D ObjLen;=0D + OldEnd =3D Ptr;=0D + // Cert=0D + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED |= MBEDTLS_ASN1_CONTEXT_SPECIFIC) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + End =3D Ptr + ObjLen;=0D +=0D + // leaf Cert=0D + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED |= MBEDTLS_ASN1_SEQUENCE) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + Ptr +=3D ObjLen;=0D +=0D + while ((Ptr !=3D End) && (Ptr < End)) {=0D + if (IsCertSignerCert (OldEnd, Ptr)) {=0D + break;=0D + }=0D +=0D + OldEnd =3D Ptr;=0D + if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED= | MBEDTLS_ASN1_SEQUENCE) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + Ptr +=3D ObjLen;=0D + }=0D +=0D + if (Ptr !=3D End) {=0D + return FALSE;=0D + } else {=0D + Ptr =3D End - ObjLen;=0D + }=0D +=0D + // leaf Cert=0D + ObjLen +=3D Ptr - OldEnd;=0D + Ptr =3D OldEnd;=0D +=0D + if (mbedtls_x509_crt_parse_der (&Cert, Ptr, ObjLen) !=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + Status =3D CheckEKUs (&Cert, RequiredEKUs, RequiredEKUsSize, RequireAllP= resent);=0D + if (Status !=3D EFI_SUCCESS) {=0D + goto Exit;=0D + }=0D +=0D +Exit:=0D + //=0D + // Release Resources=0D + //=0D + mbedtls_x509_crt_free (&Cert);=0D +=0D + return Status;=0D +}=0D --=20 2.26.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#119032): https://edk2.groups.io/g/devel/message/119032 Mute This Topic: https://groups.io/mt/106151219/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=-=-=-=-=-=-=-=-=-=-=-