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

Reply via email to