IN UINT8 *Certs\r
);\r
\r
+/**\r
+ Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:\r
+ Cryptographic Message Syntax Standard", and outputs two certificate lists chained and\r
+ unchained to the signer's certificates.\r
+ The input signed data could be wrapped in a ContentInfo structure.\r
+\r
+ @param[in] P7Data Pointer to the PKCS#7 message.\r
+ @param[in] P7Length Length of the PKCS#7 message in bytes.\r
+ @param[out] SingerChainCerts Pointer to the certificates list chained to signer's\r
+ certificate. It's caller's responsiblity to free the buffer.\r
+ @param[out] ChainLength Length of the chained certificates list buffer in bytes.\r
+ @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's\r
+ responsiblity to free the buffer.\r
+ @param[out] UnchainLength Length of the unchained certificates list buffer in bytes.\r
+\r
+ @retval TRUE The operation is finished successfully.\r
+ @retval FALSE Error occurs during the operation.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+Pkcs7GetCertificatesList (\r
+ IN CONST UINT8 *P7Data,\r
+ IN UINTN P7Length,\r
+ OUT UINT8 **SignerChainCerts,\r
+ OUT UINTN *ChainLength,\r
+ OUT UINT8 **UnchainCerts,\r
+ OUT UINTN *UnchainLength\r
+ );\r
+\r
/**\r
Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message\r
Syntax Standard, version 1.5". This interface is only intended to be used for\r
free (Certs);\r
}\r
\r
+/**\r
+ Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:\r
+ Cryptographic Message Syntax Standard", and outputs two certificate lists chained and\r
+ unchained to the signer's certificates.\r
+ The input signed data could be wrapped in a ContentInfo structure.\r
+\r
+ @param[in] P7Data Pointer to the PKCS#7 message.\r
+ @param[in] P7Length Length of the PKCS#7 message in bytes.\r
+ @param[out] SingerChainCerts Pointer to the certificates list chained to signer's\r
+ certificate. It's caller's responsiblity to free the buffer.\r
+ @param[out] ChainLength Length of the chained certificates list buffer in bytes.\r
+ @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's\r
+ responsiblity to free the buffer.\r
+ @param[out] UnchainLength Length of the unchained certificates list buffer in bytes.\r
+\r
+ @retval TRUE The operation is finished successfully.\r
+ @retval FALSE Error occurs during the operation.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+Pkcs7GetCertificatesList (\r
+ IN CONST UINT8 *P7Data,\r
+ IN UINTN P7Length,\r
+ OUT UINT8 **SignerChainCerts,\r
+ OUT UINTN *ChainLength,\r
+ OUT UINT8 **UnchainCerts,\r
+ OUT UINTN *UnchainLength\r
+ )\r
+{\r
+ BOOLEAN Status;\r
+ UINT8 *NewP7Data;\r
+ UINTN NewP7Length;\r
+ BOOLEAN Wrapped;\r
+ UINT8 Index;\r
+ PKCS7 *Pkcs7;\r
+ X509_STORE_CTX CertCtx;\r
+ STACK_OF(X509) *Signers;\r
+ X509 *Signer;\r
+ X509 *Cert;\r
+ X509 *TempCert;\r
+ X509 *Issuer;\r
+ UINT8 *CertBuf;\r
+ UINT8 *OldBuf;\r
+ UINTN BufferSize;\r
+ UINTN OldSize;\r
+ UINT8 *SingleCert;\r
+ UINTN CertSize;\r
+\r
+ //\r
+ // Initializations\r
+ //\r
+ Status = FALSE;\r
+ NewP7Data = NULL;\r
+ Pkcs7 = NULL;\r
+ Cert = NULL;\r
+ TempCert = NULL;\r
+ SingleCert = NULL;\r
+ CertBuf = NULL;\r
+ OldBuf = NULL;\r
+ Signers = NULL;\r
+\r
+ //\r
+ // Parameter Checking\r
+ //\r
+ if ((P7Data == NULL) || (SignerChainCerts == NULL) || (ChainLength == NULL) ||\r
+ (UnchainCerts == NULL) || (UnchainLength == NULL) || (P7Length > INT_MAX)) {\r
+ return Status;\r
+ }\r
+\r
+ *SignerChainCerts = NULL;\r
+ *ChainLength = 0;\r
+ *UnchainCerts = NULL;\r
+ *UnchainLength = 0;\r
+\r
+ //\r
+ // Construct a new PKCS#7 data wrapping with ContentInfo structure if needed.\r
+ //\r
+ Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &NewP7Data, &NewP7Length);\r
+ if (!Status || (NewP7Length > INT_MAX)) {\r
+ goto _Error;\r
+ }\r
+\r
+ //\r
+ // Decodes PKCS#7 SignedData\r
+ //\r
+ Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &NewP7Data, (int) NewP7Length);\r
+ if ((Pkcs7 == NULL) || (!PKCS7_type_is_signed (Pkcs7))) {\r
+ goto _Error;\r
+ }\r
+\r
+ //\r
+ // Obtains Signer's Certificate from PKCS#7 data\r
+ // NOTE: Only one signer case will be handled in this function, which means SignerInfos\r
+ // should include only one singer's certificate.\r
+ //\r
+ Signers = PKCS7_get0_signers (Pkcs7, NULL, PKCS7_BINARY);\r
+ if ((Signers == NULL) || (sk_X509_num (Signers) != 1)) {\r
+ goto _Error;\r
+ }\r
+ Signer = sk_X509_value (Signers, 0);\r
+\r
+ if (!X509_STORE_CTX_init (&CertCtx, NULL, Signer, Pkcs7->d.sign->cert)) {\r
+ goto _Error;\r
+ }\r
+ //\r
+ // Initialize Chained & Untrusted stack\r
+ //\r
+ if (CertCtx.chain == NULL) {\r
+ if (((CertCtx.chain = sk_X509_new_null ()) == NULL) ||\r
+ (!sk_X509_push (CertCtx.chain, CertCtx.cert))) {\r
+ goto _Error;\r
+ }\r
+ }\r
+ sk_X509_delete_ptr (CertCtx.untrusted, Signer);\r
+\r
+ //\r
+ // Build certificates stack chained from Signer's certificate.\r
+ //\r
+ Cert = Signer;\r
+ for (; ;) {\r
+ //\r
+ // Self-Issue checking\r
+ //\r
+ if (CertCtx.check_issued (&CertCtx, Cert, Cert)) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Found the issuer of the current certificate\r
+ //\r
+ if (CertCtx.untrusted != NULL) {\r
+ Issuer = NULL;\r
+ for (Index = 0; Index < sk_X509_num (CertCtx.untrusted); Index++) {\r
+ TempCert = sk_X509_value (CertCtx.untrusted, Index);\r
+ if (CertCtx.check_issued (&CertCtx, Cert, TempCert)) {\r
+ Issuer = TempCert;\r
+ break;\r
+ }\r
+ }\r
+ if (Issuer != NULL) {\r
+ if (!sk_X509_push (CertCtx.chain, Issuer)) {\r
+ goto _Error;\r
+ }\r
+ sk_X509_delete_ptr (CertCtx.untrusted, Issuer);\r
+\r
+ Cert = Issuer;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Converts Chained and Untrusted Certificate to Certificate Buffer in following format:\r
+ // UINT8 CertNumber;\r
+ // UINT32 Cert1Length;\r
+ // UINT8 Cert1[];\r
+ // UINT32 Cert2Length;\r
+ // UINT8 Cert2[];\r
+ // ...\r
+ // UINT32 CertnLength;\r
+ // UINT8 Certn[];\r
+ //\r
+\r
+ if (CertCtx.chain != NULL) {\r
+ BufferSize = sizeof (UINT8);\r
+ OldSize = BufferSize;\r
+ CertBuf = NULL;\r
+\r
+ for (Index = 0; ; Index++) {\r
+ Status = X509PopCertificate (CertCtx.chain, &SingleCert, &CertSize);\r
+ if (!Status) {\r
+ break;\r
+ }\r
+\r
+ OldSize = BufferSize;\r
+ OldBuf = CertBuf;\r
+ BufferSize = OldSize + CertSize + sizeof (UINT32);\r
+ CertBuf = malloc (BufferSize);\r
+\r
+ if (CertBuf == NULL) {\r
+ Status = FALSE;\r
+ goto _Error;\r
+ }\r
+ if (OldBuf != NULL) {\r
+ CopyMem (CertBuf, OldBuf, OldSize);\r
+ free (OldBuf);\r
+ OldBuf = NULL;\r
+ }\r
+\r
+ WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize);\r
+ CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize);\r
+\r
+ free (SingleCert);\r
+ SingleCert = NULL;\r
+ }\r
+\r
+ if (CertBuf != NULL) {\r
+ //\r
+ // Update CertNumber.\r
+ //\r
+ CertBuf[0] = Index;\r
+\r
+ *SignerChainCerts = CertBuf;\r
+ *ChainLength = BufferSize;\r
+ }\r
+ }\r
+\r
+ if (CertCtx.untrusted != NULL) {\r
+ BufferSize = sizeof (UINT8);\r
+ OldSize = BufferSize;\r
+ CertBuf = NULL;\r
+\r
+ for (Index = 0; ; Index++) {\r
+ Status = X509PopCertificate (CertCtx.untrusted, &SingleCert, &CertSize);\r
+ if (!Status) {\r
+ break;\r
+ }\r
+\r
+ OldSize = BufferSize;\r
+ OldBuf = CertBuf;\r
+ BufferSize = OldSize + CertSize + sizeof (UINT32);\r
+ CertBuf = malloc (BufferSize);\r
+\r
+ if (CertBuf == NULL) {\r
+ Status = FALSE;\r
+ goto _Error;\r
+ }\r
+ if (OldBuf != NULL) {\r
+ CopyMem (CertBuf, OldBuf, OldSize);\r
+ free (OldBuf);\r
+ OldBuf = NULL;\r
+ }\r
+\r
+ WriteUnaligned32 ((UINT32 *) (CertBuf + OldSize), (UINT32) CertSize);\r
+ CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, CertSize);\r
+\r
+ free (SingleCert);\r
+ SingleCert = NULL;\r
+ }\r
+\r
+ if (CertBuf != NULL) {\r
+ //\r
+ // Update CertNumber.\r
+ //\r
+ CertBuf[0] = Index;\r
+\r
+ *UnchainCerts = CertBuf;\r
+ *UnchainLength = BufferSize;\r
+ }\r
+ }\r
+\r
+ Status = TRUE;\r
+\r
+_Error:\r
+ //\r
+ // Release Resources.\r
+ //\r
+ if (!Wrapped && (NewP7Data != NULL)) {\r
+ free (NewP7Data);\r
+ }\r
+\r
+ if (Pkcs7 != NULL) {\r
+ PKCS7_free (Pkcs7);\r
+ }\r
+ sk_X509_free (Signers);\r
+\r
+ X509_STORE_CTX_cleanup (&CertCtx);\r
+\r
+ if (SingleCert != NULL) {\r
+ free (SingleCert);\r
+ }\r
+\r
+ if (OldBuf != NULL) {\r
+ free (OldBuf);\r
+ }\r
+\r
+ if (!Status && (CertBuf != NULL)) {\r
+ free (CertBuf);\r
+ *SignerChainCerts = NULL;\r
+ *UnchainCerts = NULL;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
/**\r
Verifies the validility of a PKCS#7 signed data as described in "PKCS #7:\r
Cryptographic Message Syntax Standard". The input signed data could be wrapped\r
ASSERT (FALSE);\r
}\r
\r
+/**\r
+ Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:\r
+ Cryptographic Message Syntax Standard", and outputs two certificate lists chained and\r
+ unchained to the signer's certificates.\r
+ The input signed data could be wrapped in a ContentInfo structure.\r
+\r
+ @param[in] P7Data Pointer to the PKCS#7 message.\r
+ @param[in] P7Length Length of the PKCS#7 message in bytes.\r
+ @param[out] SingerChainCerts Pointer to the certificates list chained to signer's\r
+ certificate. It's caller's responsiblity to free the buffer.\r
+ @param[out] ChainLength Length of the chained certificates list buffer in bytes.\r
+ @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's\r
+ responsiblity to free the buffer.\r
+ @param[out] UnchainLength Length of the unchained certificates list buffer in bytes.\r
+\r
+ @retval TRUE The operation is finished successfully.\r
+ @retval FALSE Error occurs during the operation.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+Pkcs7GetCertificatesList (\r
+ IN CONST UINT8 *P7Data,\r
+ IN UINTN P7Length,\r
+ OUT UINT8 **SignerChainCerts,\r
+ OUT UINTN *ChainLength,\r
+ OUT UINT8 **UnchainCerts,\r
+ OUT UINTN *UnchainLength\r
+ )\r
+{\r
+ ASSERT (FALSE);\r
+ return FALSE;\r
+}\r
+\r
/**\r
Verifies the validility of a PKCS#7 signed data as described in "PKCS #7:\r
Cryptographic Message Syntax Standard". The input signed data could be wrapped\r
ASSERT (FALSE);\r
}\r
\r
+/**\r
+ Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:\r
+ Cryptographic Message Syntax Standard", and outputs two certificate lists chained and\r
+ unchained to the signer's certificates.\r
+ The input signed data could be wrapped in a ContentInfo structure.\r
+\r
+ @param[in] P7Data Pointer to the PKCS#7 message.\r
+ @param[in] P7Length Length of the PKCS#7 message in bytes.\r
+ @param[out] SingerChainCerts Pointer to the certificates list chained to signer's\r
+ certificate. It's caller's responsiblity to free the buffer.\r
+ @param[out] ChainLength Length of the chained certificates list buffer in bytes.\r
+ @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's\r
+ responsiblity to free the buffer.\r
+ @param[out] UnchainLength Length of the unchained certificates list buffer in bytes.\r
+\r
+ @retval TRUE The operation is finished successfully.\r
+ @retval FALSE Error occurs during the operation.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+Pkcs7GetCertificatesList (\r
+ IN CONST UINT8 *P7Data,\r
+ IN UINTN P7Length,\r
+ OUT UINT8 **SignerChainCerts,\r
+ OUT UINTN *ChainLength,\r
+ OUT UINT8 **UnchainCerts,\r
+ OUT UINTN *UnchainLength\r
+ )\r
+{\r
+ ASSERT (FALSE);\r
+ return FALSE;\r
+}\r
+\r
/**\r
Verifies the validility of a PKCS#7 signed data as described in "PKCS #7:\r
Cryptographic Message Syntax Standard". The input signed data could be wrapped\r