Projects
openEuler:24.03:SP1:Everything:64G
rpm
_service:tar_scm:backport-Use-EVP_PKEY_verify-t...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-Use-EVP_PKEY_verify-to-verify-DSA-signatures.patch of Package rpm
From 8bf5c6b094e4f703d9fa1422a463654b512b25ae Mon Sep 17 00:00:00 2001 From: Michael Schroeder <mls@suse.de> Date: Wed, 17 Apr 2024 11:05:17 +0200 Subject: [PATCH] Use EVP_PKEY_verify to verify DSA signatures Conflict:modify digest_openssl.c in rpmio Reference:https://github.com/rpm-software-management/rpmpgp_legacy/commit/8bf5c6b094e4f703d9fa1422a463654b512b25ae The low level API will be deprecated in openssl-3 --- rpmio/digest_openssl.c | 179 +++++++++++++++++++++++------------------------ 1 file changed, 86 insertions(+), 93 deletions(-) diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c index 8dd7abe..2a39115 100644 --- a/rpmio/digest_openssl.c +++ b/rpmio/digest_openssl.c @@ -43,17 +43,12 @@ struct pgpDigKeyRSA_s { BIGNUM *n; /* Common Modulus */ BIGNUM *e; /* Public Exponent */ EVP_PKEY *evp_pkey; /* Fully constructed key */ - unsigned char immutable; /* if set, this key cannot be mutated */ }; static int constructRSASigningKey(struct pgpDigKeyRSA_s *key) { - if (key->evp_pkey) { - /* We've already constructed it, so just reuse it */ - return 1; - } else if (key->immutable) - return 0; - key->immutable = 1; + if (key->evp_pkey) + return 1; /* We've already constructed it, so just reuse it */ /* Create the RSA key */ RSA *rsa = RSA_new(); @@ -88,7 +83,7 @@ static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p) if (!key) key = pgpkey->data = xcalloc(1, sizeof(*key)); - else if (key->immutable) + else if (key->evp_pkey) return 1; switch (num) { @@ -238,7 +233,8 @@ static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, } done: - EVP_PKEY_CTX_free(pkey_ctx); + if (pkey_ctx) + EVP_PKEY_CTX_free(pkey_ctx); free(padded_sig); return rc; } @@ -252,40 +248,41 @@ struct pgpDigKeyDSA_s { BIGNUM *g; /* Base */ BIGNUM *y; /* Public Key */ - DSA *dsa_key; /* Fully constructed key */ + EVP_PKEY *evp_pkey; /* Fully constructed key */ }; static int constructDSASigningKey(struct pgpDigKeyDSA_s *key) { - int rc; - - if (key->dsa_key) { - /* We've already constructed it, so just reuse it */ - return 1; - } + if (key->evp_pkey) + return 1; /* We've already constructed it, so just reuse it */ /* Create the DSA key */ DSA *dsa = DSA_new(); if (!dsa) return 0; if (!DSA_set0_pqg(dsa, key->p, key->q, key->g)) { - rc = 0; - goto done; + goto exit; } - if (!DSA_set0_key(dsa, key->y, NULL)) { - rc = 0; - goto done; + goto exit; } - key->dsa_key = dsa; + /* Create an EVP_PKEY container to abstract the key-type. */ + if (!(key->evp_pkey = EVP_PKEY_new())) + goto exit; - rc = 1; -done: - if (rc == 0) { - DSA_free(dsa); + /* Assign the DSA key to the EVP_PKEY structure. + This will take over memory management of the RSA key */ + if (!EVP_PKEY_assign_DSA(key->evp_pkey, dsa)) { + EVP_PKEY_free(key->evp_pkey); + key->evp_pkey = NULL; + goto exit; } - return rc; + return 1; + +exit: + DSA_free(dsa); + return 0; } @@ -349,10 +346,10 @@ static void pgpFreeKeyDSA(pgpDigAlg pgpkey) { struct pgpDigKeyDSA_s *key = pgpkey->data; if (key) { - if (key->dsa_key) { - DSA_free(key->dsa_key); + if (key->evp_pkey) { + EVP_PKEY_free(key->evp_pkey); } else { - /* If sig->dsa_key was constructed, + /* If key->evp_pkey was constructed, * the memory management of these BNs * are freed with it. */ BN_clear_free(key->p); @@ -367,82 +364,72 @@ static void pgpFreeKeyDSA(pgpDigAlg pgpkey) /* Signature */ struct pgpDigSigDSA_s { - BIGNUM *r; - BIGNUM *s; - - DSA_SIG *dsa_sig; + unsigned char *r; + int rlen; + unsigned char *s; + int slen; }; -static int constructDSASignature(struct pgpDigSigDSA_s *sig) +static void add_asn1_tag(unsigned char *p, int tag, int len) { - int rc; - - if (sig->dsa_sig) { - /* We've already constructed it, so just reuse it */ - return 1; - } - - /* Create the DSA signature */ - DSA_SIG *dsa_sig = DSA_SIG_new(); - if (!dsa_sig) return 0; - - if (!DSA_SIG_set0(dsa_sig, sig->r, sig->s)) { - rc = 0; - goto done; + *p++ = tag; + if (len >= 256) { + *p++ = 130; + *p++ = len >> 8; + } else if (len > 128) { + *p++ = 129; } + *p++ = len; +} - sig->dsa_sig = dsa_sig; - - rc = 1; -done: - if (rc == 0) { - DSA_SIG_free(sig->dsa_sig); - } - return rc; +static unsigned char *constructDSASignature(unsigned char *r, int rlen, unsigned char *s, int slen, size_t *siglenp) +{ + int len1 = rlen + (!rlen || (*r & 0x80) != 0 ? 1 : 0), hlen1 = len1 < 128 ? 2 : len1 < 256 ? 3 : 4; + int len2 = slen + (!slen || (*s & 0x80) != 0 ? 1 : 0), hlen2 = len2 < 128 ? 2 : len2 < 256 ? 3 : 4; + int len3 = hlen1 + len1 + hlen2 + len2, hlen3 = len3 < 128 ? 2 : len3 < 256 ? 3 : 4; + unsigned char *buf; + if (rlen < 0 || rlen >= 65534 || slen < 0 || slen >= 65534 || len3 > 65535) + return 0; /* should never happen as pgp's MPIs have a length < 8192 */ + buf = xmalloc(hlen3 + len3); + add_asn1_tag(buf, 0x30, len3); + add_asn1_tag(buf + hlen3, 0x02, len1); + buf[hlen3 + hlen1] = 0; /* zero first byte of the integer */ + memcpy(buf + hlen3 + hlen1 + len1 - rlen, r, rlen); + add_asn1_tag(buf + hlen3 + hlen1 + len1, 0x02, len2); + buf[hlen3 + len3 - len2] = 0; /* zero first byte of the integer */ + memcpy(buf + hlen3 + len3 - slen, s, slen); + *siglenp = hlen3 + len3; + return buf; } static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, const uint8_t *p) { - BIGNUM *bn = NULL; - int mlen = pgpMpiLen(p) - 2; int rc = 1; struct pgpDigSigDSA_s *sig = pgpsig->data; if (!sig) { sig = xcalloc(1, sizeof(*sig)); + pgpsig->data = sig; } - /* Create a BIGNUM from the signature pointer. - Note: this assumes big-endian data as required - by the PGP multiprecision integer format - (RFC4880, Section 3.2) */ - bn = BN_bin2bn(p+2, mlen, NULL); - if (!bn) return 1; - switch (num) { case 0: - if (sig->r) { - /* This should only ever happen once per signature */ - BN_free(bn); - return 1; - } - sig->r = bn; + 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) { - /* This should only ever happen once per signature */ - BN_free(bn); - return 1; - } - sig->s = bn; + 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; } - pgpsig->data = sig; - return rc; } @@ -450,17 +437,10 @@ static void pgpFreeSigDSA(pgpDigAlg pgpsig) { struct pgpDigSigDSA_s *sig = pgpsig->data; if (sig) { - if (sig->dsa_sig) { - DSA_SIG_free(sig->dsa_sig); - } else { - /* If sig->dsa_sig was constructed, - * the memory management of these BNs - * are freed with it. */ - BN_clear_free(sig->r); - BN_clear_free(sig->s); - } - free(pgpsig->data); + free(sig->r); + free(sig->s); } + free(pgpsig->data); } static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, @@ -468,22 +448,35 @@ static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, { int rc = 1; /* assume failure */ struct pgpDigSigDSA_s *sig = pgpsig->data; - struct pgpDigKeyDSA_s *key = pgpkey->data; + unsigned char *xsig = NULL; /* signature encoded for X509 */ + size_t xsig_len = 0; + EVP_PKEY_CTX *pkey_ctx = NULL; if (!constructDSASigningKey(key)) goto done; - if (!constructDSASignature(sig)) + 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 (DSA_do_verify(hash, hashlen, sig->dsa_sig, key->dsa_key) == 1) + 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; } -- 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