]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
CryptoPkg: Apply uncrustify changes
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptX509.c
index f90600473a0db474166522f974d86d951a081b77..e6bb45e64135e37a5d331f828d12dcf4f6a27292 100644 (file)
@@ -1,20 +1,14 @@
 /** @file\r
   X.509 Certificate Handler Wrapper Implementation over OpenSSL.\r
 \r
-Copyright (c) 2010 - 2012, 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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "InternalCryptLib.h"\r
 #include <openssl/x509.h>\r
-\r
+#include <openssl/rsa.h>\r
 \r
 /**\r
   Construct a X509 object from DER-encoded certificate data.\r
@@ -38,74 +32,63 @@ X509ConstructCertificate (
   OUT  UINT8        **SingleX509Cert\r
   )\r
 {\r
-  BIO      *CertBio;\r
-  X509     *X509Cert;\r
-  BOOLEAN  Status;\r
+  X509         *X509Cert;\r
+  CONST UINT8  *Temp;\r
 \r
   //\r
   // Check input parameters.\r
   //\r
-  if (Cert == NULL || SingleX509Cert == NULL || CertSize > INT_MAX) {\r
+  if ((Cert == NULL) || (SingleX509Cert == NULL) || (CertSize > INT_MAX)) {\r
     return FALSE;\r
   }\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
+  Temp     = Cert;\r
+  X509Cert = d2i_X509 (NULL, &Temp, (long)CertSize);\r
   if (X509Cert == NULL) {\r
-    goto _Exit;\r
+    return FALSE;\r
   }\r
 \r
-  *SingleX509Cert = (UINT8 *) X509Cert;\r
-  Status = TRUE;\r
+  *SingleX509Cert = (UINT8 *)X509Cert;\r
 \r
-_Exit:\r
-  //\r
-  // Release Resources.\r
-  //\r
-  BIO_free (CertBio);\r
-\r
-  return Status;\r
+  return TRUE;\r
 }\r
 \r
 /**\r
   Construct a X509 stack object from a list of DER-encoded certificate data.\r
 \r
   If X509Stack is NULL, then return FALSE.\r
+  If this interface is not supported, then return FALSE.\r
 \r
-  @param[in, out]  X509Stack  On input, pointer to an existing X509 stack object.\r
+  @param[in, out]  X509Stack  On input, pointer to an existing or NULL 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
+  @param[in]       Args       VA_LIST marker for the variable argument list.\r
+                              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
+\r
   @retval     TRUE            The X509 stack construction succeeded.\r
   @retval     FALSE           The construction operation failed.\r
+  @retval     FALSE           This interface is not supported.\r
 \r
 **/\r
 BOOLEAN\r
 EFIAPI\r
-X509ConstructCertificateStack (\r
-  IN OUT  UINT8  **X509Stack,\r
-  ...  \r
+X509ConstructCertificateStackV (\r
+  IN OUT  UINT8    **X509Stack,\r
+  IN      VA_LIST  Args\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
+  UINT8  *Cert;\r
+  UINTN  CertSize;\r
+  X509   *X509Cert;\r
+\r
+  STACK_OF (X509)  *CertStack;\r
+  BOOLEAN  Status;\r
+  UINTN    Index;\r
 \r
   //\r
   // Check input parameters.\r
@@ -119,7 +102,7 @@ X509ConstructCertificateStack (
   //\r
   // Initialize X509 stack object.\r
   //\r
-  CertStack = (STACK_OF(X509) *) (*X509Stack);\r
+  CertStack = (STACK_OF (X509) *)(*X509Stack);\r
   if (CertStack == NULL) {\r
     CertStack = sk_X509_new_null ();\r
     if (CertStack == NULL) {\r
@@ -127,8 +110,6 @@ X509ConstructCertificateStack (
     }\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
@@ -139,17 +120,24 @@ X509ConstructCertificateStack (
     }\r
 \r
     CertSize = VA_ARG (Args, UINTN);\r
+    if (CertSize == 0) {\r
+      break;\r
+    }\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
+    X509Cert = NULL;\r
+    Status   = X509ConstructCertificate (\r
+                 (CONST UINT8 *)Cert,\r
+                 CertSize,\r
+                 (UINT8 **)&X509Cert\r
+                 );\r
     if (!Status) {\r
-      X509_free (X509Cert);\r
+      if (X509Cert != NULL) {\r
+        X509_free (X509Cert);\r
+      }\r
+\r
       break;\r
     }\r
 \r
@@ -159,17 +147,47 @@ X509ConstructCertificateStack (
     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
+    *X509Stack = (UINT8 *)CertStack;\r
   }\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 return FALSE.\r
+\r
+  @param[in, out]  X509Stack  On input, pointer to an existing or NULL 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
+  VA_LIST  Args;\r
+  BOOLEAN  Result;\r
+\r
+  VA_START (Args, X509Stack);\r
+  Result = X509ConstructCertificateStackV (X509Stack, Args);\r
+  VA_END (Args);\r
+  return Result;\r
+}\r
+\r
 /**\r
   Release the specified X509 object.\r
 \r
@@ -183,18 +201,18 @@ EFIAPI
 X509Free (\r
   IN  VOID  *X509Cert\r
   )\r
-{ \r
+{\r
   //\r
   // Check input parameters.\r
   //\r
   if (X509Cert == NULL) {\r
     return;\r
   }\r
-  \r
+\r
   //\r
   // Free OpenSSL X509 object.\r
   //\r
-  X509_free ((X509 *) X509Cert);\r
+  X509_free ((X509 *)X509Cert);\r
 }\r
 \r
 /**\r
@@ -217,167 +235,315 @@ X509StackFree (
   if (X509Stack == NULL) {\r
     return;\r
   }\r
-  \r
+\r
   //\r
   // Free OpenSSL X509 stack object.\r
   //\r
-  sk_X509_pop_free ((STACK_OF(X509) *) X509Stack, X509_free);\r
+  sk_X509_pop_free ((STACK_OF (X509) *) X509Stack, X509_free);\r
 }\r
 \r
 /**\r
-  Pop single certificate from STACK_OF(X509).\r
+  Retrieve the subject bytes from one X.509 certificate.\r
+\r
+  @param[in]      Cert         Pointer to the DER-encoded X509 certificate.\r
+  @param[in]      CertSize     Size of the X509 certificate in bytes.\r
+  @param[out]     CertSubject  Pointer to the retrieved certificate subject bytes.\r
+  @param[in, out] SubjectSize  The size in bytes of the CertSubject buffer on input,\r
+                               and the size of buffer returned CertSubject on output.\r
 \r
-  If X509Stack, Cert, or CertSize is NULL, then return FALSE.\r
+  If Cert is NULL, then return FALSE.\r
+  If SubjectSize is NULL, then return FALSE.\r
 \r
-  @param[in]  X509Stack       Pointer to a X509 stack object.\r
-  @param[out] Cert            Pointer to a X509 certificate.\r
-  @param[out] CertSize        Length of output X509 certificate in bytes.\r
-                                 \r
-  @retval     TRUE            The X509 stack pop succeeded.\r
-  @retval     FALSE           The pop operation failed.\r
+  @retval  TRUE   The certificate subject retrieved successfully.\r
+  @retval  FALSE  Invalid certificate, or the SubjectSize is too small for the result.\r
+                  The SubjectSize will be updated with the required size.\r
 \r
 **/\r
 BOOLEAN\r
-X509PopCertificate (\r
-  IN  VOID  *X509Stack,\r
-  OUT UINT8 **Cert,\r
-  OUT UINTN *CertSize\r
+EFIAPI\r
+X509GetSubjectName (\r
+  IN      CONST UINT8  *Cert,\r
+  IN      UINTN        CertSize,\r
+  OUT     UINT8        *CertSubject,\r
+  IN OUT  UINTN        *SubjectSize\r
   )\r
 {\r
-  BIO             *CertBio;\r
-  X509            *X509Cert;\r
-  STACK_OF(X509)  *CertStack;\r
-  BOOLEAN         Status;\r
-  int             Result;\r
-  int             Length;\r
-  VOID            *Buffer;\r
-\r
-  Status = FALSE;\r
-\r
-  if ((X509Stack == NULL) || (Cert == NULL) || (CertSize == NULL)) {\r
-    return Status;\r
-  }\r
-\r
-  CertStack = (STACK_OF(X509) *) X509Stack;\r
-\r
-  X509Cert = sk_X509_pop (CertStack);\r
+  BOOLEAN    Status;\r
+  X509       *X509Cert;\r
+  X509_NAME  *X509Name;\r
+  UINTN      X509NameSize;\r
 \r
-  if (X509Cert == NULL) {\r
-    return Status;\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if ((Cert == NULL) || (SubjectSize == NULL)) {\r
+    return FALSE;\r
   }\r
 \r
-  Buffer = NULL;\r
-\r
-  CertBio = BIO_new (BIO_s_mem ());\r
-  if (CertBio == NULL) {\r
-    return Status;\r
-  }\r
+  X509Cert = NULL;\r
 \r
-  Result = i2d_X509_bio (CertBio, X509Cert);\r
-  if (Result == 0) {\r
+  //\r
+  // Read DER-encoded X509 Certificate and Construct X509 object.\r
+  //\r
+  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);\r
+  if ((X509Cert == NULL) || (!Status)) {\r
+    Status = FALSE;\r
     goto _Exit;\r
   }\r
 \r
-  Length = ((BUF_MEM *) CertBio->ptr)->length;\r
-  if (Length <= 0) {\r
-    goto _Exit;\r
-  }\r
+  Status = FALSE;\r
 \r
-  Buffer = malloc (Length);\r
-  if (Buffer == NULL) {\r
+  //\r
+  // Retrieve subject name from certificate object.\r
+  //\r
+  X509Name = X509_get_subject_name (X509Cert);\r
+  if (X509Name == NULL) {\r
     goto _Exit;\r
   }\r
 \r
-  Result = BIO_read (CertBio, Buffer, Length);\r
-  if (Result != Length) {\r
+  X509NameSize = i2d_X509_NAME (X509Name, NULL);\r
+  if (*SubjectSize < X509NameSize) {\r
+    *SubjectSize = X509NameSize;\r
     goto _Exit;\r
   }\r
 \r
-  *Cert     = Buffer;\r
-  *CertSize = Length;\r
-\r
-  Status = TRUE;\r
+  *SubjectSize = X509NameSize;\r
+  if (CertSubject != NULL) {\r
+    i2d_X509_NAME (X509Name, &CertSubject);\r
+    Status = TRUE;\r
+  }\r
 \r
 _Exit:\r
-\r
-  BIO_free (CertBio);\r
-\r
-  if (!Status && (Buffer != NULL)) {\r
-    free (Buffer);\r
+  //\r
+  // Release Resources.\r
+  //\r
+  if (X509Cert != NULL) {\r
+    X509_free (X509Cert);\r
   }\r
 \r
   return Status;\r
 }\r
 \r
 /**\r
-  Retrieve the subject bytes from one X.509 certificate.\r
-\r
-  @param[in]      Cert         Pointer to the DER-encoded X509 certificate.\r
-  @param[in]      CertSize     Size of the X509 certificate in bytes.\r
-  @param[out]     CertSubject  Pointer to the retrieved certificate subject bytes.\r
-  @param[in, out] SubjectSize  The size in bytes of the CertSubject buffer on input,\r
-                               and the size of buffer returned CertSubject on output.\r
-\r
-  If Cert is NULL, then return FALSE.\r
-  If SubjectSize is NULL, then return FALSE.\r
-\r
-  @retval  TRUE   The certificate subject retrieved successfully.\r
-  @retval  FALSE  Invalid certificate, or the SubjectSize is too small for the result.\r
-                  The SubjectSize will be updated with the required size.\r
+  Retrieve a string from one X.509 certificate base on the Request_NID.\r
+\r
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.\r
+  @param[in]      CertSize         Size of the X509 certificate in bytes.\r
+  @param[in]      Request_NID      NID of string to obtain\r
+  @param[out]     CommonName       Buffer to contain the retrieved certificate common\r
+                                   name string (UTF8). At most CommonNameSize bytes will be\r
+                                   written and the string will be null terminated. May be\r
+                                   NULL in order to determine the size buffer needed.\r
+  @param[in,out]  CommonNameSize   The size in bytes of the CommonName buffer on input,\r
+                                   and the size of buffer returned CommonName on output.\r
+                                   If CommonName is NULL then the amount of space needed\r
+                                   in buffer (including the final null) is returned.\r
+\r
+  @retval RETURN_SUCCESS           The certificate CommonName retrieved successfully.\r
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.\r
+                                   If CommonNameSize is NULL.\r
+                                   If CommonName is not NULL and *CommonNameSize is 0.\r
+                                   If Certificate is invalid.\r
+  @retval RETURN_NOT_FOUND         If no NID Name entry exists.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If the CommonName is NULL. The required buffer size\r
+                                   (including the final null) is returned in the\r
+                                   CommonNameSize parameter.\r
+  @retval RETURN_UNSUPPORTED       The operation is not supported.\r
 \r
 **/\r
-BOOLEAN\r
-EFIAPI\r
-X509GetSubjectName (\r
+STATIC\r
+RETURN_STATUS\r
+InternalX509GetNIDName (\r
   IN      CONST UINT8  *Cert,\r
   IN      UINTN        CertSize,\r
-  OUT     UINT8        *CertSubject,\r
-  IN OUT  UINTN        *SubjectSize\r
+  IN      INT32        Request_NID,\r
+  OUT     CHAR8        *CommonName   OPTIONAL,\r
+  IN OUT  UINTN        *CommonNameSize\r
   )\r
 {\r
-  BOOLEAN    Status;\r
-  X509       *X509Cert;\r
-  X509_NAME  *X509Name;\r
+  RETURN_STATUS    ReturnStatus;\r
+  BOOLEAN          Status;\r
+  X509             *X509Cert;\r
+  X509_NAME        *X509Name;\r
+  INT32            Index;\r
+  INTN             Length;\r
+  X509_NAME_ENTRY  *Entry;\r
+  ASN1_STRING      *EntryData;\r
+  UINT8            *UTF8Name;\r
+\r
+  ReturnStatus = RETURN_INVALID_PARAMETER;\r
+  UTF8Name     = NULL;\r
 \r
   //\r
   // Check input parameters.\r
   //\r
-  if (Cert == NULL || SubjectSize == NULL) {\r
-    return FALSE;\r
+  if ((Cert == NULL) || (CertSize > INT_MAX) || (CommonNameSize == NULL)) {\r
+    return ReturnStatus;\r
   }\r
 \r
-  Status   = FALSE;\r
-  X509Cert = NULL;\r
+  if ((CommonName != NULL) && (*CommonNameSize == 0)) {\r
+    return ReturnStatus;\r
+  }\r
 \r
+  X509Cert = NULL;\r
   //\r
   // Read DER-encoded X509 Certificate and Construct X509 object.\r
   //\r
-  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);\r
+  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);\r
   if ((X509Cert == NULL) || (!Status)) {\r
+    //\r
+    // Invalid X.509 Certificate\r
+    //\r
     goto _Exit;\r
   }\r
 \r
+  Status = FALSE;\r
+\r
   //\r
   // Retrieve subject name from certificate object.\r
   //\r
   X509Name = X509_get_subject_name (X509Cert);\r
-  if (*SubjectSize < (UINTN) X509Name->bytes->length) {\r
-    *SubjectSize = (UINTN) X509Name->bytes->length;\r
+  if (X509Name == NULL) {\r
+    //\r
+    // Fail to retrieve subject name content\r
+    //\r
     goto _Exit;\r
   }\r
-  *SubjectSize = (UINTN) X509Name->bytes->length;\r
-  if (CertSubject != NULL) {\r
-    CopyMem (CertSubject, (UINT8 *) X509Name->bytes->data, *SubjectSize);\r
-    Status = TRUE;\r
+\r
+  //\r
+  // Retrive the string from X.509 Subject base on the Request_NID\r
+  //\r
+  Index = X509_NAME_get_index_by_NID (X509Name, Request_NID, -1);\r
+  if (Index < 0) {\r
+    //\r
+    // No Request_NID name entry exists in X509_NAME object\r
+    //\r
+    *CommonNameSize = 0;\r
+    ReturnStatus    = RETURN_NOT_FOUND;\r
+    goto _Exit;\r
+  }\r
+\r
+  Entry = X509_NAME_get_entry (X509Name, Index);\r
+  if (Entry == NULL) {\r
+    //\r
+    // Fail to retrieve name entry data\r
+    //\r
+    *CommonNameSize = 0;\r
+    ReturnStatus    = RETURN_NOT_FOUND;\r
+    goto _Exit;\r
+  }\r
+\r
+  EntryData = X509_NAME_ENTRY_get_data (Entry);\r
+\r
+  Length = ASN1_STRING_to_UTF8 (&UTF8Name, EntryData);\r
+  if (Length < 0) {\r
+    //\r
+    // Fail to convert the Name string\r
+    //\r
+    *CommonNameSize = 0;\r
+    ReturnStatus    = RETURN_INVALID_PARAMETER;\r
+    goto _Exit;\r
+  }\r
+\r
+  if (CommonName == NULL) {\r
+    *CommonNameSize = Length + 1;\r
+    ReturnStatus    = RETURN_BUFFER_TOO_SMALL;\r
+  } else {\r
+    *CommonNameSize = MIN ((UINTN)Length, *CommonNameSize - 1) + 1;\r
+    CopyMem (CommonName, UTF8Name, *CommonNameSize - 1);\r
+    CommonName[*CommonNameSize - 1] = '\0';\r
+    ReturnStatus                    = RETURN_SUCCESS;\r
   }\r
 \r
 _Exit:\r
   //\r
   // Release Resources.\r
   //\r
-  X509_free (X509Cert);\r
+  if (X509Cert != NULL) {\r
+    X509_free (X509Cert);\r
+  }\r
 \r
-  return Status;\r
+  if (UTF8Name != NULL) {\r
+    OPENSSL_free (UTF8Name);\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+/**\r
+  Retrieve the common name (CN) string from one X.509 certificate.\r
+\r
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.\r
+  @param[in]      CertSize         Size of the X509 certificate in bytes.\r
+  @param[out]     CommonName       Buffer to contain the retrieved certificate common\r
+                                   name string. At most CommonNameSize bytes will be\r
+                                   written and the string will be null terminated. May be\r
+                                   NULL in order to determine the size buffer needed.\r
+  @param[in,out]  CommonNameSize   The size in bytes of the CommonName buffer on input,\r
+                                   and the size of buffer returned CommonName on output.\r
+                                   If CommonName is NULL then the amount of space needed\r
+                                   in buffer (including the final null) is returned.\r
+\r
+  @retval RETURN_SUCCESS           The certificate CommonName retrieved successfully.\r
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.\r
+                                   If CommonNameSize is NULL.\r
+                                   If CommonName is not NULL and *CommonNameSize is 0.\r
+                                   If Certificate is invalid.\r
+  @retval RETURN_NOT_FOUND         If no CommonName entry exists.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If the CommonName is NULL. The required buffer size\r
+                                   (including the final null) is returned in the\r
+                                   CommonNameSize parameter.\r
+  @retval RETURN_UNSUPPORTED       The operation is not supported.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+X509GetCommonName (\r
+  IN      CONST UINT8  *Cert,\r
+  IN      UINTN        CertSize,\r
+  OUT     CHAR8        *CommonName   OPTIONAL,\r
+  IN OUT  UINTN        *CommonNameSize\r
+  )\r
+{\r
+  return InternalX509GetNIDName (Cert, CertSize, NID_commonName, CommonName, CommonNameSize);\r
+}\r
+\r
+/**\r
+  Retrieve the organization name (O) string from one X.509 certificate.\r
+\r
+  @param[in]      Cert             Pointer to the DER-encoded X509 certificate.\r
+  @param[in]      CertSize         Size of the X509 certificate in bytes.\r
+  @param[out]     NameBuffer       Buffer to contain the retrieved certificate organization\r
+                                   name string. At most NameBufferSize bytes will be\r
+                                   written and the string will be null terminated. May be\r
+                                   NULL in order to determine the size buffer needed.\r
+  @param[in,out]  NameBufferSize   The size in bytes of the Name buffer on input,\r
+                                   and the size of buffer returned Name on output.\r
+                                   If NameBuffer is NULL then the amount of space needed\r
+                                   in buffer (including the final null) is returned.\r
+\r
+  @retval RETURN_SUCCESS           The certificate Organization Name retrieved successfully.\r
+  @retval RETURN_INVALID_PARAMETER If Cert is NULL.\r
+                                   If NameBufferSize is NULL.\r
+                                   If NameBuffer is not NULL and *CommonNameSize is 0.\r
+                                   If Certificate is invalid.\r
+  @retval RETURN_NOT_FOUND         If no Organization Name entry exists.\r
+  @retval RETURN_BUFFER_TOO_SMALL  If the NameBuffer is NULL. The required buffer size\r
+                                   (including the final null) is returned in the\r
+                                   CommonNameSize parameter.\r
+  @retval RETURN_UNSUPPORTED       The operation is not supported.\r
+\r
+**/\r
+RETURN_STATUS\r
+EFIAPI\r
+X509GetOrganizationName (\r
+  IN      CONST UINT8  *Cert,\r
+  IN      UINTN        CertSize,\r
+  OUT     CHAR8        *NameBuffer   OPTIONAL,\r
+  IN OUT  UINTN        *NameBufferSize\r
+  )\r
+{\r
+  return InternalX509GetNIDName (Cert, CertSize, NID_organizationName, NameBuffer, NameBufferSize);\r
 }\r
 \r
 /**\r
@@ -407,38 +573,40 @@ RsaGetPublicKeyFromX509 (
   BOOLEAN   Status;\r
   EVP_PKEY  *Pkey;\r
   X509      *X509Cert;\r
-  \r
+\r
   //\r
   // Check input parameters.\r
   //\r
-  if (Cert == NULL || RsaContext == NULL) {\r
+  if ((Cert == NULL) || (RsaContext == NULL)) {\r
     return FALSE;\r
   }\r
 \r
-  Status   = FALSE;\r
   Pkey     = NULL;\r
   X509Cert = NULL;\r
 \r
   //\r
   // Read DER-encoded X509 Certificate and Construct X509 object.\r
   //\r
-  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);\r
+  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);\r
   if ((X509Cert == NULL) || (!Status)) {\r
+    Status = FALSE;\r
     goto _Exit;\r
   }\r
 \r
+  Status = FALSE;\r
+\r
   //\r
   // Retrieve and check EVP_PKEY data from X509 Certificate.\r
   //\r
   Pkey = X509_get_pubkey (X509Cert);\r
-  if ((Pkey == NULL) || (Pkey->type != EVP_PKEY_RSA)) {\r
+  if ((Pkey == NULL) || (EVP_PKEY_id (Pkey) != EVP_PKEY_RSA)) {\r
     goto _Exit;\r
   }\r
 \r
   //\r
   // Duplicate RSA Context from the retrieved EVP_PKEY.\r
   //\r
-  if ((*RsaContext = RSAPublicKey_dup (Pkey->pkey.rsa)) != NULL) {\r
+  if ((*RsaContext = RSAPublicKey_dup (EVP_PKEY_get0_RSA (Pkey))) != NULL) {\r
     Status = TRUE;\r
   }\r
 \r
@@ -446,8 +614,13 @@ _Exit:
   //\r
   // Release Resources.\r
   //\r
-  X509_free (X509Cert);\r
-  EVP_PKEY_free (Pkey);\r
+  if (X509Cert != NULL) {\r
+    X509_free (X509Cert);\r
+  }\r
+\r
+  if (Pkey != NULL) {\r
+    EVP_PKEY_free (Pkey);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -481,12 +654,12 @@ X509VerifyCert (
   X509            *X509Cert;\r
   X509            *X509CACert;\r
   X509_STORE      *CertStore;\r
-  X509_STORE_CTX  CertCtx;\r
-  \r
+  X509_STORE_CTX  *CertCtx;\r
+\r
   //\r
   // Check input parameters.\r
   //\r
-  if (Cert == NULL || CACert == NULL) {\r
+  if ((Cert == NULL) || (CACert == NULL)) {\r
     return FALSE;\r
   }\r
 \r
@@ -494,30 +667,43 @@ X509VerifyCert (
   X509Cert   = NULL;\r
   X509CACert = NULL;\r
   CertStore  = NULL;\r
+  CertCtx    = NULL;\r
 \r
   //\r
   // Register & Initialize necessary digest algorithms for certificate verification.\r
   //\r
-  EVP_add_digest (EVP_md5());\r
-  EVP_add_digest (EVP_sha1());\r
-  EVP_add_digest (EVP_sha256());\r
+  if (EVP_add_digest (EVP_md5 ()) == 0) {\r
+    goto _Exit;\r
+  }\r
+\r
+  if (EVP_add_digest (EVP_sha1 ()) == 0) {\r
+    goto _Exit;\r
+  }\r
+\r
+  if (EVP_add_digest (EVP_sha256 ()) == 0) {\r
+    goto _Exit;\r
+  }\r
 \r
   //\r
   // Read DER-encoded certificate to be verified and Construct X509 object.\r
   //\r
-  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);\r
+  Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);\r
   if ((X509Cert == NULL) || (!Status)) {\r
+    Status = FALSE;\r
     goto _Exit;\r
   }\r
 \r
   //\r
   // Read DER-encoded root certificate and Construct X509 object.\r
   //\r
-  Status = X509ConstructCertificate (CACert, CACertSize, (UINT8 **) &X509CACert);\r
+  Status = X509ConstructCertificate (CACert, CACertSize, (UINT8 **)&X509CACert);\r
   if ((X509CACert == NULL) || (!Status)) {\r
+    Status = FALSE;\r
     goto _Exit;\r
   }\r
 \r
+  Status = FALSE;\r
+\r
   //\r
   // Set up X509 Store for trusted certificate.\r
   //\r
@@ -525,30 +711,134 @@ X509VerifyCert (
   if (CertStore == NULL) {\r
     goto _Exit;\r
   }\r
+\r
   if (!(X509_STORE_add_cert (CertStore, X509CACert))) {\r
     goto _Exit;\r
   }\r
 \r
+  //\r
+  // Allow partial certificate chains, terminated by a non-self-signed but\r
+  // still trusted intermediate certificate. Also disable time checks.\r
+  //\r
+  X509_STORE_set_flags (\r
+    CertStore,\r
+    X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME\r
+    );\r
+\r
   //\r
   // Set up X509_STORE_CTX for the subsequent verification operation.\r
   //\r
-  if (!X509_STORE_CTX_init (&CertCtx, CertStore, X509Cert, NULL)) {\r
+  CertCtx = X509_STORE_CTX_new ();\r
+  if (CertCtx == NULL) {\r
+    goto _Exit;\r
+  }\r
+\r
+  if (!X509_STORE_CTX_init (CertCtx, CertStore, X509Cert, NULL)) {\r
     goto _Exit;\r
   }\r
 \r
   //\r
   // X509 Certificate Verification.\r
   //\r
-  Status = (BOOLEAN) X509_verify_cert (&CertCtx);\r
-  X509_STORE_CTX_cleanup (&CertCtx);\r
+  Status = (BOOLEAN)X509_verify_cert (CertCtx);\r
+  X509_STORE_CTX_cleanup (CertCtx);\r
 \r
 _Exit:\r
   //\r
   // Release Resources.\r
   //\r
-  X509_free (X509Cert);\r
-  X509_free (X509CACert);\r
-  X509_STORE_free (CertStore);\r
+  if (X509Cert != NULL) {\r
+    X509_free (X509Cert);\r
+  }\r
+\r
+  if (X509CACert != NULL) {\r
+    X509_free (X509CACert);\r
+  }\r
+\r
+  if (CertStore != NULL) {\r
+    X509_STORE_free (CertStore);\r
+  }\r
+\r
+  X509_STORE_CTX_free (CertCtx);\r
 \r
   return Status;\r
 }\r
+\r
+/**\r
+  Retrieve the TBSCertificate from one given X.509 certificate.\r
+\r
+  @param[in]      Cert         Pointer to the given DER-encoded X509 certificate.\r
+  @param[in]      CertSize     Size of the X509 certificate in bytes.\r
+  @param[out]     TBSCert      DER-Encoded To-Be-Signed certificate.\r
+  @param[out]     TBSCertSize  Size of the TBS certificate in bytes.\r
+\r
+  If Cert is NULL, then return FALSE.\r
+  If TBSCert is NULL, then return FALSE.\r
+  If TBSCertSize is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   The TBSCertificate was retrieved successfully.\r
+  @retval  FALSE  Invalid X.509 certificate.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+X509GetTBSCert (\r
+  IN  CONST UINT8  *Cert,\r
+  IN  UINTN        CertSize,\r
+  OUT UINT8        **TBSCert,\r
+  OUT UINTN        *TBSCertSize\r
+  )\r
+{\r
+  CONST UINT8  *Temp;\r
+  UINT32       Asn1Tag;\r
+  UINT32       ObjClass;\r
+  UINTN        Length;\r
+\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if ((Cert == NULL) || (TBSCert == NULL) ||\r
+      (TBSCertSize == NULL) || (CertSize > INT_MAX))\r
+  {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // An X.509 Certificate is: (defined in RFC3280)\r
+  //   Certificate  ::=  SEQUENCE  {\r
+  //     tbsCertificate       TBSCertificate,\r
+  //     signatureAlgorithm   AlgorithmIdentifier,\r
+  //     signature            BIT STRING }\r
+  //\r
+  // and\r
+  //\r
+  //  TBSCertificate  ::=  SEQUENCE  {\r
+  //    version         [0]  Version DEFAULT v1,\r
+  //    ...\r
+  //    }\r
+  //\r
+  // So we can just ASN1-parse the x.509 DER-encoded data. If we strip\r
+  // the first SEQUENCE, the second SEQUENCE is the TBSCertificate.\r
+  //\r
+  Temp   = Cert;\r
+  Length = 0;\r
+  ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)CertSize);\r
+\r
+  if (Asn1Tag != V_ASN1_SEQUENCE) {\r
+    return FALSE;\r
+  }\r
+\r
+  *TBSCert = (UINT8 *)Temp;\r
+\r
+  ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)Length);\r
+  //\r
+  // Verify the parsed TBSCertificate is one correct SEQUENCE data.\r
+  //\r
+  if (Asn1Tag != V_ASN1_SEQUENCE) {\r
+    return FALSE;\r
+  }\r
+\r
+  *TBSCertSize = Length + (Temp - *TBSCert);\r
+\r
+  return TRUE;\r
+}\r