CryptoPkg: Add new API to retrieve commonName of X.509 certificate
authorQin Long <qin.long@intel.com>
Sun, 24 Sep 2017 15:42:16 +0000 (23:42 +0800)
committerQin Long <qin.long@intel.com>
Sun, 24 Sep 2017 16:06:41 +0000 (00:06 +0800)
v3: Add extra CommonNameSize check since OpenSSL didn't check this
    input parameter. (One openssl issue was filed to address this risk:
    https://github.com/openssl/openssl/issues/4392)
v2: Update function interface to return RETURN_STATUS to represent
    different error cases.

Add one new API (X509GetCommonName()) to retrieve the subject commonName
string from one X.509 certificate.

Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ting Ye <ting.ye@intel.com>
Cc: Chao Zhang <chao.b.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Qin Long <qin.long@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
CryptoPkg/Application/Cryptest/RsaVerify2.c
CryptoPkg/Include/Library/BaseCryptLib.h
CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c
CryptoPkg/Library/BaseCryptLibRuntimeCryptProtocol/Pk/CryptX509Null.c

index 98b5aad..9db43d6 100644 (file)
@@ -204,13 +204,17 @@ ValidateCryptRsa2 (
   VOID\r
   )\r
 {\r
-  BOOLEAN  Status;\r
-  VOID     *RsaPrivKey;\r
-  VOID     *RsaPubKey;\r
-  UINT8    *Signature;\r
-  UINTN    SigSize;\r
-  UINT8    *Subject;\r
-  UINTN    SubjectSize;\r
+  BOOLEAN        Status;\r
+  VOID           *RsaPrivKey;\r
+  VOID           *RsaPubKey;\r
+  UINT8          *Signature;\r
+  UINTN          SigSize;\r
+  UINT8          *Subject;\r
+  UINTN          SubjectSize;\r
+  RETURN_STATUS  ReturnStatus;\r
+  CHAR8          CommonName[64];\r
+  CHAR16         CommonNameUnicode[64];\r
+  UINTN          CommonNameSize;\r
 \r
   Print (L"\nUEFI-OpenSSL RSA Key Retrieving Testing: ");\r
 \r
@@ -287,6 +291,20 @@ ValidateCryptRsa2 (
   }\r
 \r
   //\r
+  // Get CommonName from X509 Certificate Subject\r
+  //\r
+  CommonNameSize = 64;\r
+  ZeroMem (CommonName, CommonNameSize);\r
+  ReturnStatus = X509GetCommonName (TestCert, sizeof (TestCert), CommonName, &CommonNameSize);\r
+  if (RETURN_ERROR (ReturnStatus)) {\r
+    Print (L"\n  - Retrieving Common Name - [Fail]");\r
+    return EFI_ABORTED;\r
+  } else {\r
+    AsciiStrToUnicodeStrS (CommonName, CommonNameUnicode, CommonNameSize);\r
+    Print (L"\n  - Retrieving Common Name = \"%s\" (Size = %d)", CommonNameUnicode, CommonNameSize);\r
+  }\r
+\r
+  //\r
   // X509 Certificate Verification.\r
   //\r
   Print (L"\n- X509 Certificate Verification with Trusted CA ...");\r
index 9c5ffcd..5f67ecb 100644 (file)
@@ -2172,6 +2172,41 @@ X509GetSubjectName (
   );\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
+/**\r
   Verify one X509 certificate was issued by the trusted CA.\r
 \r
   If Cert is NULL, then return FALSE.\r
index 7d27597..bf7c4cc 100644 (file)
@@ -298,6 +298,115 @@ _Exit:
 }\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_STATUS  ReturnStatus;\r
+  BOOLEAN        Status;\r
+  X509           *X509Cert;\r
+  X509_NAME      *X509Name;\r
+  INTN           Length;\r
+\r
+  ReturnStatus = RETURN_INVALID_PARAMETER;\r
+\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if ((Cert == NULL) || (CertSize > INT_MAX) || (CommonNameSize == NULL)) {\r
+    return ReturnStatus;\r
+  }\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
+  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 (X509Name == NULL) {\r
+    //\r
+    // Fail to retrieve subject name content\r
+    //\r
+    goto _Exit;\r
+  }\r
+\r
+  //\r
+  // Retrieve the CommonName information from X.509 Subject\r
+  //\r
+  Length = (INTN) X509_NAME_get_text_by_NID (X509Name, NID_commonName, CommonName, (int)(*CommonNameSize));\r
+  if (Length < 0) {\r
+    //\r
+    // No CommonName entry exists in X509_NAME object\r
+    //\r
+    *CommonNameSize = 0;\r
+    ReturnStatus    = RETURN_NOT_FOUND;\r
+    goto _Exit;\r
+  }\r
+\r
+  *CommonNameSize = (UINTN)(Length + 1);\r
+  if (CommonName == NULL) {\r
+    ReturnStatus = RETURN_BUFFER_TOO_SMALL;\r
+  } else {\r
+    ReturnStatus = RETURN_SUCCESS;\r
+  }\r
+\r
+_Exit:\r
+  //\r
+  // Release Resources.\r
+  //\r
+  if (X509Cert != NULL) {\r
+    X509_free (X509Cert);\r
+  }\r
+\r
+  return ReturnStatus;\r
+}\r
+\r
+/**\r
   Retrieve the RSA Public Key from one DER-encoded X509 certificate.\r
 \r
   @param[in]  Cert         Pointer to the DER-encoded X509 certificate.\r
index 51aa063..d00f38d 100644 (file)
@@ -128,6 +128,38 @@ X509GetSubjectName (
 }\r
 \r
 /**\r
+  Retrieve the common name (CN) string from one X.509 certificate.\r
+\r
+  Return RETURN_UNSUPPORTED to indicate this interface is not supported.\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_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
+  ASSERT (FALSE);\r
+  return RETURN_UNSUPPORTED;\r
+}\r
+\r
+/**\r
   Retrieve the RSA Public Key from one DER-encoded X509 certificate.\r
 \r
   Return FALSE to indicate this interface is not supported.\r
index f5d9aa1..d00f38d 100644 (file)
@@ -128,6 +128,38 @@ X509GetSubjectName (
 }\r
 \r
 /**\r
+  Retrieve the common name (CN) string from one X.509 certificate.\r
+\r
+  Return RETURN_UNSUPPORTED to indicate this interface is not supported.\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_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
+  ASSERT (FALSE);\r
+  return RETURN_UNSUPPORTED;\r
+}\r
+\r
+/**\r
   Retrieve the RSA Public Key from one DER-encoded X509 certificate.\r
 \r
   Return FALSE to indicate this interface is not supported.\r
@@ -203,4 +235,4 @@ X509GetTBSCert (
 {\r
   ASSERT (FALSE);\r
   return FALSE;\r
-}
\ No newline at end of file
+}\r