]> git.proxmox.com Git - mirror_edk2.git/commitdiff
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 98b5aad9009808fd74d3d932889731bcbf4bd5e7..9db43d6eef7aed481a1674b2f24b36d29e6e21d9 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
@@ -286,6 +290,20 @@ ValidateCryptRsa2 (
     Print (L"[Pass]");\r
   }\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
index 9c5ffcd9cfdc936432ebcdc7ffaccca07c748e5d..5f67ecb709e06e92d2d2898833e1013cc3b37c25 100644 (file)
@@ -2171,6 +2171,41 @@ X509GetSubjectName (
   IN OUT  UINTN        *SubjectSize\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
 /**\r
   Verify one X509 certificate was issued by the trusted CA.\r
 \r
index 7d275977c59724c87149291c673fe7ba4828f705..bf7c4ccd42feb8bb0ca283394d3be9018c5d0ebc 100644 (file)
@@ -297,6 +297,115 @@ _Exit:
   return Status;\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_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
index 51aa0633a827f0042bc2a004522f9e4438ef5662..d00f38daa83f8dc0fd2b31eb5acfaf62748af5fa 100644 (file)
@@ -127,6 +127,38 @@ X509GetSubjectName (
   return FALSE;\r
 }\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
index f5d9aa107614de37e00e832468ed230a3f2326e4..d00f38daa83f8dc0fd2b31eb5acfaf62748af5fa 100644 (file)
@@ -127,6 +127,38 @@ X509GetSubjectName (
   return FALSE;\r
 }\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
@@ -203,4 +235,4 @@ X509GetTBSCert (
 {\r
   ASSERT (FALSE);\r
   return FALSE;\r
-}
\ No newline at end of file
+}\r