On 3 November 2015 at 07:38, Qin Long <[email protected]> wrote:
> Adding one new API (Pkcs7GetCertificatesList) to retrieve and sort all
> embedded certificates from Pkcs7 signedData. This new API will provide
> the support for UEFI 2.5 Secure-Boot AuditMode feature.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Qin Long <[email protected]>
This patch breaks the CLANG35 build for AARCH64. Please see the patch
in the other thread.
> ---
> CryptoPkg/Include/Library/BaseCryptLib.h | 30 +++
> .../Library/BaseCryptLib/Pk/CryptPkcs7Verify.c | 288
> +++++++++++++++++++++
> .../Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c | 34 +++
> .../Pk/CryptPkcs7VerifyNull.c | 34 +++
> 4 files changed, 386 insertions(+)
>
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> b/CryptoPkg/Include/Library/BaseCryptLib.h
> index 95b75c9..390e302 100644
> --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> @@ -1985,6 +1985,36 @@ Pkcs7FreeSigners (
> );
>
> /**
> + 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] SingerChainCerts Pointer to the certificates list chained to
> signer's
> + certificate. It's caller's responsiblity to
> free the buffer.
> + @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
> + responsiblity to free the buffer.
> + @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
> + );
> +
> +/**
> 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.
> diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Verify.c
> b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Verify.c
> index fafcf1b..541156e 100644
> --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Verify.c
> +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Verify.c
> @@ -428,6 +428,294 @@ Pkcs7FreeSigners (
> }
>
> /**
> + 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] SingerChainCerts Pointer to the certificates list chained to
> signer's
> + certificate. It's caller's responsiblity to
> free the buffer.
> + @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
> + responsiblity to free the buffer.
> + @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
> + )
> +{
> + BOOLEAN Status;
> + UINT8 *NewP7Data;
> + UINTN NewP7Length;
> + BOOLEAN Wrapped;
> + UINT8 Index;
> + PKCS7 *Pkcs7;
> + X509_STORE_CTX CertCtx;
> + STACK_OF(X509) *Signers;
> + X509 *Signer;
> + X509 *Cert;
> + X509 *TempCert;
> + X509 *Issuer;
> + UINT8 *CertBuf;
> + UINT8 *OldBuf;
> + UINTN BufferSize;
> + UINTN OldSize;
> + UINT8 *SingleCert;
> + UINTN CertSize;
> +
> + //
> + // Initializations
> + //
> + Status = FALSE;
> + NewP7Data = NULL;
> + Pkcs7 = NULL;
> + Cert = NULL;
> + TempCert = NULL;
> + SingleCert = NULL;
> + CertBuf = NULL;
> + OldBuf = NULL;
> + Signers = NULL;
> +
> + //
> + // Parameter Checking
> + //
> + if ((P7Data == NULL) || (SignerChainCerts == NULL) || (ChainLength ==
> NULL) ||
> + (UnchainCerts == NULL) || (UnchainLength == NULL) || (P7Length >
> INT_MAX)) {
> + return Status;
> + }
> +
> + *SignerChainCerts = NULL;
> + *ChainLength = 0;
> + *UnchainCerts = NULL;
> + *UnchainLength = 0;
> +
> + //
> + // Construct a new PKCS#7 data wrapping with ContentInfo structure if
> needed.
> + //
> + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &NewP7Data,
> &NewP7Length);
> + if (!Status || (NewP7Length > INT_MAX)) {
> + goto _Error;
> + }
> +
> + //
> + // Decodes PKCS#7 SignedData
> + //
> + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &NewP7Data, (int)
> NewP7Length);
> + if ((Pkcs7 == NULL) || (!PKCS7_type_is_signed (Pkcs7))) {
> + goto _Error;
> + }
> +
> + //
> + // Obtains Signer's Certificate from PKCS#7 data
> + // NOTE: Authenticode supports only one signer. So SignerInfos should
> include
> + // only one singer's certificate.
> + //
> + Signers = PKCS7_get0_signers (Pkcs7, NULL, PKCS7_BINARY);
> + if ((Signers == NULL) || (sk_X509_num (Signers) != 1)) {
> + goto _Error;
> + }
> + Signer = sk_X509_value (Signers, 0);
> +
> + if (!X509_STORE_CTX_init (&CertCtx, NULL, Signer, Pkcs7->d.sign->cert)) {
> + goto _Error;
> + }
> + //
> + // Initialize Chained & Untrusted stack
> + //
> + if (CertCtx.chain == NULL) {
> + if (((CertCtx.chain = sk_X509_new_null ()) == NULL) ||
> + (!sk_X509_push (CertCtx.chain, CertCtx.cert))) {
> + goto _Error;
> + }
> + }
> + sk_X509_delete_ptr (CertCtx.untrusted, Signer);
> +
> + //
> + // Build certificates stack chained from Signer's certificate.
> + //
> + Cert = Signer;
> + for (; ;) {
> + //
> + // Self-Issue checking
> + //
> + if (CertCtx.check_issued (&CertCtx, Cert, Cert)) {
> + break;
> + }
> +
> + //
> + // Found the issuer of the current certificate
> + //
> + if (CertCtx.untrusted != NULL) {
> + Issuer = NULL;
> + for (Index = 0; Index < sk_X509_num (CertCtx.untrusted); Index++) {
> + TempCert = sk_X509_value (CertCtx.untrusted, Index);
> + if (CertCtx.check_issued (&CertCtx, Cert, TempCert)) {
> + Issuer = TempCert;
> + break;
> + }
> + }
> + if (Issuer != NULL) {
> + if (!sk_X509_push (CertCtx.chain, Issuer)) {
> + goto _Error;
> + }
> + sk_X509_delete_ptr (CertCtx.untrusted, Issuer);
> +
> + Cert = Issuer;
> + continue;
> + }
> + }
> +
> + break;
> + }
> +
> + //
> + // Converts Chained and Untrusted Certificate to Certificate Buffer in
> following format:
> + // UINT8 CertNumber;
> + // UINT32 Cert1Length;
> + // UINT8 Cert1[];
> + // UINT32 Cert2Length;
> + // UINT8 Cert2[];
> + // ...
> + // UINT32 CertnLength;
> + // UINT8 Certn[];
> + //
> +
> + if (CertCtx.chain != NULL) {
> + BufferSize = sizeof (UINT8);
> + OldSize = BufferSize;
> + CertBuf = NULL;
> +
> + for (Index = 0; ; Index++) {
> + Status = X509PopCertificate (CertCtx.chain, &SingleCert, &CertSize);
> + if (!Status) {
> + break;
> + }
> +
> + OldSize = BufferSize;
> + OldBuf = CertBuf;
> + BufferSize = OldSize + CertSize + sizeof (UINT32);
> + CertBuf = malloc (BufferSize);
> +
> + if (CertBuf == NULL) {
> + Status = FALSE;
> + goto _Error;
> + }
> + if (OldBuf != NULL) {
> + CopyMem (CertBuf, OldBuf, OldSize);
> + free (OldBuf);
> + OldBuf = NULL;
> + }
> +
> + WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize);
> + CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize);
> +
> + free (SingleCert);
> + SingleCert = NULL;
> + }
> +
> + if (CertBuf != NULL) {
> + //
> + // Update CertNumber.
> + //
> + CertBuf[0] = Index;
> +
> + *SignerChainCerts = CertBuf;
> + *ChainLength = BufferSize;
> + }
> + }
> +
> + if (CertCtx.untrusted != NULL) {
> + BufferSize = sizeof (UINT8);
> + OldSize = BufferSize;
> + CertBuf = NULL;
> +
> + for (Index = 0; ; Index++) {
> + Status = X509PopCertificate (CertCtx.untrusted, &SingleCert,
> &CertSize);
> + if (!Status) {
> + break;
> + }
> +
> + OldSize = BufferSize;
> + OldBuf = CertBuf;
> + BufferSize = OldSize + CertSize + sizeof (UINT32);
> + CertBuf = malloc (BufferSize);
> +
> + if (CertBuf == NULL) {
> + Status = FALSE;
> + goto _Error;
> + }
> + if (OldBuf != NULL) {
> + CopyMem (CertBuf, OldBuf, OldSize);
> + free (OldBuf);
> + OldBuf = NULL;
> + }
> +
> + WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize);
> + CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize);
> +
> + free (SingleCert);
> + SingleCert = NULL;
> + }
> +
> + if (CertBuf != NULL) {
> + //
> + // Update CertNumber.
> + //
> + CertBuf[0] = Index;
> +
> + *UnchainCerts = CertBuf;
> + *UnchainLength = BufferSize;
> + }
> + }
> +
> + Status = TRUE;
> +
> +_Error:
> + //
> + // Release Resources.
> + //
> + if (!Wrapped && (NewP7Data != NULL)) {
> + free (NewP7Data);
> + }
> +
> + if (Pkcs7 != NULL) {
> + PKCS7_free (Pkcs7);
> + }
> + sk_X509_free (Signers);
> +
> + X509_STORE_CTX_cleanup (&CertCtx);
> +
> + if (SingleCert != NULL) {
> + free (SingleCert);
> + }
> +
> + if (OldBuf != NULL) {
> + free (OldBuf);
> + }
> +
> + if (!Status && (CertBuf != NULL)) {
> + free (CertBuf);
> + *SignerChainCerts = NULL;
> + *UnchainCerts = NULL;
> + }
> +
> + return Status;
> +}
> +
> +/**
> Verifies the validility 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.
> diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c
> b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c
> index 09b92c7..b9affe4 100644
> --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c
> +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c
> @@ -67,6 +67,40 @@ Pkcs7FreeSigners (
> }
>
> /**
> + 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] SingerChainCerts Pointer to the certificates list chained to
> signer's
> + certificate. It's caller's responsiblity to
> free the buffer.
> + @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
> + responsiblity to free the buffer.
> + @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;
> +}
> +
> +/**
> Verifies the validility 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.
> diff --git
> a/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptPkcs7VerifyNull.c
>
> b/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptPkcs7VerifyNull.c
> index 09b92c7..b9affe4 100644
> ---
> a/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptPkcs7VerifyNull.c
> +++
> b/CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptPkcs7VerifyNull.c
> @@ -67,6 +67,40 @@ Pkcs7FreeSigners (
> }
>
> /**
> + 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] SingerChainCerts Pointer to the certificates list chained to
> signer's
> + certificate. It's caller's responsiblity to
> free the buffer.
> + @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
> + responsiblity to free the buffer.
> + @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;
> +}
> +
> +/**
> Verifies the validility 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.
> --
> 2.5.1.windows.1
>
> _______________________________________________
> edk2-devel mailing list
> [email protected]
> https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel