Projects
openEuler:24.03:SP1:Everything
rpm
_service:tar_scm:backport-Add-ECDSA-support-to-...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-Add-ECDSA-support-to-digest_openssl.patch of Package rpm
From d2d35d1acb89d4113647a9aad2d049808112b935 Mon Sep 17 00:00:00 2001 From: Michael Schroeder <mls@suse.de> Date: Wed, 17 Apr 2024 14:07:53 +0200 Subject: [PATCH] Add ECDSA support to digest_openssl Conflict:modify digest_openssl.c in rpmio; adapt context Reference:https://github.com/rpm-software-management/rpmpgp_legacy/commit/783a5ea3851b8509eb11a4998d6e4ea41cc7ba38 --- rpmio/digest_openssl.c | 208 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 207 insertions(+), 1 deletion(-) diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c index 4d930c9..c8eb15f 100644 --- a/rpmio/digest_openssl.c +++ b/rpmio/digest_openssl.c @@ -6,6 +6,7 @@ #endif #include <openssl/rsa.h> #include <openssl/dsa.h> +#include <openssl/ec.h> #include <rpm/rpmcrypto.h> #include "rpmio/rpmpgp_internal.h" @@ -801,6 +802,181 @@ done: return rc; } +/****************************** ECDSA ***************************************/ + +struct pgpDigKeyECDSA_s { + EVP_PKEY *evp_pkey; /* Fully constructed key */ + unsigned char *q; /* compressed point */ + int qlen; +}; + +static int constructECDSASigningKey(struct pgpDigKeyECDSA_s *key, int curve) +{ + if (key->evp_pkey) + return 1; /* We've already constructed it, so just reuse it */ + +#if OPENSSL_VERSION_MAJOR >= 3 + if (curve == PGPCURVE_NIST_P_256) { + OSSL_PARAM params[] = { + OSSL_PARAM_utf8_string("group", "P-256", 5), + OSSL_PARAM_octet_string("pub", key->q, key->qlen), + OSSL_PARAM_END + }; + key->evp_pkey = construct_pkey_from_param(EVP_PKEY_EC, params); + } else if (curve == PGPCURVE_NIST_P_384) { + OSSL_PARAM params[] = { + OSSL_PARAM_utf8_string("group", "P-384", 5), + OSSL_PARAM_octet_string("pub", key->q, key->qlen), + OSSL_PARAM_END + }; + key->evp_pkey = construct_pkey_from_param(EVP_PKEY_EC, params); + } + return key->evp_pkey ? 1 : 0; +#else + /* Create the EC key */ + EC_KEY *ec = NULL; + if (curve == PGPCURVE_NIST_P_256) + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + else if (curve == PGPCURVE_NIST_P_384) + ec = EC_KEY_new_by_curve_name(NID_secp384r1); + if (!ec) + return 0; + + if (!EC_KEY_oct2key(ec, key->q, key->qlen, NULL)) + goto exit; + + /* Create an EVP_PKEY container to abstract the key-type. */ + if (!(key->evp_pkey = EVP_PKEY_new())) + goto exit; + + /* Assign the EC key to the EVP_PKEY structure. + This will take over memory management of the RSA key */ + if (!EVP_PKEY_assign_EC_KEY(key->evp_pkey, ec)) { + EVP_PKEY_free(key->evp_pkey); + key->evp_pkey = NULL; + goto exit; + } + return 1; + +exit: + EC_KEY_free(ec); + return 0; +#endif +} + +static int pgpSetKeyMpiECDSA(pgpDigAlg pgpkey, int num, const uint8_t *p) +{ + size_t mlen = pgpMpiLen(p) - 2; + struct pgpDigKeyECDSA_s *key = pgpkey->data; + int rc = 1; + + if (!key) + key = pgpkey->data = xcalloc(1, sizeof(*key)); + if (num == 0 && !key->q && mlen > 1 && p[2] == 0x04) { + key->qlen = mlen; + key->q = xmalloc(key->qlen); + memcpy(key->q, p + 2, key->qlen), + rc = 0; + } + return rc; +} + +static void pgpFreeKeyECDSA(pgpDigAlg pgpkey) +{ + struct pgpDigKeyECDSA_s *key = pgpkey->data; + if (key) { + if (key->q) + free(key->q); + if (key->evp_pkey) + EVP_PKEY_free(key->evp_pkey); + free(key); + } +} + +struct pgpDigSigECDSA_s { + unsigned char *r; + int rlen; + unsigned char *s; + int slen; +}; + +static int pgpSetSigMpiECDSA(pgpDigAlg pgpsig, int num, const uint8_t *p) +{ + int mlen = pgpMpiLen(p) - 2; + int rc = 1; + + struct pgpDigSigECDSA_s *sig = pgpsig->data; + if (!sig) { + sig = xcalloc(1, sizeof(*sig)); + pgpsig->data = sig; + } + + switch (num) { + case 0: + if (sig->r) + return 1; /* This should only ever happen once per signature */ + sig->rlen = mlen; + sig->r = memcpy(xmalloc(mlen), p + 2, mlen); + rc = 0; + break; + case 1: + if (sig->s) + return 1; /* This should only ever happen once per signature */ + sig->slen = mlen; + sig->s = memcpy(xmalloc(mlen), p + 2, mlen); + rc = 0; + break; + } + + return rc; +} + +static void pgpFreeSigECDSA(pgpDigAlg pgpsig) +{ + struct pgpDigSigECDSA_s *sig = pgpsig->data; + if (sig) { + free(sig->r); + free(sig->s); + } + free(pgpsig->data); +} + +static int pgpVerifySigECDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, + uint8_t *hash, size_t hashlen, int hash_algo) +{ + int rc = 1; /* assume failure */ + struct pgpDigSigECDSA_s *sig = pgpsig->data; + struct pgpDigKeyECDSA_s *key = pgpkey->data; + unsigned char *xsig = NULL; /* signature encoded for X509 */ + size_t xsig_len = 0; + EVP_PKEY_CTX *pkey_ctx = NULL; + + if (!constructECDSASigningKey(key, pgpkey->curve)) + goto done; + + xsig = constructDSASignature(sig->r, sig->rlen, sig->s, sig->slen, &xsig_len); + if (!xsig) + goto done; + + pkey_ctx = EVP_PKEY_CTX_new(key->evp_pkey, NULL); + if (!pkey_ctx) + goto done; + + if (EVP_PKEY_verify_init(pkey_ctx) != 1) + goto done; + + if (EVP_PKEY_verify(pkey_ctx, xsig, xsig_len, hash, hashlen) == 1) + { + /* Success */ + rc = 0; + } + +done: + if (pkey_ctx) + EVP_PKEY_CTX_free(pkey_ctx); + free(xsig); + return rc; +} /****************************** EDDSA ***************************************/ @@ -912,6 +1088,19 @@ static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig, return 1; } +static int pgpSupportedCurve(int algo, int curve) +{ +#ifdef EVP_PKEY_ED25519 + if (algo == PGPPUBKEYALGO_EDDSA && curve == PGPCURVE_ED25519) + return 1; +#endif + if (algo == PGPPUBKEYALGO_ECDSA && curve == PGPCURVE_NIST_P_256) + return 1; + if (algo == PGPPUBKEYALGO_ECDSA && curve == PGPCURVE_NIST_P_384) + return 1; + return 0; +} + /****************************** PGP **************************************/ pgpDigAlg pgpPubkeyNew(int algo, int curve) { @@ -928,9 +1117,20 @@ pgpDigAlg pgpPubkeyNew(int algo, int curve) ka->free = pgpFreeKeyDSA; ka->mpis = 4; break; + case PGPPUBKEYALGO_ECDSA: + if (!pgpSupportedCurve(algo, curve)) { + ka->setmpi = pgpSetMpiNULL; + ka->mpis = -1; + break; + } + ka->setmpi = pgpSetKeyMpiECDSA; + ka->free = pgpFreeKeyECDSA; + ka->mpis = 1; + ka->curve = curve; + break; #ifdef EVP_PKEY_ED25519 case PGPPUBKEYALGO_EDDSA: - if (curve != PGPCURVE_ED25519) { + if (!pgpSupportedCurve(algo, curve)) { ka->setmpi = pgpSetMpiNULL; /* unsupported curve */ ka->mpis = -1; break; @@ -969,6 +1169,12 @@ pgpDigAlg pgpSignatureNew(int algo) sa->verify = pgpVerifySigDSA; sa->mpis = 2; break; + case PGPPUBKEYALGO_ECDSA: + sa->setmpi = pgpSetSigMpiECDSA; + sa->free = pgpFreeSigECDSA; + sa->verify = pgpVerifySigECDSA; + sa->mpis = 2; + break; #ifdef EVP_PKEY_ED25519 case PGPPUBKEYALGO_EDDSA: sa->setmpi = pgpSetSigMpiEDDSA; -- 2.23.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2