From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mx.groups.io with SMTP id smtpd.web11.16075.1665542890380960943 for ; Tue, 11 Oct 2022 19:48:11 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=Odsfgl8j; spf=pass (domain: intel.com, ip: 134.134.136.65, mailfrom: qi1.zhang@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1665542891; x=1697078891; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=6l/jHRCeO8HLwtsnQriz99t9Vks61bDaeY9/trF5rQA=; b=Odsfgl8jcUFwTntF77Qdgp7m0Zae2nIV1oq3aEu8diufLFHVwVRk1syg qm4Go9iYbAob4z5BKB/obUnXCcVlM7+oeAq09u5bq59wwqWDWJlL5wZlO T64wS534crTe2IVtH41Qw6qPNduHuMJ8xJeHr2kDC0Fww9LgA8YsuDL14 zVN2r6TcFtnDdHLo+E8wA+QH8Ad1o61Y/nk8IQW9hqGHCAMhQ/cNU35qy xePFzfW7APWsy2JQ2Mn/Nn7UGojNsdOdDASGpkahIEJB6en+6CAcpguLQ t4Q425aU74y0JQHN7eYjamORG83UDnGw7HaSR5z/l8c7ZBbw5wh+ERI7G Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10497"; a="306308542" X-IronPort-AV: E=Sophos;i="5.95,177,1661842800"; d="scan'208";a="306308542" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Oct 2022 19:48:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10497"; a="801688866" X-IronPort-AV: E=Sophos;i="5.95,177,1661842800"; d="scan'208";a="801688866" Received: from shwdesssddpdqi.ccr.corp.intel.com ([10.239.157.129]) by orsmga005.jf.intel.com with ESMTP; 11 Oct 2022 19:48:04 -0700 From: "Qi Zhang" To: devel@edk2.groups.io Cc: Qi Zhang , Jiewen Yao , Jian J Wang , Xiaoyu Lu , Guomin Jiang Subject: [PATCH V2 1/3] CryptoPkg: Add EC key retrieving and signature interface. Date: Wed, 12 Oct 2022 10:47:58 +0800 Message-Id: X-Mailer: git-send-email 2.26.2.windows.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=3D4102 Cc: Jiewen Yao Cc: Jian J Wang Cc: Xiaoyu Lu Cc: Guomin Jiang Signed-off-by: Qi Zhang --- 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/L= ibrary/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 =0D #define CRYPTO_NID_NULL 0x0000=0D =0D +// Hash=0D +#define CRYPTO_NID_SHA256 0x0001=0D +#define CRYPTO_NID_SHA384 0x0002=0D +#define CRYPTO_NID_SHA512 0x0003=0D +=0D // Key Exchange=0D #define CRYPTO_NID_SECP256R1 0x0204=0D #define CRYPTO_NID_SECP384R1 0x0205=0D @@ -3678,4 +3683,128 @@ EcDhComputeKey ( IN OUT UINTN *KeySize=0D );=0D =0D +/**=0D + Retrieve the EC Private Key from the password-protected PEM key data.=0D +=0D + @param[in] PemData Pointer to the PEM-encoded key data to be retri= eved.=0D + @param[in] PemSize Size of the PEM key data in bytes.=0D + @param[in] Password NULL-terminated passphrase used for encrypted P= EM key data.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC private key component. Use EcFree() function= to free the=0D + resource.=0D +=0D + If PemData is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Private Key was retrieved successfully.=0D + @retval FALSE Invalid PEM key data or incorrect password.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPrivateKeyFromPem (=0D + IN CONST UINT8 *PemData,=0D + IN UINTN PemSize,=0D + IN CONST CHAR8 *Password,=0D + OUT VOID **EcContext=0D + );=0D +=0D +/**=0D + Retrieve the EC Public Key from one DER-encoded X509 certificate.=0D +=0D + @param[in] Cert Pointer to the DER-encoded X509 certificate.=0D + @param[in] CertSize Size of the X509 certificate in bytes.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC public key component. Use EcFree() function = to free the=0D + resource.=0D +=0D + If Cert is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Public Key was retrieved successfully.=0D + @retval FALSE Fail to retrieve EC public key from X509 certificate.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPublicKeyFromX509 (=0D + IN CONST UINT8 *Cert,=0D + IN UINTN CertSize,=0D + OUT VOID **EcContext=0D + );=0D +=0D +/**=0D + Carries out the EC-DSA signature.=0D +=0D + This function carries out the EC-DSA signature.=0D + If the Signature buffer is too small to hold the contents of signature, = FALSE=0D + is returned and SigSize is set to the required buffer size to obtain the= signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D + If SigSize is large enough but Signature is NULL, then return FALSE.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature genera= tion.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be signed= .=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[out] Signature Pointer to buffer to receive EC-DSA signat= ure.=0D + @param[in, out] SigSize On input, the size of Signature buffer in = bytes.=0D + On output, the size of data returned in Si= gnature buffer in bytes.=0D +=0D + @retval TRUE Signature successfully generated in EC-DSA.=0D + @retval FALSE Signature generation failed.=0D + @retval FALSE SigSize is too small.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaSign (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + OUT UINT8 *Signature,=0D + IN OUT UINTN *SigSize=0D + );=0D +=0D +/**=0D + Verifies the EC-DSA signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If Signature is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature verificatio= n.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be checked.=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[in] Signature Pointer to EC-DSA signature to be verified.=0D + @param[in] SigSize Size of signature in bytes.=0D +=0D + @retval TRUE Valid signature encoded in EC-DSA.=0D + @retval FALSE Invalid signature or invalid EC context.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaVerify (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + IN CONST UINT8 *Signature,=0D + IN UINTN SigSize=0D + );=0D +=0D #endif // __BASE_CRYPT_LIB_H__=0D diff --git a/CryptoPkg/Library/BaseCryptLib/Pem/CryptPem.c b/CryptoPkg/Libr= ary/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: =0D return Status;=0D }=0D +=0D +/**=0D + Retrieve the EC Private Key from the password-protected PEM key data.=0D +=0D + @param[in] PemData Pointer to the PEM-encoded key data to be retri= eved.=0D + @param[in] PemSize Size of the PEM key data in bytes.=0D + @param[in] Password NULL-terminated passphrase used for encrypted P= EM key data.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC private key component. Use EcFree() function= to free the=0D + resource.=0D +=0D + If PemData is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Private Key was retrieved successfully.=0D + @retval FALSE Invalid PEM key data or incorrect password.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPrivateKeyFromPem (=0D + IN CONST UINT8 *PemData,=0D + IN UINTN PemSize,=0D + IN CONST CHAR8 *Password,=0D + OUT VOID **EcContext=0D + )=0D +{=0D + #if FixedPcdGetBool (PcdOpensslEcEnabled)=0D + BOOLEAN Status;=0D + BIO *PemBio;=0D +=0D + //=0D + // Check input parameters.=0D + //=0D + if ((PemData =3D=3D NULL) || (EcContext =3D=3D NULL) || (PemSize > INT_M= AX)) {=0D + return FALSE;=0D + }=0D +=0D + //=0D + // Add possible block-cipher descriptor for PEM data decryption.=0D + // NOTE: Only support most popular ciphers AES for the encrypted PEM.=0D + //=0D + if (EVP_add_cipher (EVP_aes_128_cbc ()) =3D=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + if (EVP_add_cipher (EVP_aes_192_cbc ()) =3D=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + if (EVP_add_cipher (EVP_aes_256_cbc ()) =3D=3D 0) {=0D + return FALSE;=0D + }=0D +=0D + Status =3D FALSE;=0D +=0D + //=0D + // Read encrypted PEM Data.=0D + //=0D + PemBio =3D BIO_new (BIO_s_mem ());=0D + if (PemBio =3D=3D NULL) {=0D + goto _Exit;=0D + }=0D +=0D + if (BIO_write (PemBio, PemData, (int)PemSize) <=3D 0) {=0D + goto _Exit;=0D + }=0D +=0D + //=0D + // Retrieve EC Private Key from encrypted PEM data.=0D + //=0D + *EcContext =3D PEM_read_bio_ECPrivateKey (PemBio, NULL, (pem_password_cb= *)&PasswordCallback, (void *)Password);=0D + if (*EcContext !=3D NULL) {=0D + Status =3D TRUE;=0D + }=0D +=0D +_Exit:=0D + //=0D + // Release Resources.=0D + //=0D + BIO_free (PemBio);=0D +=0D + return Status;=0D + #else=0D + return FALSE;=0D + #endif=0D +}=0D 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);=0D return FALSE;=0D }=0D +=0D +/**=0D + Retrieve the EC Private Key from the password-protected PEM key data.=0D +=0D + @param[in] PemData Pointer to the PEM-encoded key data to be retri= eved.=0D + @param[in] PemSize Size of the PEM key data in bytes.=0D + @param[in] Password NULL-terminated passphrase used for encrypted P= EM key data.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC private key component. Use EcFree() function= to free the=0D + resource.=0D +=0D + If PemData is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Private Key was retrieved successfully.=0D + @retval FALSE Invalid PEM key data or incorrect password.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPrivateKeyFromPem (=0D + IN CONST UINT8 *PemData,=0D + IN UINTN PemSize,=0D + IN CONST CHAR8 *Password,=0D + OUT VOID **EcContext=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEc.c b/CryptoPkg/Librar= y/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);=0D return RetVal;=0D }=0D +=0D +/**=0D + Carries out the EC-DSA signature.=0D +=0D + This function carries out the EC-DSA signature.=0D + If the Signature buffer is too small to hold the contents of signature, = FALSE=0D + is returned and SigSize is set to the required buffer size to obtain the= signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D + If SigSize is large enough but Signature is NULL, then return FALSE.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature genera= tion.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be signed= .=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[out] Signature Pointer to buffer to receive EC-DSA signat= ure.=0D + @param[in, out] SigSize On input, the size of Signature buffer in = bytes.=0D + On output, the size of data returned in Si= gnature buffer in bytes.=0D +=0D + @retval TRUE Signature successfully generated in EC-DSA.=0D + @retval FALSE Signature generation failed.=0D + @retval FALSE SigSize is too small.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaSign (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + OUT UINT8 *Signature,=0D + IN OUT UINTN *SigSize=0D + )=0D +{=0D + EC_KEY *EcKey;=0D + ECDSA_SIG *EcDsaSig;=0D + INT32 OpenSslNid;=0D + UINT8 HalfSize;=0D + BIGNUM *R;=0D + BIGNUM *S;=0D + INTN RSize;=0D + INTN SSize;=0D +=0D + if ((EcContext =3D=3D NULL) || (MessageHash =3D=3D NULL)) {=0D + return FALSE;=0D + }=0D +=0D + if (Signature =3D=3D NULL) {=0D + return FALSE;=0D + }=0D +=0D + EcKey =3D (EC_KEY *)EcContext;=0D + OpenSslNid =3D EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey));=0D + switch (OpenSslNid) {=0D + case NID_X9_62_prime256v1:=0D + HalfSize =3D 32;=0D + break;=0D + case NID_secp384r1:=0D + HalfSize =3D 48;=0D + break;=0D + case NID_secp521r1:=0D + HalfSize =3D 66;=0D + break;=0D + default:=0D + return FALSE;=0D + }=0D +=0D + if (*SigSize < (UINTN)(HalfSize * 2)) {=0D + *SigSize =3D HalfSize * 2;=0D + return FALSE;=0D + }=0D +=0D + *SigSize =3D HalfSize * 2;=0D + ZeroMem (Signature, *SigSize);=0D +=0D + switch (HashNid) {=0D + case CRYPTO_NID_SHA256:=0D + if (HashSize !=3D SHA256_DIGEST_SIZE) {=0D + return FALSE;=0D + }=0D +=0D + break;=0D +=0D + case CRYPTO_NID_SHA384:=0D + if (HashSize !=3D SHA384_DIGEST_SIZE) {=0D + return FALSE;=0D + }=0D +=0D + break;=0D +=0D + case CRYPTO_NID_SHA512:=0D + if (HashSize !=3D SHA512_DIGEST_SIZE) {=0D + return FALSE;=0D + }=0D +=0D + break;=0D +=0D + default:=0D + return FALSE;=0D + }=0D +=0D + EcDsaSig =3D ECDSA_do_sign (=0D + MessageHash,=0D + (UINT32)HashSize,=0D + (EC_KEY *)EcContext=0D + );=0D + if (EcDsaSig =3D=3D NULL) {=0D + return FALSE;=0D + }=0D +=0D + ECDSA_SIG_get0 (EcDsaSig, (CONST BIGNUM **)&R, (CONST BIGNUM **)&S);=0D +=0D + RSize =3D BN_num_bytes (R);=0D + SSize =3D BN_num_bytes (S);=0D + if ((RSize <=3D 0) || (SSize <=3D 0)) {=0D + ECDSA_SIG_free (EcDsaSig);=0D + return FALSE;=0D + }=0D +=0D + ASSERT ((UINTN)RSize <=3D HalfSize && (UINTN)SSize <=3D HalfSize);=0D +=0D + BN_bn2bin (R, &Signature[0 + HalfSize - RSize]);=0D + BN_bn2bin (S, &Signature[HalfSize + HalfSize - SSize]);=0D +=0D + ECDSA_SIG_free (EcDsaSig);=0D +=0D + return TRUE;=0D +}=0D +=0D +/**=0D + Verifies the EC-DSA signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If Signature is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature verificatio= n.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be checked.=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[in] Signature Pointer to EC-DSA signature to be verified.=0D + @param[in] SigSize Size of signature in bytes.=0D +=0D + @retval TRUE Valid signature encoded in EC-DSA.=0D + @retval FALSE Invalid signature or invalid EC context.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaVerify (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + IN CONST UINT8 *Signature,=0D + IN UINTN SigSize=0D + )=0D +{=0D + INT32 Result;=0D + EC_KEY *EcKey;=0D + ECDSA_SIG *EcDsaSig;=0D + INT32 OpenSslNid;=0D + UINT8 HalfSize;=0D + BIGNUM *R;=0D + BIGNUM *S;=0D +=0D + if ((EcContext =3D=3D NULL) || (MessageHash =3D=3D NULL) || (Signature = =3D=3D NULL)) {=0D + return FALSE;=0D + }=0D +=0D + if ((SigSize > INT_MAX) || (SigSize =3D=3D 0)) {=0D + return FALSE;=0D + }=0D +=0D + EcKey =3D (EC_KEY *)EcContext;=0D + OpenSslNid =3D EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey));=0D + switch (OpenSslNid) {=0D + case NID_X9_62_prime256v1:=0D + HalfSize =3D 32;=0D + break;=0D + case NID_secp384r1:=0D + HalfSize =3D 48;=0D + break;=0D + case NID_secp521r1:=0D + HalfSize =3D 66;=0D + break;=0D + default:=0D + return FALSE;=0D + }=0D +=0D + if (SigSize !=3D (UINTN)(HalfSize * 2)) {=0D + return FALSE;=0D + }=0D +=0D + switch (HashNid) {=0D + case CRYPTO_NID_SHA256:=0D + if (HashSize !=3D SHA256_DIGEST_SIZE) {=0D + return FALSE;=0D + }=0D +=0D + break;=0D +=0D + case CRYPTO_NID_SHA384:=0D + if (HashSize !=3D SHA384_DIGEST_SIZE) {=0D + return FALSE;=0D + }=0D +=0D + break;=0D +=0D + case CRYPTO_NID_SHA512:=0D + if (HashSize !=3D SHA512_DIGEST_SIZE) {=0D + return FALSE;=0D + }=0D +=0D + break;=0D +=0D + default:=0D + return FALSE;=0D + }=0D +=0D + EcDsaSig =3D ECDSA_SIG_new ();=0D + if (EcDsaSig =3D=3D NULL) {=0D + ECDSA_SIG_free (EcDsaSig);=0D + return FALSE;=0D + }=0D +=0D + R =3D BN_bin2bn (Signature, (UINT32)HalfSize, NULL);=0D + S =3D BN_bin2bn (Signature + HalfSize, (UINT32)HalfSize, NULL);=0D + if ((R =3D=3D NULL) || (S =3D=3D NULL)) {=0D + ECDSA_SIG_free (EcDsaSig);=0D + return FALSE;=0D + }=0D +=0D + ECDSA_SIG_set0 (EcDsaSig, R, S);=0D +=0D + Result =3D ECDSA_do_verify (=0D + MessageHash,=0D + (UINT32)HashSize,=0D + EcDsaSig,=0D + (EC_KEY *)EcContext=0D + );=0D +=0D + ECDSA_SIG_free (EcDsaSig);=0D +=0D + return (Result =3D=3D 1);=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptEcNull.c b/CryptoPkg/Li= brary/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);=0D return FALSE;=0D }=0D +=0D +/**=0D + Carries out the EC-DSA signature.=0D +=0D + This function carries out the EC-DSA signature.=0D + If the Signature buffer is too small to hold the contents of signature, = FALSE=0D + is returned and SigSize is set to the required buffer size to obtain the= signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D + If SigSize is large enough but Signature is NULL, then return FALSE.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature genera= tion.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be signed= .=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[out] Signature Pointer to buffer to receive EC-DSA signat= ure.=0D + @param[in, out] SigSize On input, the size of Signature buffer in = bytes.=0D + On output, the size of data returned in Si= gnature buffer in bytes.=0D +=0D + @retval TRUE Signature successfully generated in EC-DSA.=0D + @retval FALSE Signature generation failed.=0D + @retval FALSE SigSize is too small.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaSign (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + OUT UINT8 *Signature,=0D + IN OUT UINTN *SigSize=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D +=0D +/**=0D + Verifies the EC-DSA signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If Signature is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature verificatio= n.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be checked.=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[in] Signature Pointer to EC-DSA signature to be verified.=0D + @param[in] SigSize Size of signature in bytes.=0D +=0D + @retval TRUE Valid signature encoded in EC-DSA.=0D + @retval FALSE Invalid signature or invalid EC context.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaVerify (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + IN CONST UINT8 *Signature,=0D + IN UINTN SigSize=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c b/CryptoPkg/Libr= ary/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 ( =0D return TRUE;=0D }=0D +=0D +/**=0D + Retrieve the EC Public Key from one DER-encoded X509 certificate.=0D +=0D + @param[in] Cert Pointer to the DER-encoded X509 certificate.=0D + @param[in] CertSize Size of the X509 certificate in bytes.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC public key component. Use EcFree() function = to free the=0D + resource.=0D +=0D + If Cert is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Public Key was retrieved successfully.=0D + @retval FALSE Fail to retrieve EC public key from X509 certificate.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPublicKeyFromX509 (=0D + IN CONST UINT8 *Cert,=0D + IN UINTN CertSize,=0D + OUT VOID **EcContext=0D + )=0D +{=0D + #if FixedPcdGetBool (PcdOpensslEcEnabled)=0D + BOOLEAN Status;=0D + EVP_PKEY *Pkey;=0D + X509 *X509Cert;=0D +=0D + //=0D + // Check input parameters.=0D + //=0D + if ((Cert =3D=3D NULL) || (EcContext =3D=3D NULL)) {=0D + return FALSE;=0D + }=0D +=0D + Pkey =3D NULL;=0D + X509Cert =3D NULL;=0D +=0D + //=0D + // Read DER-encoded X509 Certificate and Construct X509 object.=0D + //=0D + Status =3D X509ConstructCertificate (Cert, CertSize, (UINT8 **)&X509Cert= );=0D + if ((X509Cert =3D=3D NULL) || (!Status)) {=0D + Status =3D FALSE;=0D + goto _Exit;=0D + }=0D +=0D + Status =3D FALSE;=0D +=0D + //=0D + // Retrieve and check EVP_PKEY data from X509 Certificate.=0D + //=0D + Pkey =3D X509_get_pubkey (X509Cert);=0D + if ((Pkey =3D=3D NULL) || (EVP_PKEY_id (Pkey) !=3D EVP_PKEY_EC)) {=0D + goto _Exit;=0D + }=0D +=0D + //=0D + // Duplicate EC Context from the retrieved EVP_PKEY.=0D + //=0D + if ((*EcContext =3D EC_KEY_dup (EVP_PKEY_get0_EC_KEY (Pkey))) !=3D NULL)= {=0D + Status =3D TRUE;=0D + }=0D +=0D +_Exit:=0D + //=0D + // Release Resources.=0D + //=0D + if (X509Cert !=3D NULL) {=0D + X509_free (X509Cert);=0D + }=0D +=0D + if (Pkey !=3D NULL) {=0D + EVP_PKEY_free (Pkey);=0D + }=0D +=0D + return Status;=0D + #else=0D + return FALSE;=0D + #endif=0D +}=0D 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);=0D return FALSE;=0D }=0D +=0D +/**=0D + Retrieve the EC Public Key from one DER-encoded X509 certificate.=0D +=0D + @param[in] Cert Pointer to the DER-encoded X509 certificate.=0D + @param[in] CertSize Size of the X509 certificate in bytes.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC public key component. Use EcFree() function = to free the=0D + resource.=0D +=0D + If Cert is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Public Key was retrieved successfully.=0D + @retval FALSE Fail to retrieve EC public key from X509 certificate.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPublicKeyFromX509 (=0D + IN CONST UINT8 *Cert,=0D + IN UINTN CertSize,=0D + OUT VOID **EcContext=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pem/CryptPemNull.c b/Crypto= Pkg/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);=0D return FALSE;=0D }=0D +=0D +/**=0D + Retrieve the EC Private Key from the password-protected PEM key data.=0D +=0D + @param[in] PemData Pointer to the PEM-encoded key data to be retri= eved.=0D + @param[in] PemSize Size of the PEM key data in bytes.=0D + @param[in] Password NULL-terminated passphrase used for encrypted P= EM key data.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC private key component. Use EcFree() function= to free the=0D + resource.=0D +=0D + If PemData is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Private Key was retrieved successfully.=0D + @retval FALSE Invalid PEM key data or incorrect password.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPrivateKeyFromPem (=0D + IN CONST UINT8 *PemData,=0D + IN UINTN PemSize,=0D + IN CONST CHAR8 *Password,=0D + OUT VOID **EcContext=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptEcNull.c b/CryptoPk= g/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);=0D return FALSE;=0D }=0D +=0D +/**=0D + Carries out the EC-DSA signature.=0D +=0D + This function carries out the EC-DSA signature.=0D + If the Signature buffer is too small to hold the contents of signature, = FALSE=0D + is returned and SigSize is set to the required buffer size to obtain the= signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D + If SigSize is large enough but Signature is NULL, then return FALSE.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature genera= tion.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be signed= .=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[out] Signature Pointer to buffer to receive EC-DSA signat= ure.=0D + @param[in, out] SigSize On input, the size of Signature buffer in = bytes.=0D + On output, the size of data returned in Si= gnature buffer in bytes.=0D +=0D + @retval TRUE Signature successfully generated in EC-DSA.=0D + @retval FALSE Signature generation failed.=0D + @retval FALSE SigSize is too small.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaSign (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + OUT UINT8 *Signature,=0D + IN OUT UINTN *SigSize=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D +=0D +/**=0D + Verifies the EC-DSA signature.=0D +=0D + If EcContext is NULL, then return FALSE.=0D + If MessageHash is NULL, then return FALSE.=0D + If Signature is NULL, then return FALSE.=0D + If HashSize need match the HashNid. HashNid could be SHA256, SHA384, SHA= 512, SHA3_256, SHA3_384, SHA3_512.=0D +=0D + For P-256, the SigSize is 64. First 32-byte is R, Second 32-byte is S.=0D + For P-384, the SigSize is 96. First 48-byte is R, Second 48-byte is S.=0D + For P-521, the SigSize is 132. First 66-byte is R, Second 66-byte is S.= =0D +=0D + @param[in] EcContext Pointer to EC context for signature verificatio= n.=0D + @param[in] HashNid hash NID=0D + @param[in] MessageHash Pointer to octet message hash to be checked.=0D + @param[in] HashSize Size of the message hash in bytes.=0D + @param[in] Signature Pointer to EC-DSA signature to be verified.=0D + @param[in] SigSize Size of signature in bytes.=0D +=0D + @retval TRUE Valid signature encoded in EC-DSA.=0D + @retval FALSE Invalid signature or invalid EC context.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcDsaVerify (=0D + IN VOID *EcContext,=0D + IN UINTN HashNid,=0D + IN CONST UINT8 *MessageHash,=0D + IN UINTN HashSize,=0D + IN CONST UINT8 *Signature,=0D + IN UINTN SigSize=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptX509Null.c b/Crypto= Pkg/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);=0D return FALSE;=0D }=0D +=0D +/**=0D + Retrieve the EC Public Key from one DER-encoded X509 certificate.=0D +=0D + @param[in] Cert Pointer to the DER-encoded X509 certificate.=0D + @param[in] CertSize Size of the X509 certificate in bytes.=0D + @param[out] EcContext Pointer to new-generated EC DSA context which c= ontain the retrieved=0D + EC public key component. Use EcFree() function = to free the=0D + resource.=0D +=0D + If Cert is NULL, then return FALSE.=0D + If EcContext is NULL, then return FALSE.=0D +=0D + @retval TRUE EC Public Key was retrieved successfully.=0D + @retval FALSE Fail to retrieve EC public key from X509 certificate.=0D +=0D +**/=0D +BOOLEAN=0D +EFIAPI=0D +EcGetPublicKeyFromX509 (=0D + IN CONST UINT8 *Cert,=0D + IN UINTN CertSize,=0D + OUT VOID **EcContext=0D + )=0D +{=0D + ASSERT (FALSE);=0D + return FALSE;=0D +}=0D --=20 2.26.2.windows.1