diff options
| author | Yogita Urade <yogita.urade@windriver.com> | 2025-07-22 16:16:29 +0530 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2025-07-30 07:47:48 -0700 |
| commit | 87e1bc09cabe609981d5ee7ea4919755e2072ad9 (patch) | |
| tree | 5458aab689c389ee58dfc9e069e0bb0348b21d65 /meta | |
| parent | db3621b9837ae1efe7c30e359e5a64a4ca1cbbd2 (diff) | |
| download | poky-87e1bc09cabe609981d5ee7ea4919755e2072ad9.tar.gz | |
gnupg: fix CVE-2025-30258
In GnuPG before 2.5.5, if a user chooses to import a certificate
with certain crafted subkey data that lacks a valid backsig or
that has incorrect usage flags, the user loses the ability to
verify signatures made from certain other signing keys, aka a
"verification DoS."
CVE-2025-30258-0002 is the dependent commit while rest
are CVE fixes.
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2025-30258
Upstream patches:
https://dev.gnupg.org/rG25d748c3dfc0102f9e54afea59ff26b3969bd8c1
https://dev.gnupg.org/rG9cd371b12d80cfc5bc85cb6e5f5eebb4decbe94f
https://dev.gnupg.org/rGda0164efc7f32013bc24d97b9afa9f8d67c318bb
https://dev.gnupg.org/rG1e581619bf5315957f2be06b3b1a7f513304c126
https://dev.gnupg.org/rG4be25979a6b3e2a79d7c9667b07db8b09fb046e9
(From OE-Core rev: 467081219407cd30bcc9e575bedcb127b6bcea65)
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
6 files changed, 1130 insertions, 0 deletions
diff --git a/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0001.patch b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0001.patch new file mode 100644 index 0000000000..56aa2ce3e1 --- /dev/null +++ b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0001.patch | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | From 25d748c3dfc0102f9e54afea59ff26b3969bd8c1 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Werner Koch <wk@gnupg.org> | ||
| 3 | Date: Tue, 11 Feb 2025 14:44:23 +0100 | ||
| 4 | Subject: [PATCH] gpg: Lookup key for merging/inserting only by primary key. | ||
| 5 | |||
| 6 | * g10/getkey.c (get_keyblock_byfpr_fast): Add arg primary_only and | ||
| 7 | implement. | ||
| 8 | * g10/import.c (import_one_real): Simplify filling the fpr buffer with | ||
| 9 | zeroes. | ||
| 10 | (import_one_real): Find key only by primary fingerprint. | ||
| 11 | -- | ||
| 12 | |||
| 13 | This should have been done early: When looking up the original | ||
| 14 | keyblock we want to update, we need to lookup it up only using the | ||
| 15 | primary key. This avoids to find a key which has the primary key also | ||
| 16 | has a subkey. | ||
| 17 | |||
| 18 | GnuPG-bug-id: 7527 | ||
| 19 | |||
| 20 | CVE: CVE-2025-30258 | ||
| 21 | Upstream-Status: Backport [https://dev.gnupg.org/rG25d748c3dfc0102f9e54afea59ff26b3969bd8c1] | ||
| 22 | |||
| 23 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 24 | --- | ||
| 25 | g10/getkey.c | 23 ++++++++++++++++++++--- | ||
| 26 | g10/import.c | 6 +++--- | ||
| 27 | g10/keydb.h | 3 ++- | ||
| 28 | 3 files changed, 25 insertions(+), 7 deletions(-) | ||
| 29 | |||
| 30 | diff --git a/g10/getkey.c b/g10/getkey.c | ||
| 31 | index e49718e..7a25643 100644 | ||
| 32 | --- a/g10/getkey.c | ||
| 33 | +++ b/g10/getkey.c | ||
| 34 | @@ -1895,7 +1895,7 @@ get_pubkey_byfprint_fast (ctrl_t ctrl, PKT_public_key * pk, | ||
| 35 | KBNODE keyblock; | ||
| 36 | |||
| 37 | err = get_keyblock_byfprint_fast (ctrl, | ||
| 38 | - &keyblock, NULL, fprint, fprint_len, 0); | ||
| 39 | + &keyblock, NULL, 0, fprint, fprint_len, 0); | ||
| 40 | if (!err) | ||
| 41 | { | ||
| 42 | if (pk) | ||
| 43 | @@ -1912,11 +1912,14 @@ get_pubkey_byfprint_fast (ctrl_t ctrl, PKT_public_key * pk, | ||
| 44 | * R_HD may be NULL. If LOCK is set the handle has been opend in | ||
| 45 | * locked mode and keydb_disable_caching () has been called. On error | ||
| 46 | * R_KEYBLOCK is set to NULL but R_HD must be released by the caller; | ||
| 47 | - * it may have a value of NULL, though. This allows to do an insert | ||
| 48 | - * operation on a locked keydb handle. */ | ||
| 49 | + * it may have a value of NULL, though. This allows to do an | ||
| 50 | + * insert operation on a locked keydb handle. If PRIMARY_ONLY is set | ||
| 51 | + * the function returns a keyblock which has the requested fingerprint | ||
| 52 | + * has primary key. */ | ||
| 53 | gpg_error_t | ||
| 54 | get_keyblock_byfprint_fast (ctrl_t ctrl, | ||
| 55 | kbnode_t *r_keyblock, KEYDB_HANDLE *r_hd, | ||
| 56 | + int primary_only, | ||
| 57 | const byte *fprint, size_t fprint_len, int lock) | ||
| 58 | { | ||
| 59 | gpg_error_t err; | ||
| 60 | @@ -1924,6 +1927,8 @@ get_keyblock_byfprint_fast (ctrl_t ctrl, | ||
| 61 | kbnode_t keyblock; | ||
| 62 | byte fprbuf[MAX_FINGERPRINT_LEN]; | ||
| 63 | int i; | ||
| 64 | + byte tmpfpr[MAX_FINGERPRINT_LEN]; | ||
| 65 | + size_t tmpfprlen; | ||
| 66 | |||
| 67 | if (r_keyblock) | ||
| 68 | *r_keyblock = NULL; | ||
| 69 | @@ -1955,6 +1960,7 @@ get_keyblock_byfprint_fast (ctrl_t ctrl, | ||
| 70 | if (r_hd) | ||
| 71 | *r_hd = hd; | ||
| 72 | |||
| 73 | +again: | ||
| 74 | err = keydb_search_fpr (hd, fprbuf, fprint_len); | ||
| 75 | if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) | ||
| 76 | { | ||
| 77 | @@ -1974,6 +1980,17 @@ get_keyblock_byfprint_fast (ctrl_t ctrl, | ||
| 78 | log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY | ||
| 79 | || keyblock->pkt->pkttype == PKT_PUBLIC_SUBKEY); | ||
| 80 | |||
| 81 | + if (primary_only) | ||
| 82 | + { | ||
| 83 | + fingerprint_from_pk (keyblock->pkt->pkt.public_key, tmpfpr, &tmpfprlen); | ||
| 84 | + if (fprint_len != tmpfprlen || memcmp (fprint, tmpfpr, fprint_len)) | ||
| 85 | + { | ||
| 86 | + release_kbnode (keyblock); | ||
| 87 | + keyblock = NULL; | ||
| 88 | + goto again; | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | /* Not caching key here since it won't have all of the fields | ||
| 93 | properly set. */ | ||
| 94 | |||
| 95 | diff --git a/g10/import.c b/g10/import.c | ||
| 96 | index bb0bf67..fb0e2ee 100644 | ||
| 97 | --- a/g10/import.c | ||
| 98 | +++ b/g10/import.c | ||
| 99 | @@ -1893,7 +1893,6 @@ import_one_real (ctrl_t ctrl, | ||
| 100 | int mod_key = 0; | ||
| 101 | int same_key = 0; | ||
| 102 | int non_self = 0; | ||
| 103 | - size_t an; | ||
| 104 | char pkstrbuf[PUBKEY_STRING_SIZE]; | ||
| 105 | int merge_keys_done = 0; | ||
| 106 | int any_filter = 0; | ||
| 107 | @@ -1914,8 +1913,8 @@ import_one_real (ctrl_t ctrl, | ||
| 108 | pk = node->pkt->pkt.public_key; | ||
| 109 | |||
| 110 | fingerprint_from_pk (pk, fpr2, &fpr2len); | ||
| 111 | - for (an = fpr2len; an < MAX_FINGERPRINT_LEN; an++) | ||
| 112 | - fpr2[an] = 0; | ||
| 113 | + if (MAX_FINGERPRINT_LEN > fpr2len) | ||
| 114 | + memset (fpr2+fpr2len, 0, MAX_FINGERPRINT_LEN - fpr2len); | ||
| 115 | keyid_from_pk( pk, keyid ); | ||
| 116 | uidnode = find_next_kbnode( keyblock, PKT_USER_ID ); | ||
| 117 | |||
| 118 | @@ -2097,6 +2096,7 @@ import_one_real (ctrl_t ctrl, | ||
| 119 | |||
| 120 | /* Do we have this key already in one of our pubrings ? */ | ||
| 121 | err = get_keyblock_byfprint_fast (ctrl, &keyblock_orig, &hd, | ||
| 122 | + 1 /*primary only */, | ||
| 123 | fpr2, fpr2len, 1/*locked*/); | ||
| 124 | if ((err | ||
| 125 | && gpg_err_code (err) != GPG_ERR_NO_PUBKEY | ||
| 126 | diff --git a/g10/keydb.h b/g10/keydb.h | ||
| 127 | index a91309a..51dfece 100644 | ||
| 128 | --- a/g10/keydb.h | ||
| 129 | +++ b/g10/keydb.h | ||
| 130 | @@ -418,7 +418,8 @@ gpg_error_t get_pubkey_byfprint_fast (ctrl_t ctrl, PKT_public_key *pk, | ||
| 131 | gpg_error_t get_keyblock_byfprint_fast (ctrl_t ctrl, | ||
| 132 | kbnode_t *r_keyblock, | ||
| 133 | KEYDB_HANDLE *r_hd, | ||
| 134 | - const byte *fprint, size_t fprint_len, | ||
| 135 | + int primary_only, | ||
| 136 | + const byte *fpr, size_t fprlen, | ||
| 137 | int lock); | ||
| 138 | |||
| 139 | |||
| 140 | -- | ||
| 141 | 2.40.0 | ||
diff --git a/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0002.patch b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0002.patch new file mode 100644 index 0000000000..58e50fabac --- /dev/null +++ b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0002.patch | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | From 9cd371b12d80cfc5bc85cb6e5f5eebb4decbe94f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Werner Koch <wk@gnupg.org> | ||
| 3 | Date: Thu, 20 Feb 2025 14:50:20 +0100 | ||
| 4 | Subject: [PATCH] gpg: Remove a signature check function wrapper. | ||
| 5 | |||
| 6 | * g10/sig-check.c (check_signature2): Rename to | ||
| 7 | (check_signature): this and remove the old wrapper. Adjust all | ||
| 8 | callers. | ||
| 9 | |||
| 10 | CVE: CVE-2025-30258 | ||
| 11 | Upstream-Status: Backport [https://dev.gnupg.org/rG9cd371b12d80cfc5bc85cb6e5f5eebb4decbe94f] | ||
| 12 | |||
| 13 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 14 | --- | ||
| 15 | g10/mainproc.c | 13 +++++-------- | ||
| 16 | g10/packet.h | 6 +----- | ||
| 17 | g10/sig-check.c | 26 ++++++++------------------ | ||
| 18 | 3 files changed, 14 insertions(+), 31 deletions(-) | ||
| 19 | |||
| 20 | diff --git a/g10/mainproc.c b/g10/mainproc.c | ||
| 21 | index af11877..79d9ff2 100644 | ||
| 22 | --- a/g10/mainproc.c | ||
| 23 | +++ b/g10/mainproc.c | ||
| 24 | @@ -1198,19 +1198,17 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, | ||
| 25 | |||
| 26 | /* We only get here if we are checking the signature of a binary | ||
| 27 | (0x00) or text document (0x01). */ | ||
| 28 | - rc = check_signature2 (c->ctrl, sig, md, extrahash, extrahashlen, | ||
| 29 | - forced_pk, | ||
| 30 | - NULL, is_expkey, is_revkey, r_pk); | ||
| 31 | + rc = check_signature (c->ctrl, sig, md, extrahash, extrahashlen, | ||
| 32 | + forced_pk, NULL, is_expkey, is_revkey, r_pk); | ||
| 33 | if (! rc) | ||
| 34 | md_good = md; | ||
| 35 | else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2) | ||
| 36 | { | ||
| 37 | PKT_public_key *pk2; | ||
| 38 | |||
| 39 | - rc = check_signature2 (c->ctrl, sig, md2, extrahash, extrahashlen, | ||
| 40 | - forced_pk, | ||
| 41 | - NULL, is_expkey, is_revkey, | ||
| 42 | - r_pk? &pk2 : NULL); | ||
| 43 | + rc = check_signature (c->ctrl, sig, md2, extrahash, extrahashlen, | ||
| 44 | + forced_pk, NULL, is_expkey, is_revkey, | ||
| 45 | + r_pk? &pk2 : NULL); | ||
| 46 | if (!rc) | ||
| 47 | { | ||
| 48 | md_good = md2; | ||
| 49 | @@ -1792,7 +1790,6 @@ issuer_fpr_string (PKT_signature *sig) | ||
| 50 | return p? bin2hex (p, n, NULL) : NULL; | ||
| 51 | } | ||
| 52 | |||
| 53 | - | ||
| 54 | static void | ||
| 55 | print_good_bad_signature (int statno, const char *keyid_str, kbnode_t un, | ||
| 56 | PKT_signature *sig, int rc) | ||
| 57 | diff --git a/g10/packet.h b/g10/packet.h | ||
| 58 | index 5a14015..8aaf32d 100644 | ||
| 59 | --- a/g10/packet.h | ||
| 60 | +++ b/g10/packet.h | ||
| 61 | @@ -889,16 +889,12 @@ int cmp_user_ids( PKT_user_id *a, PKT_user_id *b ); | ||
| 62 | |||
| 63 | |||
| 64 | /*-- sig-check.c --*/ | ||
| 65 | -/* Check a signature. This is shorthand for check_signature2 with | ||
| 66 | - the unnamed arguments passed as NULL. */ | ||
| 67 | -int check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest); | ||
| 68 | - | ||
| 69 | /* Check a signature. Looks up the public key from the key db. (If | ||
| 70 | * R_PK is not NULL, it is stored at RET_PK.) DIGEST contains a | ||
| 71 | * valid hash context that already includes the signed data. This | ||
| 72 | * function adds the relevant meta-data to the hash before finalizing | ||
| 73 | * it and verifying the signature. FOCRED_PK is usually NULL. */ | ||
| 74 | -gpg_error_t check_signature2 (ctrl_t ctrl, | ||
| 75 | +gpg_error_t check_signature (ctrl_t ctrl, | ||
| 76 | PKT_signature *sig, gcry_md_hd_t digest, | ||
| 77 | const void *extrahash, size_t extrahashlen, | ||
| 78 | PKT_public_key *forced_pk, | ||
| 79 | diff --git a/g10/sig-check.c b/g10/sig-check.c | ||
| 80 | index eb6c966..2272fa4 100644 | ||
| 81 | --- a/g10/sig-check.c | ||
| 82 | +++ b/g10/sig-check.c | ||
| 83 | @@ -95,17 +95,6 @@ check_key_verify_compliance (PKT_public_key *pk) | ||
| 84 | } | ||
| 85 | |||
| 86 | |||
| 87 | - | ||
| 88 | -/* Check a signature. This is shorthand for check_signature2 with | ||
| 89 | - the unnamed arguments passed as NULL. */ | ||
| 90 | -int | ||
| 91 | -check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest) | ||
| 92 | -{ | ||
| 93 | - return check_signature2 (ctrl, sig, digest, NULL, 0, NULL, | ||
| 94 | - NULL, NULL, NULL, NULL); | ||
| 95 | -} | ||
| 96 | - | ||
| 97 | - | ||
| 98 | /* Check a signature. | ||
| 99 | * | ||
| 100 | * Looks up the public key that created the signature (SIG->KEYID) | ||
| 101 | @@ -151,12 +140,12 @@ check_signature (ctrl_t ctrl, PKT_signature *sig, gcry_md_hd_t digest) | ||
| 102 | * | ||
| 103 | * Returns 0 on success. An error code otherwise. */ | ||
| 104 | gpg_error_t | ||
| 105 | -check_signature2 (ctrl_t ctrl, | ||
| 106 | - PKT_signature *sig, gcry_md_hd_t digest, | ||
| 107 | - const void *extrahash, size_t extrahashlen, | ||
| 108 | - PKT_public_key *forced_pk, | ||
| 109 | - u32 *r_expiredate, | ||
| 110 | - int *r_expired, int *r_revoked, PKT_public_key **r_pk) | ||
| 111 | +check_signature (ctrl_t ctrl, | ||
| 112 | + PKT_signature *sig, gcry_md_hd_t digest, | ||
| 113 | + const void *extrahash, size_t extrahashlen, | ||
| 114 | + PKT_public_key *forced_pk, | ||
| 115 | + u32 *r_expiredate, int *r_expired, int *r_revoked, | ||
| 116 | + PKT_public_key **r_pk) | ||
| 117 | { | ||
| 118 | int rc=0; | ||
| 119 | PKT_public_key *pk; | ||
| 120 | @@ -808,7 +797,8 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig) | ||
| 121 | hash_public_key(md,pk); | ||
| 122 | /* Note: check_signature only checks that the signature | ||
| 123 | is good. It does not fail if the key is revoked. */ | ||
| 124 | - rc = check_signature (ctrl, sig, md); | ||
| 125 | + rc = check_signature (ctrl, sig, md, NULL, 0, NULL, | ||
| 126 | + NULL, NULL, NULL, NULL); | ||
| 127 | cache_sig_result(sig,rc); | ||
| 128 | gcry_md_close (md); | ||
| 129 | break; | ||
| 130 | -- | ||
| 131 | 2.40.0 | ||
diff --git a/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0003.patch b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0003.patch new file mode 100644 index 0000000000..223972788f --- /dev/null +++ b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0003.patch | |||
| @@ -0,0 +1,624 @@ | |||
| 1 | From da0164efc7f32013bc24d97b9afa9f8d67c318bb Mon Sep 17 00:00:00 2001 | ||
| 2 | rom: Werner Koch <wk@gnupg.org> | ||
| 3 | Date: Fri, 21 Feb 2025 12:16:17 +0100 | ||
| 4 | Subject: [PATCH] gpg: Fix a verification DoS due to a malicious subkey in the | ||
| 5 | keyring. | ||
| 6 | |||
| 7 | * g10/getkey.c (get_pubkey): Factor code out to ... | ||
| 8 | (get_pubkey_bykid): new. Add feature to return the keyblock. | ||
| 9 | (get_pubkey_for_sig): Add arg r_keyblock to return the used keyblock. | ||
| 10 | Request a signing usage. | ||
| 11 | (get_pubkeyblock_for_sig): Remove. | ||
| 12 | (finish_lookup): Improve debug output. | ||
| 13 | * g10/sig-check.c (check_signature): Add arg r_keyblock and pass it | ||
| 14 | down. | ||
| 15 | * g10/mainproc.c (do_check_sig): Ditto. | ||
| 16 | (check_sig_and_print): Use the keyblock returned by do_check_sig to | ||
| 17 | show further information instead of looking it up again with | ||
| 18 | get_pubkeyblock_for_sig. Also re-check the signature after the import | ||
| 19 | of an included keyblock. | ||
| 20 | -- | ||
| 21 | |||
| 22 | The problem here is that it is possible to import a key from someone | ||
| 23 | who added a signature subkey from another public key and thus inhibits | ||
| 24 | that a good signature good be verified. | ||
| 25 | |||
| 26 | Such a malicious key signature subkey must have been created w/o the | ||
| 27 | mandatory backsig which bind a signature subkey to its primary key. | ||
| 28 | For encryption subkeys this is not an issue because the existence of a | ||
| 29 | decryption private key is all you need to decrypt something and then | ||
| 30 | it does not matter if the public subkey or its binding signature has | ||
| 31 | been put below another primary key; in fact we do the latter for | ||
| 32 | ADSKs. | ||
| 33 | |||
| 34 | GnuPG-bug-id: 7527 | ||
| 35 | Backported-from-master: 48978ccb4e20866472ef18436a32744350a65158 | ||
| 36 | |||
| 37 | CVE: CVE-2025-30258 | ||
| 38 | Upstream-Status: Backport [https://dev.gnupg.org/rGda0164efc7f32013bc24d97b9afa9f8d67c318bb] | ||
| 39 | |||
| 40 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 41 | --- | ||
| 42 | g10/getkey.c | 106 ++++++++++++++++++++++++++++++------------------ | ||
| 43 | g10/gpg.h | 3 +- | ||
| 44 | g10/keydb.h | 10 ++++- | ||
| 45 | g10/mainproc.c | 92 ++++++++++++++++++++++++++--------------- | ||
| 46 | g10/packet.h | 2 +- | ||
| 47 | g10/sig-check.c | 23 +++++++---- | ||
| 48 | 6 files changed, 152 insertions(+), 84 deletions(-) | ||
| 49 | |||
| 50 | diff --git a/g10/getkey.c b/g10/getkey.c | ||
| 51 | index 7a25643..0fa763a 100644 | ||
| 52 | --- a/g10/getkey.c | ||
| 53 | +++ b/g10/getkey.c | ||
| 54 | @@ -310,27 +310,50 @@ pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key) | ||
| 55 | |||
| 56 | /* Specialized version of get_pubkey which retrieves the key based on | ||
| 57 | * information in SIG. In contrast to get_pubkey PK is required. IF | ||
| 58 | - * FORCED_PK is not NULL, this public key is used and copied to PK. */ | ||
| 59 | + * FORCED_PK is not NULL, this public key is used and copied to PK. | ||
| 60 | + * If R_KEYBLOCK is not NULL the entire keyblock is stored there if | ||
| 61 | + * found and FORCED_PK is not used; if not used or on error NULL is | ||
| 62 | + * stored there. */ | ||
| 63 | gpg_error_t | ||
| 64 | get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig, | ||
| 65 | - PKT_public_key *forced_pk) | ||
| 66 | + PKT_public_key *forced_pk, kbnode_t *r_keyblock) | ||
| 67 | { | ||
| 68 | + gpg_error_t err; | ||
| 69 | const byte *fpr; | ||
| 70 | size_t fprlen; | ||
| 71 | |||
| 72 | + if (r_keyblock) | ||
| 73 | + *r_keyblock = NULL; | ||
| 74 | + | ||
| 75 | if (forced_pk) | ||
| 76 | { | ||
| 77 | copy_public_key (pk, forced_pk); | ||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | + /* Make sure to request only keys cabable of signing. This makes | ||
| 82 | + * sure that a subkey w/o a valid backsig or with bad usage flags | ||
| 83 | + * will be skipped. */ | ||
| 84 | + pk->req_usage = PUBKEY_USAGE_SIG; | ||
| 85 | + | ||
| 86 | /* First try the ISSUER_FPR info. */ | ||
| 87 | fpr = issuer_fpr_raw (sig, &fprlen); | ||
| 88 | - if (fpr && !get_pubkey_byfprint (ctrl, pk, NULL, fpr, fprlen)) | ||
| 89 | + if (fpr && !get_pubkey_byfprint (ctrl, pk, r_keyblock, fpr, fprlen)) | ||
| 90 | return 0; | ||
| 91 | + if (r_keyblock) | ||
| 92 | + { | ||
| 93 | + release_kbnode (*r_keyblock); | ||
| 94 | + *r_keyblock = NULL; | ||
| 95 | + } | ||
| 96 | |||
| 97 | /* Fallback to use the ISSUER_KEYID. */ | ||
| 98 | - return get_pubkey (ctrl, pk, sig->keyid); | ||
| 99 | + err = get_pubkey_bykid (ctrl, pk, r_keyblock, sig->keyid); | ||
| 100 | + if (err && r_keyblock) | ||
| 101 | + { | ||
| 102 | + release_kbnode (*r_keyblock); | ||
| 103 | + *r_keyblock = NULL; | ||
| 104 | + } | ||
| 105 | + return err; | ||
| 106 | } | ||
| 107 | |||
| 108 | |||
| 109 | @@ -348,6 +371,10 @@ get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig, | ||
| 110 | * usage will be returned. As such, it is essential that | ||
| 111 | * PK->REQ_USAGE be correctly initialized! | ||
| 112 | * | ||
| 113 | + * If R_KEYBLOCK is not NULL, then the first result's keyblock is | ||
| 114 | + * returned in *R_KEYBLOCK. This should be freed using | ||
| 115 | + * release_kbnode(). | ||
| 116 | + * | ||
| 117 | * Returns 0 on success, GPG_ERR_NO_PUBKEY if there is no public key | ||
| 118 | * with the specified key id, or another error code if an error | ||
| 119 | * occurs. | ||
| 120 | @@ -355,24 +382,30 @@ get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig, | ||
| 121 | * If the data was not read from the cache, then the self-signed data | ||
| 122 | * has definitely been merged into the public key using | ||
| 123 | * merge_selfsigs. */ | ||
| 124 | -int | ||
| 125 | -get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid) | ||
| 126 | +gpg_error_t | ||
| 127 | +get_pubkey_bykid (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock, | ||
| 128 | + u32 *keyid) | ||
| 129 | { | ||
| 130 | int internal = 0; | ||
| 131 | - int rc = 0; | ||
| 132 | + gpg_error_t rc = 0; | ||
| 133 | + | ||
| 134 | + if (r_keyblock) | ||
| 135 | + *r_keyblock = NULL; | ||
| 136 | |||
| 137 | #if MAX_PK_CACHE_ENTRIES | ||
| 138 | - if (pk) | ||
| 139 | + if (pk && !r_keyblock) | ||
| 140 | { | ||
| 141 | /* Try to get it from the cache. We don't do this when pk is | ||
| 142 | - NULL as it does not guarantee that the user IDs are | ||
| 143 | - cached. */ | ||
| 144 | + * NULL as it does not guarantee that the user IDs are cached. | ||
| 145 | + * The old get_pubkey_function did not check PK->REQ_USAGE when | ||
| 146 | + * reading form the caceh. This is probably a bug. Note that | ||
| 147 | + * the cache is not used when the caller asked to return the | ||
| 148 | + * entire keyblock. This is because the cache does not | ||
| 149 | + * associate the public key wit its primary key. */ | ||
| 150 | pk_cache_entry_t ce; | ||
| 151 | for (ce = pk_cache; ce; ce = ce->next) | ||
| 152 | { | ||
| 153 | if (ce->keyid[0] == keyid[0] && ce->keyid[1] == keyid[1]) | ||
| 154 | - /* XXX: We don't check PK->REQ_USAGE here, but if we don't | ||
| 155 | - read from the cache, we do check it! */ | ||
| 156 | { | ||
| 157 | copy_public_key (pk, ce->pk); | ||
| 158 | return 0; | ||
| 159 | @@ -380,6 +413,7 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid) | ||
| 160 | } | ||
| 161 | } | ||
| 162 | #endif | ||
| 163 | + | ||
| 164 | /* More init stuff. */ | ||
| 165 | if (!pk) | ||
| 166 | { | ||
| 167 | @@ -425,16 +459,18 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid) | ||
| 168 | ctx.req_usage = pk->req_usage; | ||
| 169 | rc = lookup (ctrl, &ctx, 0, &kb, &found_key); | ||
| 170 | if (!rc) | ||
| 171 | + pk_from_block (pk, kb, found_key); | ||
| 172 | + getkey_end (ctrl, &ctx); | ||
| 173 | + if (!rc && r_keyblock) | ||
| 174 | { | ||
| 175 | - pk_from_block (pk, kb, found_key); | ||
| 176 | + *r_keyblock = kb; | ||
| 177 | + kb = NULL; | ||
| 178 | } | ||
| 179 | - getkey_end (ctrl, &ctx); | ||
| 180 | release_kbnode (kb); | ||
| 181 | } | ||
| 182 | - if (!rc) | ||
| 183 | - goto leave; | ||
| 184 | |||
| 185 | - rc = GPG_ERR_NO_PUBKEY; | ||
| 186 | + if (rc) /* Return a more useful error code. */ | ||
| 187 | + rc = gpg_error (GPG_ERR_NO_PUBKEY); | ||
| 188 | |||
| 189 | leave: | ||
| 190 | if (!rc) | ||
| 191 | @@ -445,6 +481,14 @@ leave: | ||
| 192 | } | ||
| 193 | |||
| 194 | |||
| 195 | +/* Wrapper for get_pubkey_bykid w/o keyblock return feature. */ | ||
| 196 | +int | ||
| 197 | +get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid) | ||
| 198 | +{ | ||
| 199 | + return get_pubkey_bykid (ctrl, pk, NULL, keyid); | ||
| 200 | +} | ||
| 201 | + | ||
| 202 | + | ||
| 203 | /* Same as get_pubkey but if the key was not found the function tries | ||
| 204 | * to import it from LDAP. FIXME: We should not need this but swicth | ||
| 205 | * to a fingerprint lookup. */ | ||
| 206 | @@ -557,28 +601,6 @@ get_pubkey_fast (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid) | ||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 210 | -/* Return the entire keyblock used to create SIG. This is a | ||
| 211 | - * specialized version of get_pubkeyblock. | ||
| 212 | - * | ||
| 213 | - * FIXME: This is a hack because get_pubkey_for_sig was already called | ||
| 214 | - * and it could have used a cache to hold the key. */ | ||
| 215 | -kbnode_t | ||
| 216 | -get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig) | ||
| 217 | -{ | ||
| 218 | - const byte *fpr; | ||
| 219 | - size_t fprlen; | ||
| 220 | - kbnode_t keyblock; | ||
| 221 | - | ||
| 222 | - /* First try the ISSUER_FPR info. */ | ||
| 223 | - fpr = issuer_fpr_raw (sig, &fprlen); | ||
| 224 | - if (fpr && !get_pubkey_byfprint (ctrl, NULL, &keyblock, fpr, fprlen)) | ||
| 225 | - return keyblock; | ||
| 226 | - | ||
| 227 | - /* Fallback to use the ISSUER_KEYID. */ | ||
| 228 | - return get_pubkeyblock (ctrl, sig->keyid); | ||
| 229 | -} | ||
| 230 | - | ||
| 231 | - | ||
| 232 | /* Return the key block for the key with key id KEYID or NULL, if an | ||
| 233 | * error occurs. Use release_kbnode() to release the key block. | ||
| 234 | * | ||
| 235 | @@ -3611,6 +3633,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 236 | kbnode_t latest_key; | ||
| 237 | PKT_public_key *pk; | ||
| 238 | int req_prim; | ||
| 239 | + int diag_exactfound = 0; | ||
| 240 | u32 curtime = make_timestamp (); | ||
| 241 | |||
| 242 | if (r_flags) | ||
| 243 | @@ -3641,6 +3664,7 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 244 | foundk = k; | ||
| 245 | pk = k->pkt->pkt.public_key; | ||
| 246 | pk->flags.exact = 1; | ||
| 247 | + diag_exactfound = 1; | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | @@ -3661,10 +3685,14 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 252 | log_debug ("finish_lookup: checking key %08lX (%s)(req_usage=%x)\n", | ||
| 253 | (ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL), | ||
| 254 | foundk ? "one" : "all", req_usage); | ||
| 255 | + if (diag_exactfound && DBG_LOOKUP) | ||
| 256 | + log_debug ("\texact search requested and found\n"); | ||
| 257 | |||
| 258 | if (!req_usage) | ||
| 259 | { | ||
| 260 | latest_key = foundk ? foundk : keyblock; | ||
| 261 | + if (DBG_LOOKUP) | ||
| 262 | + log_debug ("\tno usage requested - accepting key\n"); | ||
| 263 | goto found; | ||
| 264 | } | ||
| 265 | |||
| 266 | diff --git a/g10/gpg.h b/g10/gpg.h | ||
| 267 | index c51bbbb..0cdcb8b 100644 | ||
| 268 | --- a/g10/gpg.h | ||
| 269 | +++ b/g10/gpg.h | ||
| 270 | @@ -69,7 +69,8 @@ struct dirmngr_local_s; | ||
| 271 | typedef struct dirmngr_local_s *dirmngr_local_t; | ||
| 272 | |||
| 273 | /* Object used to describe a keyblock node. */ | ||
| 274 | -typedef struct kbnode_struct *KBNODE; /* Deprecated use kbnode_t. */typedef struct kbnode_struct *kbnode_t; | ||
| 275 | +typedef struct kbnode_struct *KBNODE; /* Deprecated use kbnode_t. */ | ||
| 276 | +typedef struct kbnode_struct *kbnode_t; | ||
| 277 | |||
| 278 | /* The handle for keydb operations. */ | ||
| 279 | typedef struct keydb_handle_s *KEYDB_HANDLE; | ||
| 280 | diff --git a/g10/keydb.h b/g10/keydb.h | ||
| 281 | index 51dfece..8e494f6 100644 | ||
| 282 | --- a/g10/keydb.h | ||
| 283 | +++ b/g10/keydb.h | ||
| 284 | @@ -332,9 +332,15 @@ void getkey_disable_caches(void); | ||
| 285 | /* Return the public key used for signature SIG and store it at PK. */ | ||
| 286 | gpg_error_t get_pubkey_for_sig (ctrl_t ctrl, | ||
| 287 | PKT_public_key *pk, PKT_signature *sig, | ||
| 288 | - PKT_public_key *forced_pk); | ||
| 289 | + PKT_public_key *forced_pk, | ||
| 290 | + kbnode_t *r_keyblock); | ||
| 291 | |||
| 292 | -/* Return the public key with the key id KEYID and store it at PK. */ | ||
| 293 | +/* Return the public key with the key id KEYID and store it at PK. | ||
| 294 | + * Optionally return the entire keyblock. */ | ||
| 295 | +gpg_error_t get_pubkey_bykid (ctrl_t ctrl, PKT_public_key *pk, | ||
| 296 | + kbnode_t *r_keyblock, u32 *keyid); | ||
| 297 | + | ||
| 298 | +/* Same as get_pubkey_bykid but w/o r_keyblock. */ | ||
| 299 | int get_pubkey (ctrl_t ctrl, PKT_public_key *pk, u32 *keyid); | ||
| 300 | |||
| 301 | /* Same as get_pubkey but with auto LDAP fetch. */ | ||
| 302 | diff --git a/g10/mainproc.c b/g10/mainproc.c | ||
| 303 | index 79d9ff2..6e114d2 100644 | ||
| 304 | --- a/g10/mainproc.c | ||
| 305 | +++ b/g10/mainproc.c | ||
| 306 | @@ -1108,12 +1108,15 @@ proc_compressed (CTX c, PACKET *pkt) | ||
| 307 | * used to verify the signature will be stored there, or NULL if not | ||
| 308 | * found. If FORCED_PK is not NULL, this public key is used to verify | ||
| 309 | * _data signatures_ and no key lookup is done. Returns: 0 = valid | ||
| 310 | - * signature or an error code | ||
| 311 | + * signature or an error code. If R_KEYBLOCK is not NULL the keyblock | ||
| 312 | + * carries the used PK is stored there. The caller should always free | ||
| 313 | + * the return value using release_kbnode. | ||
| 314 | */ | ||
| 315 | static int | ||
| 316 | do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, | ||
| 317 | PKT_public_key *forced_pk, int *is_selfsig, | ||
| 318 | - int *is_expkey, int *is_revkey, PKT_public_key **r_pk) | ||
| 319 | + int *is_expkey, int *is_revkey, | ||
| 320 | + PKT_public_key **r_pk, kbnode_t *r_keyblock) | ||
| 321 | { | ||
| 322 | PKT_signature *sig; | ||
| 323 | gcry_md_hd_t md = NULL; | ||
| 324 | @@ -1123,6 +1126,8 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, | ||
| 325 | |||
| 326 | if (r_pk) | ||
| 327 | *r_pk = NULL; | ||
| 328 | + if (r_keyblock) | ||
| 329 | + *r_keyblock = NULL; | ||
| 330 | |||
| 331 | log_assert (node->pkt->pkttype == PKT_SIGNATURE); | ||
| 332 | if (is_selfsig) | ||
| 333 | @@ -1199,16 +1204,19 @@ do_check_sig (CTX c, kbnode_t node, const void *extrahash, size_t extrahashlen, | ||
| 334 | /* We only get here if we are checking the signature of a binary | ||
| 335 | (0x00) or text document (0x01). */ | ||
| 336 | rc = check_signature (c->ctrl, sig, md, extrahash, extrahashlen, | ||
| 337 | - forced_pk, NULL, is_expkey, is_revkey, r_pk); | ||
| 338 | + forced_pk, NULL, is_expkey, is_revkey, | ||
| 339 | + r_pk, r_keyblock); | ||
| 340 | if (! rc) | ||
| 341 | md_good = md; | ||
| 342 | else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2) | ||
| 343 | { | ||
| 344 | PKT_public_key *pk2; | ||
| 345 | |||
| 346 | + if (r_keyblock) | ||
| 347 | + release_kbnode (*r_keyblock); | ||
| 348 | rc = check_signature (c->ctrl, sig, md2, extrahash, extrahashlen, | ||
| 349 | forced_pk, NULL, is_expkey, is_revkey, | ||
| 350 | - r_pk? &pk2 : NULL); | ||
| 351 | + r_pk? &pk2 : NULL, r_keyblock); | ||
| 352 | if (!rc) | ||
| 353 | { | ||
| 354 | md_good = md2; | ||
| 355 | @@ -1371,7 +1379,7 @@ list_node (CTX c, kbnode_t node) | ||
| 356 | { | ||
| 357 | fflush (stdout); | ||
| 358 | rc2 = do_check_sig (c, node, NULL, 0, NULL, | ||
| 359 | - &is_selfsig, NULL, NULL, NULL); | ||
| 360 | + &is_selfsig, NULL, NULL, NULL, NULL); | ||
| 361 | switch (gpg_err_code (rc2)) | ||
| 362 | { | ||
| 363 | case 0: sigrc = '!'; break; | ||
| 364 | @@ -1830,7 +1838,7 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 365 | PKT_public_key *pk = NULL; /* The public key for the signature or NULL. */ | ||
| 366 | const void *extrahash = NULL; | ||
| 367 | size_t extrahashlen = 0; | ||
| 368 | - kbnode_t included_keyblock = NULL; | ||
| 369 | + kbnode_t keyblock = NULL; | ||
| 370 | |||
| 371 | if (opt.skip_verify) | ||
| 372 | { | ||
| 373 | @@ -1949,7 +1957,8 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 374 | { | ||
| 375 | ambiguous: | ||
| 376 | log_error(_("can't handle this ambiguous signature data\n")); | ||
| 377 | - return 0; | ||
| 378 | + rc = 0; | ||
| 379 | + goto leave; | ||
| 380 | } | ||
| 381 | } /* End checking signature packet composition. */ | ||
| 382 | |||
| 383 | @@ -1985,7 +1994,7 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 384 | log_info (_(" issuer \"%s\"\n"), sig->signers_uid); | ||
| 385 | |||
| 386 | rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 387 | - NULL, &is_expkey, &is_revkey, &pk); | ||
| 388 | + NULL, &is_expkey, &is_revkey, &pk, &keyblock); | ||
| 389 | |||
| 390 | /* If the key is not found but the signature includes a key block we | ||
| 391 | * use that key block for verification and on success import it. */ | ||
| 392 | @@ -1993,6 +2002,7 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 393 | && sig->flags.key_block | ||
| 394 | && opt.flags.auto_key_import) | ||
| 395 | { | ||
| 396 | + kbnode_t included_keyblock = NULL; | ||
| 397 | PKT_public_key *included_pk; | ||
| 398 | const byte *kblock; | ||
| 399 | size_t kblock_len; | ||
| 400 | @@ -2004,10 +2014,12 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 401 | kblock+1, kblock_len-1, | ||
| 402 | sig->keyid, &included_keyblock)) | ||
| 403 | { | ||
| 404 | + /* Note: This is the only place where we use the forced_pk | ||
| 405 | + * arg (ie. included_pk) with do_check_sig. */ | ||
| 406 | rc = do_check_sig (c, node, extrahash, extrahashlen, included_pk, | ||
| 407 | - NULL, &is_expkey, &is_revkey, &pk); | ||
| 408 | + NULL, &is_expkey, &is_revkey, &pk, NULL); | ||
| 409 | if (opt.verbose) | ||
| 410 | - log_debug ("checked signature using included key block: %s\n", | ||
| 411 | + log_info ("checked signature using included key block: %s\n", | ||
| 412 | gpg_strerror (rc)); | ||
| 413 | if (!rc) | ||
| 414 | { | ||
| 415 | @@ -2017,6 +2029,18 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 416 | |||
| 417 | } | ||
| 418 | free_public_key (included_pk); | ||
| 419 | + release_kbnode (included_keyblock); | ||
| 420 | + | ||
| 421 | + /* To make sure that nothing strange happened we check the | ||
| 422 | + * signature again now using our own key store. This also | ||
| 423 | + * returns the keyblock which we use later on. */ | ||
| 424 | + if (!rc) | ||
| 425 | + { | ||
| 426 | + release_kbnode (keyblock); | ||
| 427 | + keyblock = NULL; | ||
| 428 | + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 429 | + NULL, &is_expkey, &is_revkey, &pk, &keyblock); | ||
| 430 | + } | ||
| 431 | } | ||
| 432 | |||
| 433 | /* If the key isn't found, check for a preferred keyserver. Note | ||
| 434 | @@ -2063,8 +2087,13 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 435 | KEYSERVER_IMPORT_FLAG_QUICK); | ||
| 436 | glo_ctrl.in_auto_key_retrieve--; | ||
| 437 | if (!res) | ||
| 438 | - rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 439 | - NULL, &is_expkey, &is_revkey, &pk); | ||
| 440 | + { | ||
| 441 | + release_kbnode (keyblock); | ||
| 442 | + keyblock = NULL; | ||
| 443 | + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 444 | + NULL, &is_expkey, &is_revkey, &pk, | ||
| 445 | + &keyblock); | ||
| 446 | + } | ||
| 447 | else if (DBG_LOOKUP) | ||
| 448 | log_debug ("lookup via %s failed: %s\n", "Pref-KS", | ||
| 449 | gpg_strerror (res)); | ||
| 450 | @@ -2105,8 +2134,12 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 451 | /* Fixme: If the fingerprint is embedded in the signature, | ||
| 452 | * compare it to the fingerprint of the returned key. */ | ||
| 453 | if (!res) | ||
| 454 | - rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 455 | - NULL, &is_expkey, &is_revkey, &pk); | ||
| 456 | + { | ||
| 457 | + release_kbnode (keyblock); | ||
| 458 | + keyblock = NULL; | ||
| 459 | + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 460 | + NULL, &is_expkey, &is_revkey, &pk, &keyblock); | ||
| 461 | + } | ||
| 462 | else if (DBG_LOOKUP) | ||
| 463 | log_debug ("lookup via %s failed: %s\n", "WKD", gpg_strerror (res)); | ||
| 464 | } | ||
| 465 | @@ -2136,8 +2169,13 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 466 | KEYSERVER_IMPORT_FLAG_QUICK); | ||
| 467 | glo_ctrl.in_auto_key_retrieve--; | ||
| 468 | if (!res) | ||
| 469 | - rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 470 | - NULL, &is_expkey, &is_revkey, &pk); | ||
| 471 | + { | ||
| 472 | + release_kbnode (keyblock); | ||
| 473 | + keyblock = NULL; | ||
| 474 | + rc = do_check_sig (c, node, extrahash, extrahashlen, NULL, | ||
| 475 | + NULL, &is_expkey, &is_revkey, &pk, | ||
| 476 | + &keyblock); | ||
| 477 | + } | ||
| 478 | else if (DBG_LOOKUP) | ||
| 479 | log_debug ("lookup via %s failed: %s\n", "KS", gpg_strerror (res)); | ||
| 480 | } | ||
| 481 | @@ -2148,7 +2186,7 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 482 | { | ||
| 483 | /* We have checked the signature and the result is either a good | ||
| 484 | * signature or a bad signature. Further examination follows. */ | ||
| 485 | - kbnode_t un, keyblock; | ||
| 486 | + kbnode_t un; | ||
| 487 | int count = 0; | ||
| 488 | int keyblock_has_pk = 0; /* For failsafe check. */ | ||
| 489 | int statno; | ||
| 490 | @@ -2166,18 +2204,6 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 491 | else | ||
| 492 | statno = STATUS_GOODSIG; | ||
| 493 | |||
| 494 | - /* FIXME: We should have the public key in PK and thus the | ||
| 495 | - * keyblock has already been fetched. Thus we could use the | ||
| 496 | - * fingerprint or PK itself to lookup the entire keyblock. That | ||
| 497 | - * would best be done with a cache. */ | ||
| 498 | - if (included_keyblock) | ||
| 499 | - { | ||
| 500 | - keyblock = included_keyblock; | ||
| 501 | - included_keyblock = NULL; | ||
| 502 | - } | ||
| 503 | - else | ||
| 504 | - keyblock = get_pubkeyblock_for_sig (c->ctrl, sig); | ||
| 505 | - | ||
| 506 | snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ", | ||
| 507 | (ulong)sig->keyid[0], (ulong)sig->keyid[1]); | ||
| 508 | |||
| 509 | @@ -2243,10 +2269,10 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 510 | * contained in the keyring.*/ | ||
| 511 | } | ||
| 512 | |||
| 513 | - log_assert (mainpk); | ||
| 514 | - if (!keyblock_has_pk) | ||
| 515 | + if (!mainpk || !keyblock_has_pk) | ||
| 516 | { | ||
| 517 | - log_error ("signature key lost from keyblock\n"); | ||
| 518 | + log_error ("signature key lost from keyblock (%p,%p,%d)\n", | ||
| 519 | + keyblock, mainpk, keyblock_has_pk); | ||
| 520 | rc = gpg_error (GPG_ERR_INTERNAL); | ||
| 521 | } | ||
| 522 | |||
| 523 | @@ -2514,8 +2540,8 @@ check_sig_and_print (CTX c, kbnode_t node) | ||
| 524 | log_error (_("Can't check signature: %s\n"), gpg_strerror (rc)); | ||
| 525 | } | ||
| 526 | |||
| 527 | + leave: | ||
| 528 | free_public_key (pk); | ||
| 529 | - release_kbnode (included_keyblock); | ||
| 530 | xfree (issuer_fpr); | ||
| 531 | return rc; | ||
| 532 | } | ||
| 533 | diff --git a/g10/packet.h b/g10/packet.h | ||
| 534 | index 8aaf32d..669739a 100644 | ||
| 535 | --- a/g10/packet.h | ||
| 536 | +++ b/g10/packet.h | ||
| 537 | @@ -899,7 +899,7 @@ gpg_error_t check_signature (ctrl_t ctrl, | ||
| 538 | const void *extrahash, size_t extrahashlen, | ||
| 539 | PKT_public_key *forced_pk, | ||
| 540 | u32 *r_expiredate, int *r_expired, int *r_revoked, | ||
| 541 | - PKT_public_key **r_pk); | ||
| 542 | + PKT_public_key **r_pk, kbnode_t *r_keyblock); | ||
| 543 | |||
| 544 | |||
| 545 | /*-- pubkey-enc.c --*/ | ||
| 546 | diff --git a/g10/sig-check.c b/g10/sig-check.c | ||
| 547 | index 2272fa4..11f3e0c 100644 | ||
| 548 | --- a/g10/sig-check.c | ||
| 549 | +++ b/g10/sig-check.c | ||
| 550 | @@ -138,6 +138,11 @@ check_key_verify_compliance (PKT_public_key *pk) | ||
| 551 | * If R_PK is not NULL, the public key is stored at that address if it | ||
| 552 | * was found; other wise NULL is stored. | ||
| 553 | * | ||
| 554 | + * If R_KEYBLOCK is not NULL, the entire keyblock used to verify the | ||
| 555 | + * signature is stored at that address. If no key was found or on | ||
| 556 | + * some other errors NULL is stored there. The callers needs to | ||
| 557 | + * release the keyblock using release_kbnode (kb). | ||
| 558 | + * | ||
| 559 | * Returns 0 on success. An error code otherwise. */ | ||
| 560 | gpg_error_t | ||
| 561 | check_signature (ctrl_t ctrl, | ||
| 562 | @@ -145,7 +150,7 @@ check_signature (ctrl_t ctrl, | ||
| 563 | const void *extrahash, size_t extrahashlen, | ||
| 564 | PKT_public_key *forced_pk, | ||
| 565 | u32 *r_expiredate, int *r_expired, int *r_revoked, | ||
| 566 | - PKT_public_key **r_pk) | ||
| 567 | + PKT_public_key **r_pk, kbnode_t *r_keyblock) | ||
| 568 | { | ||
| 569 | int rc=0; | ||
| 570 | PKT_public_key *pk; | ||
| 571 | @@ -158,6 +163,8 @@ check_signature (ctrl_t ctrl, | ||
| 572 | *r_revoked = 0; | ||
| 573 | if (r_pk) | ||
| 574 | *r_pk = NULL; | ||
| 575 | + if (r_keyblock) | ||
| 576 | + *r_keyblock = NULL; | ||
| 577 | |||
| 578 | pk = xtrycalloc (1, sizeof *pk); | ||
| 579 | if (!pk) | ||
| 580 | @@ -188,7 +195,7 @@ check_signature (ctrl_t ctrl, | ||
| 581 | log_info(_("WARNING: signature digest conflict in message\n")); | ||
| 582 | rc = gpg_error (GPG_ERR_GENERAL); | ||
| 583 | } | ||
| 584 | - else if (get_pubkey_for_sig (ctrl, pk, sig, forced_pk)) | ||
| 585 | + else if (get_pubkey_for_sig (ctrl, pk, sig, forced_pk, r_keyblock)) | ||
| 586 | rc = gpg_error (GPG_ERR_NO_PUBKEY); | ||
| 587 | else if ((rc = check_key_verify_compliance (pk))) | ||
| 588 | ;/* Compliance failure. */ | ||
| 589 | @@ -786,9 +793,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig) | ||
| 590 | keyid_from_fingerprint (ctrl, pk->revkey[i].fpr, pk->revkey[i].fprlen, | ||
| 591 | keyid); | ||
| 592 | |||
| 593 | - if(keyid[0]==sig->keyid[0] && keyid[1]==sig->keyid[1]) | ||
| 594 | - /* The signature was generated by a designated revoker. | ||
| 595 | - Verify the signature. */ | ||
| 596 | + /* If the signature was generated by a designated revoker | ||
| 597 | + * verify the signature. */ | ||
| 598 | + if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]) | ||
| 599 | { | ||
| 600 | gcry_md_hd_t md; | ||
| 601 | |||
| 602 | @@ -796,9 +803,9 @@ check_revocation_keys (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig) | ||
| 603 | BUG (); | ||
| 604 | hash_public_key(md,pk); | ||
| 605 | /* Note: check_signature only checks that the signature | ||
| 606 | - is good. It does not fail if the key is revoked. */ | ||
| 607 | + * is good. It does not fail if the key is revoked. */ | ||
| 608 | rc = check_signature (ctrl, sig, md, NULL, 0, NULL, | ||
| 609 | - NULL, NULL, NULL, NULL); | ||
| 610 | + NULL, NULL, NULL, NULL, NULL); | ||
| 611 | cache_sig_result(sig,rc); | ||
| 612 | gcry_md_close (md); | ||
| 613 | break; | ||
| 614 | @@ -1003,7 +1010,7 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, | ||
| 615 | if (IS_CERT (sig)) | ||
| 616 | signer->req_usage = PUBKEY_USAGE_CERT; | ||
| 617 | |||
| 618 | - rc = get_pubkey_for_sig (ctrl, signer, sig, NULL); | ||
| 619 | + rc = get_pubkey_for_sig (ctrl, signer, sig, NULL, NULL); | ||
| 620 | if (rc) | ||
| 621 | { | ||
| 622 | xfree (signer); | ||
| 623 | -- | ||
| 624 | 2.40.0 | ||
diff --git a/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0004.patch b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0004.patch new file mode 100644 index 0000000000..67cf6efb6e --- /dev/null +++ b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0004.patch | |||
| @@ -0,0 +1,193 @@ | |||
| 1 | From 1e581619bf5315957f2be06b3b1a7f513304c126 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Werner Koch <wk@gnupg.org> | ||
| 3 | Date: Thu, 6 Mar 2025 17:17:17 +0100 | ||
| 4 | Subject: [PATCH] gpg: Fix regression for the recent malicious subkey DoS fix. | ||
| 5 | |||
| 6 | * g10/packet.h (PUBKEY_USAGE_VERIFY): New. | ||
| 7 | * g10/getkey.c (get_pubkey_for_sig): Pass new flag also to requested | ||
| 8 | usage. | ||
| 9 | (finish_lookup): Introduce a verify_mode. | ||
| 10 | -- | ||
| 11 | |||
| 12 | Fixes-commit: da0164efc7f32013bc24d97b9afa9f8d67c318bb | ||
| 13 | GnuPG-bug-id: 7547 | ||
| 14 | |||
| 15 | CVE: CVE-2025-30258 | ||
| 16 | Upstream-Status: Backport [https://dev.gnupg.org/rG1e581619bf5315957f2be06b3b1a7f513304c126] | ||
| 17 | |||
| 18 | Reference: | ||
| 19 | https://git.launchpad.net/ubuntu/+source/gnupg2/commit/?id=d086c55a85faafdf8448c12ed726d587e729d2d0 | ||
| 20 | |||
| 21 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 22 | --- | ||
| 23 | g10/getkey.c | 42 ++++++++++++++++++++++++++---------------- | ||
| 24 | g10/packet.h | 5 +++-- | ||
| 25 | 2 files changed, 29 insertions(+), 18 deletions(-) | ||
| 26 | |||
| 27 | diff --git a/g10/getkey.c b/g10/getkey.c | ||
| 28 | index 0fa763a..2a1b330 100644 | ||
| 29 | --- a/g10/getkey.c | ||
| 30 | +++ b/g10/getkey.c | ||
| 31 | @@ -309,11 +309,12 @@ pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key) | ||
| 32 | |||
| 33 | |||
| 34 | /* Specialized version of get_pubkey which retrieves the key based on | ||
| 35 | - * information in SIG. In contrast to get_pubkey PK is required. IF | ||
| 36 | + * information in SIG. In contrast to get_pubkey PK is required. If | ||
| 37 | * FORCED_PK is not NULL, this public key is used and copied to PK. | ||
| 38 | * If R_KEYBLOCK is not NULL the entire keyblock is stored there if | ||
| 39 | * found and FORCED_PK is not used; if not used or on error NULL is | ||
| 40 | - * stored there. */ | ||
| 41 | + * stored there. Use this function only to find the key for | ||
| 42 | + * verification; it can't be used to select a key for signing. */ | ||
| 43 | gpg_error_t | ||
| 44 | get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig, | ||
| 45 | PKT_public_key *forced_pk, kbnode_t *r_keyblock) | ||
| 46 | @@ -333,8 +334,9 @@ get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig, | ||
| 47 | |||
| 48 | /* Make sure to request only keys cabable of signing. This makes | ||
| 49 | * sure that a subkey w/o a valid backsig or with bad usage flags | ||
| 50 | - * will be skipped. */ | ||
| 51 | - pk->req_usage = PUBKEY_USAGE_SIG; | ||
| 52 | + * will be skipped. We also request the verification mode so that | ||
| 53 | + * expired and reoked keys are returned. */ | ||
| 54 | + pk->req_usage = (PUBKEY_USAGE_SIG | PUBKEY_USAGE_VERIFY); | ||
| 55 | |||
| 56 | /* First try the ISSUER_FPR info. */ | ||
| 57 | fpr = issuer_fpr_raw (sig, &fprlen); | ||
| 58 | @@ -398,10 +400,10 @@ get_pubkey_bykid (ctrl_t ctrl, PKT_public_key *pk, kbnode_t *r_keyblock, | ||
| 59 | /* Try to get it from the cache. We don't do this when pk is | ||
| 60 | * NULL as it does not guarantee that the user IDs are cached. | ||
| 61 | * The old get_pubkey_function did not check PK->REQ_USAGE when | ||
| 62 | - * reading form the caceh. This is probably a bug. Note that | ||
| 63 | + * reading from the cache. This is probably a bug. Note that | ||
| 64 | * the cache is not used when the caller asked to return the | ||
| 65 | * entire keyblock. This is because the cache does not | ||
| 66 | - * associate the public key wit its primary key. */ | ||
| 67 | + * associate the public key with its primary key. */ | ||
| 68 | pk_cache_entry_t ce; | ||
| 69 | for (ce = pk_cache; ce; ce = ce->next) | ||
| 70 | { | ||
| 71 | @@ -3634,11 +3636,17 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 72 | PKT_public_key *pk; | ||
| 73 | int req_prim; | ||
| 74 | int diag_exactfound = 0; | ||
| 75 | + int verify_mode = 0; | ||
| 76 | u32 curtime = make_timestamp (); | ||
| 77 | |||
| 78 | if (r_flags) | ||
| 79 | *r_flags = 0; | ||
| 80 | |||
| 81 | + /* The verify mode is used to change the behaviour so that we can | ||
| 82 | + * return an expired or revoked key for signature verification. */ | ||
| 83 | + verify_mode = ((req_usage & PUBKEY_USAGE_VERIFY) | ||
| 84 | + && (req_usage & PUBKEY_USAGE_SIG)); | ||
| 85 | + | ||
| 86 | #define USAGE_MASK (PUBKEY_USAGE_SIG|PUBKEY_USAGE_ENC|PUBKEY_USAGE_CERT) | ||
| 87 | req_usage &= USAGE_MASK; | ||
| 88 | |||
| 89 | @@ -3682,9 +3690,9 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 90 | } | ||
| 91 | |||
| 92 | if (DBG_LOOKUP) | ||
| 93 | - log_debug ("finish_lookup: checking key %08lX (%s)(req_usage=%x)\n", | ||
| 94 | + log_debug ("finish_lookup: checking key %08lX (%s)(req_usage=%x%s)\n", | ||
| 95 | (ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL), | ||
| 96 | - foundk ? "one" : "all", req_usage); | ||
| 97 | + foundk ? "one" : "all", req_usage, verify_mode? ",verify":""); | ||
| 98 | if (diag_exactfound && DBG_LOOKUP) | ||
| 99 | log_debug ("\texact search requested and found\n"); | ||
| 100 | |||
| 101 | @@ -3747,28 +3755,28 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 102 | } | ||
| 103 | |||
| 104 | n_subkeys++; | ||
| 105 | - if (pk->flags.revoked) | ||
| 106 | + if (!verify_mode && pk->flags.revoked) | ||
| 107 | { | ||
| 108 | if (DBG_LOOKUP) | ||
| 109 | log_debug ("\tsubkey has been revoked\n"); | ||
| 110 | n_revoked_or_expired++; | ||
| 111 | continue; | ||
| 112 | } | ||
| 113 | - if (pk->has_expired) | ||
| 114 | + if (!verify_mode && pk->has_expired) | ||
| 115 | { | ||
| 116 | if (DBG_LOOKUP) | ||
| 117 | log_debug ("\tsubkey has expired\n"); | ||
| 118 | n_revoked_or_expired++; | ||
| 119 | continue; | ||
| 120 | } | ||
| 121 | - if (pk->timestamp > curtime && !opt.ignore_valid_from) | ||
| 122 | + if (!verify_mode && pk->timestamp > curtime && !opt.ignore_valid_from) | ||
| 123 | { | ||
| 124 | if (DBG_LOOKUP) | ||
| 125 | log_debug ("\tsubkey not yet valid\n"); | ||
| 126 | continue; | ||
| 127 | } | ||
| 128 | |||
| 129 | - if (want_secret) | ||
| 130 | + if (!verify_mode && want_secret) | ||
| 131 | { | ||
| 132 | int secret_key_avail = agent_probe_secret_key (NULL, pk); | ||
| 133 | |||
| 134 | @@ -3788,7 +3796,8 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 135 | } | ||
| 136 | |||
| 137 | if (DBG_LOOKUP) | ||
| 138 | - log_debug ("\tsubkey might be fine\n"); | ||
| 139 | + log_debug ("\tsubkey might be fine%s\n", | ||
| 140 | + verify_mode? " for verification":""); | ||
| 141 | /* In case a key has a timestamp of 0 set, we make sure | ||
| 142 | that it is used. A better change would be to compare | ||
| 143 | ">=" but that might also change the selected keys and | ||
| 144 | @@ -3829,12 +3838,12 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 145 | log_debug ("\tprimary key usage does not match: " | ||
| 146 | "want=%x have=%x\n", req_usage, pk->pubkey_usage); | ||
| 147 | } | ||
| 148 | - else if (pk->flags.revoked) | ||
| 149 | + else if (!verify_mode && pk->flags.revoked) | ||
| 150 | { | ||
| 151 | if (DBG_LOOKUP) | ||
| 152 | log_debug ("\tprimary key has been revoked\n"); | ||
| 153 | } | ||
| 154 | - else if (pk->has_expired) | ||
| 155 | + else if (!verify_mode && pk->has_expired) | ||
| 156 | { | ||
| 157 | if (DBG_LOOKUP) | ||
| 158 | log_debug ("\tprimary key has expired\n"); | ||
| 159 | @@ -3842,7 +3851,8 @@ finish_lookup (kbnode_t keyblock, unsigned int req_usage, int want_exact, | ||
| 160 | else /* Okay. */ | ||
| 161 | { | ||
| 162 | if (DBG_LOOKUP) | ||
| 163 | - log_debug ("\tprimary key may be used\n"); | ||
| 164 | + log_debug ("\tprimary key may be used%s\n", | ||
| 165 | + verify_mode? " for verification":""); | ||
| 166 | latest_key = keyblock; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | diff --git a/g10/packet.h b/g10/packet.h | ||
| 170 | index 669739a..061a9b1 100644 | ||
| 171 | --- a/g10/packet.h | ||
| 172 | +++ b/g10/packet.h | ||
| 173 | @@ -135,6 +135,7 @@ typedef struct { | ||
| 174 | gcry_mpi_t data[PUBKEY_MAX_NENC]; | ||
| 175 | } PKT_pubkey_enc; | ||
| 176 | |||
| 177 | +#define PUBKEY_USAGE_VERIFY 16384 /* Verify only modifier. */ | ||
| 178 | |||
| 179 | /* An object to build a list of public-key encrypted session key. */ | ||
| 180 | struct pubkey_enc_list | ||
| 181 | @@ -385,8 +386,8 @@ typedef struct | ||
| 182 | byte selfsigversion; /* highest version of all of the self-sigs */ | ||
| 183 | /* The public key algorithm. (Serialized.) */ | ||
| 184 | byte pubkey_algo; | ||
| 185 | - byte pubkey_usage; /* for now only used to pass it to getkey() */ | ||
| 186 | - byte req_usage; /* hack to pass a request to getkey() */ | ||
| 187 | + u16 pubkey_usage; /* for now only used to pass it to getkey() */ | ||
| 188 | + u16 req_usage; /* hack to pass a request to getkey() */ | ||
| 189 | byte fprlen; /* 0 or length of FPR. */ | ||
| 190 | u32 has_expired; /* set to the expiration date if expired */ | ||
| 191 | /* keyid of the primary key. Never access this value directly. | ||
| 192 | -- | ||
| 193 | 2.40.0 | ||
diff --git a/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0005.patch b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0005.patch new file mode 100644 index 0000000000..527ef47cf4 --- /dev/null +++ b/meta/recipes-support/gnupg/gnupg/CVE-2025-30258-0005.patch | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | From 4be25979a6b3e2a79d7c9667b07db8b09fb046e9 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Werner Koch <wk@gnupg.org> | ||
| 3 | Date: Thu, 13 Mar 2025 11:35:34 +0100 | ||
| 4 | Subject: [PATCH] gpg: Fix double free of internal data. | ||
| 5 | |||
| 6 | * g10/sig-check.c (check_signature_over_key_or_uid): Do not free in | ||
| 7 | no-sig-cache mode if allocated by caller. | ||
| 8 | -- | ||
| 9 | |||
| 10 | GnuPG-bug-id: 7547 | ||
| 11 | Fixes-commit: 44cdb9d73f1a0b7d2c8483a119b9c4d6caabc1ec | ||
| 12 | |||
| 13 | CVE: CVE-2025-30258 | ||
| 14 | Upstream-Status: Backport [https://dev.gnupg.org/rG4be25979a6b3e2a79d7c9667b07db8b09fb046e9] | ||
| 15 | |||
| 16 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 17 | --- | ||
| 18 | g10/sig-check.c | 3 ++- | ||
| 19 | 1 file changed, 2 insertions(+), 1 deletion(-) | ||
| 20 | |||
| 21 | diff --git a/g10/sig-check.c b/g10/sig-check.c | ||
| 22 | index 11f3e0c..a8fbdc7 100644 | ||
| 23 | --- a/g10/sig-check.c | ||
| 24 | +++ b/g10/sig-check.c | ||
| 25 | @@ -1013,7 +1013,8 @@ check_signature_over_key_or_uid (ctrl_t ctrl, PKT_public_key *signer, | ||
| 26 | rc = get_pubkey_for_sig (ctrl, signer, sig, NULL, NULL); | ||
| 27 | if (rc) | ||
| 28 | { | ||
| 29 | - xfree (signer); | ||
| 30 | + if (signer_alloced != 1) | ||
| 31 | + xfree (signer); | ||
| 32 | signer = NULL; | ||
| 33 | signer_alloced = 0; | ||
| 34 | goto leave; | ||
| 35 | -- | ||
| 36 | 2.40.0 | ||
diff --git a/meta/recipes-support/gnupg/gnupg_2.3.7.bb b/meta/recipes-support/gnupg/gnupg_2.3.7.bb index 7075a61898..461ec6687c 100644 --- a/meta/recipes-support/gnupg/gnupg_2.3.7.bb +++ b/meta/recipes-support/gnupg/gnupg_2.3.7.bb | |||
| @@ -18,6 +18,11 @@ SRC_URI = "${GNUPG_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \ | |||
| 18 | file://0002-use-pkgconfig-instead-of-npth-config.patch \ | 18 | file://0002-use-pkgconfig-instead-of-npth-config.patch \ |
| 19 | file://0004-autogen.sh-fix-find-version-for-beta-checking.patch \ | 19 | file://0004-autogen.sh-fix-find-version-for-beta-checking.patch \ |
| 20 | file://0001-Woverride-init-is-not-needed-with-gcc-9.patch \ | 20 | file://0001-Woverride-init-is-not-needed-with-gcc-9.patch \ |
| 21 | file://CVE-2025-30258-0001.patch \ | ||
| 22 | file://CVE-2025-30258-0002.patch \ | ||
| 23 | file://CVE-2025-30258-0003.patch \ | ||
| 24 | file://CVE-2025-30258-0004.patch \ | ||
| 25 | file://CVE-2025-30258-0005.patch \ | ||
| 21 | " | 26 | " |
| 22 | SRC_URI:append:class-native = " file://0001-configure.ac-use-a-custom-value-for-the-location-of-.patch \ | 27 | SRC_URI:append:class-native = " file://0001-configure.ac-use-a-custom-value-for-the-location-of-.patch \ |
| 23 | file://relocate.patch" | 28 | file://relocate.patch" |
