From 9286d81264a2fb8985fb41363841176001cf625e Mon Sep 17 00:00:00 2001 From: azurelinux-security Date: Sat, 4 Jul 2026 10:20:13 +0000 Subject: [PATCH] Patch libreswan for CVE-2026-50722 --- base/comps/components.toml | 1 - base/comps/libreswan/CVE-2026-50722.patch | 181 ++++++++++++++++++++++ base/comps/libreswan/libreswan.comp.toml | 6 + locks/libreswan.lock | 2 +- specs/l/libreswan/CVE-2026-50722.patch | 181 ++++++++++++++++++++++ specs/l/libreswan/libreswan.spec | 10 +- 6 files changed, 376 insertions(+), 5 deletions(-) create mode 100644 base/comps/libreswan/CVE-2026-50722.patch create mode 100644 base/comps/libreswan/libreswan.comp.toml create mode 100644 specs/l/libreswan/CVE-2026-50722.patch diff --git a/base/comps/components.toml b/base/comps/components.toml index bb8ce516b0f..24a2ee1a0fd 100644 --- a/base/comps/components.toml +++ b/base/comps/components.toml @@ -1866,7 +1866,6 @@ includes = ["**/*.comp.toml", "component-check-disablement.toml", "component-min [components.librelp] [components.librepo] [components.libreport] -[components.libreswan] [components.libretls] [components.librevenge] [components.librhsm] diff --git a/base/comps/libreswan/CVE-2026-50722.patch b/base/comps/libreswan/CVE-2026-50722.patch new file mode 100644 index 00000000000..c7502022e85 --- /dev/null +++ b/base/comps/libreswan/CVE-2026-50722.patch @@ -0,0 +1,181 @@ +From a688deb518dbdd414196f6eba9367af3c018d91a Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Sat, 4 Jul 2026 10:13:50 +0000 +Subject: [PATCH] lib/libswan: verify PKCS1.1.5 RSA signatures with + VFY_VerifyDigestDirect + +Signed-off-by: autosec +Upstream-reference: https://libreswan.org/security/CVE-2026-50722/libreswan-5.3-CVE-2026-50722.patch +--- + lib/libswan/pubkey_rsa.c | 124 +++++++++------------------------------ + 1 file changed, 28 insertions(+), 96 deletions(-) + +diff --git a/lib/libswan/pubkey_rsa.c b/lib/libswan/pubkey_rsa.c +index a97590a..60be3cb 100644 +--- a/lib/libswan/pubkey_rsa.c ++++ b/lib/libswan/pubkey_rsa.c +@@ -388,7 +388,7 @@ static struct hash_signature RSA_raw_sign_hash(const struct secret_pubkey_stuff + static bool RSA_authenticate_signature_raw_rsa(const struct crypt_mac *expected_hash, + shunk_t signature, + struct pubkey *pubkey, +- const struct hash_desc *unused_hash_algo UNUSED, ++ const struct hash_desc *hash_alg, + diag_t *fatal_diag, + struct logger *logger) + { +@@ -406,58 +406,24 @@ static bool RSA_authenticate_signature_raw_rsa(const struct crypt_mac *expected_ + LDBG_hunk(logger, *expected_hash); + } + +- /* +- * Use the same space used by the out going hash. +- */ +- +- SECItem decrypted_signature = { +- .type = siBuffer, +- }; +- +- if (SECITEM_AllocItem(NULL, &decrypted_signature, signature.len) == NULL) { +- llog_nss_error(RC_LOG, logger, "allocating space for decrypted RSA signature"); +- return false; +- } +- + /* NSS doesn't do const */ +- const SECItem encrypted_signature = { +- .type = siBuffer, +- .data = DISCARD_CONST(unsigned char *, signature.ptr), +- .len = signature.len, +- }; ++ SECItem hash_item = ++ same_shunk_as_secitem(HUNK_AS_SHUNK(*expected_hash), siBuffer); + +- if (PK11_VerifyRecover(seckey_public, &encrypted_signature, &decrypted_signature, +- lsw_nss_get_password_context(logger)) != SECSuccess) { +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); +- ldbg(logger, "NSS RSA verify: decrypting signature is failed"); +- *fatal_diag = NULL; +- return false; +- } +- +- if (LDBGP(DBG_CRYPT, logger)) { +- LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { +- jam_string(buf, "NSS RSA verify: decrypted sig: "); +- jam_nss_secitem(buf, &decrypted_signature); +- } +- } +- +- /* +- * Expect the matching hash to appear at the end. See above +- * for length check. It may, or may not, be prefixed by a +- * PKCS#1 1.5 RSA ASN.1 blob. +- */ +- passert(decrypted_signature.len >= expected_hash->len); +- uint8_t *start = (decrypted_signature.data +- + decrypted_signature.len +- - expected_hash->len); +- if (!memeq(start, expected_hash->ptr, expected_hash->len)) { +- ldbg(logger, "RSA Signature NOT verified"); +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); ++ /* NSS doesn't do const */ ++ SECItem signature_item = ++ same_shunk_as_secitem(signature, siBuffer); ++ ++ if (VFY_VerifyDigestDirect(&hash_item, ++ seckey_public, ++ &signature_item, ++ /*pubkey algorithm*/SEC_OID_PKCS1_RSA_ENCRYPTION, ++ /*hash algorithm*/hash_alg->nss.oid_tag, ++ lsw_nss_get_password_context(logger)) != SECSuccess) { ++ ldbg_nss_error(logger, "NSS VFY_VerifyDigest() failed"); + *fatal_diag = NULL; + return false; + } +- +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); + *fatal_diag = NULL; + return true; + } +@@ -533,7 +499,7 @@ static struct hash_signature RSA_pkcs1_1_5_sign_hash(const struct secret_pubkey_ + static bool RSA_authenticate_signature_pkcs1_1_5_rsa(const struct crypt_mac *expected_hash, + shunk_t signature, + struct pubkey *pubkey, +- const struct hash_desc *unused_hash_algo UNUSED, ++ const struct hash_desc *hash_alg, + diag_t *fatal_diag, + struct logger *logger) + { +@@ -551,58 +517,24 @@ static bool RSA_authenticate_signature_pkcs1_1_5_rsa(const struct crypt_mac *exp + LDBG_hunk(logger, *expected_hash); + } + +- /* +- * Use the same space used by the out going hash. +- */ +- +- SECItem decrypted_signature = { +- .type = siBuffer, +- }; +- +- if (SECITEM_AllocItem(NULL, &decrypted_signature, signature.len) == NULL) { +- llog_nss_error(RC_LOG, logger, "allocating space for decrypted RSA signature"); +- return false; +- } +- + /* NSS doesn't do const */ +- const SECItem encrypted_signature = { +- .type = siBuffer, +- .data = DISCARD_CONST(unsigned char *, signature.ptr), +- .len = signature.len, +- }; ++ SECItem hash_item = ++ same_shunk_as_secitem(HUNK_AS_SHUNK(*expected_hash), siBuffer); + +- if (PK11_VerifyRecover(seckey_public, &encrypted_signature, &decrypted_signature, +- lsw_nss_get_password_context(logger)) != SECSuccess) { +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); +- ldbg(logger, "NSS RSA verify: decrypting signature is failed"); +- *fatal_diag = NULL; +- return false; +- } +- +- if (LDBGP(DBG_CRYPT, logger)) { +- LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { +- jam_string(buf, "NSS RSA verify: decrypted sig: "); +- jam_nss_secitem(buf, &decrypted_signature); +- } +- } +- +- /* +- * Expect the matching hash to appear at the end. See above +- * for length check. It may, or may not, be prefixed by a +- * PKCS#1 1.5 RSA ASN.1 blob. +- */ +- passert(decrypted_signature.len >= expected_hash->len); +- uint8_t *start = (decrypted_signature.data +- + decrypted_signature.len +- - expected_hash->len); +- if (!memeq(start, expected_hash->ptr, expected_hash->len)) { +- ldbg(logger, "RSA Signature NOT verified"); +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); ++ /* NSS doesn't do const */ ++ SECItem signature_item = ++ same_shunk_as_secitem(signature, siBuffer); ++ ++ if (VFY_VerifyDigestDirect(&hash_item, ++ seckey_public, ++ &signature_item, ++ /*pubkey algorithm*/SEC_OID_PKCS1_RSA_ENCRYPTION, ++ /*hash algorithm*/hash_alg->nss.oid_tag, ++ lsw_nss_get_password_context(logger)) != SECSuccess) { ++ ldbg_nss_error(logger, "NSS VFY_VerifyDigest() failed"); + *fatal_diag = NULL; + return false; + } +- +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); + *fatal_diag = NULL; + return true; + } +-- +2.45.4 + diff --git a/base/comps/libreswan/libreswan.comp.toml b/base/comps/libreswan/libreswan.comp.toml new file mode 100644 index 00000000000..b821c77f780 --- /dev/null +++ b/base/comps/libreswan/libreswan.comp.toml @@ -0,0 +1,6 @@ +[components.libreswan] + +[[components.libreswan.overlays]] +description = "Fix CVE-2026-50722 — https://libreswan.org/security/CVE-2026-50722/libreswan-5.3-CVE-2026-50722.patch" +type = "patch-add" +source = "CVE-2026-50722.patch" diff --git a/locks/libreswan.lock b/locks/libreswan.lock index 2f9836e5878..ada73f76d5b 100644 --- a/locks/libreswan.lock +++ b/locks/libreswan.lock @@ -2,5 +2,5 @@ version = 1 import-commit = '3a4974c4c3f418736c3a1f328720796bc4f36a19' upstream-commit = '3a4974c4c3f418736c3a1f328720796bc4f36a19' -input-fingerprint = 'sha256:ce58265c0c545f1ea50a9907a30651ef6404c380df259c48b65aa869ce0a8c59' +input-fingerprint = 'sha256:822b90d4eab56ea49efe8341f0d2089b57dd4f043270d71f36da9956676cc1b3' resolution-input-hash = 'sha256:466421704711c4fd3c71f0b2ed715a0e61d49e3e26f3a2637fee755795849c8e' diff --git a/specs/l/libreswan/CVE-2026-50722.patch b/specs/l/libreswan/CVE-2026-50722.patch new file mode 100644 index 00000000000..c7502022e85 --- /dev/null +++ b/specs/l/libreswan/CVE-2026-50722.patch @@ -0,0 +1,181 @@ +From a688deb518dbdd414196f6eba9367af3c018d91a Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Sat, 4 Jul 2026 10:13:50 +0000 +Subject: [PATCH] lib/libswan: verify PKCS1.1.5 RSA signatures with + VFY_VerifyDigestDirect + +Signed-off-by: autosec +Upstream-reference: https://libreswan.org/security/CVE-2026-50722/libreswan-5.3-CVE-2026-50722.patch +--- + lib/libswan/pubkey_rsa.c | 124 +++++++++------------------------------ + 1 file changed, 28 insertions(+), 96 deletions(-) + +diff --git a/lib/libswan/pubkey_rsa.c b/lib/libswan/pubkey_rsa.c +index a97590a..60be3cb 100644 +--- a/lib/libswan/pubkey_rsa.c ++++ b/lib/libswan/pubkey_rsa.c +@@ -388,7 +388,7 @@ static struct hash_signature RSA_raw_sign_hash(const struct secret_pubkey_stuff + static bool RSA_authenticate_signature_raw_rsa(const struct crypt_mac *expected_hash, + shunk_t signature, + struct pubkey *pubkey, +- const struct hash_desc *unused_hash_algo UNUSED, ++ const struct hash_desc *hash_alg, + diag_t *fatal_diag, + struct logger *logger) + { +@@ -406,58 +406,24 @@ static bool RSA_authenticate_signature_raw_rsa(const struct crypt_mac *expected_ + LDBG_hunk(logger, *expected_hash); + } + +- /* +- * Use the same space used by the out going hash. +- */ +- +- SECItem decrypted_signature = { +- .type = siBuffer, +- }; +- +- if (SECITEM_AllocItem(NULL, &decrypted_signature, signature.len) == NULL) { +- llog_nss_error(RC_LOG, logger, "allocating space for decrypted RSA signature"); +- return false; +- } +- + /* NSS doesn't do const */ +- const SECItem encrypted_signature = { +- .type = siBuffer, +- .data = DISCARD_CONST(unsigned char *, signature.ptr), +- .len = signature.len, +- }; ++ SECItem hash_item = ++ same_shunk_as_secitem(HUNK_AS_SHUNK(*expected_hash), siBuffer); + +- if (PK11_VerifyRecover(seckey_public, &encrypted_signature, &decrypted_signature, +- lsw_nss_get_password_context(logger)) != SECSuccess) { +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); +- ldbg(logger, "NSS RSA verify: decrypting signature is failed"); +- *fatal_diag = NULL; +- return false; +- } +- +- if (LDBGP(DBG_CRYPT, logger)) { +- LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { +- jam_string(buf, "NSS RSA verify: decrypted sig: "); +- jam_nss_secitem(buf, &decrypted_signature); +- } +- } +- +- /* +- * Expect the matching hash to appear at the end. See above +- * for length check. It may, or may not, be prefixed by a +- * PKCS#1 1.5 RSA ASN.1 blob. +- */ +- passert(decrypted_signature.len >= expected_hash->len); +- uint8_t *start = (decrypted_signature.data +- + decrypted_signature.len +- - expected_hash->len); +- if (!memeq(start, expected_hash->ptr, expected_hash->len)) { +- ldbg(logger, "RSA Signature NOT verified"); +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); ++ /* NSS doesn't do const */ ++ SECItem signature_item = ++ same_shunk_as_secitem(signature, siBuffer); ++ ++ if (VFY_VerifyDigestDirect(&hash_item, ++ seckey_public, ++ &signature_item, ++ /*pubkey algorithm*/SEC_OID_PKCS1_RSA_ENCRYPTION, ++ /*hash algorithm*/hash_alg->nss.oid_tag, ++ lsw_nss_get_password_context(logger)) != SECSuccess) { ++ ldbg_nss_error(logger, "NSS VFY_VerifyDigest() failed"); + *fatal_diag = NULL; + return false; + } +- +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); + *fatal_diag = NULL; + return true; + } +@@ -533,7 +499,7 @@ static struct hash_signature RSA_pkcs1_1_5_sign_hash(const struct secret_pubkey_ + static bool RSA_authenticate_signature_pkcs1_1_5_rsa(const struct crypt_mac *expected_hash, + shunk_t signature, + struct pubkey *pubkey, +- const struct hash_desc *unused_hash_algo UNUSED, ++ const struct hash_desc *hash_alg, + diag_t *fatal_diag, + struct logger *logger) + { +@@ -551,58 +517,24 @@ static bool RSA_authenticate_signature_pkcs1_1_5_rsa(const struct crypt_mac *exp + LDBG_hunk(logger, *expected_hash); + } + +- /* +- * Use the same space used by the out going hash. +- */ +- +- SECItem decrypted_signature = { +- .type = siBuffer, +- }; +- +- if (SECITEM_AllocItem(NULL, &decrypted_signature, signature.len) == NULL) { +- llog_nss_error(RC_LOG, logger, "allocating space for decrypted RSA signature"); +- return false; +- } +- + /* NSS doesn't do const */ +- const SECItem encrypted_signature = { +- .type = siBuffer, +- .data = DISCARD_CONST(unsigned char *, signature.ptr), +- .len = signature.len, +- }; ++ SECItem hash_item = ++ same_shunk_as_secitem(HUNK_AS_SHUNK(*expected_hash), siBuffer); + +- if (PK11_VerifyRecover(seckey_public, &encrypted_signature, &decrypted_signature, +- lsw_nss_get_password_context(logger)) != SECSuccess) { +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); +- ldbg(logger, "NSS RSA verify: decrypting signature is failed"); +- *fatal_diag = NULL; +- return false; +- } +- +- if (LDBGP(DBG_CRYPT, logger)) { +- LLOG_JAMBUF(DEBUG_STREAM, logger, buf) { +- jam_string(buf, "NSS RSA verify: decrypted sig: "); +- jam_nss_secitem(buf, &decrypted_signature); +- } +- } +- +- /* +- * Expect the matching hash to appear at the end. See above +- * for length check. It may, or may not, be prefixed by a +- * PKCS#1 1.5 RSA ASN.1 blob. +- */ +- passert(decrypted_signature.len >= expected_hash->len); +- uint8_t *start = (decrypted_signature.data +- + decrypted_signature.len +- - expected_hash->len); +- if (!memeq(start, expected_hash->ptr, expected_hash->len)) { +- ldbg(logger, "RSA Signature NOT verified"); +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); ++ /* NSS doesn't do const */ ++ SECItem signature_item = ++ same_shunk_as_secitem(signature, siBuffer); ++ ++ if (VFY_VerifyDigestDirect(&hash_item, ++ seckey_public, ++ &signature_item, ++ /*pubkey algorithm*/SEC_OID_PKCS1_RSA_ENCRYPTION, ++ /*hash algorithm*/hash_alg->nss.oid_tag, ++ lsw_nss_get_password_context(logger)) != SECSuccess) { ++ ldbg_nss_error(logger, "NSS VFY_VerifyDigest() failed"); + *fatal_diag = NULL; + return false; + } +- +- SECITEM_FreeItem(&decrypted_signature, PR_FALSE/*not-pointer*/); + *fatal_diag = NULL; + return true; + } +-- +2.45.4 + diff --git a/specs/l/libreswan/libreswan.spec b/specs/l/libreswan/libreswan.spec index a282766b63e..5de4144497e 100644 --- a/specs/l/libreswan/libreswan.spec +++ b/specs/l/libreswan/libreswan.spec @@ -2,7 +2,7 @@ ## (rpmautospec version 0.8.3) ## RPMAUTOSPEC: autorelease, autochangelog %define autorelease(e:s:pb:n) %{?-p:0.}%{lua: - release_number = 4; + release_number = 5; base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); print(release_number + base_release_number - 1); }%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} @@ -107,6 +107,7 @@ Requires: filesystem(unmerged-sbin-symlinks) Provides: /usr/sbin/ipsec %endif +Patch2: CVE-2026-50722.patch %description Libreswan is a free implementation of IPsec & IKE for Linux. IPsec is the Internet Protocol Security and uses strong cryptography to provide @@ -258,8 +259,11 @@ certutil -N -d sql:$tmpdir --empty-password %changelog ## START: Generated by rpmautospec -* Thu Apr 30 2026 Daniel McIlvaney - 5.3-4 -- feat: introduce deterministic commit resolution via Azure Linux lock file +* Sat Jul 04 2026 azldev - 5.3-5 +- Local changes (uncommitted) + +* Thu Jul 02 2026 Tobias Brick - 5.3-4 +- chore(swift-lang): remove component from distro * Thu Jul 24 2025 Fedora Release Engineering - 5.3-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild