]> git.proxmox.com Git - mirror_edk2.git/commitdiff
CryptoPkg: Add EC key retrieving and signature interface.
authorQi Zhang <qi1.zhang@intel.com>
Wed, 12 Oct 2022 02:47:58 +0000 (10:47 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 12 Oct 2022 05:56:00 +0000 (05:56 +0000)
This patch is used to retrieve EC key from PEM and X509 and
carry out the EC-DSA signature and verify it.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4102

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Qi Zhang <qi1.zhang@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
CryptoPkg/Include/Library/BaseCryptLib.h
CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c
CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c
CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c
CryptoPkg/Library/BaseCryptLibNull/Pem/CryptPemNull.c
CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
CryptoPkg/Library/BaseCryptLibNull/Pk/CryptX509Null.c

index 63c6228368c631d3a048183d84451dd27b98b3f1..dfeb8c7d5573a82aff1f973d254c28aa7fb1f2c9 100644 (file)
@@ -16,6 +16,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 \r
 #define CRYPTO_NID_NULL  0x0000\r
 \r
+// Hash\r
+#define CRYPTO_NID_SHA256  0x0001\r
+#define CRYPTO_NID_SHA384  0x0002\r
+#define CRYPTO_NID_SHA512  0x0003\r
+\r
 // Key Exchange\r
 #define CRYPTO_NID_SECP256R1  0x0204\r
 #define CRYPTO_NID_SECP384R1  0x0205\r
@@ -3678,4 +3683,128 @@ EcDhComputeKey (
   IN OUT  UINTN        *KeySize\r
   );\r
 \r
+/**\r
+  Retrieve the EC Private Key from the password-protected PEM key data.\r
+\r
+  @param[in]  PemData      Pointer to the PEM-encoded key data to be retrieved.\r
+  @param[in]  PemSize      Size of the PEM key data in bytes.\r
+  @param[in]  Password     NULL-terminated passphrase used for encrypted PEM key data.\r
+  @param[out] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC private key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If PemData is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Private Key was retrieved successfully.\r
+  @retval  FALSE  Invalid PEM key data or incorrect password.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPrivateKeyFromPem (\r
+  IN   CONST UINT8  *PemData,\r
+  IN   UINTN        PemSize,\r
+  IN   CONST CHAR8  *Password,\r
+  OUT  VOID         **EcContext\r
+  );\r
+\r
+/**\r
+  Retrieve the EC Public Key from one DER-encoded X509 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] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC public key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If Cert is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Public Key was retrieved successfully.\r
+  @retval  FALSE  Fail to retrieve EC public key from X509 certificate.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPublicKeyFromX509 (\r
+  IN   CONST UINT8  *Cert,\r
+  IN   UINTN        CertSize,\r
+  OUT  VOID         **EcContext\r
+  );\r
+\r
+/**\r
+  Carries out the EC-DSA signature.\r
+\r
+  This function carries out the EC-DSA signature.\r
+  If the Signature buffer is too small to hold the contents of signature, FALSE\r
+  is returned and SigSize is set to the required buffer size to obtain the signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+  If SigSize is large enough but Signature is NULL, then return FALSE.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]       EcContext    Pointer to EC context for signature generation.\r
+  @param[in]       HashNid      hash NID\r
+  @param[in]       MessageHash  Pointer to octet message hash to be signed.\r
+  @param[in]       HashSize     Size of the message hash in bytes.\r
+  @param[out]      Signature    Pointer to buffer to receive EC-DSA signature.\r
+  @param[in, out]  SigSize      On input, the size of Signature buffer in bytes.\r
+                                On output, the size of data returned in Signature buffer in bytes.\r
+\r
+  @retval  TRUE   Signature successfully generated in EC-DSA.\r
+  @retval  FALSE  Signature generation failed.\r
+  @retval  FALSE  SigSize is too small.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaSign (\r
+  IN      VOID         *EcContext,\r
+  IN      UINTN        HashNid,\r
+  IN      CONST UINT8  *MessageHash,\r
+  IN      UINTN        HashSize,\r
+  OUT     UINT8        *Signature,\r
+  IN OUT  UINTN        *SigSize\r
+  );\r
+\r
+/**\r
+  Verifies the EC-DSA signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If Signature is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]  EcContext    Pointer to EC context for signature verification.\r
+  @param[in]  HashNid      hash NID\r
+  @param[in]  MessageHash  Pointer to octet message hash to be checked.\r
+  @param[in]  HashSize     Size of the message hash in bytes.\r
+  @param[in]  Signature    Pointer to EC-DSA signature to be verified.\r
+  @param[in]  SigSize      Size of signature in bytes.\r
+\r
+  @retval  TRUE   Valid signature encoded in EC-DSA.\r
+  @retval  FALSE  Invalid signature or invalid EC context.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaVerify (\r
+  IN  VOID         *EcContext,\r
+  IN  UINTN        HashNid,\r
+  IN  CONST UINT8  *MessageHash,\r
+  IN  UINTN        HashSize,\r
+  IN  CONST UINT8  *Signature,\r
+  IN  UINTN        SigSize\r
+  );\r
+\r
 #endif // __BASE_CRYPT_LIB_H__\r
index 7733d772f40ab023119257511f940993192a4a8a..559a6b4df037256068b6adee2ca09c0d89767fdc 100644 (file)
@@ -126,3 +126,90 @@ _Exit:
 \r
   return Status;\r
 }\r
+\r
+/**\r
+  Retrieve the EC Private Key from the password-protected PEM key data.\r
+\r
+  @param[in]  PemData      Pointer to the PEM-encoded key data to be retrieved.\r
+  @param[in]  PemSize      Size of the PEM key data in bytes.\r
+  @param[in]  Password     NULL-terminated passphrase used for encrypted PEM key data.\r
+  @param[out] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC private key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If PemData is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Private Key was retrieved successfully.\r
+  @retval  FALSE  Invalid PEM key data or incorrect password.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPrivateKeyFromPem (\r
+  IN   CONST UINT8  *PemData,\r
+  IN   UINTN        PemSize,\r
+  IN   CONST CHAR8  *Password,\r
+  OUT  VOID         **EcContext\r
+  )\r
+{\r
+ #if FixedPcdGetBool (PcdOpensslEcEnabled)\r
+  BOOLEAN  Status;\r
+  BIO      *PemBio;\r
+\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if ((PemData == NULL) || (EcContext == NULL) || (PemSize > INT_MAX)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Add possible block-cipher descriptor for PEM data decryption.\r
+  // NOTE: Only support most popular ciphers AES for the encrypted PEM.\r
+  //\r
+  if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  Status = FALSE;\r
+\r
+  //\r
+  // Read encrypted PEM Data.\r
+  //\r
+  PemBio = BIO_new (BIO_s_mem ());\r
+  if (PemBio == NULL) {\r
+    goto _Exit;\r
+  }\r
+\r
+  if (BIO_write (PemBio, PemData, (int)PemSize) <= 0) {\r
+    goto _Exit;\r
+  }\r
+\r
+  //\r
+  // Retrieve EC Private Key from encrypted PEM data.\r
+  //\r
+  *EcContext = PEM_read_bio_ECPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password);\r
+  if (*EcContext != NULL) {\r
+    Status = TRUE;\r
+  }\r
+\r
+_Exit:\r
+  //\r
+  // Release Resources.\r
+  //\r
+  BIO_free (PemBio);\r
+\r
+  return Status;\r
+ #else\r
+  return FALSE;\r
+ #endif\r
+}\r
index 4eeabd91ad6ed297b2beaddfd70148814418c067..4ca9357c96333f04f965db53feaf47a8c11efa1f 100644 (file)
@@ -36,3 +36,33 @@ RsaGetPrivateKeyFromPem (
   ASSERT (FALSE);\r
   return FALSE;\r
 }\r
+\r
+/**\r
+  Retrieve the EC Private Key from the password-protected PEM key data.\r
+\r
+  @param[in]  PemData      Pointer to the PEM-encoded key data to be retrieved.\r
+  @param[in]  PemSize      Size of the PEM key data in bytes.\r
+  @param[in]  Password     NULL-terminated passphrase used for encrypted PEM key data.\r
+  @param[out] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC private key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If PemData is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Private Key was retrieved successfully.\r
+  @retval  FALSE  Invalid PEM key data or incorrect password.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPrivateKeyFromPem (\r
+  IN   CONST UINT8  *PemData,\r
+  IN   UINTN        PemSize,\r
+  IN   CONST CHAR8  *Password,\r
+  OUT  VOID         **EcContext\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
index 396c819834bd64c445171b08555f824cbad0ba06..d8cc9ba0e8f968f6cbd9ac4c56018f9a4392cd0b 100644 (file)
@@ -763,3 +763,261 @@ fail:
   EC_KEY_free (PeerEcKey);\r
   return RetVal;\r
 }\r
+\r
+/**\r
+  Carries out the EC-DSA signature.\r
+\r
+  This function carries out the EC-DSA signature.\r
+  If the Signature buffer is too small to hold the contents of signature, FALSE\r
+  is returned and SigSize is set to the required buffer size to obtain the signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+  If SigSize is large enough but Signature is NULL, then return FALSE.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]       EcContext    Pointer to EC context for signature generation.\r
+  @param[in]       HashNid      hash NID\r
+  @param[in]       MessageHash  Pointer to octet message hash to be signed.\r
+  @param[in]       HashSize     Size of the message hash in bytes.\r
+  @param[out]      Signature    Pointer to buffer to receive EC-DSA signature.\r
+  @param[in, out]  SigSize      On input, the size of Signature buffer in bytes.\r
+                                On output, the size of data returned in Signature buffer in bytes.\r
+\r
+  @retval  TRUE   Signature successfully generated in EC-DSA.\r
+  @retval  FALSE  Signature generation failed.\r
+  @retval  FALSE  SigSize is too small.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaSign (\r
+  IN      VOID         *EcContext,\r
+  IN      UINTN        HashNid,\r
+  IN      CONST UINT8  *MessageHash,\r
+  IN      UINTN        HashSize,\r
+  OUT     UINT8        *Signature,\r
+  IN OUT  UINTN        *SigSize\r
+  )\r
+{\r
+  EC_KEY     *EcKey;\r
+  ECDSA_SIG  *EcDsaSig;\r
+  INT32      OpenSslNid;\r
+  UINT8      HalfSize;\r
+  BIGNUM     *R;\r
+  BIGNUM     *S;\r
+  INTN       RSize;\r
+  INTN       SSize;\r
+\r
+  if ((EcContext == NULL) || (MessageHash == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (Signature == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  EcKey      = (EC_KEY *)EcContext;\r
+  OpenSslNid = EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey));\r
+  switch (OpenSslNid) {\r
+    case NID_X9_62_prime256v1:\r
+      HalfSize = 32;\r
+      break;\r
+    case NID_secp384r1:\r
+      HalfSize = 48;\r
+      break;\r
+    case NID_secp521r1:\r
+      HalfSize = 66;\r
+      break;\r
+    default:\r
+      return FALSE;\r
+  }\r
+\r
+  if (*SigSize < (UINTN)(HalfSize * 2)) {\r
+    *SigSize = HalfSize * 2;\r
+    return FALSE;\r
+  }\r
+\r
+  *SigSize = HalfSize * 2;\r
+  ZeroMem (Signature, *SigSize);\r
+\r
+  switch (HashNid) {\r
+    case CRYPTO_NID_SHA256:\r
+      if (HashSize != SHA256_DIGEST_SIZE) {\r
+        return FALSE;\r
+      }\r
+\r
+      break;\r
+\r
+    case CRYPTO_NID_SHA384:\r
+      if (HashSize != SHA384_DIGEST_SIZE) {\r
+        return FALSE;\r
+      }\r
+\r
+      break;\r
+\r
+    case CRYPTO_NID_SHA512:\r
+      if (HashSize != SHA512_DIGEST_SIZE) {\r
+        return FALSE;\r
+      }\r
+\r
+      break;\r
+\r
+    default:\r
+      return FALSE;\r
+  }\r
+\r
+  EcDsaSig = ECDSA_do_sign (\r
+               MessageHash,\r
+               (UINT32)HashSize,\r
+               (EC_KEY *)EcContext\r
+               );\r
+  if (EcDsaSig == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  ECDSA_SIG_get0 (EcDsaSig, (CONST BIGNUM **)&R, (CONST BIGNUM **)&S);\r
+\r
+  RSize = BN_num_bytes (R);\r
+  SSize = BN_num_bytes (S);\r
+  if ((RSize <= 0) || (SSize <= 0)) {\r
+    ECDSA_SIG_free (EcDsaSig);\r
+    return FALSE;\r
+  }\r
+\r
+  ASSERT ((UINTN)RSize <= HalfSize && (UINTN)SSize <= HalfSize);\r
+\r
+  BN_bn2bin (R, &Signature[0 + HalfSize - RSize]);\r
+  BN_bn2bin (S, &Signature[HalfSize + HalfSize - SSize]);\r
+\r
+  ECDSA_SIG_free (EcDsaSig);\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Verifies the EC-DSA signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If Signature is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]  EcContext    Pointer to EC context for signature verification.\r
+  @param[in]  HashNid      hash NID\r
+  @param[in]  MessageHash  Pointer to octet message hash to be checked.\r
+  @param[in]  HashSize     Size of the message hash in bytes.\r
+  @param[in]  Signature    Pointer to EC-DSA signature to be verified.\r
+  @param[in]  SigSize      Size of signature in bytes.\r
+\r
+  @retval  TRUE   Valid signature encoded in EC-DSA.\r
+  @retval  FALSE  Invalid signature or invalid EC context.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaVerify (\r
+  IN  VOID         *EcContext,\r
+  IN  UINTN        HashNid,\r
+  IN  CONST UINT8  *MessageHash,\r
+  IN  UINTN        HashSize,\r
+  IN  CONST UINT8  *Signature,\r
+  IN  UINTN        SigSize\r
+  )\r
+{\r
+  INT32      Result;\r
+  EC_KEY     *EcKey;\r
+  ECDSA_SIG  *EcDsaSig;\r
+  INT32      OpenSslNid;\r
+  UINT8      HalfSize;\r
+  BIGNUM     *R;\r
+  BIGNUM     *S;\r
+\r
+  if ((EcContext == NULL) || (MessageHash == NULL) || (Signature == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((SigSize > INT_MAX) || (SigSize == 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  EcKey      = (EC_KEY *)EcContext;\r
+  OpenSslNid = EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey));\r
+  switch (OpenSslNid) {\r
+    case NID_X9_62_prime256v1:\r
+      HalfSize = 32;\r
+      break;\r
+    case NID_secp384r1:\r
+      HalfSize = 48;\r
+      break;\r
+    case NID_secp521r1:\r
+      HalfSize = 66;\r
+      break;\r
+    default:\r
+      return FALSE;\r
+  }\r
+\r
+  if (SigSize != (UINTN)(HalfSize * 2)) {\r
+    return FALSE;\r
+  }\r
+\r
+  switch (HashNid) {\r
+    case CRYPTO_NID_SHA256:\r
+      if (HashSize != SHA256_DIGEST_SIZE) {\r
+        return FALSE;\r
+      }\r
+\r
+      break;\r
+\r
+    case CRYPTO_NID_SHA384:\r
+      if (HashSize != SHA384_DIGEST_SIZE) {\r
+        return FALSE;\r
+      }\r
+\r
+      break;\r
+\r
+    case CRYPTO_NID_SHA512:\r
+      if (HashSize != SHA512_DIGEST_SIZE) {\r
+        return FALSE;\r
+      }\r
+\r
+      break;\r
+\r
+    default:\r
+      return FALSE;\r
+  }\r
+\r
+  EcDsaSig = ECDSA_SIG_new ();\r
+  if (EcDsaSig == NULL) {\r
+    ECDSA_SIG_free (EcDsaSig);\r
+    return FALSE;\r
+  }\r
+\r
+  R = BN_bin2bn (Signature, (UINT32)HalfSize, NULL);\r
+  S = BN_bin2bn (Signature + HalfSize, (UINT32)HalfSize, NULL);\r
+  if ((R == NULL) || (S == NULL)) {\r
+    ECDSA_SIG_free (EcDsaSig);\r
+    return FALSE;\r
+  }\r
+\r
+  ECDSA_SIG_set0 (EcDsaSig, R, S);\r
+\r
+  Result = ECDSA_do_verify (\r
+             MessageHash,\r
+             (UINT32)HashSize,\r
+             EcDsaSig,\r
+             (EC_KEY *)EcContext\r
+             );\r
+\r
+  ECDSA_SIG_free (EcDsaSig);\r
+\r
+  return (Result == 1);\r
+}\r
index d9f1004f6ce7100681b5bb54ca5252ce144b0d63..1129fa76968a821a66d3d264308c3537112c4538 100644 (file)
@@ -494,3 +494,85 @@ EcDhComputeKey (
   ASSERT (FALSE);\r
   return FALSE;\r
 }\r
+\r
+/**\r
+  Carries out the EC-DSA signature.\r
+\r
+  This function carries out the EC-DSA signature.\r
+  If the Signature buffer is too small to hold the contents of signature, FALSE\r
+  is returned and SigSize is set to the required buffer size to obtain the signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+  If SigSize is large enough but Signature is NULL, then return FALSE.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]       EcContext    Pointer to EC context for signature generation.\r
+  @param[in]       HashNid      hash NID\r
+  @param[in]       MessageHash  Pointer to octet message hash to be signed.\r
+  @param[in]       HashSize     Size of the message hash in bytes.\r
+  @param[out]      Signature    Pointer to buffer to receive EC-DSA signature.\r
+  @param[in, out]  SigSize      On input, the size of Signature buffer in bytes.\r
+                                On output, the size of data returned in Signature buffer in bytes.\r
+\r
+  @retval  TRUE   Signature successfully generated in EC-DSA.\r
+  @retval  FALSE  Signature generation failed.\r
+  @retval  FALSE  SigSize is too small.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaSign (\r
+  IN      VOID         *EcContext,\r
+  IN      UINTN        HashNid,\r
+  IN      CONST UINT8  *MessageHash,\r
+  IN      UINTN        HashSize,\r
+  OUT     UINT8        *Signature,\r
+  IN OUT  UINTN        *SigSize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Verifies the EC-DSA signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If Signature is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]  EcContext    Pointer to EC context for signature verification.\r
+  @param[in]  HashNid      hash NID\r
+  @param[in]  MessageHash  Pointer to octet message hash to be checked.\r
+  @param[in]  HashSize     Size of the message hash in bytes.\r
+  @param[in]  Signature    Pointer to EC-DSA signature to be verified.\r
+  @param[in]  SigSize      Size of signature in bytes.\r
+\r
+  @retval  TRUE   Valid signature encoded in EC-DSA.\r
+  @retval  FALSE  Invalid signature or invalid EC context.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaVerify (\r
+  IN  VOID         *EcContext,\r
+  IN  UINTN        HashNid,\r
+  IN  CONST UINT8  *MessageHash,\r
+  IN  UINTN        HashSize,\r
+  IN  CONST UINT8  *Signature,\r
+  IN  UINTN        SigSize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
index e6bb45e64135e37a5d331f828d12dcf4f6a27292..58d3f27b11f2d890b92593688fa585b646b533ee 100644 (file)
@@ -842,3 +842,86 @@ X509GetTBSCert (
 \r
   return TRUE;\r
 }\r
+\r
+/**\r
+  Retrieve the EC Public Key from one DER-encoded X509 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] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC public key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If Cert is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Public Key was retrieved successfully.\r
+  @retval  FALSE  Fail to retrieve EC public key from X509 certificate.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPublicKeyFromX509 (\r
+  IN   CONST UINT8  *Cert,\r
+  IN   UINTN        CertSize,\r
+  OUT  VOID         **EcContext\r
+  )\r
+{\r
+ #if FixedPcdGetBool (PcdOpensslEcEnabled)\r
+  BOOLEAN   Status;\r
+  EVP_PKEY  *Pkey;\r
+  X509      *X509Cert;\r
+\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if ((Cert == NULL) || (EcContext == NULL)) {\r
+    return FALSE;\r
+  }\r
+\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
+  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) || (EVP_PKEY_id (Pkey) != EVP_PKEY_EC)) {\r
+    goto _Exit;\r
+  }\r
+\r
+  //\r
+  // Duplicate EC Context from the retrieved EVP_PKEY.\r
+  //\r
+  if ((*EcContext = EC_KEY_dup (EVP_PKEY_get0_EC_KEY (Pkey))) != NULL) {\r
+    Status = TRUE;\r
+  }\r
+\r
+_Exit:\r
+  //\r
+  // Release Resources.\r
+  //\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
+ #else\r
+  return FALSE;\r
+ #endif\r
+}\r
index 38819723c791e8845f0cb442cafdda379f496f91..c6718e6aeb52a956b3d84d912cd9646b7caa8da2 100644 (file)
@@ -292,3 +292,31 @@ X509GetTBSCert (
   ASSERT (FALSE);\r
   return FALSE;\r
 }\r
+\r
+/**\r
+  Retrieve the EC Public Key from one DER-encoded X509 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] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC public key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If Cert is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Public Key was retrieved successfully.\r
+  @retval  FALSE  Fail to retrieve EC public key from X509 certificate.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPublicKeyFromX509 (\r
+  IN   CONST UINT8  *Cert,\r
+  IN   UINTN        CertSize,\r
+  OUT  VOID         **EcContext\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
index 4eeabd91ad6ed297b2beaddfd70148814418c067..4ca9357c96333f04f965db53feaf47a8c11efa1f 100644 (file)
@@ -36,3 +36,33 @@ RsaGetPrivateKeyFromPem (
   ASSERT (FALSE);\r
   return FALSE;\r
 }\r
+\r
+/**\r
+  Retrieve the EC Private Key from the password-protected PEM key data.\r
+\r
+  @param[in]  PemData      Pointer to the PEM-encoded key data to be retrieved.\r
+  @param[in]  PemSize      Size of the PEM key data in bytes.\r
+  @param[in]  Password     NULL-terminated passphrase used for encrypted PEM key data.\r
+  @param[out] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC private key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If PemData is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Private Key was retrieved successfully.\r
+  @retval  FALSE  Invalid PEM key data or incorrect password.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPrivateKeyFromPem (\r
+  IN   CONST UINT8  *PemData,\r
+  IN   UINTN        PemSize,\r
+  IN   CONST CHAR8  *Password,\r
+  OUT  VOID         **EcContext\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
index d9f1004f6ce7100681b5bb54ca5252ce144b0d63..1129fa76968a821a66d3d264308c3537112c4538 100644 (file)
@@ -494,3 +494,85 @@ EcDhComputeKey (
   ASSERT (FALSE);\r
   return FALSE;\r
 }\r
+\r
+/**\r
+  Carries out the EC-DSA signature.\r
+\r
+  This function carries out the EC-DSA signature.\r
+  If the Signature buffer is too small to hold the contents of signature, FALSE\r
+  is returned and SigSize is set to the required buffer size to obtain the signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+  If SigSize is large enough but Signature is NULL, then return FALSE.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]       EcContext    Pointer to EC context for signature generation.\r
+  @param[in]       HashNid      hash NID\r
+  @param[in]       MessageHash  Pointer to octet message hash to be signed.\r
+  @param[in]       HashSize     Size of the message hash in bytes.\r
+  @param[out]      Signature    Pointer to buffer to receive EC-DSA signature.\r
+  @param[in, out]  SigSize      On input, the size of Signature buffer in bytes.\r
+                                On output, the size of data returned in Signature buffer in bytes.\r
+\r
+  @retval  TRUE   Signature successfully generated in EC-DSA.\r
+  @retval  FALSE  Signature generation failed.\r
+  @retval  FALSE  SigSize is too small.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaSign (\r
+  IN      VOID         *EcContext,\r
+  IN      UINTN        HashNid,\r
+  IN      CONST UINT8  *MessageHash,\r
+  IN      UINTN        HashSize,\r
+  OUT     UINT8        *Signature,\r
+  IN OUT  UINTN        *SigSize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Verifies the EC-DSA signature.\r
+\r
+  If EcContext is NULL, then return FALSE.\r
+  If MessageHash is NULL, then return FALSE.\r
+  If Signature is NULL, then return FALSE.\r
+  If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.\r
+\r
+  For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.\r
+  For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.\r
+  For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.\r
+\r
+  @param[in]  EcContext    Pointer to EC context for signature verification.\r
+  @param[in]  HashNid      hash NID\r
+  @param[in]  MessageHash  Pointer to octet message hash to be checked.\r
+  @param[in]  HashSize     Size of the message hash in bytes.\r
+  @param[in]  Signature    Pointer to EC-DSA signature to be verified.\r
+  @param[in]  SigSize      Size of signature in bytes.\r
+\r
+  @retval  TRUE   Valid signature encoded in EC-DSA.\r
+  @retval  FALSE  Invalid signature or invalid EC context.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcDsaVerify (\r
+  IN  VOID         *EcContext,\r
+  IN  UINTN        HashNid,\r
+  IN  CONST UINT8  *MessageHash,\r
+  IN  UINTN        HashSize,\r
+  IN  CONST UINT8  *Signature,\r
+  IN  UINTN        SigSize\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r
index 38819723c791e8845f0cb442cafdda379f496f91..c6718e6aeb52a956b3d84d912cd9646b7caa8da2 100644 (file)
@@ -292,3 +292,31 @@ X509GetTBSCert (
   ASSERT (FALSE);\r
   return FALSE;\r
 }\r
+\r
+/**\r
+  Retrieve the EC Public Key from one DER-encoded X509 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] EcContext    Pointer to new-generated EC DSA context which contain the retrieved\r
+                           EC public key component. Use EcFree() function to free the\r
+                           resource.\r
+\r
+  If Cert is NULL, then return FALSE.\r
+  If EcContext is NULL, then return FALSE.\r
+\r
+  @retval  TRUE   EC Public Key was retrieved successfully.\r
+  @retval  FALSE  Fail to retrieve EC public key from X509 certificate.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EcGetPublicKeyFromX509 (\r
+  IN   CONST UINT8  *Cert,\r
+  IN   UINTN        CertSize,\r
+  OUT  VOID         **EcContext\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return FALSE;\r
+}\r