From f21a1d48fe7200c80f893d805f49410836443cc5 Mon Sep 17 00:00:00 2001 From: Qi Zhang Date: Wed, 12 Oct 2022 10:47:58 +0800 Subject: [PATCH] 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. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4102 Cc: Jiewen Yao Cc: Jian J Wang Cc: Xiaoyu Lu Cc: Guomin Jiang Signed-off-by: Qi Zhang Reviewed-by: Jiewen Yao --- 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.39.2