+\r
+/**\r
+ Construct a X509 object from DER-encoded certificate data.\r
+\r
+ If Cert is NULL, then ASSERT().\r
+ If SingleX509Cert is NULL, then ASSERT().\r
+\r
+ @param[in] Cert Pointer to the DER-encoded certificate data.\r
+ @param[in] CertSize The size of certificate data in bytes.\r
+ @param[out] SingleX509Cert The generated X509 object.\r
+\r
+ @retval TRUE The X509 object generation succeeded.\r
+ @retval FALSE The operation failed.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+X509ConstructCertificate (\r
+ IN CONST UINT8 *Cert,\r
+ IN UINTN CertSize,\r
+ OUT UINT8 **SingleX509Cert\r
+ )\r
+{\r
+ BIO *CertBio;\r
+ X509 *X509Cert;\r
+ BOOLEAN Status;\r
+\r
+ //\r
+ // ASSERT if Cert is NULL or SingleX509Cert is NULL.\r
+ //\r
+ ASSERT (Cert != NULL);\r
+ ASSERT (SingleX509Cert != NULL);\r
+\r
+ Status = FALSE;\r
+\r
+ //\r
+ // Read DER-encoded X509 Certificate and Construct X509 object.\r
+ //\r
+ CertBio = BIO_new (BIO_s_mem ());\r
+ BIO_write (CertBio, Cert, (int) CertSize);\r
+ if (CertBio == NULL) {\r
+ goto _Exit;\r
+ }\r
+ X509Cert = d2i_X509_bio (CertBio, NULL);\r
+ if (X509Cert == NULL) {\r
+ goto _Exit;\r
+ }\r
+\r
+ *SingleX509Cert = (UINT8 *) X509Cert;\r
+ Status = TRUE;\r
+\r
+_Exit:\r
+ //\r
+ // Release Resources.\r
+ //\r
+ BIO_free (CertBio);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Construct a X509 stack object from a list of DER-encoded certificate data.\r
+\r
+ If X509Stack is NULL, then ASSERT().\r
+\r
+ @param[in, out] X509Stack On input, pointer to an existing X509 stack object.\r
+ On output, pointer to the X509 stack object with new\r
+ inserted X509 certificate.\r
+ @param ... A list of DER-encoded single certificate data followed\r
+ by certificate size. A NULL terminates the list. The\r
+ pairs are the arguments to X509ConstructCertificate().\r
+ \r
+ @retval TRUE The X509 stack construction succeeded.\r
+ @retval FALSE The construction operation failed.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+X509ConstructCertificateStack (\r
+ IN OUT UINT8 **X509Stack,\r
+ ... \r
+ )\r
+{\r
+ UINT8 *Cert;\r
+ UINTN CertSize;\r
+ X509 *X509Cert;\r
+ STACK_OF(X509) *CertStack;\r
+ BOOLEAN Status;\r
+ VA_LIST Args;\r
+ UINTN Index;\r
+\r
+ //\r
+ // ASSERT if input X509Stack is NULL.\r
+ //\r
+ ASSERT (X509Stack != NULL);\r
+\r
+ Status = FALSE;\r
+\r
+ //\r
+ // Initialize X509 stack object.\r
+ //\r
+ CertStack = (STACK_OF(X509) *) (*X509Stack);\r
+ if (CertStack == NULL) {\r
+ CertStack = sk_X509_new_null ();\r
+ if (CertStack == NULL) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ VA_START (Args, X509Stack);\r
+\r
+ for (Index = 0; ; Index++) {\r
+ //\r
+ // If Cert is NULL, then it is the end of the list.\r
+ //\r
+ Cert = VA_ARG (Args, UINT8 *);\r
+ if (Cert == NULL) {\r
+ break;\r
+ }\r
+\r
+ CertSize = VA_ARG (Args, UINTN);\r
+\r
+ //\r
+ // Construct X509 Object from the given DER-encoded certificate data.\r
+ //\r
+ Status = X509ConstructCertificate (\r
+ (CONST UINT8 *) Cert,\r
+ CertSize,\r
+ (UINT8 **) &X509Cert\r
+ );\r
+ if (!Status) {\r
+ X509_free (X509Cert);\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Insert the new X509 object into X509 stack object.\r
+ //\r
+ sk_X509_push (CertStack, X509Cert);\r
+ }\r
+\r
+ VA_END (Args);\r
+\r
+ if (!Status) {\r
+ sk_X509_pop_free (CertStack, X509_free);\r
+ } else {\r
+ *X509Stack = (UINT8 *) CertStack;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Release the specified X509 object.\r
+\r
+ If X509Cert is NULL, then ASSERT().\r
+\r
+ @param[in] X509Cert Pointer to the X509 object to be released.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+X509Free (\r
+ IN VOID *X509Cert\r
+ )\r
+{\r
+ ASSERT (X509Cert != NULL);\r
+\r
+ //\r
+ // Free OpenSSL X509 object.\r
+ //\r
+ X509_free ((X509 *) X509Cert);\r
+}\r
+\r
+/**\r
+ Release the specified X509 stack object.\r
+\r
+ If X509Stack is NULL, then ASSERT().\r
+\r
+ @param[in] X509Stack Pointer to the X509 stack object to be released.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+X509StackFree (\r
+ IN VOID *X509Stack\r
+ )\r
+{\r
+ ASSERT (X509Stack != NULL);\r
+\r
+ //\r
+ // Free OpenSSL X509 stack object.\r
+ //\r
+ sk_X509_pop_free ((STACK_OF(X509) *) X509Stack, X509_free);\r
+}\r
+\r