CryptoPkg: Add Pkcs7 related functions based on Mbedtls
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4177 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 <jiewen.yao@intel.com> Cc: Yi Li <yi1.li@intel.com> Signed-off-by: Wenxing Hou <wenxing.hou@intel.com> Reviewed-by: Yi Li <yi1.li@intel.com> Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
This commit is contained in:
689
CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
Normal file
689
CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
Normal file
@@ -0,0 +1,689 @@
|
||||
/** @file
|
||||
This module verifies that Enhanced Key Usages (EKU's) are present within
|
||||
a PKCS7 signature blob using MbedTLS.
|
||||
|
||||
Copyright (C) Microsoft Corporation. All Rights Reserved.
|
||||
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include "InternalCryptLib.h"
|
||||
#include <mbedtls/pkcs7.h>
|
||||
#include <mbedtls/asn1write.h>
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 EkuOID[] = { 0x55, 0x1D, 0x25 };
|
||||
|
||||
/*leaf Cert basic_constraints case1: CA: false and CA object is excluded */
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase1[] = { 0x30, 0x00 };
|
||||
|
||||
/*leaf Cert basic_constraints case2: CA: false */
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase2[] = { 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 };
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gOidBasicConstraints[] = { 0x55, 0x1D, 0x13 };
|
||||
|
||||
/**
|
||||
Find first Extension data match with given OID
|
||||
|
||||
@param[in] Start Pointer to the DER-encoded extensions data
|
||||
@param[in] End extensions data size in bytes
|
||||
@param[in ] Oid OID for match
|
||||
@param[in ] OidSize OID size in bytes
|
||||
@param[out] FindExtensionData output matched extension data.
|
||||
@param[out] FindExtensionDataLen matched extension data size.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
InternalX509FindExtensionData (
|
||||
UINT8 *Start,
|
||||
UINT8 *End,
|
||||
CONST UINT8 *Oid,
|
||||
UINTN OidSize,
|
||||
UINT8 **FindExtensionData,
|
||||
UINTN *FindExtensionDataLen
|
||||
)
|
||||
{
|
||||
UINT8 *Ptr;
|
||||
UINT8 *ExtensionPtr;
|
||||
UINTN ObjLen;
|
||||
INT32 Ret;
|
||||
BOOLEAN Status;
|
||||
UINTN FindExtensionLen;
|
||||
UINTN HeaderLen;
|
||||
|
||||
/*If no Extension entry match Oid*/
|
||||
Status = FALSE;
|
||||
Ptr = Start;
|
||||
|
||||
Ret = 0;
|
||||
|
||||
while (TRUE) {
|
||||
//
|
||||
// Extension ::= SEQUENCE {
|
||||
// extnID OBJECT IDENTIFIER,
|
||||
// critical BOOLEAN DEFAULT FALSE,
|
||||
// extnValue OCTET STRING }
|
||||
//
|
||||
ExtensionPtr = Ptr;
|
||||
Ret = mbedtls_asn1_get_tag (
|
||||
&Ptr,
|
||||
End,
|
||||
&ObjLen,
|
||||
MBEDTLS_ASN1_CONSTRUCTED |
|
||||
MBEDTLS_ASN1_SEQUENCE
|
||||
);
|
||||
if (Ret == 0) {
|
||||
HeaderLen = (UINTN)(Ptr - ExtensionPtr);
|
||||
FindExtensionLen = ObjLen;
|
||||
/* Get Object Identifier*/
|
||||
Ret = mbedtls_asn1_get_tag (
|
||||
&Ptr,
|
||||
End,
|
||||
&ObjLen,
|
||||
MBEDTLS_ASN1_OID
|
||||
);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((Ret == 0) && !CompareMem (Ptr, Oid, OidSize)) {
|
||||
Ptr += ObjLen;
|
||||
|
||||
Ret = mbedtls_asn1_get_tag (
|
||||
&Ptr,
|
||||
End,
|
||||
&ObjLen,
|
||||
MBEDTLS_ASN1_BOOLEAN
|
||||
);
|
||||
if (Ret == 0) {
|
||||
Ptr += ObjLen;
|
||||
}
|
||||
|
||||
Ret = mbedtls_asn1_get_tag (
|
||||
&Ptr,
|
||||
End,
|
||||
&ObjLen,
|
||||
MBEDTLS_ASN1_OCTET_STRING
|
||||
);
|
||||
} else {
|
||||
Ret = 1;
|
||||
}
|
||||
|
||||
if (Ret == 0) {
|
||||
*FindExtensionData = Ptr;
|
||||
*FindExtensionDataLen = ObjLen;
|
||||
Status = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* move to next*/
|
||||
Ptr = ExtensionPtr + HeaderLen + FindExtensionLen;
|
||||
Ret = 0;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieve Extension data from one X.509 certificate.
|
||||
|
||||
@param[in] Cert Pointer to the X509 certificate.
|
||||
@param[in] Oid Object identifier buffer
|
||||
@param[in] OidSize Object identifier buffer size
|
||||
@param[out] ExtensionData Extension bytes.
|
||||
@param[in, out] ExtensionDataSize Extension bytes size.
|
||||
|
||||
@retval RETURN_SUCCESS The certificate Extension data retrieved successfully.
|
||||
@retval RETURN_INVALID_PARAMETER If Cert is NULL.
|
||||
If ExtensionDataSize is NULL.
|
||||
If ExtensionData is not NULL and *ExtensionDataSize is 0.
|
||||
If Certificate is invalid.
|
||||
@retval RETURN_NOT_FOUND If no Extension entry match Oid.
|
||||
@retval RETURN_BUFFER_TOO_SMALL If the ExtensionData is NULL. The required buffer size
|
||||
is returned in the ExtensionDataSize parameter.
|
||||
@retval RETURN_UNSUPPORTED The operation is not supported.
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
GetExtensionData (
|
||||
CONST mbedtls_x509_crt *Cert,
|
||||
CONST UINT8 *Oid,
|
||||
UINTN OidSize,
|
||||
UINT8 *ExtensionData,
|
||||
UINTN *ExtensionDataSize
|
||||
)
|
||||
{
|
||||
CONST mbedtls_x509_crt *Crt;
|
||||
INT32 Ret;
|
||||
BOOLEAN Status;
|
||||
UINT8 *Ptr;
|
||||
UINT8 *End;
|
||||
UINTN ObjLen;
|
||||
|
||||
Ptr = NULL;
|
||||
End = NULL;
|
||||
ObjLen = 0;
|
||||
|
||||
if ((Cert == NULL) || (Oid == NULL) || (OidSize == 0) ||
|
||||
(ExtensionDataSize == NULL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = FALSE;
|
||||
|
||||
Crt = Cert;
|
||||
|
||||
Ptr = Crt->v3_ext.p;
|
||||
End = Crt->v3_ext.p + Crt->v3_ext.len;
|
||||
Ret = mbedtls_asn1_get_tag (
|
||||
&Ptr,
|
||||
End,
|
||||
&ObjLen,
|
||||
MBEDTLS_ASN1_CONSTRUCTED |
|
||||
MBEDTLS_ASN1_SEQUENCE
|
||||
);
|
||||
|
||||
if (Ret == 0) {
|
||||
Status = InternalX509FindExtensionData (
|
||||
Ptr,
|
||||
End,
|
||||
Oid,
|
||||
OidSize,
|
||||
&Ptr,
|
||||
&ObjLen
|
||||
);
|
||||
}
|
||||
|
||||
if (Status) {
|
||||
if (*ExtensionDataSize < ObjLen) {
|
||||
*ExtensionDataSize = ObjLen;
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (Oid != NULL) {
|
||||
if (ExtensionData == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMem (ExtensionData, Ptr, ObjLen);
|
||||
}
|
||||
|
||||
*ExtensionDataSize = ObjLen;
|
||||
} else {
|
||||
*ExtensionDataSize = 0;
|
||||
}
|
||||
|
||||
Cleanup:
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if the specified EKU represented in ASN1 form is present
|
||||
in a given certificate.
|
||||
|
||||
@param[in] Cert The certificate to check.
|
||||
@param[in] EKU The EKU to look for.
|
||||
@param[in] EkuLen The size of EKU.
|
||||
|
||||
@retval EFI_SUCCESS We successfully identified the signing type.
|
||||
@retval EFI_INVALID_PARAMETER A parameter was invalid.
|
||||
@retval EFI_NOT_FOUND One or more EKU's were not found in the signature.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
IsEkuInCertificate (
|
||||
IN CONST mbedtls_x509_crt *Cert,
|
||||
IN UINT8 *EKU,
|
||||
IN UINTN EkuLen
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN Ret;
|
||||
UINT8 *Buffer;
|
||||
UINTN Index;
|
||||
UINTN Len;
|
||||
|
||||
if ((Cert == NULL) || (EKU == NULL)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
return Status;
|
||||
}
|
||||
|
||||
Len = 0;
|
||||
Buffer = NULL;
|
||||
Ret = GetExtensionData (
|
||||
Cert,
|
||||
(CONST UINT8 *)EkuOID,
|
||||
sizeof (EkuOID),
|
||||
NULL,
|
||||
&Len
|
||||
);
|
||||
if (Len == 0) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Buffer = AllocateZeroPool (Len);
|
||||
if (Buffer == NULL) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Ret = GetExtensionData (
|
||||
Cert,
|
||||
(CONST UINT8 *)EkuOID,
|
||||
sizeof (EkuOID),
|
||||
Buffer,
|
||||
&Len
|
||||
);
|
||||
|
||||
if ((Len == 0) || (!Ret)) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EFI_NOT_FOUND;
|
||||
/*find the spdm hardware identity OID*/
|
||||
for (Index = 0; Index <= Len - EkuLen; Index++) {
|
||||
if (!CompareMem (Buffer + Index, EKU, EkuLen)) {
|
||||
// check sub EKU
|
||||
if (Index == Len - EkuLen) {
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
// Ensure that the OID is complete
|
||||
} else if (Buffer[Index + EkuLen] == 0x06) {
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (Buffer != NULL) {
|
||||
FreePool (Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Get OID from txt.
|
||||
|
||||
@param[in] RequiredEKUs Array of null-terminated strings listing OIDs of
|
||||
required EKUs that must be present in the signature.
|
||||
@param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array.
|
||||
@param[in,out] CheckOid OID.
|
||||
@param[out] OidLen The size of OID.
|
||||
|
||||
**/
|
||||
VOID
|
||||
GetOidFromTxt (
|
||||
IN CONST CHAR8 *RequiredEKUs,
|
||||
IN UINTN RequiredEKUsSize,
|
||||
IN OUT UINT8 *CheckOid,
|
||||
OUT UINT8 *OidLen
|
||||
)
|
||||
{
|
||||
UINT8 *Ptr;
|
||||
UINT16 Index;
|
||||
UINT32 Data;
|
||||
UINT8 OidIndex;
|
||||
UINTN EKUsSize;
|
||||
|
||||
EKUsSize = RequiredEKUsSize;
|
||||
// https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN
|
||||
CheckOid[0] = (UINT8)((RequiredEKUs[0] - '0') * 40 + (RequiredEKUs[2] - '0'));
|
||||
|
||||
EKUsSize = EKUsSize - 4;
|
||||
Ptr = (UINT8 *)(RequiredEKUs + 4);
|
||||
|
||||
OidIndex = 1;
|
||||
|
||||
while (EKUsSize) {
|
||||
Index = 0;
|
||||
Data = 0;
|
||||
|
||||
while ((*Ptr != '.') && (*Ptr != '\0')) {
|
||||
Index++;
|
||||
Ptr++;
|
||||
EKUsSize--;
|
||||
}
|
||||
|
||||
while (Index) {
|
||||
Data = 10 * Data + (*(Ptr - Index) - '0');
|
||||
Index--;
|
||||
}
|
||||
|
||||
if (EKUsSize != 0) {
|
||||
Ptr++;
|
||||
EKUsSize--;
|
||||
}
|
||||
|
||||
if (Data < 128) {
|
||||
CheckOid[OidIndex] = (UINT8)Data;
|
||||
OidIndex++;
|
||||
} else {
|
||||
CheckOid[OidIndex + 1] = (UINT8)(Data & 0xFF);
|
||||
CheckOid[OidIndex] = (UINT8)(((((Data & 0xFF00) << 1) | 0x8000) >> 8) & 0xFF);
|
||||
OidIndex = OidIndex + 2;
|
||||
}
|
||||
}
|
||||
|
||||
*OidLen = OidIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
Verify the Cert is signer cert
|
||||
|
||||
@param[in] Start Pointer to the DER-encoded certificate data Start.
|
||||
@param[in] End Pointer to the DER-encoded certificate data End.
|
||||
|
||||
@retval true verify pass
|
||||
@retval false verify fail
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
IsCertSignerCert (
|
||||
UINT8 *Start,
|
||||
UINT8 *End
|
||||
)
|
||||
{
|
||||
BOOLEAN Status;
|
||||
UINT8 *Buffer;
|
||||
UINTN Len;
|
||||
mbedtls_x509_crt Cert;
|
||||
UINTN ObjLen;
|
||||
|
||||
mbedtls_x509_crt_init (&Cert);
|
||||
|
||||
ObjLen = End - Start;
|
||||
|
||||
if (mbedtls_x509_crt_parse_der (&Cert, Start, ObjLen) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Len = 0;
|
||||
Buffer = NULL;
|
||||
Status = GetExtensionData (
|
||||
&Cert,
|
||||
(CONST UINT8 *)gOidBasicConstraints,
|
||||
sizeof (gOidBasicConstraints),
|
||||
NULL,
|
||||
&Len
|
||||
);
|
||||
if (Len == 0) {
|
||||
/* basic constraints is not present in Cert */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Buffer = AllocateZeroPool (Len);
|
||||
if (Buffer == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = GetExtensionData (
|
||||
&Cert,
|
||||
(CONST UINT8 *)gOidBasicConstraints,
|
||||
sizeof (gOidBasicConstraints),
|
||||
Buffer,
|
||||
&Len
|
||||
);
|
||||
|
||||
if (Len == 0) {
|
||||
/* basic constraints is not present in Cert */
|
||||
Status = TRUE;
|
||||
goto Exit;
|
||||
} else if (!Status) {
|
||||
Status = FALSE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ((Len == sizeof (gBasicConstraintsCase1)) &&
|
||||
(!CompareMem (Buffer, gBasicConstraintsCase1, sizeof (gBasicConstraintsCase1))))
|
||||
{
|
||||
Status = TRUE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ((Len == sizeof (gBasicConstraintsCase2)) &&
|
||||
(!CompareMem (Buffer, gBasicConstraintsCase2, sizeof (gBasicConstraintsCase2))))
|
||||
{
|
||||
Status = TRUE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = FALSE;
|
||||
|
||||
Exit:
|
||||
mbedtls_x509_crt_free (&Cert);
|
||||
|
||||
if (Buffer != NULL) {
|
||||
FreePool (Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if the specified EKUs are present in a signing certificate.
|
||||
|
||||
@param[in] SignerCert The certificate to check.
|
||||
@param[in] RequiredEKUs The EKUs to look for.
|
||||
@param[in] RequiredEKUsSize The number of EKUs
|
||||
@param[in] RequireAllPresent If TRUE, then all the specified EKUs
|
||||
must be present in the certificate.
|
||||
|
||||
@retval EFI_SUCCESS We successfully identified the signing type.
|
||||
@retval EFI_INVALID_PARAMETER A parameter was invalid.
|
||||
@retval EFI_NOT_FOUND One or more EKU's were not found in the signature.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
CheckEKUs (
|
||||
IN CONST mbedtls_x509_crt *SignerCert,
|
||||
IN CONST CHAR8 *RequiredEKUs[],
|
||||
IN CONST UINT32 RequiredEKUsSize,
|
||||
IN BOOLEAN RequireAllPresent
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 NumEkusFound;
|
||||
UINT32 Index;
|
||||
UINT8 *EKU;
|
||||
UINTN EkuLen;
|
||||
UINT8 CheckOid[20];
|
||||
UINT8 OidLen;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
NumEkusFound = 0;
|
||||
|
||||
if ((SignerCert == NULL) || (RequiredEKUs == NULL) || (RequiredEKUsSize == 0)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < RequiredEKUsSize; Index++) {
|
||||
//
|
||||
// Finding required EKU in Cert.
|
||||
//
|
||||
GetOidFromTxt (RequiredEKUs[Index], strlen (RequiredEKUs[Index]), CheckOid, &OidLen);
|
||||
|
||||
EKU = CheckOid;
|
||||
EkuLen = OidLen;
|
||||
|
||||
Status = IsEkuInCertificate (SignerCert, EKU, EkuLen);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
NumEkusFound++;
|
||||
if (!RequireAllPresent) {
|
||||
//
|
||||
// Found at least one, so we are done.
|
||||
//
|
||||
goto Exit;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Fail to find Eku in Cert
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (RequireAllPresent &&
|
||||
(NumEkusFound == RequiredEKUsSize))
|
||||
{
|
||||
//
|
||||
// Found all required EKUs in certificate.
|
||||
//
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function receives a PKCS#7 formatted signature blob,
|
||||
looks for the EKU SEQUENCE blob, and if found then looks
|
||||
for all the required EKUs. This function was created so that
|
||||
the Surface team can cut down on the number of Certificate
|
||||
Authorities (CA's) by checking EKU's on leaf signers for
|
||||
a specific product. This prevents one product's certificate
|
||||
from signing another product's firmware or unlock blobs.
|
||||
|
||||
Note that this function does not validate the certificate chain.
|
||||
That needs to be done before using this function.
|
||||
|
||||
@param[in] Pkcs7Signature The PKCS#7 signed information content block. An array
|
||||
containing the content block with both the signature,
|
||||
the signer's certificate, and any necessary intermediate
|
||||
certificates.
|
||||
@param[in] Pkcs7SignatureSize Number of bytes in Pkcs7Signature.
|
||||
@param[in] RequiredEKUs Array of null-terminated strings listing OIDs of
|
||||
required EKUs that must be present in the signature.
|
||||
@param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array.
|
||||
@param[in] RequireAllPresent If this is TRUE, then all of the specified EKU's
|
||||
must be present in the leaf signer. If it is
|
||||
FALSE, then we will succeed if we find any
|
||||
of the specified EKU's.
|
||||
|
||||
@retval EFI_SUCCESS The required EKUs were found in the signature.
|
||||
@retval EFI_INVALID_PARAMETER A parameter was invalid.
|
||||
@retval EFI_NOT_FOUND One or more EKU's were not found in the signature.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
VerifyEKUsInPkcs7Signature (
|
||||
IN CONST UINT8 *Pkcs7Signature,
|
||||
IN CONST UINT32 SignatureSize,
|
||||
IN CONST CHAR8 *RequiredEKUs[],
|
||||
IN CONST UINT32 RequiredEKUsSize,
|
||||
IN BOOLEAN RequireAllPresent
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
mbedtls_x509_crt Cert;
|
||||
UINT8 *Ptr;
|
||||
UINT8 *End;
|
||||
INT32 Len;
|
||||
UINTN ObjLen;
|
||||
UINT8 *OldEnd;
|
||||
|
||||
//
|
||||
// Check input parameter.
|
||||
//
|
||||
if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
return Status;
|
||||
}
|
||||
|
||||
mbedtls_x509_crt_init (&Cert);
|
||||
|
||||
Ptr = (UINT8 *)(UINTN)Pkcs7Signature;
|
||||
Len = (UINT32)SignatureSize;
|
||||
End = Ptr + Len;
|
||||
|
||||
// Cert
|
||||
if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// tbscert
|
||||
if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Ptr += ObjLen;
|
||||
// signature algo
|
||||
if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Ptr += ObjLen;
|
||||
// signature
|
||||
if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Ptr += ObjLen;
|
||||
OldEnd = Ptr;
|
||||
// Cert
|
||||
if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
End = Ptr + ObjLen;
|
||||
|
||||
// leaf Cert
|
||||
if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Ptr += ObjLen;
|
||||
|
||||
while ((Ptr != End) && (Ptr < End)) {
|
||||
if (IsCertSignerCert (OldEnd, Ptr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
OldEnd = Ptr;
|
||||
if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Ptr += ObjLen;
|
||||
}
|
||||
|
||||
if (Ptr != End) {
|
||||
return FALSE;
|
||||
} else {
|
||||
Ptr = End - ObjLen;
|
||||
}
|
||||
|
||||
// leaf Cert
|
||||
ObjLen += Ptr - OldEnd;
|
||||
Ptr = OldEnd;
|
||||
|
||||
if (mbedtls_x509_crt_parse_der (&Cert, Ptr, ObjLen) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Status = CheckEKUs (&Cert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Exit:
|
||||
//
|
||||
// Release Resources
|
||||
//
|
||||
mbedtls_x509_crt_free (&Cert);
|
||||
|
||||
return Status;
|
||||
}
|
Reference in New Issue
Block a user