From 09e5eac3f00144cbecd12a69390f6db98870f7eb Mon Sep 17 00:00:00 2001 From: Demi Marie Obenour Date: Fri, 9 Apr 2021 13:34:12 -0400 Subject: Avoid double frees if EVP_PKEY_assign_RSA fails Previously, the bignums would be left as dangling and double-freed. (cherry picked from commit 0a91d1f62d5b6e1cac4d0a7c2ac9f75faad50534) --- rpmio/digest_openssl.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/rpmio/digest_openssl.c b/rpmio/digest_openssl.c index 646933eed..2efcd4a6a 100644 --- a/rpmio/digest_openssl.c +++ b/rpmio/digest_openssl.c @@ -292,8 +292,8 @@ 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) @@ -301,33 +301,34 @@ 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; /* Create the RSA key */ RSA *rsa = RSA_new(); if (!rsa) return 0; - if (!RSA_set0_key(rsa, key->n, key->e, NULL)) { - RSA_free(rsa); - return 0; - } + if (RSA_set0_key(rsa, key->n, key->e, NULL) <= 0) + goto exit; + key->n = key->e = NULL; /* Create an EVP_PKEY container to abstract the key-type. */ - key->evp_pkey = EVP_PKEY_new(); - if (!key->evp_pkey) { - RSA_free(rsa); - return 0; - } + if (!(key->evp_pkey = EVP_PKEY_new())) + goto exit; /* Assign the RSA key to the EVP_PKEY structure. This will take over memory management of the RSA key */ if (!EVP_PKEY_assign_RSA(key->evp_pkey, rsa)) { EVP_PKEY_free(key->evp_pkey); key->evp_pkey = NULL; - RSA_free(rsa); + goto exit; } return 1; +exit: + RSA_free(rsa); + return 0; } static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p) @@ -335,9 +336,10 @@ static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p) size_t mlen = pgpMpiLen(p) - 2; struct pgpDigKeyRSA_s *key = pgpkey->data; - if (!key) { + if (!key) key = pgpkey->data = xcalloc(1, sizeof(*key)); - } + else if (key->immutable) + return 1; switch (num) { case 0: @@ -347,7 +349,7 @@ static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, const uint8_t *p) return 1; } - key->nbytes = mlen; + key->nbytes = mlen; /* Create a BIGNUM from the pointer. Note: this assumes big-endian data as required by PGP */ key->n = BN_bin2bn(p+2, mlen, NULL); -- cgit v1.2.1