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:
635
CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
Normal file
635
CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
Normal file
@@ -0,0 +1,635 @@
|
||||
/** @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/ecdh.h>
|
||||
|
||||
///
|
||||
/// Enough to store any signature generated by PKCS7
|
||||
///
|
||||
#define MAX_SIGNATURE_SIZE 1024
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidDigestAlgSha256[] = MBEDTLS_OID_DIGEST_ALG_SHA256;
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidPkcs1Rsa[] = MBEDTLS_OID_PKCS1_RSA;
|
||||
|
||||
/**
|
||||
Write DigestAlgorithmIdentifier.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] DigestType Digest Type
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteDigestAlgorithm (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
mbedtls_md_type_t DigestType
|
||||
)
|
||||
{
|
||||
UINT8 *OidPtr;
|
||||
UINTN OidLen;
|
||||
INT32 Ret;
|
||||
|
||||
Ret = mbedtls_oid_get_oid_by_md (DigestType, (CONST CHAR8 **)&OidPtr, &OidLen);
|
||||
if (Ret == 0) {
|
||||
return mbedtls_asn1_write_oid (Ptr, (CONST UINT8 *)Start, (CONST CHAR8 *)OidPtr, OidLen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
DigestAlgorithmIdentifiers ::=
|
||||
SET OF DigestAlgorithmIdentifier.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] DigestTypes Digest Type array.
|
||||
@param[in] Count The index for Digest Type.
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteDigestAlgorithmSet (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
mbedtls_md_type_t *DigestTypes,
|
||||
INTN Count
|
||||
)
|
||||
{
|
||||
INTN Idx;
|
||||
INT32 Len;
|
||||
INT32 Ret;
|
||||
|
||||
Len = 0;
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_null (Ptr, Start));
|
||||
|
||||
for (Idx = 0; Idx < Count; Idx++) {
|
||||
EDKII_ASN1_CHK_ADD (
|
||||
Len,
|
||||
MbedTlsPkcs7WriteDigestAlgorithm (Ptr, Start, DigestTypes[Idx])
|
||||
);
|
||||
}
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (
|
||||
Len,
|
||||
mbedtls_asn1_write_tag (
|
||||
Ptr,
|
||||
Start,
|
||||
(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
|
||||
)
|
||||
);
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (
|
||||
Len,
|
||||
mbedtls_asn1_write_tag (
|
||||
Ptr,
|
||||
Start,
|
||||
(MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)
|
||||
)
|
||||
);
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
ContentInfo ::= SEQUENCE {
|
||||
contentType ContentType,
|
||||
content
|
||||
[0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] Content ContentInfo.
|
||||
@param[in] ContentLen Size of ContentInfo.
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteContentInfo (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
UINT8 *Content,
|
||||
INTN ContentLen
|
||||
)
|
||||
{
|
||||
INT32 Ret;
|
||||
INT32 Len;
|
||||
|
||||
Len = 0;
|
||||
if (Content != NULL) {
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, Content, ContentLen));
|
||||
}
|
||||
|
||||
EDKII_ASN1_CHK_ADD (
|
||||
Len,
|
||||
mbedtls_asn1_write_oid (
|
||||
Ptr,
|
||||
Start,
|
||||
MBEDTLS_OID_PKCS7_DATA,
|
||||
sizeof (MBEDTLS_OID_PKCS7_DATA) - 1
|
||||
)
|
||||
);
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
certificates :: SET OF ExtendedCertificateOrCertificate,
|
||||
ExtendedCertificateOrCertificate ::= CHOICE {
|
||||
certificate Certificate -- x509,
|
||||
extendedCertificate[0] IMPLICIT ExtendedCertificate }.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] Cert Certificate.
|
||||
@param[in] OtherCerts Ohter Certificate.
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteCertificates (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
mbedtls_x509_crt *Cert,
|
||||
mbedtls_x509_crt *OtherCerts
|
||||
)
|
||||
{
|
||||
INT32 Ret;
|
||||
INT32 Len;
|
||||
mbedtls_x509_crt *TmpCert;
|
||||
|
||||
Len = 0;
|
||||
|
||||
/// Write OtherCerts
|
||||
TmpCert = OtherCerts;
|
||||
while (TmpCert != NULL) {
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, TmpCert->raw.p, TmpCert->raw.len));
|
||||
TmpCert = TmpCert->next;
|
||||
}
|
||||
|
||||
/// Write Cert
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, Cert->raw.p, Cert->raw.len));
|
||||
|
||||
/// Write NextContext
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
write Pkcs7 Int.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] SerialRaw SerialRaw.
|
||||
@param[in] SerialRawLen Size of SerialRaw.
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteInt (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
UINT8 *SerialRaw,
|
||||
INTN SerialRawLen
|
||||
)
|
||||
{
|
||||
INT32 Ret;
|
||||
UINT8 *Pt;
|
||||
INT32 Len;
|
||||
|
||||
Len = 0;
|
||||
Pt = SerialRaw + SerialRawLen;
|
||||
while (Pt > SerialRaw) {
|
||||
*--(*Ptr) = *--Pt;
|
||||
Len++;
|
||||
}
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_INTEGER));
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
write Pkcs7 Issuer And SerialNumber.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] Serial Serial.
|
||||
@param[in] SerialLen Size of Serial.
|
||||
@param[in] IssuerRaw IssuerRawLen.
|
||||
@param[in] IssuerRawLen Size of IssuerRawLen.
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteIssuerAndSerialNumber (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
UINT8 *Serial,
|
||||
INTN SerialLen,
|
||||
UINT8 *IssuerRaw,
|
||||
INTN IssuerRawLen
|
||||
)
|
||||
{
|
||||
INT32 Ret;
|
||||
INT32 Len;
|
||||
|
||||
Len = 0;
|
||||
EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteInt (Ptr, Start, Serial, SerialLen));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, IssuerRaw, IssuerRawLen));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
SignerInfo ::= SEQUENCE {
|
||||
version Version;
|
||||
issuerAndSerialNumber IssuerAndSerialNumber,
|
||||
digestAlgorithm DigestAlgorithmIdentifier,
|
||||
authenticatedAttributes
|
||||
[0] IMPLICIT Attributes OPTIONAL,
|
||||
digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
|
||||
encryptedDigest EncryptedDigest,
|
||||
unauthenticatedAttributes
|
||||
[1] IMPLICIT Attributes OPTIONAL.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] SignerInfo SignerInfo.
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteSignerInfo (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
MbedtlsPkcs7SignerInfo *SignerInfo
|
||||
)
|
||||
{
|
||||
INT32 Ret;
|
||||
INT32 Len;
|
||||
|
||||
Len = 0;
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, SignerInfo->Sig.p, SignerInfo->Sig.len));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, Start, (CONST CHAR8 *)SignerInfo->SigAlgIdentifier.p, SignerInfo->SigAlgIdentifier.len, 0));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, Start, (CONST CHAR8 *)SignerInfo->AlgIdentifier.p, SignerInfo->AlgIdentifier.len, 0));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteIssuerAndSerialNumber (Ptr, Start, SignerInfo->Serial.p, SignerInfo->Serial.len, SignerInfo->IssuerRaw.p, SignerInfo->IssuerRaw.len));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, SignerInfo->Version));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
write Pkcs7 Signers Info Set.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] SignersSet SignerInfo Set.
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteSignersInfoSet (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
MbedtlsPkcs7SignerInfo *SignersSet
|
||||
)
|
||||
{
|
||||
MbedtlsPkcs7SignerInfo *SignerInfo;
|
||||
INT32 Ret;
|
||||
INT32 Len;
|
||||
|
||||
SignerInfo = SignersSet;
|
||||
Len = 0;
|
||||
|
||||
while (SignerInfo != NULL) {
|
||||
EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignerInfo (Ptr, Start, SignerInfo));
|
||||
// move to next
|
||||
SignerInfo = SignerInfo->Next;
|
||||
}
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
Signed Data Type
|
||||
SignedData ::= SEQUENCE {
|
||||
version Version,
|
||||
digestAlgorithms DigestAlgorithmIdentifiers,
|
||||
contentInfo ContentInfo,
|
||||
certificates
|
||||
[0] IMPLICIT ExtendedCertificatesAndCertificates
|
||||
OPTIONAL,
|
||||
crls
|
||||
[1] IMPLICIT CertificateRevocationLists OPTIONAL,
|
||||
signerInfos SignerInfos }
|
||||
|
||||
DigestAlgorithmIdentifiers ::=
|
||||
SET OF DigestAlgorithmIdentifier
|
||||
|
||||
SignerInfos ::= SET OF SignerInfo.
|
||||
|
||||
@param[in, out] Ptr The reference to the current position pointer.
|
||||
@param[in] Start The start of the buffer, for bounds-checking.
|
||||
@param[in] Pkcs7 MbedtlsPkcs7
|
||||
|
||||
@retval number The number of bytes written to p on success.
|
||||
@retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
|
||||
**/
|
||||
STATIC
|
||||
INT32
|
||||
MbedTlsPkcs7WriteDer (
|
||||
UINT8 **Ptr,
|
||||
UINT8 *Start,
|
||||
MbedtlsPkcs7 *Pkcs7
|
||||
)
|
||||
{
|
||||
INT32 Ret;
|
||||
INT32 Len;
|
||||
mbedtls_md_type_t DigestAlg[1];
|
||||
|
||||
DigestAlg[0] = MBEDTLS_MD_SHA256;
|
||||
Len = 0;
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignersInfoSet (Ptr, Start, &(Pkcs7->SignedData.SignerInfos)));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteCertificates (Ptr, Start, &(Pkcs7->SignedData.Certificates), Pkcs7->SignedData.Certificates.next));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteContentInfo (Ptr, Start, NULL, 0));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteDigestAlgorithmSet (Ptr, Start, DigestAlg, 1));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, Pkcs7->SignedData.Version));
|
||||
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
|
||||
EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message
|
||||
Syntax Standard, version 1.5". This interface is only intended to be used for
|
||||
application to perform PKCS#7 functionality validation.
|
||||
|
||||
If this interface is not supported, then return FALSE.
|
||||
|
||||
@param[in] PrivateKey Pointer to the PEM-formatted private key data for
|
||||
data signing.
|
||||
@param[in] PrivateKeySize Size of the PEM private key data in bytes.
|
||||
@param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM
|
||||
key data.
|
||||
@param[in] InData Pointer to the content to be signed.
|
||||
@param[in] InDataSize Size of InData in bytes.
|
||||
@param[in] SignCert Pointer to signer's DER-encoded certificate to sign with.
|
||||
@param[in] OtherCerts Pointer to an optional additional set of certificates to
|
||||
include in the PKCS#7 signedData (e.g. any intermediate
|
||||
CAs in the chain).
|
||||
@param[out] SignedData Pointer to output PKCS#7 signedData. It's caller's
|
||||
responsibility to free the buffer with FreePool().
|
||||
@param[out] SignedDataSize Size of SignedData in bytes.
|
||||
|
||||
@retval TRUE PKCS#7 data signing succeeded.
|
||||
@retval FALSE PKCS#7 data signing failed.
|
||||
@retval FALSE This interface is not supported.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
Pkcs7Sign (
|
||||
IN CONST UINT8 *PrivateKey,
|
||||
IN UINTN PrivateKeySize,
|
||||
IN CONST UINT8 *KeyPassword,
|
||||
IN UINT8 *InData,
|
||||
IN UINTN InDataSize,
|
||||
IN UINT8 *SignCert,
|
||||
IN UINT8 *OtherCerts OPTIONAL,
|
||||
OUT UINT8 **SignedData,
|
||||
OUT UINTN *SignedDataSize
|
||||
)
|
||||
{
|
||||
BOOLEAN Status;
|
||||
INT32 Ret;
|
||||
mbedtls_pk_context Pkey;
|
||||
UINT8 HashValue[SHA256_DIGEST_SIZE];
|
||||
UINT8 Signature[MAX_SIGNATURE_SIZE];
|
||||
UINTN SignatureLen;
|
||||
UINT8 *NewPrivateKey;
|
||||
mbedtls_x509_crt *Crt;
|
||||
|
||||
MbedtlsPkcs7 Pkcs7;
|
||||
MbedtlsPkcs7SignerInfo SignerInfo;
|
||||
UINT8 *Buffer;
|
||||
INTN BufferSize;
|
||||
UINT8 *Ptr;
|
||||
INT32 Len;
|
||||
|
||||
//
|
||||
// Check input parameters.
|
||||
//
|
||||
if ((PrivateKey == NULL) || (KeyPassword == NULL) || (InData == NULL) ||
|
||||
(SignCert == NULL) || (SignedData == NULL) || (SignedDataSize == NULL) || (InDataSize > INT_MAX))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BufferSize = 4096;
|
||||
|
||||
SignatureLen = MAX_SIGNATURE_SIZE;
|
||||
Crt = (mbedtls_x509_crt *)SignCert;
|
||||
|
||||
NewPrivateKey = NULL;
|
||||
if (PrivateKey[PrivateKeySize - 1] != 0) {
|
||||
NewPrivateKey = AllocateZeroPool (PrivateKeySize + 1);
|
||||
if (NewPrivateKey == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);
|
||||
NewPrivateKey[PrivateKeySize] = 0;
|
||||
PrivateKeySize++;
|
||||
} else {
|
||||
NewPrivateKey = AllocateZeroPool (PrivateKeySize);
|
||||
if (NewPrivateKey == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);
|
||||
}
|
||||
|
||||
mbedtls_pk_init (&Pkey);
|
||||
Ret = mbedtls_pk_parse_key (
|
||||
&Pkey,
|
||||
NewPrivateKey,
|
||||
PrivateKeySize,
|
||||
KeyPassword,
|
||||
KeyPassword == NULL ? 0 : AsciiStrLen ((CONST CHAR8 *)KeyPassword),
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
if (Ret != 0) {
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
/// Calculate InData Digest
|
||||
ZeroMem (HashValue, SHA256_DIGEST_SIZE);
|
||||
Status = Sha256HashAll (InData, InDataSize, HashValue);
|
||||
if (!Status) {
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
/// Pk Sign
|
||||
ZeroMem (Signature, MAX_SIGNATURE_SIZE);
|
||||
Ret = mbedtls_pk_sign (
|
||||
&Pkey,
|
||||
MBEDTLS_MD_SHA256,
|
||||
HashValue,
|
||||
SHA256_DIGEST_SIZE,
|
||||
Signature,
|
||||
MAX_SIGNATURE_SIZE,
|
||||
&SignatureLen,
|
||||
MbedtlsRand,
|
||||
NULL
|
||||
);
|
||||
if (Ret != 0) {
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
ZeroMem (&Pkcs7, sizeof (MbedtlsPkcs7));
|
||||
Pkcs7.SignedData.Version = 1;
|
||||
|
||||
Crt->next = (mbedtls_x509_crt *)OtherCerts;
|
||||
Pkcs7.SignedData.Certificates = *Crt;
|
||||
|
||||
SignerInfo.Next = NULL;
|
||||
SignerInfo.Sig.p = Signature;
|
||||
SignerInfo.Sig.len = SignatureLen;
|
||||
SignerInfo.Version = 1;
|
||||
SignerInfo.AlgIdentifier.p = MbedtlsOidDigestAlgSha256;
|
||||
SignerInfo.AlgIdentifier.len = sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1;
|
||||
if (mbedtls_pk_get_type (&Pkey) == MBEDTLS_PK_RSA) {
|
||||
SignerInfo.SigAlgIdentifier.p = MbedtlsOidPkcs1Rsa;
|
||||
SignerInfo.SigAlgIdentifier.len = sizeof (MBEDTLS_OID_PKCS1_RSA) - 1;
|
||||
} else {
|
||||
Ret = mbedtls_oid_get_oid_by_sig_alg (MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA256, (CONST CHAR8 **)&SignerInfo.SigAlgIdentifier.p, &SignerInfo.SigAlgIdentifier.len);
|
||||
if (Ret != 0) {
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
SignerInfo.Serial = ((mbedtls_x509_crt *)SignCert)->serial;
|
||||
SignerInfo.IssuerRaw = ((mbedtls_x509_crt *)SignCert)->issuer_raw;
|
||||
Pkcs7.SignedData.SignerInfos = SignerInfo;
|
||||
|
||||
Buffer = AllocateZeroPool (BufferSize);
|
||||
if (Buffer == NULL) {
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
Ptr = Buffer + BufferSize;
|
||||
Len = MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7);
|
||||
|
||||
/// Enlarge buffer if buffer is too small
|
||||
while (Len == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
|
||||
BufferSize = BufferSize * 2;
|
||||
Ptr = Buffer + BufferSize;
|
||||
FreePool (Buffer);
|
||||
Buffer = AllocateZeroPool (BufferSize);
|
||||
if (Buffer == NULL) {
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
Ptr = Buffer + BufferSize;
|
||||
Len = MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7);
|
||||
}
|
||||
|
||||
if (Len <= 0) {
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
*SignedData = AllocateZeroPool (Len);
|
||||
if (*SignedData == NULL) {
|
||||
Status = FALSE;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
*SignedDataSize = Len;
|
||||
CopyMem (*SignedData, Ptr, Len);
|
||||
Status = TRUE;
|
||||
|
||||
Cleanup:
|
||||
if (&Pkey != NULL) {
|
||||
mbedtls_pk_free (&Pkey);
|
||||
}
|
||||
|
||||
if (NewPrivateKey != NULL) {
|
||||
memset (NewPrivateKey, 0, PrivateKeySize);
|
||||
FreePool (NewPrivateKey);
|
||||
}
|
||||
|
||||
if (Buffer != NULL) {
|
||||
memset (Buffer, 0, BufferSize);
|
||||
FreePool (Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
Reference in New Issue
Block a user