| /** @file | |
| PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper | |
| Implementation over mbedtls. | |
| RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites | |
| FIPS 186-4 - Digital Signature Standard (DSS) | |
| Copyright (c) 2024, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "CryptPkcs7Internal.h" | |
| #include <mbedtls/pkcs7.h> | |
| /* Profile for backward compatibility. Allows RSA 1024, unlike the default | |
| profile. */ | |
| STATIC mbedtls_x509_crt_profile gCompatProfile = | |
| { | |
| /* Hashes from SHA-256 and above. Note that this selection | |
| * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ | |
| #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA1) | | |
| #endif | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) | | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) | | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512), | |
| 0xFFFFFFF, /* Any PK alg */ | |
| /* Curves at or above 128-bit security level. Note that this selection | |
| * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) | | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) | | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) | | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) | | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) | | |
| MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) | | |
| 0, | |
| 1024, | |
| }; | |
| /** | |
| Init MbedtlsPkcs7. | |
| @param[in] Pkcs7 MbedtlsPkcs7. | |
| **/ | |
| STATIC | |
| VOID | |
| MbedTlsPkcs7Init ( | |
| MbedtlsPkcs7 *Pkcs7 | |
| ) | |
| { | |
| ZeroMem (Pkcs7, sizeof (MbedtlsPkcs7)); | |
| } | |
| /** | |
| Get Pkcs7 Next Content Len. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] End The end of the buffer. | |
| @param[out] Len MbedtlsPkcs7 Content Len. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedTlsPkcs7GetNextContentLen ( | |
| UINT8 **Ptr, | |
| UINT8 *End, | |
| UINTN *Len | |
| ) | |
| { | |
| INT32 Ret; | |
| Ret = mbedtls_asn1_get_tag (Ptr, End, Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC); | |
| return Ret; | |
| } | |
| /** | |
| Get Pkcs7 Version.. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] End The end of the buffer. | |
| @param[out] Ver MbedtlsPkcs7 Version. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedTlsPkcs7GetVersion ( | |
| UINT8 **Ptr, | |
| UINT8 *End, | |
| INT32 *Ver | |
| ) | |
| { | |
| INT32 Ret; | |
| Ret = mbedtls_asn1_get_int (Ptr, End, Ver); | |
| return Ret; | |
| } | |
| /** | |
| ContentInfo ::= SEQUENCE { | |
| contentType ContentType, | |
| content | |
| [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] End The end of the buffer. | |
| @param[out] Pkcs7 MbedtlsPkcs7. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| Pkcs7GetContentInfoType ( | |
| UINT8 **Ptr, | |
| UINT8 *End, | |
| mbedtls_asn1_buf *Pkcs7 | |
| ) | |
| { | |
| UINTN Len; | |
| int Ret; | |
| Len = 0; | |
| Ret = mbedtls_asn1_get_tag ( | |
| Ptr, | |
| End, | |
| &Len, | |
| MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE | |
| ); | |
| if (Ret == 0) { | |
| Ret = mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OID); | |
| } | |
| if (Ret == 0) { | |
| Pkcs7->tag = MBEDTLS_ASN1_OID; | |
| Pkcs7->len = Len; | |
| Pkcs7->p = *Ptr; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| DigestAlgorithmIdentifier ::= AlgorithmIdentifier. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] End The end of the buffer. | |
| @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedTlsPkcs7GetDigestAlgorithm ( | |
| UINT8 **Ptr, | |
| UINT8 *End, | |
| mbedtls_x509_buf *Alg | |
| ) | |
| { | |
| INT32 Ret; | |
| Ret = mbedtls_asn1_get_alg_null (Ptr, End, Alg); | |
| return Ret; | |
| } | |
| /** | |
| DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] End The end of the buffer. | |
| @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedTlsPkcs7GetDigestAlgorithmSet ( | |
| UINT8 **Ptr, | |
| UINT8 *End, | |
| mbedtls_x509_buf *Alg | |
| ) | |
| { | |
| UINTN Len; | |
| INT32 Ret; | |
| Len = 0; | |
| Ret = mbedtls_asn1_get_tag ( | |
| Ptr, | |
| End, | |
| &Len, | |
| MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET | |
| ); | |
| if (Ret == 0) { | |
| End = *Ptr + Len; | |
| // assume only one digest algorithm | |
| Ret = mbedtls_asn1_get_alg_null (Ptr, End, Alg); | |
| } | |
| return Ret; | |
| } | |
| /** | |
| certificates :: SET OF ExtendedCertificateOrCertificate, | |
| ExtendedCertificateOrCertificate ::= CHOICE { | |
| certificate Certificate -- x509, | |
| extendedCertificate[0] IMPLICIT ExtendedCertificate }. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] Plen The buffer len. | |
| @param[out] Certs mbedtls_x509_crt cert. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedTlsPkcs7GetCertificates ( | |
| UINT8 **Ptr, | |
| INTN Plen, | |
| mbedtls_x509_crt *Certs | |
| ) | |
| { | |
| INT32 Ret; | |
| Ret = mbedtls_x509_crt_parse (Certs, *Ptr, Plen); | |
| return Ret; | |
| } | |
| /** | |
| EncryptedDigest ::= OCTET STRING. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] End The end of the buffer. | |
| @param[out] Signature Signature. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| Pkcs7GetSignature ( | |
| UINT8 **Ptr, | |
| UINT8 *End, | |
| mbedtls_asn1_buf *Signature | |
| ) | |
| { | |
| INT32 Ret; | |
| UINTN Len; | |
| Len = 0; | |
| Ret = mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OCTET_STRING); | |
| if (Ret == 0) { | |
| Signature->tag = MBEDTLS_ASN1_OCTET_STRING; | |
| Signature->len = Len; | |
| Signature->p = *Ptr; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| SignerInfo ::= SEQUENCE { | |
| version Version; | |
| issuerAndSerialNumber IssuerAndSerialNumber, | |
| digestAlgorithm DigestAlgorithmIdentifier, | |
| authenticatedAttributes | |
| [0] IMPLICIT Attributes OPTIONAL, | |
| digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier, | |
| encryptedDigest EncryptedDigest, | |
| unauthenticatedAttributes | |
| [1] IMPLICIT Attributes OPTIONAL. | |
| @param[in] Ptr The start of the buffer. | |
| @param[in] End The end of the buffer. | |
| @param[out] SignersSet MbedtlsPkcs7SignerInfo. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedTlsPkcs7GetSignersInfoSet ( | |
| UINT8 **Ptr, | |
| UINT8 *End, | |
| MbedtlsPkcs7SignerInfo *SignersSet | |
| ) | |
| { | |
| UINT8 *EndSet; | |
| INT32 Ret; | |
| UINTN Len; | |
| UINT8 *TempP; | |
| Len = 0; | |
| Ret = mbedtls_asn1_get_tag ( | |
| Ptr, | |
| End, | |
| &Len, | |
| MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET | |
| ); | |
| if (Ret == 0) { | |
| EndSet = *Ptr + Len; | |
| Ret = mbedtls_asn1_get_tag ( | |
| Ptr, | |
| EndSet, | |
| &Len, | |
| MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE | |
| ); | |
| } | |
| if (Ret == 0) { | |
| Ret = mbedtls_asn1_get_int (Ptr, EndSet, &SignersSet->Version); | |
| } | |
| if (Ret == 0) { | |
| Ret = mbedtls_asn1_get_tag ( | |
| Ptr, | |
| EndSet, | |
| &Len, | |
| MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE | |
| ); | |
| } | |
| if (Ret == 0) { | |
| SignersSet->IssuerRaw.p = *Ptr; | |
| Ret = mbedtls_asn1_get_tag ( | |
| Ptr, | |
| EndSet, | |
| &Len, | |
| MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE | |
| ); | |
| } | |
| if (Ret == 0) { | |
| Ret = mbedtls_x509_get_name (Ptr, *Ptr + Len, &SignersSet->Issuer); | |
| } | |
| if (Ret == 0) { | |
| SignersSet->IssuerRaw.len = *Ptr - SignersSet->IssuerRaw.p; | |
| Ret = mbedtls_x509_get_serial (Ptr, EndSet, &SignersSet->Serial); | |
| } | |
| if (Ret == 0) { | |
| Ret = MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->AlgIdentifier); | |
| } | |
| // OPTIONAL AuthenticatedAttributes | |
| if (Ret == 0) { | |
| TempP = *Ptr; | |
| if (mbedtls_asn1_get_tag (&TempP, EndSet, &Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) { | |
| SignersSet->AuthAttr.len = Len + (TempP - *Ptr); | |
| SignersSet->AuthAttr.p = *Ptr; | |
| *Ptr = TempP + Len; | |
| } else { | |
| SignersSet->AuthAttr.p = NULL; | |
| } | |
| } | |
| if (Ret == 0) { | |
| Ret = MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->SigAlgIdentifier); | |
| } | |
| if (Ret == 0) { | |
| Ret = Pkcs7GetSignature (Ptr, End, &SignersSet->Sig); | |
| } | |
| if (Ret == 0) { | |
| SignersSet->Next = NULL; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| SignedData ::= SEQUENCE { | |
| version Version, | |
| digestAlgorithms DigestAlgorithmIdentifiers, | |
| contentInfo ContentInfo, | |
| certificates | |
| [0] IMPLICIT ExtendedCertificatesAndCertificates | |
| OPTIONAL, | |
| crls | |
| [0] IMPLICIT CertificateRevocationLists OPTIONAL, | |
| signerInfos SignerInfos }. | |
| @param[in] Buffer The start of the buffer. | |
| @param[in] BufferLen The len the buffer. | |
| @param[out] SignedData MbedtlsPkcs7SignedData. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| Pkcs7GetSignedData ( | |
| UINT8 *Buffer, | |
| INTN BufferLen, | |
| MbedtlsPkcs7SignedData *SignedData | |
| ) | |
| { | |
| UINT8 *Ptr; | |
| UINT8 *End; | |
| UINTN Len; | |
| INT32 Ret; | |
| UINT8 *CertP; | |
| UINTN CertLen; | |
| UINT8 *OldCertP; | |
| UINTN TotalCertLen; | |
| mbedtls_x509_crt *MoreCert; | |
| UINT8 CertNum; | |
| mbedtls_x509_crt *LastCert; | |
| mbedtls_x509_crt *TempCrt; | |
| Len = 0; | |
| Ptr = Buffer; | |
| End = Buffer + BufferLen; | |
| MoreCert = NULL; | |
| Ret = mbedtls_asn1_get_tag ( | |
| &Ptr, | |
| End, | |
| &Len, | |
| MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE | |
| ); | |
| if (Ret == 0) { | |
| // version | |
| Ret = MbedTlsPkcs7GetVersion (&Ptr, End, &SignedData->Version); | |
| } | |
| if ((Ret == 0) && (SignedData->Version != 1)) { | |
| Ret = -1; | |
| } | |
| if (Ret == 0) { | |
| // digest algorithm | |
| Ret = MbedTlsPkcs7GetDigestAlgorithmSet ( | |
| &Ptr, | |
| End, | |
| &SignedData->DigestAlgorithms | |
| ); | |
| } | |
| if (Ret == 0) { | |
| if ( | |
| #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES | |
| ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA1) - 1) && | |
| (CompareMem ( | |
| SignedData->DigestAlgorithms.p, | |
| MBEDTLS_OID_DIGEST_ALG_SHA1, | |
| SignedData->DigestAlgorithms.len | |
| ) == 0)) || | |
| #endif | |
| ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1) && | |
| (CompareMem ( | |
| SignedData->DigestAlgorithms.p, | |
| MBEDTLS_OID_DIGEST_ALG_SHA256, | |
| SignedData->DigestAlgorithms.len | |
| ) == 0)) || | |
| ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA384) - 1) && | |
| (CompareMem ( | |
| SignedData->DigestAlgorithms.p, | |
| MBEDTLS_OID_DIGEST_ALG_SHA384, | |
| SignedData->DigestAlgorithms.len | |
| ) == 0)) || | |
| ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA512) - 1) && | |
| (CompareMem ( | |
| SignedData->DigestAlgorithms.p, | |
| MBEDTLS_OID_DIGEST_ALG_SHA512, | |
| SignedData->DigestAlgorithms.len | |
| ) == 0))) | |
| { | |
| Ret = 0; | |
| } else { | |
| Ret = -1; | |
| } | |
| } | |
| if (Ret == 0) { | |
| Ret = Pkcs7GetContentInfoType (&Ptr, End, &SignedData->ContentInfo.Oid); | |
| } | |
| if (Ret == 0) { | |
| // move to next | |
| Ptr = Ptr + SignedData->ContentInfo.Oid.len; | |
| Ret = MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len); | |
| CertP = Ptr + Len; | |
| // move to actual cert, if there are more [0] | |
| if (MbedTlsPkcs7GetNextContentLen (&CertP, End, &CertLen) == 0) { | |
| Len = CertLen; | |
| Ptr = CertP; | |
| } | |
| } | |
| // certificates: may have many certs | |
| CertP = Ptr; | |
| TotalCertLen = 0; | |
| MoreCert = &SignedData->Certificates; | |
| CertNum = 0; | |
| while (TotalCertLen < Len) { | |
| OldCertP = CertP; | |
| Ret = mbedtls_asn1_get_tag (&CertP, End, &CertLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); | |
| if (Ret != 0) { | |
| goto Out; | |
| } | |
| // cert total len | |
| CertLen = CertLen + (CertP - OldCertP); | |
| // move to next cert | |
| CertP = OldCertP + CertLen; | |
| // change TotalCertLen | |
| TotalCertLen += CertLen; | |
| mbedtls_x509_crt_init (MoreCert); | |
| Ret = MbedTlsPkcs7GetCertificates (&OldCertP, CertLen, MoreCert); | |
| if (Ret != 0) { | |
| goto Out; | |
| } | |
| CertNum++; | |
| MoreCert->next = mbedtls_calloc (1, sizeof (mbedtls_x509_crt)); | |
| MoreCert = MoreCert->next; | |
| } | |
| if (TotalCertLen != Len) { | |
| Ret = -1; | |
| goto Out; | |
| } | |
| LastCert = &(SignedData->Certificates); | |
| while (CertNum--) { | |
| if (CertNum == 0) { | |
| LastCert->next = NULL; | |
| break; | |
| } else { | |
| LastCert = LastCert->next; | |
| } | |
| } | |
| // signers info | |
| if (Ret == 0) { | |
| Ptr = Ptr + Len; | |
| Ret = MbedTlsPkcs7GetSignersInfoSet (&Ptr, End, &SignedData->SignerInfos); | |
| } | |
| Out: | |
| if (Ret == 0) { | |
| if (MoreCert != NULL) { | |
| mbedtls_x509_crt_free (MoreCert); | |
| MoreCert = NULL; | |
| } | |
| } else { | |
| if (SignedData->Certificates.next != NULL) { | |
| TempCrt = SignedData->Certificates.next; | |
| mbedtls_x509_crt_free (TempCrt); | |
| } | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Parse MbedtlsPkcs7 to Der format. | |
| @param[in] Buffer The start of the buffer. | |
| @param[in] BufferLen The len the buffer. | |
| @param[out] Pkcs7 MbedtlsPkcs7. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedtlsPkcs7ParseDer ( | |
| CONST UINT8 *Buffer, | |
| INTN BufferLen, | |
| MbedtlsPkcs7 *Pkcs7 | |
| ) | |
| { | |
| UINT8 *Ptr; | |
| UINT8 *End; | |
| UINTN Len; | |
| INT32 Ret; | |
| if (Pkcs7 == NULL) { | |
| return -1; | |
| } | |
| Len = 0; | |
| Ptr = (UINT8 *)Buffer; | |
| End = Ptr + BufferLen; | |
| Ret = Pkcs7GetContentInfoType (&Ptr, End, &Pkcs7->ContentTypeOid); | |
| if (Ret != 0) { | |
| goto Out; | |
| } | |
| if ((CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DATA, Pkcs7->ContentTypeOid.len) == 0) || | |
| (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, Pkcs7->ContentTypeOid.len) == 0) || | |
| (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || | |
| (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) || | |
| (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DIGESTED_DATA, Pkcs7->ContentTypeOid.len) == 0)) | |
| { | |
| // Invalid PKCS7 data type; | |
| Ret = -1; | |
| goto Out; | |
| } | |
| if (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA, Pkcs7->ContentTypeOid.len) != 0) { | |
| // Invalid PKCS7 data type; | |
| Ret = -1; | |
| goto Out; | |
| } | |
| // Content type is SignedData | |
| Ptr = Ptr + Pkcs7->ContentTypeOid.len; | |
| Ret = MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len); | |
| if (Ret != 0) { | |
| goto Out; | |
| } | |
| Ret = Pkcs7GetSignedData (Ptr, Len, &Pkcs7->SignedData); | |
| if (Ret != 0) { | |
| goto Out; | |
| } | |
| Out: | |
| return Ret; | |
| } | |
| /** | |
| MbedtlsPkcs7 verify MbedtlsPkcs7SignerInfo. | |
| @param[in] SignerInfo MbedtlsPkcs7 SignerInfo. | |
| @param[in] Cert cert. | |
| @param[in] Data Pointer for data. | |
| @param[in] DataLen The len the buffer. | |
| @retval 0 Success. | |
| @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure. | |
| **/ | |
| STATIC | |
| INT32 | |
| MbedtlsPkcs7SignedDataVerifySigners ( | |
| MbedtlsPkcs7SignerInfo *SignerInfo, | |
| mbedtls_x509_crt *Cert, | |
| CONST UINT8 *Data, | |
| INTN DataLen | |
| ) | |
| { | |
| INT32 Ret; | |
| UINT8 Hash[MBEDTLS_MD_MAX_SIZE]; | |
| mbedtls_pk_context Pk; | |
| CONST mbedtls_md_info_t *MdInfo; | |
| INTN HashLen; | |
| UINT8 TempAuthAttr; | |
| Pk = Cert->pk; | |
| ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); | |
| // all the hash algo | |
| #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES | |
| MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA1); | |
| HashLen = mbedtls_md_get_size (MdInfo); | |
| mbedtls_md (MdInfo, Data, DataLen, Hash); | |
| if (SignerInfo->AuthAttr.p != NULL) { | |
| TempAuthAttr = *(SignerInfo->AuthAttr.p); | |
| *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; | |
| mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); | |
| // Restore content | |
| *(SignerInfo->AuthAttr.p) = TempAuthAttr; | |
| } | |
| Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA1, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); | |
| if (Ret == 0) { | |
| return Ret; | |
| } | |
| #endif | |
| MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256); | |
| HashLen = mbedtls_md_get_size (MdInfo); | |
| ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); | |
| mbedtls_md (MdInfo, Data, DataLen, Hash); | |
| if (SignerInfo->AuthAttr.p != NULL) { | |
| TempAuthAttr = *(SignerInfo->AuthAttr.p); | |
| *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; | |
| mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); | |
| // Restore content | |
| *(SignerInfo->AuthAttr.p) = TempAuthAttr; | |
| } | |
| Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA256, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); | |
| if (Ret == 0) { | |
| return Ret; | |
| } | |
| MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA384); | |
| HashLen = mbedtls_md_get_size (MdInfo); | |
| ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); | |
| mbedtls_md (MdInfo, Data, DataLen, Hash); | |
| if (SignerInfo->AuthAttr.p != NULL) { | |
| TempAuthAttr = *(SignerInfo->AuthAttr.p); | |
| *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; | |
| mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); | |
| // Restore content | |
| *(SignerInfo->AuthAttr.p) = TempAuthAttr; | |
| } | |
| Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA384, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); | |
| if (Ret == 0) { | |
| return Ret; | |
| } | |
| MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA512); | |
| HashLen = mbedtls_md_get_size (MdInfo); | |
| ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE); | |
| mbedtls_md (MdInfo, Data, DataLen, Hash); | |
| if (SignerInfo->AuthAttr.p != NULL) { | |
| TempAuthAttr = *(SignerInfo->AuthAttr.p); | |
| *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET; | |
| mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash); | |
| // Restore content | |
| *(SignerInfo->AuthAttr.p) = TempAuthAttr; | |
| } | |
| Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA512, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len); | |
| if (Ret == 0) { | |
| return Ret; | |
| } | |
| return Ret; | |
| } | |
| /** | |
| Find signer cert in MbedtlsPkcs7SignerInfo. | |
| @param[in] SignerInfo MbedtlsPkcs7 SignerInfo. | |
| @param[in] Certs MbedtlsPkcs7 SignerInfo certs. | |
| @retval cert Signer Cert. | |
| **/ | |
| STATIC | |
| mbedtls_x509_crt * | |
| MbedTlsPkcs7FindSignerCert ( | |
| MbedtlsPkcs7SignerInfo *SignerInfo, | |
| mbedtls_x509_crt *Certs | |
| ) | |
| { | |
| mbedtls_x509_crt *Cert; | |
| Cert = Certs; | |
| while (Cert != NULL) { | |
| if ((Cert->serial.p == NULL) || (Cert->issuer_raw.p == NULL)) { | |
| return NULL; | |
| } | |
| if ((Cert->issuer_raw.len == SignerInfo->IssuerRaw.len) && | |
| (CompareMem (Cert->issuer_raw.p, SignerInfo->IssuerRaw.p, Cert->issuer_raw.len) == 0) && | |
| (Cert->serial.len == SignerInfo->Serial.len) && | |
| (CompareMem (Cert->serial.p, SignerInfo->Serial.p, Cert->serial.len) == 0)) | |
| { | |
| break; | |
| } | |
| Cert = Cert->next; | |
| } | |
| return Cert; | |
| } | |
| /** | |
| verify cert. | |
| @param[in] Ca CA cert. | |
| @param[in] CaCrl CRL. | |
| @param[in] End Cert which need be verified. | |
| @retval TRUE Verify successfully. | |
| @retval FALSE Verify failed. | |
| **/ | |
| STATIC | |
| BOOLEAN | |
| MbedTlsPkcs7VerifyCert ( | |
| mbedtls_x509_crt *Ca, | |
| mbedtls_x509_crl *CaCrl, | |
| mbedtls_x509_crt *End | |
| ) | |
| { | |
| INT32 Ret; | |
| UINT32 VFlag; | |
| mbedtls_x509_crt_profile Profile; | |
| VFlag = 0; | |
| CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile)); | |
| Ret = mbedtls_x509_crt_verify_with_profile (End, Ca, CaCrl, &Profile, NULL, &VFlag, NULL, NULL); | |
| return Ret == 0; | |
| } | |
| /** | |
| verify cert chain. | |
| @param[in] Pkcs7 MbedtlsPkcs7. | |
| @param[in] Ca CA cert. | |
| @param[in] End Cert which need be verified. | |
| @retval TRUE Verify successfully. | |
| @retval FALSE Verify failed. | |
| **/ | |
| STATIC | |
| BOOLEAN | |
| MbedTlsPkcs7VerifyCertChain ( | |
| MbedtlsPkcs7 *Pkcs7, | |
| mbedtls_x509_crt *Ca, | |
| mbedtls_x509_crt *End | |
| ) | |
| { | |
| mbedtls_x509_crt *AllCert; | |
| mbedtls_x509_crt *InterCert; | |
| AllCert = &(Pkcs7->SignedData.Certificates); | |
| InterCert = NULL; | |
| while (AllCert != NULL) { | |
| if ((AllCert->next == End) && (MbedTlsPkcs7VerifyCert (AllCert, NULL, End))) { | |
| InterCert = AllCert; | |
| break; | |
| } | |
| AllCert = AllCert->next; | |
| } | |
| if (InterCert == NULL) { | |
| return FALSE; | |
| } | |
| if (MbedTlsPkcs7VerifyCert (Ca, &(Pkcs7->SignedData.Crls), InterCert)) { | |
| return TRUE; | |
| } else { | |
| return MbedTlsPkcs7VerifyCertChain (Pkcs7, Ca, InterCert); | |
| } | |
| } | |
| /** | |
| MbedTlsPkcs7 Verify SignedData. | |
| @param[in] Pkcs7 MbedtlsPkcs7. | |
| @param[in] TrustCert CA cert. | |
| @param[in] Data Pointer for data. | |
| @param[in] DataLen The len the buffer. | |
| @retval TRUE Verify successfully. | |
| @retval FALSE Verify failed. | |
| **/ | |
| STATIC | |
| BOOLEAN | |
| MbedTlsPkcs7SignedDataVerify ( | |
| MbedtlsPkcs7 *Pkcs7, | |
| mbedtls_x509_crt *TrustCert, | |
| CONST UINT8 *Data, | |
| INTN DataLen | |
| ) | |
| { | |
| MbedtlsPkcs7SignerInfo *SignerInfo; | |
| mbedtls_x509_crt *Cert; | |
| mbedtls_x509_crt *AllCert; | |
| BOOLEAN Result; | |
| SignerInfo = &(Pkcs7->SignedData.SignerInfos); | |
| Result = TRUE; | |
| // | |
| // Traverse signers and verify each signers | |
| // | |
| while (SignerInfo != NULL) { | |
| Result = FALSE; | |
| // 1. Find signers cert | |
| Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7->SignedData.Certificates)); | |
| if (Cert != NULL) { | |
| // 2. Check signer cert is trusted by trustCert | |
| if (MbedTlsPkcs7VerifyCert (TrustCert, &(Pkcs7->SignedData.Crls), Cert)) { | |
| // root cert verify pass | |
| Result = TRUE; | |
| } else { | |
| if (MbedTlsPkcs7VerifyCertChain (Pkcs7, TrustCert, Cert)) { | |
| Result = TRUE; | |
| } else { | |
| Result = FALSE; | |
| } | |
| } | |
| if (Result == TRUE) { | |
| // 3. Check signed data | |
| AllCert = &(Pkcs7->SignedData.Certificates); | |
| while (AllCert != NULL) { | |
| if (MbedtlsPkcs7SignedDataVerifySigners (SignerInfo, AllCert, Data, DataLen) == 0) { | |
| return TRUE; | |
| } | |
| AllCert = AllCert->next; | |
| } | |
| Result = FALSE; | |
| } | |
| } | |
| // move to next | |
| SignerInfo = SignerInfo->Next; | |
| } | |
| return Result; | |
| } | |
| /** | |
| Check input P7Data is a wrapped ContentInfo structure or not. If not construct | |
| a new structure to wrap P7Data. | |
| Caution: This function may receive untrusted input. | |
| UEFI Authenticated Variable is external input, so this function will do basic | |
| check for PKCS#7 data structure. | |
| @param[in] P7Data Pointer to the PKCS#7 message to verify. | |
| @param[in] P7Length Length of the PKCS#7 message in bytes. | |
| @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise | |
| return FALSE. | |
| @param[out] WrapData If return status of this function is TRUE: | |
| 1) when WrapFlag is TRUE, pointer to P7Data. | |
| 2) when WrapFlag is FALSE, pointer to a new ContentInfo | |
| structure. It's caller's responsibility to free this | |
| buffer. | |
| @param[out] WrapDataSize Length of ContentInfo structure in bytes. | |
| @retval TRUE The operation is finished successfully. | |
| @retval FALSE The operation is failed due to lack of resources. | |
| **/ | |
| BOOLEAN | |
| WrapPkcs7Data ( | |
| IN CONST UINT8 *P7Data, | |
| IN UINTN P7Length, | |
| OUT BOOLEAN *WrapFlag, | |
| OUT UINT8 **WrapData, | |
| OUT UINTN *WrapDataSize | |
| ) | |
| { | |
| BOOLEAN Wrapped; | |
| UINT8 *SignedData; | |
| // | |
| // Check whether input P7Data is a wrapped ContentInfo structure or not. | |
| // | |
| Wrapped = FALSE; | |
| if ((P7Data[4] == MBEDTLS_ASN1_OID) && (P7Data[5] == sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1)) { | |
| if (CompareMem (P7Data + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1) == 0) { | |
| if ((P7Data[15] == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) && (P7Data[16] == 0x82)) { | |
| Wrapped = TRUE; | |
| } | |
| } | |
| } | |
| if (Wrapped) { | |
| *WrapData = (UINT8 *)P7Data; | |
| *WrapDataSize = P7Length; | |
| } else { | |
| // | |
| // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes. | |
| // | |
| *WrapDataSize = P7Length + 19; | |
| *WrapData = AllocateZeroPool (*WrapDataSize); | |
| if (*WrapData == NULL) { | |
| *WrapFlag = Wrapped; | |
| return FALSE; | |
| } | |
| SignedData = *WrapData; | |
| // | |
| // Part1: 0x30, 0x82. | |
| // | |
| SignedData[0] = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE; | |
| SignedData[1] = 0x82; | |
| // | |
| // Part2: Length1 = P7Length + 19 - 4, in big endian. | |
| // | |
| SignedData[2] = (UINT8)(((UINT16)(*WrapDataSize - 4)) >> 8); | |
| SignedData[3] = (UINT8)(((UINT16)(*WrapDataSize - 4)) & 0xff); | |
| // | |
| // Part3: 0x06, 0x09. | |
| // | |
| SignedData[4] = MBEDTLS_ASN1_OID; | |
| SignedData[5] = sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1; | |
| // | |
| // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02. | |
| // | |
| CopyMem (SignedData + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1); | |
| // | |
| // Part5: 0xA0, 0x82. | |
| // | |
| SignedData[15] = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC; | |
| SignedData[16] = 0x82; | |
| // | |
| // Part6: Length2 = P7Length, in big endian. | |
| // | |
| SignedData[17] = (UINT8)(((UINT16)P7Length) >> 8); | |
| SignedData[18] = (UINT8)(((UINT16)P7Length) & 0xff); | |
| // | |
| // Part7: P7Data. | |
| // | |
| CopyMem (SignedData + 19, P7Data, P7Length); | |
| } | |
| *WrapFlag = Wrapped; | |
| return TRUE; | |
| } | |
| /** | |
| Verifies the validity of a PKCS#7 signed data as described in "PKCS #7: | |
| Cryptographic Message Syntax Standard". The input signed data could be wrapped | |
| in a ContentInfo structure. | |
| If P7Data, TrustedCert or InData is NULL, then return FALSE. | |
| If P7Length, CertLength or DataLength overflow, then return FALSE. | |
| If this interface is not supported, then return FALSE. | |
| @param[in] P7Data Pointer to the PKCS#7 message to verify. | |
| @param[in] P7Length Length of the PKCS#7 message in bytes. | |
| @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which | |
| is used for certificate chain verification. | |
| @param[in] CertLength Length of the trusted certificate in bytes. | |
| @param[in] InData Pointer to the content to be verified. | |
| @param[in] DataLength Length of InData in bytes. | |
| @retval TRUE The specified PKCS#7 signed data is valid. | |
| @retval FALSE Invalid PKCS#7 signed data. | |
| @retval FALSE This interface is not supported. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| Pkcs7Verify ( | |
| IN CONST UINT8 *P7Data, | |
| IN UINTN P7Length, | |
| IN CONST UINT8 *TrustedCert, | |
| IN UINTN CertLength, | |
| IN CONST UINT8 *InData, | |
| IN UINTN DataLength | |
| ) | |
| { | |
| BOOLEAN Status; | |
| UINT8 *WrapData; | |
| UINTN WrapDataSize; | |
| BOOLEAN Wrapped; | |
| MbedtlsPkcs7 Pkcs7; | |
| INT32 Ret; | |
| mbedtls_x509_crt Crt; | |
| mbedtls_x509_crt *TempCrt; | |
| // | |
| // Check input parameters. | |
| // | |
| if ((P7Data == NULL) || (TrustedCert == NULL) || (InData == NULL) || | |
| (P7Length > INT_MAX) || (CertLength > INT_MAX) || (DataLength > INT_MAX)) | |
| { | |
| return FALSE; | |
| } | |
| Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize); | |
| if (!Status) { | |
| return FALSE; | |
| } | |
| Status = FALSE; | |
| MbedTlsPkcs7Init (&Pkcs7); | |
| mbedtls_x509_crt_init (&Crt); | |
| Ret = MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7); | |
| if (Ret != 0) { | |
| goto Cleanup; | |
| } | |
| Ret = mbedtls_x509_crt_parse_der (&Crt, TrustedCert, CertLength); | |
| if (Ret != 0) { | |
| goto Cleanup; | |
| } | |
| Status = MbedTlsPkcs7SignedDataVerify (&Pkcs7, &Crt, InData, (INT32)DataLength); | |
| Cleanup: | |
| if (&Crt != NULL) { | |
| mbedtls_x509_crt_free (&Crt); | |
| } | |
| if (Pkcs7.SignedData.Certificates.next != NULL) { | |
| TempCrt = Pkcs7.SignedData.Certificates.next; | |
| mbedtls_x509_crt_free (TempCrt); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Wrap function to use free() to free allocated memory for certificates. | |
| @param[in] Certs Pointer to the certificates to be freed. | |
| **/ | |
| VOID | |
| EFIAPI | |
| Pkcs7FreeSigners ( | |
| IN UINT8 *Certs | |
| ) | |
| { | |
| if (Certs == NULL) { | |
| return; | |
| } | |
| FreePool (Certs); | |
| } | |
| /** | |
| Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7: | |
| Cryptographic Message Syntax Standard". The input signed data could be wrapped | |
| in a ContentInfo structure. | |
| If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then | |
| return FALSE. If P7Length overflow, then return FALSE. | |
| Caution: This function may receive untrusted input. | |
| UEFI Authenticated Variable is external input, so this function will do basic | |
| check for PKCS#7 data structure. | |
| @param[in] P7Data Pointer to the PKCS#7 message to verify. | |
| @param[in] P7Length Length of the PKCS#7 message in bytes. | |
| @param[out] CertStack Pointer to Signer's certificates retrieved from P7Data. | |
| It's caller's responsibility to free the buffer with | |
| Pkcs7FreeSigners(). | |
| This data structure is EFI_CERT_STACK type. | |
| @param[out] StackLength Length of signer's certificates in bytes. | |
| @param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates. | |
| It's caller's responsibility to free the buffer with | |
| Pkcs7FreeSigners(). | |
| @param[out] CertLength Length of the trusted certificate in bytes. | |
| @retval TRUE The operation is finished successfully. | |
| @retval FALSE Error occurs during the operation. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| Pkcs7GetSigners ( | |
| IN CONST UINT8 *P7Data, | |
| IN UINTN P7Length, | |
| OUT UINT8 **CertStack, | |
| OUT UINTN *StackLength, | |
| OUT UINT8 **TrustedCert, | |
| OUT UINTN *CertLength | |
| ) | |
| { | |
| MbedtlsPkcs7SignerInfo *SignerInfo; | |
| mbedtls_x509_crt *Cert; | |
| MbedtlsPkcs7 Pkcs7; | |
| BOOLEAN Status; | |
| UINT8 *WrapData; | |
| UINTN WrapDataSize; | |
| BOOLEAN Wrapped; | |
| mbedtls_x509_crt *TempCrt; | |
| UINTN CertSize; | |
| UINT8 Index; | |
| UINT8 *CertBuf; | |
| UINT8 *OldBuf; | |
| UINTN BufferSize; | |
| UINTN OldSize; | |
| if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) || | |
| (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX)) | |
| { | |
| return FALSE; | |
| } | |
| Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize); | |
| if (!Status) { | |
| return FALSE; | |
| } | |
| Status = FALSE; | |
| CertBuf = NULL; | |
| OldBuf = NULL; | |
| Cert = NULL; | |
| MbedTlsPkcs7Init (&Pkcs7); | |
| if (MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7) != 0) { | |
| goto _Exit; | |
| } | |
| SignerInfo = &(Pkcs7.SignedData.SignerInfos); | |
| // | |
| // Traverse each signers | |
| // | |
| // Convert CertStack to buffer in following format: | |
| // UINT8 CertNumber; | |
| // UINT32 Cert1Length; | |
| // UINT8 Cert1[]; | |
| // UINT32 Cert2Length; | |
| // UINT8 Cert2[]; | |
| // ... | |
| // UINT32 CertnLength; | |
| // UINT8 Certn[]; | |
| // | |
| BufferSize = sizeof (UINT8); | |
| OldSize = BufferSize; | |
| Index = 0; | |
| while (SignerInfo != NULL) { | |
| // Find signers cert | |
| Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7.SignedData.Certificates)); | |
| if (Cert == NULL) { | |
| goto _Exit; | |
| } | |
| CertSize = Cert->raw.len; | |
| OldSize = BufferSize; | |
| OldBuf = CertBuf; | |
| BufferSize = OldSize + CertSize + sizeof (UINT32); | |
| CertBuf = AllocateZeroPool (BufferSize); | |
| if (CertBuf == NULL) { | |
| goto _Exit; | |
| } | |
| if (OldBuf != NULL) { | |
| CopyMem (CertBuf, OldBuf, OldSize); | |
| FreePool (OldBuf); | |
| OldBuf = NULL; | |
| } | |
| WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)CertSize); | |
| CopyMem (CertBuf + OldSize + sizeof (UINT32), Cert->raw.p, CertSize); | |
| Index++; | |
| // move to next | |
| SignerInfo = SignerInfo->Next; | |
| } | |
| if (CertBuf != NULL) { | |
| // | |
| // Update CertNumber. | |
| // | |
| CertBuf[0] = Index; | |
| *CertLength = BufferSize - OldSize - sizeof (UINT32); | |
| *TrustedCert = AllocateZeroPool (*CertLength); | |
| if (*TrustedCert == NULL) { | |
| goto _Exit; | |
| } | |
| CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength); | |
| *CertStack = CertBuf; | |
| *StackLength = BufferSize; | |
| Status = TRUE; | |
| } | |
| _Exit: | |
| // | |
| // Release Resources | |
| // | |
| if (!Status && (CertBuf != NULL)) { | |
| FreePool (CertBuf); | |
| *CertStack = NULL; | |
| } | |
| if (Status) { | |
| if (Pkcs7.SignedData.Certificates.next != NULL) { | |
| TempCrt = Pkcs7.SignedData.Certificates.next; | |
| mbedtls_x509_crt_free (TempCrt); | |
| } | |
| } | |
| if (OldBuf != NULL) { | |
| FreePool (OldBuf); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7: | |
| Cryptographic Message Syntax Standard", and outputs two certificate lists chained and | |
| unchained to the signer's certificates. | |
| The input signed data could be wrapped in a ContentInfo structure. | |
| @param[in] P7Data Pointer to the PKCS#7 message. | |
| @param[in] P7Length Length of the PKCS#7 message in bytes. | |
| @param[out] SignerChainCerts Pointer to the certificates list chained to signer's | |
| certificate. It's caller's responsibility to free the buffer | |
| with Pkcs7FreeSigners(). | |
| This data structure is EFI_CERT_STACK type. | |
| @param[out] ChainLength Length of the chained certificates list buffer in bytes. | |
| @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's | |
| responsibility to free the buffer with Pkcs7FreeSigners(). | |
| This data structure is EFI_CERT_STACK type. | |
| @param[out] UnchainLength Length of the unchained certificates list buffer in bytes. | |
| @retval TRUE The operation is finished successfully. | |
| @retval FALSE Error occurs during the operation. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| Pkcs7GetCertificatesList ( | |
| IN CONST UINT8 *P7Data, | |
| IN UINTN P7Length, | |
| OUT UINT8 **SignerChainCerts, | |
| OUT UINTN *ChainLength, | |
| OUT UINT8 **UnchainCerts, | |
| OUT UINTN *UnchainLength | |
| ) | |
| { | |
| ASSERT (FALSE); | |
| return FALSE; | |
| } |