mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-28 08:04:07 +02:00
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 <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>
This commit is contained in:
parent
f80580f56b
commit
f21a1d48fe
@ -16,6 +16,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||||||
|
|
||||||
#define CRYPTO_NID_NULL 0x0000
|
#define CRYPTO_NID_NULL 0x0000
|
||||||
|
|
||||||
|
// Hash
|
||||||
|
#define CRYPTO_NID_SHA256 0x0001
|
||||||
|
#define CRYPTO_NID_SHA384 0x0002
|
||||||
|
#define CRYPTO_NID_SHA512 0x0003
|
||||||
|
|
||||||
// Key Exchange
|
// Key Exchange
|
||||||
#define CRYPTO_NID_SECP256R1 0x0204
|
#define CRYPTO_NID_SECP256R1 0x0204
|
||||||
#define CRYPTO_NID_SECP384R1 0x0205
|
#define CRYPTO_NID_SECP384R1 0x0205
|
||||||
@ -3678,4 +3683,128 @@ EcDhComputeKey (
|
|||||||
IN OUT UINTN *KeySize
|
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__
|
#endif // __BASE_CRYPT_LIB_H__
|
||||||
|
@ -126,3 +126,90 @@ _Exit:
|
|||||||
|
|
||||||
return Status;
|
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
|
||||||
|
}
|
||||||
|
@ -36,3 +36,33 @@ RsaGetPrivateKeyFromPem (
|
|||||||
ASSERT (FALSE);
|
ASSERT (FALSE);
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
@ -763,3 +763,261 @@ fail:
|
|||||||
EC_KEY_free (PeerEcKey);
|
EC_KEY_free (PeerEcKey);
|
||||||
return RetVal;
|
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);
|
||||||
|
}
|
||||||
|
@ -494,3 +494,85 @@ EcDhComputeKey (
|
|||||||
ASSERT (FALSE);
|
ASSERT (FALSE);
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
@ -842,3 +842,86 @@ X509GetTBSCert (
|
|||||||
|
|
||||||
return TRUE;
|
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
|
||||||
|
}
|
||||||
|
@ -292,3 +292,31 @@ X509GetTBSCert (
|
|||||||
ASSERT (FALSE);
|
ASSERT (FALSE);
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
@ -36,3 +36,33 @@ RsaGetPrivateKeyFromPem (
|
|||||||
ASSERT (FALSE);
|
ASSERT (FALSE);
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
@ -494,3 +494,85 @@ EcDhComputeKey (
|
|||||||
ASSERT (FALSE);
|
ASSERT (FALSE);
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
@ -292,3 +292,31 @@ X509GetTBSCert (
|
|||||||
ASSERT (FALSE);
|
ASSERT (FALSE);
|
||||||
return 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;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user