* [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface.
@ 2022-10-12 2:47 Qi Zhang
2022-10-12 2:47 ` [PATCH V2 1/3] " Qi Zhang
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Qi Zhang @ 2022-10-12 2:47 UTC (permalink / raw)
To: devel; +Cc: Qi Zhang, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang
This patch is used to retrieve EC key from PEM and X509 and
carry out the EC-DSA signature and verify it.
The interface was tested by:
1. DeviceSecurity on edk2-staging
https://github.com/tianocore/edk2-staging/tree/DeviceSecurity.
2. Unit test in CryptoPkg/Test
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4102
PR: https://github.com/tianocore/edk2/pull/3464
V2 change: change the protocol version.
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>
Qi Zhang (3):
CryptoPkg: Add EC key retrieving and signature interface.
CryptoPkg: Add EC key interface to DXE and protocol
CryptoPkg: add unit test for EC key interface.
CryptoPkg/Driver/Crypto.c | 143 +++++++++-
CryptoPkg/Include/Library/BaseCryptLib.h | 129 +++++++++
.../Pcd/PcdCryptoServiceFamilyEnable.h | 4 +
CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c | 87 ++++++
.../Library/BaseCryptLib/Pem/CryptPemNull.c | 30 ++
CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 258 ++++++++++++++++++
.../Library/BaseCryptLib/Pk/CryptEcNull.c | 82 ++++++
CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c | 83 ++++++
.../Library/BaseCryptLib/Pk/CryptX509Null.c | 28 ++
.../BaseCryptLibNull/Pem/CryptPemNull.c | 30 ++
.../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 82 ++++++
.../BaseCryptLibNull/Pk/CryptX509Null.c | 28 ++
.../BaseCryptLibOnProtocolPpi/CryptLib.c | 136 +++++++++
CryptoPkg/Private/Protocol/Crypto.h | 131 ++++++++-
.../UnitTest/Library/BaseCryptLib/EcTests.c | 156 +++++++++++
15 files changed, 1405 insertions(+), 2 deletions(-)
--
2.26.2.windows.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH V2 1/3] CryptoPkg: Add EC key retrieving and signature interface.
2022-10-12 2:47 [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Qi Zhang
@ 2022-10-12 2:47 ` Qi Zhang
2022-10-12 2:47 ` [PATCH V2 2/3] CryptoPkg: Add EC key interface to DXE and protocol Qi Zhang
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Qi Zhang @ 2022-10-12 2:47 UTC (permalink / raw)
To: devel; +Cc: Qi Zhang, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang
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>
---
CryptoPkg/Include/Library/BaseCryptLib.h | 129 +++++++++
CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c | 87 ++++++
.../Library/BaseCryptLib/Pem/CryptPemNull.c | 30 ++
CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 258 ++++++++++++++++++
.../Library/BaseCryptLib/Pk/CryptEcNull.c | 82 ++++++
CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c | 83 ++++++
.../Library/BaseCryptLib/Pk/CryptX509Null.c | 28 ++
.../BaseCryptLibNull/Pem/CryptPemNull.c | 30 ++
.../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 82 ++++++
.../BaseCryptLibNull/Pk/CryptX509Null.c | 28 ++
10 files changed, 837 insertions(+)
diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index 63c6228368..dfeb8c7d55 100644
--- a/CryptoPkg/Include/Library/BaseCryptLib.h
+++ b/CryptoPkg/Include/Library/BaseCryptLib.h
@@ -16,6 +16,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define CRYPTO_NID_NULL 0x0000
+// Hash
+#define CRYPTO_NID_SHA256 0x0001
+#define CRYPTO_NID_SHA384 0x0002
+#define CRYPTO_NID_SHA512 0x0003
+
// Key Exchange
#define CRYPTO_NID_SECP256R1 0x0204
#define CRYPTO_NID_SECP384R1 0x0205
@@ -3678,4 +3683,128 @@ EcDhComputeKey (
IN OUT UINTN *KeySize
);
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ );
+
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ );
+
+/**
+ Carries out the EC-DSA signature.
+
+ This function carries out the EC-DSA signature.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature generation.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive EC-DSA signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in EC-DSA.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaSign (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ );
+
+/**
+ Verifies the EC-DSA signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If Signature is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature verification.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be checked.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[in] Signature Pointer to EC-DSA signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+
+ @retval TRUE Valid signature encoded in EC-DSA.
+ @retval FALSE Invalid signature or invalid EC context.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaVerify (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize
+ );
+
#endif // __BASE_CRYPT_LIB_H__
diff --git a/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c b/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c
index 7733d772f4..559a6b4df0 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c
@@ -126,3 +126,90 @@ _Exit:
return Status;
}
+
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ )
+{
+ #if FixedPcdGetBool (PcdOpensslEcEnabled)
+ BOOLEAN Status;
+ BIO *PemBio;
+
+ //
+ // Check input parameters.
+ //
+ if ((PemData == NULL) || (EcContext == NULL) || (PemSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ //
+ // Add possible block-cipher descriptor for PEM data decryption.
+ // NOTE: Only support most popular ciphers AES for the encrypted PEM.
+ //
+ if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) {
+ return FALSE;
+ }
+
+ if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) {
+ return FALSE;
+ }
+
+ if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) {
+ return FALSE;
+ }
+
+ Status = FALSE;
+
+ //
+ // Read encrypted PEM Data.
+ //
+ PemBio = BIO_new (BIO_s_mem ());
+ if (PemBio == NULL) {
+ goto _Exit;
+ }
+
+ if (BIO_write (PemBio, PemData, (int)PemSize) <= 0) {
+ goto _Exit;
+ }
+
+ //
+ // Retrieve EC Private Key from encrypted PEM data.
+ //
+ *EcContext = PEM_read_bio_ECPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password);
+ if (*EcContext != NULL) {
+ Status = TRUE;
+ }
+
+_Exit:
+ //
+ // Release Resources.
+ //
+ BIO_free (PemBio);
+
+ return Status;
+ #else
+ return FALSE;
+ #endif
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c b/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c
index 4eeabd91ad..4ca9357c96 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pem/CryptPemNull.c
@@ -36,3 +36,33 @@ RsaGetPrivateKeyFromPem (
ASSERT (FALSE);
return FALSE;
}
+
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
index 396c819834..d8cc9ba0e8 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c
@@ -763,3 +763,261 @@ fail:
EC_KEY_free (PeerEcKey);
return RetVal;
}
+
+/**
+ Carries out the EC-DSA signature.
+
+ This function carries out the EC-DSA signature.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature generation.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive EC-DSA signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in EC-DSA.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaSign (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ EC_KEY *EcKey;
+ ECDSA_SIG *EcDsaSig;
+ INT32 OpenSslNid;
+ UINT8 HalfSize;
+ BIGNUM *R;
+ BIGNUM *S;
+ INTN RSize;
+ INTN SSize;
+
+ if ((EcContext == NULL) || (MessageHash == NULL)) {
+ return FALSE;
+ }
+
+ if (Signature == NULL) {
+ return FALSE;
+ }
+
+ EcKey = (EC_KEY *)EcContext;
+ OpenSslNid = EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey));
+ switch (OpenSslNid) {
+ case NID_X9_62_prime256v1:
+ HalfSize = 32;
+ break;
+ case NID_secp384r1:
+ HalfSize = 48;
+ break;
+ case NID_secp521r1:
+ HalfSize = 66;
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (*SigSize < (UINTN)(HalfSize * 2)) {
+ *SigSize = HalfSize * 2;
+ return FALSE;
+ }
+
+ *SigSize = HalfSize * 2;
+ ZeroMem (Signature, *SigSize);
+
+ switch (HashNid) {
+ case CRYPTO_NID_SHA256:
+ if (HashSize != SHA256_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA384:
+ if (HashSize != SHA384_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA512:
+ if (HashSize != SHA512_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ EcDsaSig = ECDSA_do_sign (
+ MessageHash,
+ (UINT32)HashSize,
+ (EC_KEY *)EcContext
+ );
+ if (EcDsaSig == NULL) {
+ return FALSE;
+ }
+
+ ECDSA_SIG_get0 (EcDsaSig, (CONST BIGNUM **)&R, (CONST BIGNUM **)&S);
+
+ RSize = BN_num_bytes (R);
+ SSize = BN_num_bytes (S);
+ if ((RSize <= 0) || (SSize <= 0)) {
+ ECDSA_SIG_free (EcDsaSig);
+ return FALSE;
+ }
+
+ ASSERT ((UINTN)RSize <= HalfSize && (UINTN)SSize <= HalfSize);
+
+ BN_bn2bin (R, &Signature[0 + HalfSize - RSize]);
+ BN_bn2bin (S, &Signature[HalfSize + HalfSize - SSize]);
+
+ ECDSA_SIG_free (EcDsaSig);
+
+ return TRUE;
+}
+
+/**
+ Verifies the EC-DSA signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If Signature is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature verification.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be checked.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[in] Signature Pointer to EC-DSA signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+
+ @retval TRUE Valid signature encoded in EC-DSA.
+ @retval FALSE Invalid signature or invalid EC context.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaVerify (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize
+ )
+{
+ INT32 Result;
+ EC_KEY *EcKey;
+ ECDSA_SIG *EcDsaSig;
+ INT32 OpenSslNid;
+ UINT8 HalfSize;
+ BIGNUM *R;
+ BIGNUM *S;
+
+ if ((EcContext == NULL) || (MessageHash == NULL) || (Signature == NULL)) {
+ return FALSE;
+ }
+
+ if ((SigSize > INT_MAX) || (SigSize == 0)) {
+ return FALSE;
+ }
+
+ EcKey = (EC_KEY *)EcContext;
+ OpenSslNid = EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey));
+ switch (OpenSslNid) {
+ case NID_X9_62_prime256v1:
+ HalfSize = 32;
+ break;
+ case NID_secp384r1:
+ HalfSize = 48;
+ break;
+ case NID_secp521r1:
+ HalfSize = 66;
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (SigSize != (UINTN)(HalfSize * 2)) {
+ return FALSE;
+ }
+
+ switch (HashNid) {
+ case CRYPTO_NID_SHA256:
+ if (HashSize != SHA256_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA384:
+ if (HashSize != SHA384_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA512:
+ if (HashSize != SHA512_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ EcDsaSig = ECDSA_SIG_new ();
+ if (EcDsaSig == NULL) {
+ ECDSA_SIG_free (EcDsaSig);
+ return FALSE;
+ }
+
+ R = BN_bin2bn (Signature, (UINT32)HalfSize, NULL);
+ S = BN_bin2bn (Signature + HalfSize, (UINT32)HalfSize, NULL);
+ if ((R == NULL) || (S == NULL)) {
+ ECDSA_SIG_free (EcDsaSig);
+ return FALSE;
+ }
+
+ ECDSA_SIG_set0 (EcDsaSig, R, S);
+
+ Result = ECDSA_do_verify (
+ MessageHash,
+ (UINT32)HashSize,
+ EcDsaSig,
+ (EC_KEY *)EcContext
+ );
+
+ ECDSA_SIG_free (EcDsaSig);
+
+ return (Result == 1);
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
index d9f1004f6c..1129fa7696 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c
@@ -494,3 +494,85 @@ EcDhComputeKey (
ASSERT (FALSE);
return FALSE;
}
+
+/**
+ Carries out the EC-DSA signature.
+
+ This function carries out the EC-DSA signature.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature generation.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive EC-DSA signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in EC-DSA.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaSign (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Verifies the EC-DSA signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If Signature is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature verification.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be checked.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[in] Signature Pointer to EC-DSA signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+
+ @retval TRUE Valid signature encoded in EC-DSA.
+ @retval FALSE Invalid signature or invalid EC context.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaVerify (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
index e6bb45e641..58d3f27b11 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
@@ -842,3 +842,86 @@ X509GetTBSCert (
return TRUE;
}
+
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ )
+{
+ #if FixedPcdGetBool (PcdOpensslEcEnabled)
+ BOOLEAN Status;
+ EVP_PKEY *Pkey;
+ X509 *X509Cert;
+
+ //
+ // Check input parameters.
+ //
+ if ((Cert == NULL) || (EcContext == NULL)) {
+ return FALSE;
+ }
+
+ Pkey = NULL;
+ X509Cert = NULL;
+
+ //
+ // Read DER-encoded X509 Certificate and Construct X509 object.
+ //
+ Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert);
+ if ((X509Cert == NULL) || (!Status)) {
+ Status = FALSE;
+ goto _Exit;
+ }
+
+ Status = FALSE;
+
+ //
+ // Retrieve and check EVP_PKEY data from X509 Certificate.
+ //
+ Pkey = X509_get_pubkey (X509Cert);
+ if ((Pkey == NULL) || (EVP_PKEY_id (Pkey) != EVP_PKEY_EC)) {
+ goto _Exit;
+ }
+
+ //
+ // Duplicate EC Context from the retrieved EVP_PKEY.
+ //
+ if ((*EcContext = EC_KEY_dup (EVP_PKEY_get0_EC_KEY (Pkey))) != NULL) {
+ Status = TRUE;
+ }
+
+_Exit:
+ //
+ // Release Resources.
+ //
+ if (X509Cert != NULL) {
+ X509_free (X509Cert);
+ }
+
+ if (Pkey != NULL) {
+ EVP_PKEY_free (Pkey);
+ }
+
+ return Status;
+ #else
+ return FALSE;
+ #endif
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c
index 38819723c7..c6718e6aeb 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509Null.c
@@ -292,3 +292,31 @@ X509GetTBSCert (
ASSERT (FALSE);
return FALSE;
}
+
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pem/CryptPemNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pem/CryptPemNull.c
index 4eeabd91ad..4ca9357c96 100644
--- a/CryptoPkg/Library/BaseCryptLibNull/Pem/CryptPemNull.c
+++ b/CryptoPkg/Library/BaseCryptLibNull/Pem/CryptPemNull.c
@@ -36,3 +36,33 @@ RsaGetPrivateKeyFromPem (
ASSERT (FALSE);
return FALSE;
}
+
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
index d9f1004f6c..1129fa7696 100644
--- a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
+++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c
@@ -494,3 +494,85 @@ EcDhComputeKey (
ASSERT (FALSE);
return FALSE;
}
+
+/**
+ Carries out the EC-DSA signature.
+
+ This function carries out the EC-DSA signature.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature generation.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive EC-DSA signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in EC-DSA.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaSign (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Verifies the EC-DSA signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If Signature is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature verification.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be checked.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[in] Signature Pointer to EC-DSA signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+
+ @retval TRUE Valid signature encoded in EC-DSA.
+ @retval FALSE Invalid signature or invalid EC context.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaVerify (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptX509Null.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptX509Null.c
index 38819723c7..c6718e6aeb 100644
--- a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptX509Null.c
+++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptX509Null.c
@@ -292,3 +292,31 @@ X509GetTBSCert (
ASSERT (FALSE);
return FALSE;
}
+
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH V2 2/3] CryptoPkg: Add EC key interface to DXE and protocol
2022-10-12 2:47 [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Qi Zhang
2022-10-12 2:47 ` [PATCH V2 1/3] " Qi Zhang
@ 2022-10-12 2:47 ` Qi Zhang
2022-10-12 2:48 ` [PATCH V2 3/3] CryptoPkg: add unit test for EC key interface Qi Zhang
2022-10-12 5:57 ` [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Yao, Jiewen
3 siblings, 0 replies; 5+ messages in thread
From: Qi Zhang @ 2022-10-12 2:47 UTC (permalink / raw)
To: devel; +Cc: Qi Zhang, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang
The implementation provide EC key interface for EFI
driver nad EFI BaseCrypt protocol.
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>
---
CryptoPkg/Driver/Crypto.c | 143 +++++++++++++++++-
.../Pcd/PcdCryptoServiceFamilyEnable.h | 4 +
.../BaseCryptLibOnProtocolPpi/CryptLib.c | 136 +++++++++++++++++
CryptoPkg/Private/Protocol/Crypto.h | 131 +++++++++++++++-
4 files changed, 412 insertions(+), 2 deletions(-)
diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index f1ff77855c..1928adbff7 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -6137,6 +6137,142 @@ CryptoServiceEcDhComputeKey (
return CALL_BASECRYPTLIB (Ec.Services.DhComputeKey, EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
}
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.GetPublicKeyFromX509, EcGetPublicKeyFromX509, (Cert, CertSize, EcContext), FALSE);
+}
+
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.GetPrivateKeyFromPem, EcGetPrivateKeyFromPem, (PemData, PemSize, Password, EcContext), FALSE);
+}
+
+/**
+ Carries out the EC-DSA signature.
+
+ This function carries out the EC-DSA signature.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature generation.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive EC-DSA signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in EC-DSA.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcDsaSign (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.DsaSign, EcDsaSign, (EcContext, HashNid, MessageHash, HashSize, Signature, SigSize), FALSE);
+}
+
+/**
+ Verifies the EC-DSA signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If Signature is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature verification.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be checked.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[in] Signature Pointer to EC-DSA signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+
+ @retval TRUE Valid signature encoded in EC-DSA.
+ @retval FALSE Invalid signature or invalid EC context.
+
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceEcDsaVerify (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize
+ )
+{
+ return CALL_BASECRYPTLIB (Ec.Services.DsaVerify, EcDsaVerify, (EcContext, HashNid, MessageHash, HashSize, Signature, SigSize), FALSE);
+}
+
const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
/// Version
CryptoServiceGetCryptoVersion,
@@ -6416,5 +6552,10 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
CryptoServiceTlsSetSignatureAlgoList,
CryptoServiceTlsSetEcCurve,
/// TLS Get (continued)
- CryptoServiceTlsGetExportKey
+ CryptoServiceTlsGetExportKey,
+ /// Ec (Continued)
+ CryptoServiceEcGetPublicKeyFromX509,
+ CryptoServiceEcGetPrivateKeyFromPem,
+ CryptoServiceEcDsaSign,
+ CryptoServiceEcDsaVerify
};
diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
index 4740589417..12b0c0583e 100644
--- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
+++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
@@ -383,6 +383,10 @@ typedef struct {
UINT8 GenerateKey : 1;
UINT8 GetPubKey : 1;
UINT8 DhComputeKey : 1;
+ UINT8 GetPublicKeyFromX509 : 1;
+ UINT8 GetPrivateKeyFromPem : 1;
+ UINT8 DsaSign : 1;
+ UINT8 DsaVerify : 1;
} Services;
UINT32 Family;
} Ec;
diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
index 52b934a545..48ec6d3528 100644
--- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -5164,3 +5164,139 @@ EcDhComputeKey (
{
CALL_CRYPTO_SERVICE (EcDhComputeKey, (EcContext, PeerPublic, PeerPublicSize, CompressFlag, Key, KeySize), FALSE);
}
+
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ )
+{
+ CALL_CRYPTO_SERVICE (EcGetPublicKeyFromX509, (Cert, CertSize, EcContext), FALSE);
+}
+
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ )
+{
+ CALL_CRYPTO_SERVICE (EcGetPrivateKeyFromPem, (PemData, PemSize, Password, EcContext), FALSE);
+}
+
+/**
+ Carries out the EC-DSA signature.
+
+ This function carries out the EC-DSA signature.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature generation.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive EC-DSA signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in EC-DSA.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaSign (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ CALL_CRYPTO_SERVICE (EcDsaSign, (EcContext, HashNid, MessageHash, HashSize, Signature, SigSize), FALSE);
+}
+
+/**
+ Verifies the EC-DSA signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If Signature is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature verification.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be checked.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[in] Signature Pointer to EC-DSA signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+
+ @retval TRUE Valid signature encoded in EC-DSA.
+ @retval FALSE Invalid signature or invalid EC context.
+
+**/
+BOOLEAN
+EFIAPI
+EcDsaVerify (
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize
+ )
+{
+ CALL_CRYPTO_SERVICE (EcDsaVerify, (EcContext, HashNid, MessageHash, HashSize, Signature, SigSize), FALSE);
+}
diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h
index 6293efa36b..bfb278d388 100644
--- a/CryptoPkg/Private/Protocol/Crypto.h
+++ b/CryptoPkg/Private/Protocol/Crypto.h
@@ -21,7 +21,7 @@
/// the EDK II Crypto Protocol is extended, this version define must be
/// increased.
///
-#define EDKII_CRYPTO_VERSION 14
+#define EDKII_CRYPTO_VERSION 15
///
/// EDK II Crypto Protocol forward declaration
@@ -4821,6 +4821,130 @@ BOOLEAN
IN OUT UINTN *KeySize
);
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GET_PUBLIC_KEY_FROM_X509)(
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ );
+
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_GET_PRIVATE_KEY_FROM_PEM)(
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ );
+
+/**
+ Carries out the EC-DSA signature.
+
+ This function carries out the EC-DSA signature.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature generation.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive EC-DSA signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in EC-DSA.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_DSA_SIGN)(
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ );
+
+/**
+ Verifies the EC-DSA signature.
+
+ If EcContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If Signature is NULL, then return FALSE.
+ If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA512, SHA3_256, SHA3_384, SHA3_512.
+
+ For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.
+ For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.
+ For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.
+
+ @param[in] EcContext Pointer to EC context for signature verification.
+ @param[in] HashNid hash NID
+ @param[in] MessageHash Pointer to octet message hash to be checked.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[in] Signature Pointer to EC-DSA signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+
+ @retval TRUE Valid signature encoded in EC-DSA.
+ @retval FALSE Invalid signature or invalid EC context.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_EC_DSA_VERIFY)(
+ IN VOID *EcContext,
+ IN UINTN HashNid,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize
+ );
+
///
/// EDK II Crypto Protocol
///
@@ -5084,6 +5208,11 @@ struct _EDKII_CRYPTO_PROTOCOL {
EDKII_CRYPTO_TLS_SET_EC_CURVE TlsSetEcCurve;
/// TLS Get (continued)
EDKII_CRYPTO_TLS_GET_EXPORT_KEY TlsGetExportKey;
+ /// Ec (Continued)
+ EDKII_CRYPTO_EC_GET_PUBLIC_KEY_FROM_X509 EcGetPublicKeyFromX509;
+ EDKII_CRYPTO_EC_GET_PRIVATE_KEY_FROM_PEM EcGetPrivateKeyFromPem;
+ EDKII_CRYPTO_EC_DSA_SIGN EcDsaSign;
+ EDKII_CRYPTO_EC_DSA_VERIFY EcDsaVerify;
};
extern GUID gEdkiiCryptoProtocolGuid;
--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH V2 3/3] CryptoPkg: add unit test for EC key interface.
2022-10-12 2:47 [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Qi Zhang
2022-10-12 2:47 ` [PATCH V2 1/3] " Qi Zhang
2022-10-12 2:47 ` [PATCH V2 2/3] CryptoPkg: Add EC key interface to DXE and protocol Qi Zhang
@ 2022-10-12 2:48 ` Qi Zhang
2022-10-12 5:57 ` [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Yao, Jiewen
3 siblings, 0 replies; 5+ messages in thread
From: Qi Zhang @ 2022-10-12 2:48 UTC (permalink / raw)
To: devel; +Cc: Qi Zhang, Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang
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>
---
.../UnitTest/Library/BaseCryptLib/EcTests.c | 156 ++++++++++++++++++
1 file changed, 156 insertions(+)
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
index 54ce0b22df..ee1e6e870b 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/EcTests.c
@@ -60,6 +60,89 @@ struct Generator EcCurveGenerator[EC_CURVE_NUM_SUPPORTED] =
}
};
+//
+// Root CA X509 Certificate for X509 Verification Routine (Generated by OpenSSL utility).
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mEccTestRootCer[] = {
+ 0x30, 0x82, 0x01, 0xd2, 0x30, 0x82, 0x01, 0x77, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x09, 0x00, 0xcc, 0x10, 0x45, 0x50, 0xaf, 0x50, 0x1b, 0xe2,
+ 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
+ 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30,
+ 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x32, 0x32, 0x37, 0x31, 0x32, 0x30,
+ 0x32, 0x31, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x30, 0x32, 0x32, 0x34,
+ 0x31, 0x32, 0x30, 0x32, 0x31, 0x30, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d,
+ 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+ 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x11, 0xa4, 0x06,
+ 0x65, 0xb6, 0x79, 0x6e, 0x72, 0xb6, 0xd8, 0x09, 0x84, 0x92, 0x86, 0x11,
+ 0x09, 0xde, 0xea, 0xd0, 0x0c, 0x60, 0xf1, 0x8a, 0xff, 0x7c, 0xde, 0xce,
+ 0xec, 0x07, 0xba, 0xa5, 0xb8, 0xd5, 0x17, 0xe5, 0x62, 0x33, 0x2d, 0x88,
+ 0xb1, 0x9a, 0xe6, 0xf3, 0x09, 0x43, 0x0e, 0xa9, 0xf7, 0x3c, 0xe9, 0x20,
+ 0xba, 0xbd, 0xb1, 0x3c, 0x03, 0x89, 0x1e, 0x2a, 0xff, 0x6e, 0x08, 0xff,
+ 0x2e, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0x62, 0xe6, 0xd9, 0xa0, 0xee, 0x38, 0x18, 0x83,
+ 0xfa, 0xe3, 0xed, 0x44, 0xa4, 0x37, 0xfd, 0x4a, 0x04, 0xdf, 0xe1, 0xd5,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0x62, 0xe6, 0xd9, 0xa0, 0xee, 0x38, 0x18, 0x83, 0xfa, 0xe3, 0xed,
+ 0x44, 0xa4, 0x37, 0xfd, 0x4a, 0x04, 0xdf, 0xe1, 0xd5, 0x30, 0x0c, 0x06,
+ 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
+ 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x99, 0x2f, 0x43, 0xeb, 0xdc,
+ 0x4e, 0x53, 0xc7, 0xc1, 0xbd, 0xed, 0x95, 0xdc, 0xae, 0xd3, 0x75, 0xfa,
+ 0xc4, 0xf7, 0xa4, 0x61, 0x00, 0x57, 0xce, 0xf3, 0xe0, 0x23, 0xf6, 0xf0,
+ 0x41, 0x6f, 0xb5, 0x02, 0x21, 0x00, 0xf3, 0x97, 0x11, 0x06, 0x61, 0x10,
+ 0xc7, 0x35, 0xe9, 0xf8, 0x3b, 0x59, 0xec, 0xf5, 0x51, 0xa0, 0xa6, 0x64,
+ 0x6e, 0xe1, 0x44, 0xc7, 0xe1, 0xa2, 0xce, 0x90, 0x7f, 0xae, 0xad, 0xf4,
+ 0xa9, 0xfa,
+};
+
+//
+// PEM key data for EC Private key Retrieving. (Generated by OpenSSL utility).
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mEccTestPemKey[] = {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x45,
+ 0x43, 0x20, 0x50, 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x53,
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x42, 0x67, 0x67, 0x71, 0x68, 0x6b,
+ 0x6a, 0x4f, 0x50, 0x51, 0x4d, 0x42, 0x42, 0x77, 0x3d, 0x3d, 0x0a, 0x2d,
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50,
+ 0x41, 0x52, 0x41, 0x4d, 0x45, 0x54, 0x45, 0x52, 0x53, 0x2d, 0x2d, 0x2d,
+ 0x2d, 0x2d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49,
+ 0x4e, 0x20, 0x45, 0x43, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45,
+ 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x4d, 0x48,
+ 0x63, 0x43, 0x41, 0x51, 0x45, 0x45, 0x49, 0x4d, 0x4a, 0x54, 0x69, 0x75,
+ 0x34, 0x56, 0x54, 0x54, 0x57, 0x68, 0x78, 0x4b, 0x62, 0x51, 0x65, 0x78,
+ 0x6e, 0x30, 0x43, 0x58, 0x41, 0x77, 0x33, 0x44, 0x57, 0x6b, 0x6f, 0x78,
+ 0x79, 0x77, 0x6b, 0x7a, 0x46, 0x50, 0x62, 0x32, 0x48, 0x68, 0x5a, 0x6e,
+ 0x5a, 0x52, 0x6f, 0x41, 0x6f, 0x47, 0x43, 0x43, 0x71, 0x47, 0x53, 0x4d,
+ 0x34, 0x39, 0x0a, 0x41, 0x77, 0x45, 0x48, 0x6f, 0x55, 0x51, 0x44, 0x51,
+ 0x67, 0x41, 0x45, 0x45, 0x61, 0x51, 0x47, 0x5a, 0x62, 0x5a, 0x35, 0x62,
+ 0x6e, 0x4b, 0x32, 0x32, 0x41, 0x6d, 0x45, 0x6b, 0x6f, 0x59, 0x52, 0x43,
+ 0x64, 0x37, 0x71, 0x30, 0x41, 0x78, 0x67, 0x38, 0x59, 0x72, 0x2f, 0x66,
+ 0x4e, 0x37, 0x4f, 0x37, 0x41, 0x65, 0x36, 0x70, 0x62, 0x6a, 0x56, 0x46,
+ 0x2b, 0x56, 0x69, 0x4d, 0x79, 0x32, 0x49, 0x0a, 0x73, 0x5a, 0x72, 0x6d,
+ 0x38, 0x77, 0x6c, 0x44, 0x44, 0x71, 0x6e, 0x33, 0x50, 0x4f, 0x6b, 0x67,
+ 0x75, 0x72, 0x32, 0x78, 0x50, 0x41, 0x4f, 0x4a, 0x48, 0x69, 0x72, 0x2f,
+ 0x62, 0x67, 0x6a, 0x2f, 0x4c, 0x67, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d,
+ 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x45, 0x43, 0x20, 0x50, 0x52, 0x49,
+ 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d,
+ 0x2d, 0x0a,
+};
+
+//
+// Payload for PKCS#7 Signing & Verification Validation.
+//
+CONST CHAR8 *mEcPayload = "payload data for PKCS#7 EC Signing";
+
VOID *Ec1;
VOID *Ec2;
VOID *Group;
@@ -279,12 +362,85 @@ TestVerifyEcDh (
return UNIT_TEST_PASSED;
}
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEcKey (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ VOID *EcPrivKey;
+ VOID *EcPubKey;
+ UINT8 HashValue[SHA256_DIGEST_SIZE];
+ UINTN HashSize;
+ UINT8 Signature[66 * 2];
+ UINTN SigSize;
+
+ //
+ // Retrieve EC private key from PEM data.
+ //
+ Status = EcGetPrivateKeyFromPem (
+ mEccTestPemKey,
+ sizeof (mEccTestPemKey),
+ NULL,
+ &EcPrivKey
+ );
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Retrieve EC public key from X509 Certificate.
+ //
+ Status = EcGetPublicKeyFromX509 (
+ mEccTestRootCer,
+ sizeof (mEccTestRootCer),
+ &EcPubKey
+ );
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Verify EC-DSA
+ //
+ HashSize = sizeof (HashValue);
+ SigSize = sizeof (Signature);
+ //
+ // EC-DSA Signing ...
+ //
+ Status = EcDsaSign (
+ EcPrivKey,
+ CRYPTO_NID_SHA256,
+ HashValue,
+ HashSize,
+ Signature,
+ &SigSize
+ );
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // EC-DSA Verification ...
+ //
+ Status = EcDsaVerify (
+ EcPubKey,
+ CRYPTO_NID_SHA256,
+ HashValue,
+ HashSize,
+ Signature,
+ SigSize
+ );
+ UT_ASSERT_TRUE (Status);
+
+ EcFree (EcPrivKey);
+ EcFree (EcPubKey);
+
+ return UNIT_TEST_PASSED;
+}
+
TEST_DESC mEcTest[] = {
//
// -----Description-----------------Class------------------Function----Pre----Post----Context
//
{ "TestVerifyEcBasic()", "CryptoPkg.BaseCryptLib.Ec", TestVerifyEcBasic, TestVerifyEcPreReq, TestVerifyEcCleanUp, NULL },
{ "TestVerifyEcDh()", "CryptoPkg.BaseCryptLib.Ec", TestVerifyEcDh, TestVerifyEcPreReq, TestVerifyEcCleanUp, NULL },
+ { "TestVerifyEcKey()", "CryptoPkg.BaseCryptLib.Ec", TestVerifyEcKey, NULL, NULL, NULL },
};
UINTN mEcTestNum = ARRAY_SIZE (mEcTest);
--
2.26.2.windows.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface.
2022-10-12 2:47 [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Qi Zhang
` (2 preceding siblings ...)
2022-10-12 2:48 ` [PATCH V2 3/3] CryptoPkg: add unit test for EC key interface Qi Zhang
@ 2022-10-12 5:57 ` Yao, Jiewen
3 siblings, 0 replies; 5+ messages in thread
From: Yao, Jiewen @ 2022-10-12 5:57 UTC (permalink / raw)
To: Zhang, Qi1, devel@edk2.groups.io; +Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin
Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>
Merged https://github.com/tianocore/edk2/pull/3469
> -----Original Message-----
> From: Zhang, Qi1 <qi1.zhang@intel.com>
> Sent: Wednesday, October 12, 2022 10:48 AM
> To: devel@edk2.groups.io
> Cc: Zhang, Qi1 <qi1.zhang@intel.com>; Yao, Jiewen
> <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1
> <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>
> Subject: [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature
> interface.
>
> This patch is used to retrieve EC key from PEM and X509 and
> carry out the EC-DSA signature and verify it.
>
> The interface was tested by:
> 1. DeviceSecurity on edk2-staging
> https://github.com/tianocore/edk2-staging/tree/DeviceSecurity.
> 2. Unit test in CryptoPkg/Test
>
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4102
> PR: https://github.com/tianocore/edk2/pull/3464
>
> V2 change: change the protocol version.
>
> 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>
>
> Qi Zhang (3):
> CryptoPkg: Add EC key retrieving and signature interface.
> CryptoPkg: Add EC key interface to DXE and protocol
> CryptoPkg: add unit test for EC key interface.
>
> CryptoPkg/Driver/Crypto.c | 143 +++++++++-
> CryptoPkg/Include/Library/BaseCryptLib.h | 129 +++++++++
> .../Pcd/PcdCryptoServiceFamilyEnable.h | 4 +
> CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c | 87 ++++++
> .../Library/BaseCryptLib/Pem/CryptPemNull.c | 30 ++
> CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c | 258
> ++++++++++++++++++
> .../Library/BaseCryptLib/Pk/CryptEcNull.c | 82 ++++++
> CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c | 83 ++++++
> .../Library/BaseCryptLib/Pk/CryptX509Null.c | 28 ++
> .../BaseCryptLibNull/Pem/CryptPemNull.c | 30 ++
> .../Library/BaseCryptLibNull/Pk/CryptEcNull.c | 82 ++++++
> .../BaseCryptLibNull/Pk/CryptX509Null.c | 28 ++
> .../BaseCryptLibOnProtocolPpi/CryptLib.c | 136 +++++++++
> CryptoPkg/Private/Protocol/Crypto.h | 131 ++++++++-
> .../UnitTest/Library/BaseCryptLib/EcTests.c | 156 +++++++++++
> 15 files changed, 1405 insertions(+), 2 deletions(-)
>
> --
> 2.26.2.windows.1
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-10-12 5:58 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-10-12 2:47 [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Qi Zhang
2022-10-12 2:47 ` [PATCH V2 1/3] " Qi Zhang
2022-10-12 2:47 ` [PATCH V2 2/3] CryptoPkg: Add EC key interface to DXE and protocol Qi Zhang
2022-10-12 2:48 ` [PATCH V2 3/3] CryptoPkg: add unit test for EC key interface Qi Zhang
2022-10-12 5:57 ` [PATCH V2 0/3] CryptoPkg: Add EC key retrieving and signature interface Yao, Jiewen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox