Add new interfaces to support PKCS7#7 signed data and authenticode signature. Update...
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptX509.c
index 6d687c6..7557399 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   X.509 Certificate Handler Wrapper Implementation over OpenSSL.\r
 \r
-Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -15,6 +15,202 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "InternalCryptLib.h"\r
 #include <openssl/x509.h>\r
 \r
+\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
 /**\r
   Retrieve the subject bytes from one X.509 certificate.\r
 \r
@@ -42,7 +238,6 @@ X509GetSubjectName (
   )\r
 {\r
   BOOLEAN    Status;\r
-  BIO        *CertBio;\r
   X509       *X509Cert;\r
   X509_NAME  *X509Name;\r
 \r
@@ -58,13 +253,8 @@ X509GetSubjectName (
   //\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 (Cert == NULL) {\r
+  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);\r
+  if ((X509Cert == NULL) || (!Status)) {\r
     goto _Exit;\r
   }\r
 \r
@@ -86,7 +276,6 @@ _Exit:
   //\r
   // Release Resources.\r
   //\r
-  BIO_free (CertBio);\r
   X509_free (X509Cert);\r
 \r
   return Status;\r
@@ -118,7 +307,6 @@ RsaGetPublicKeyFromX509 (
 {\r
   BOOLEAN   Status;\r
   EVP_PKEY  *Pkey;\r
-  BIO       *CertBio;\r
   X509      *X509Cert;\r
 \r
   //\r
@@ -129,19 +317,13 @@ RsaGetPublicKeyFromX509 (
 \r
   Status   = FALSE;\r
   Pkey     = NULL;\r
-  CertBio  = NULL;\r
   X509Cert = NULL;\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
+  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);\r
+  if ((X509Cert == NULL) || (!Status)) {\r
     goto _Exit;\r
   }\r
 \r
@@ -164,7 +346,6 @@ _Exit:
   //\r
   // Release Resources.\r
   //\r
-  BIO_free (CertBio);\r
   X509_free (X509Cert);\r
   EVP_PKEY_free (Pkey);\r
 \r
@@ -197,8 +378,6 @@ X509VerifyCert (
   )\r
 {\r
   BOOLEAN         Status;\r
-  BIO             *BioCert;\r
-  BIO             *BioCACert;\r
   X509            *X509Cert;\r
   X509            *X509CACert;\r
   X509_STORE      *CertStore;\r
@@ -211,8 +390,6 @@ X509VerifyCert (
   ASSERT (CACert != NULL);\r
 \r
   Status     = FALSE;\r
-  BioCert    = NULL;\r
-  BioCACert  = NULL;\r
   X509Cert   = NULL;\r
   X509CACert = NULL;\r
   CertStore  = NULL;\r
@@ -227,26 +404,16 @@ X509VerifyCert (
   //\r
   // Read DER-encoded certificate to be verified and Construct X509 object.\r
   //\r
-  BioCert = BIO_new (BIO_s_mem ());\r
-  BIO_write (BioCert, Cert, (int)CertSize);\r
-  if (BioCert == NULL) {\r
-    goto _Exit;\r
-  }\r
-  X509Cert = d2i_X509_bio (BioCert, NULL);\r
-  if (X509Cert == NULL) {\r
+  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);\r
+  if ((X509Cert == NULL) || (!Status)) {\r
     goto _Exit;\r
   }\r
 \r
   //\r
   // Read DER-encoded root certificate and Construct X509 object.\r
   //\r
-  BioCACert = BIO_new (BIO_s_mem());\r
-  BIO_write (BioCACert, CACert, (int)CACertSize);\r
-  if (BioCert == NULL) {\r
-    goto _Exit;\r
-  }\r
-  X509CACert = d2i_X509_bio (BioCACert, NULL);\r
-  if (CACert == NULL) {\r
+  Status = X509ConstructCertificate (CACert, CACertSize, (UINT8 **) &X509CACert);\r
+  if ((X509CACert == NULL) || (!Status)) {\r
     goto _Exit;\r
   }\r
 \r
@@ -277,8 +444,6 @@ _Exit:
   //\r
   // Release Resources.\r
   //\r
-  BIO_free (BioCert);\r
-  BIO_free (BioCACert);\r
   X509_free (X509Cert);\r
   X509_free (X509CACert);\r
   X509_STORE_free (CertStore);\r