Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package s390-tools for openSUSE:Factory checked in at 2024-04-04 22:26:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/s390-tools (Old) and /work/SRC/openSUSE:Factory/.s390-tools.new.1905 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "s390-tools" Thu Apr 4 22:26:15 2024 rev:74 rq:1164464 version:2.31.0 Changes: -------- --- /work/SRC/openSUSE:Factory/s390-tools/s390-tools.changes 2024-04-02 16:46:33.917938613 +0200 +++ /work/SRC/openSUSE:Factory/.s390-tools.new.1905/s390-tools.changes 2024-04-04 22:27:26.381919918 +0200 @@ -1,0 +2,9 @@ +Thu Apr 4 03:51:55 UTC 2024 - Nikolay Gueorguiev <[email protected]> + +- SE-tooling: New IBM host-key subject locality (s390-tools) (bsc#1222282) + * s390-tools-sles15sp5-01-rust-pv-support-Armonk-in-IBM-signing-key-subject.patch + * s390-tools-sles15sp6-02-genprotimg-support-Armonk-in-IBM-signing-key-subject.patch + * s390-tools-sles15sp6-03-libpv-support-Armonk-in-IBM-signing-key-subject.patch + * s390-tools-sles15sp6-04-pvattest-Fix-root-ca-parsing.patch + +------------------------------------------------------------------- New: ---- s390-tools-sles15sp5-01-rust-pv-support-Armonk-in-IBM-signing-key-subject.patch s390-tools-sles15sp6-02-genprotimg-support-Armonk-in-IBM-signing-key-subject.patch s390-tools-sles15sp6-03-libpv-support-Armonk-in-IBM-signing-key-subject.patch s390-tools-sles15sp6-04-pvattest-Fix-root-ca-parsing.patch BETA DEBUG BEGIN: New:- SE-tooling: New IBM host-key subject locality (s390-tools) (bsc#1222282) * s390-tools-sles15sp5-01-rust-pv-support-Armonk-in-IBM-signing-key-subject.patch * s390-tools-sles15sp6-02-genprotimg-support-Armonk-in-IBM-signing-key-subject.patch New: * s390-tools-sles15sp5-01-rust-pv-support-Armonk-in-IBM-signing-key-subject.patch * s390-tools-sles15sp6-02-genprotimg-support-Armonk-in-IBM-signing-key-subject.patch * s390-tools-sles15sp6-03-libpv-support-Armonk-in-IBM-signing-key-subject.patch New: * s390-tools-sles15sp6-02-genprotimg-support-Armonk-in-IBM-signing-key-subject.patch * s390-tools-sles15sp6-03-libpv-support-Armonk-in-IBM-signing-key-subject.patch * s390-tools-sles15sp6-04-pvattest-Fix-root-ca-parsing.patch New: * s390-tools-sles15sp6-03-libpv-support-Armonk-in-IBM-signing-key-subject.patch * s390-tools-sles15sp6-04-pvattest-Fix-root-ca-parsing.patch BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ s390-tools.spec ++++++ --- /var/tmp/diff_new_pack.OC2qBp/_old 2024-04-04 22:27:30.214061003 +0200 +++ /var/tmp/diff_new_pack.OC2qBp/_new 2024-04-04 22:27:30.214061003 +0200 @@ -155,6 +155,11 @@ Patch913: s390-tools-sles15sp6-kdump-initrd-59-zfcp-compat-rules.patch Patch914: s390-tools-sles15sp6-genprotimg-makefile.patch Patch915: s390-tools-sles15sp6-01-parse-ipl-device-for-activation.patch +### SE-tooling: New IBM host-key subject locality (s390-tools) +Patch916: s390-tools-sles15sp5-01-rust-pv-support-Armonk-in-IBM-signing-key-subject.patch +Patch917: s390-tools-sles15sp6-02-genprotimg-support-Armonk-in-IBM-signing-key-subject.patch +Patch918: s390-tools-sles15sp6-03-libpv-support-Armonk-in-IBM-signing-key-subject.patch +Patch919: s390-tools-sles15sp6-04-pvattest-Fix-root-ca-parsing.patch ### BuildRequires: curl-devel ++++++ s390-tools-sles15sp5-01-rust-pv-support-Armonk-in-IBM-signing-key-subject.patch ++++++ Index: s390-tools-service/rust/pv/src/verify.rs =================================================================== --- s390-tools-service.orig/rust/pv/src/verify.rs +++ s390-tools-service/rust/pv/src/verify.rs @@ -3,10 +3,11 @@ // Copyright IBM Corp. 2023 use core::slice; -use log::debug; +use log::{debug, trace}; +use openssl::error::ErrorStack; use openssl::stack::Stack; use openssl::x509::store::X509Store; -use openssl::x509::{CrlStatus, X509Ref, X509StoreContext, X509}; +use openssl::x509::{CrlStatus, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef, X509}; use openssl_extensions::crl::StackableX509Crl; use openssl_extensions::crl::X509StoreContextExtension; @@ -82,8 +83,8 @@ impl HkdVerifier for CertVerifier { if verified_crls.is_empty() { bail_hkd_verify!(NoCrl); } - for crl in &verified_crls { - match crl.get_by_cert(&hkd.to_owned()) { + for crl in verified_crls { + match crl.get_by_serial(hkd.serial_number()) { CrlStatus::NotRevoked => (), _ => bail_hkd_verify!(HdkRevoked), } @@ -94,21 +95,54 @@ impl HkdVerifier for CertVerifier { } impl CertVerifier { + fn quirk_crls( + ctx: &mut X509StoreContextRef, + subject: &X509NameRef, + ) -> Result<Stack<StackableX509Crl>, ErrorStack> { + match ctx.crls(subject) { + Ok(ret) if !ret.is_empty() => return Ok(ret), + _ => (), + } + + // Armonk/Poughkeepsie fixup + trace!("quirk_crls: Try Locality"); + if let Some(locality_subject) = helper::armonk_locality_fixup(subject) { + match ctx.crls(&locality_subject) { + Ok(ret) if !ret.is_empty() => return Ok(ret), + _ => (), + } + + // reorder + trace!("quirk_crls: Try Locality+Reorder"); + if let Ok(locality_ordered_subject) = helper::reorder_x509_names(&locality_subject) { + match ctx.crls(&locality_ordered_subject) { + Ok(ret) if !ret.is_empty() => return Ok(ret), + _ => (), + } + } + } + + // reorder unchanged loaciliy subject + trace!("quirk_crls: Try Reorder"); + if let Ok(ordered_subject) = helper::reorder_x509_names(subject) { + match ctx.crls(&ordered_subject) { + Ok(ret) if !ret.is_empty() => return Ok(ret), + _ => (), + } + } + // nothing found, return empty stack + Stack::new() + } + ///Download the CLRs that a HKD refers to. pub fn hkd_crls(&self, hkd: &X509Ref) -> Result<Stack<StackableX509Crl>> { let mut ctx = X509StoreContext::new()?; // Unfortunately we cannot use a dedicated function here and have to use a closure (E0434) // Otherwise, we cannot refer to self + // Search for local CRLs let mut crls = ctx.init_opt(&self.store, None, None, |ctx| { let subject = self.ibm_z_sign_key.subject_name(); - match ctx.crls(subject) { - Ok(crls) => Ok(crls), - _ => { - // reorder the name and try again - let broken_subj = helper::reorder_x509_names(subject)?; - ctx.crls(&broken_subj).or_else(helper::stack_err_hlp) - } - } + Self::quirk_crls(ctx, subject) })?; if !self.offline { Index: s390-tools-service/rust/pv/src/verify/helper.rs =================================================================== --- s390-tools-service.orig/rust/pv/src/verify/helper.rs +++ s390-tools-service/rust/pv/src/verify/helper.rs @@ -13,7 +13,7 @@ use openssl::{ error::ErrorStack, nid::Nid, ssl::SslFiletype, - stack::{Stack, Stackable}, + stack::Stack, x509::{ store::{File, X509Lookup, X509StoreBuilder, X509StoreBuilderRef, X509StoreRef}, verify::{X509VerifyFlags, X509VerifyParam}, @@ -25,6 +25,7 @@ use openssl_extensions::{ akid::{AkidCheckResult, AkidExtension}, crl::X509StoreExtension, }; +use std::str::from_utf8; use std::{cmp::Ordering, ffi::c_int, time::Duration, usize}; /// Minimum security level for the keys/certificates used to establish a chain of @@ -39,7 +40,6 @@ const SECURITY_CHAIN_MAX_LEN: c_int = 2; /// verifies that the HKD /// * has enough security bits /// * is inside its validity period -/// * issuer name is the subject name of the [`sign_key`] /// * the Authority Key ID matches the Signing Key ID of the [`sign_key`] pub fn verify_hkd_options(hkd: &X509Ref, sign_key: &X509Ref) -> Result<()> { let hk_pkey = hkd.public_key()?; @@ -53,9 +53,6 @@ pub fn verify_hkd_options(hkd: &X509Ref, // verify that the hkd is still valid check_validity_period(hkd.not_before(), hkd.not_after())?; - // check if hkd.issuer_name == issuer.subject - check_x509_name_equal(sign_key.subject_name(), hkd.issuer_name())?; - // verify that the AKID of the hkd matches the SKID of the issuer if let Some(akid) = hkd.akid() { if akid.check(sign_key) != AkidCheckResult::OK { @@ -75,9 +72,6 @@ pub fn verify_crl(crl: &X509CrlRef, issu return None; } } - - check_x509_name_equal(crl.issuer_name(), issuer.subject_name()).ok()?; - match crl.verify(issuer.public_key().ok()?.as_ref()).ok()? { true => Some(()), false => None, @@ -207,7 +201,8 @@ pub fn download_crls_into_store(store: & //Asn1StringRef::as_slice aka ASN1_STRING_get0_data gives a string without \0 delimiter const IBM_Z_COMMON_NAME: &[u8; 43usize] = b"International Business Machines Corporation"; const IBM_Z_COUNTRY_NAME: &[u8; 2usize] = b"US"; -const IBM_Z_LOCALITY_NAME: &[u8; 12usize] = b"Poughkeepsie"; +const IBM_Z_LOCALITY_NAME_POUGHKEEPSIE: &[u8; 12usize] = b"Poughkeepsie"; +const IBM_Z_LOCALITY_NAME_ARMONK: &[u8; 6usize] = b"Armonk"; const IBM_Z_ORGANIZATIONAL_UNIT_NAME_SUFFIX: &str = "Key Signing Service"; const IBM_Z_ORGANIZATION_NAME: &[u8; 43usize] = b"International Business Machines Corporation"; const IBM_Z_STATE: &[u8; 8usize] = b"New York"; @@ -226,7 +221,8 @@ fn is_ibm_signing_cert(cert: &X509) -> b if subj.entries().count() != IMB_Z_ENTRY_COUNT || !name_data_eq(subj, Nid::COUNTRYNAME, IBM_Z_COUNTRY_NAME) || !name_data_eq(subj, Nid::STATEORPROVINCENAME, IBM_Z_STATE) - || !name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME) + || !(name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_POUGHKEEPSIE) + || name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_ARMONK)) || !name_data_eq(subj, Nid::ORGANIZATIONNAME, IBM_Z_ORGANIZATION_NAME) || !name_data_eq(subj, Nid::COMMONNAME, IBM_Z_COMMON_NAME) { @@ -367,24 +363,6 @@ fn check_validity_period(not_before: &As } } -fn check_x509_name_equal(lhs: &X509NameRef, rhs: &X509NameRef) -> Result<()> { - if lhs.entries().count() != rhs.entries().count() { - bail_hkd_verify!(IssuerMismatch); - } - - for l in lhs.entries() { - // search for the matching value in the rhs names - // found none? -> names are not equal - if !rhs - .entries() - .any(|r| l.data().as_slice() == r.data().as_slice()) - { - bail_hkd_verify!(IssuerMismatch); - } - } - Ok(()) -} - const NIDS_CORRECT_ORDER: [Nid; 6] = [ Nid::COUNTRYNAME, Nid::ORGANIZATIONNAME, @@ -407,13 +385,28 @@ pub fn reorder_x509_names(subject: &X509 Ok(correct_subj.build()) } -pub fn stack_err_hlp<T: Stackable>( - e: ErrorStack, -) -> std::result::Result<Stack<T>, openssl::error::ErrorStack> { - match e.errors().len() { - 0 => Stack::<T>::new(), - _ => Err(e), +/** +* Workaround for potential locality mismatches between CRLs and Certs +* # Return +* fixed subject or none if locality was not Armonk or any OpenSSL error +*/ +pub fn armonk_locality_fixup(subject: &X509NameRef) -> Option<X509Name> { + if !name_data_eq(subject, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_ARMONK) { + return None; + } + + let mut ret = X509Name::builder().ok()?; + for entry in subject.entries() { + match entry.object().nid() { + nid @ Nid::LOCALITYNAME => ret + .append_entry_by_nid(nid, from_utf8(IBM_Z_LOCALITY_NAME_POUGHKEEPSIE).ok()?) + .ok()?, + _ => { + ret.append_entry(entry).ok()?; + } + } } + Some(ret.build()) } #[cfg(test)] @@ -451,20 +444,6 @@ mod test { )); } - #[test] - fn x509_name_equal() { - let sign_crt = load_gen_cert("ibm.crt"); - let hkd = load_gen_cert("host.crt"); - let other = load_gen_cert("inter_ca.crt"); - - assert!(super::check_x509_name_equal(sign_crt.subject_name(), hkd.issuer_name()).is_ok(),); - - assert!(matches!( - super::check_x509_name_equal(other.subject_name(), hkd.subject_name()), - Err(Error::HkdVerify(IssuerMismatch)) - )); - } - #[test] fn is_ibm_z_sign_key() { let ibm_crt = load_gen_cert("ibm.crt"); Index: s390-tools-service/rust/pv/src/verify/test.rs =================================================================== --- s390-tools-service.orig/rust/pv/src/verify/test.rs +++ s390-tools-service/rust/pv/src/verify/test.rs @@ -84,7 +84,6 @@ fn verify_online() { let inter_crt = get_cert_asset_path_string("inter_ca.crt"); let ibm_crt = get_cert_asset_path_string("ibm.crt"); let hkd_revoked = load_gen_cert("host_rev.crt"); - let hkd_inv = load_gen_cert("host_invalid_signing_key.crt"); let hkd_exp = load_gen_cert("host_crt_expired.crt"); let hkd = load_gen_cert("host.crt"); @@ -112,11 +111,6 @@ fn verify_online() { )); assert!(matches!( - verifier.verify(&hkd_inv), - Err(Error::HkdVerify(IssuerMismatch)) - )); - - assert!(matches!( verifier.verify(&hkd_exp), Err(Error::HkdVerify(AfterValidity)) )); @@ -130,7 +124,6 @@ fn verify_offline() { let ibm_crt = get_cert_asset_path_string("ibm.crt"); let ibm_crl = get_cert_asset_path_string("ibm.crl"); let hkd_revoked = load_gen_cert("host_rev.crt"); - let hkd_inv = load_gen_cert("host_invalid_signing_key.crt"); let hkd_exp = load_gen_cert("host_crt_expired.crt"); let hkd = load_gen_cert("host.crt"); @@ -149,11 +142,6 @@ fn verify_offline() { )); assert!(matches!( - verifier.verify(&hkd_inv), - Err(Error::HkdVerify(IssuerMismatch)) - )); - - assert!(matches!( verifier.verify(&hkd_exp), Err(Error::HkdVerify(AfterValidity)) )); ++++++ s390-tools-sles15sp6-02-genprotimg-support-Armonk-in-IBM-signing-key-subject.patch ++++++ Index: s390-tools-service/genprotimg/src/include/pv_crypto_def.h =================================================================== --- s390-tools-service.orig/genprotimg/src/include/pv_crypto_def.h +++ s390-tools-service/genprotimg/src/include/pv_crypto_def.h @@ -17,7 +17,8 @@ /* IBM signing key subject */ #define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation" #define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US" -#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie" +#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie" +#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk" #define PV_IBM_Z_SUBJECT_ORGANIZATIONONAL_UNIT_NAME_SUFFIX "Key Signing Service" #define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation" #define PV_IBM_Z_SUBJECT_STATE "New York" Index: s390-tools-service/genprotimg/src/utils/crypto.c =================================================================== --- s390-tools-service.orig/genprotimg/src/utils/crypto.c +++ s390-tools-service/genprotimg/src/utils/crypto.c @@ -664,62 +664,9 @@ static gboolean x509_name_data_by_nid_eq return memcmp(data, y, data_len) == 0; } -static gboolean own_X509_NAME_ENTRY_equal(const X509_NAME_ENTRY *x, - const X509_NAME_ENTRY *y) -{ - const ASN1_OBJECT *x_obj = X509_NAME_ENTRY_get_object(x); - const ASN1_STRING *x_data = X509_NAME_ENTRY_get_data(x); - const ASN1_OBJECT *y_obj = X509_NAME_ENTRY_get_object(y); - const ASN1_STRING *y_data = X509_NAME_ENTRY_get_data(y); - gint x_len = ASN1_STRING_length(x_data); - gint y_len = ASN1_STRING_length(y_data); - - if (x_len < 0 || x_len != y_len) - return FALSE; - - /* ASN1_STRING_cmp(x_data, y_data) == 0 doesn't work because it also - * compares the type, which is sometimes different. - */ - return OBJ_cmp(x_obj, y_obj) == 0 && - memcmp(ASN1_STRING_get0_data(x_data), - ASN1_STRING_get0_data(y_data), - (unsigned long)x_len) == 0; -} - -static gboolean own_X509_NAME_equal(const X509_NAME *x, const X509_NAME *y) -{ - gint x_count = X509_NAME_entry_count(x); - gint y_count = X509_NAME_entry_count(y); - - if (x != y && (!x || !y)) - return FALSE; - - if (x_count != y_count) - return FALSE; - - for (gint i = 0; i < x_count; i++) { - const X509_NAME_ENTRY *entry_i = X509_NAME_get_entry(x, i); - gboolean entry_found = FALSE; - - for (gint j = 0; j < y_count; j++) { - const X509_NAME_ENTRY *entry_j = - X509_NAME_get_entry(y, j); - - if (own_X509_NAME_ENTRY_equal(entry_i, entry_j)) { - entry_found = TRUE; - break; - } - } - - if (!entry_found) - return FALSE; - } - return TRUE; -} - /* Checks whether the subject of @cert is a IBM signing key subject. For this we * must check that the subject is equal to: 'C = US, ST = New York, L = - * Poughkeepsie, O = International Business Machines Corporation, CN = + * Poughkeepsie or Armonk, O = International Business Machines Corporation, CN = * International Business Machines Corporation' and the organization unit (OUT) * must end with the suffix ' Key Signing Service'. */ @@ -743,8 +690,10 @@ static gboolean has_ibm_signing_subject( PV_IBM_Z_SUBJECT_STATE)) return FALSE; - if (!x509_name_data_by_nid_equal(subject, NID_localityName, - PV_IBM_Z_SUBJECT_LOCALITY_NAME)) + if (!(x509_name_data_by_nid_equal(subject, NID_localityName, + PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) || + x509_name_data_by_nid_equal(subject, NID_localityName, + PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))) return FALSE; if (!x509_name_data_by_nid_equal(subject, NID_organizationName, @@ -806,6 +755,39 @@ static X509_NAME *x509_name_reorder_attr return g_steal_pointer(&ret); } +/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return + * `NULL`. + */ +static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name) +{ + g_autoptr(X509_NAME) ret = NULL; + int pos; + + /* Check if ``L=Armonk`` */ + if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName, + PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)) + return NULL; + + ret = X509_NAME_dup(name); + if (!ret) + g_abort(); + + pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1); + if (pos == -1) + return NULL; + + X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos)); + + /* Create a new name entry at the same position as before */ + if (X509_NAME_add_entry_by_NID( + ret, NID_localityName, MBSTRING_UTF8, + (const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE, + sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1) + return NULL; + + return g_steal_pointer(&ret); +} + /* In RFC 5280 the attributes of a (subject/issuer) name is not mandatory * ordered. The problem is that our certificates are not consistent in the order * (see https://tools.ietf.org/html/rfc5280#section-4.1.2.4 for details). @@ -828,24 +810,10 @@ X509_NAME *c2b_name(const X509_NAME *nam return X509_NAME_dup((X509_NAME *)name); } -/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */ +/* Verify that SKID(issuer) == AKID(crl) if available */ static gint check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **err) { - const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl); - const X509_NAME *issuer_subject = X509_get_subject_name(issuer); - AUTHORITY_KEYID *akid = NULL; - - if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) { - g_autofree char *issuer_subject_str = X509_NAME_oneline(issuer_subject, - NULL, 0); - g_autofree char *crl_issuer_str = X509_NAME_oneline(crl_issuer, NULL, 0); - - g_set_error(err, PV_CRYPTO_ERROR, - PV_CRYPTO_ERROR_CRL_SUBJECT_ISSUER_MISMATCH, - _("issuer mismatch:\n%s\n%s"), - issuer_subject_str, crl_issuer_str); - return -1; - } + g_autoptr(AUTHORITY_KEYID) akid = NULL; /* If AKID(@crl) is specified it must match with SKID(@issuer) */ akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL); @@ -881,7 +849,6 @@ gint check_crl_valid_for_cert(X509_CRL * return -1; } - /* check that the @crl issuer matches with the subject name of @cert*/ if (check_crl_issuer(crl, cert, err) < 0) return -1; @@ -910,6 +877,60 @@ gint check_crl_valid_for_cert(X509_CRL * return 0; } +/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL) + * issues. + */ +static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx, + const X509_NAME *subject, GError **err) +{ + g_autoptr(X509_NAME) fixed_subject = NULL; + g_autoptr(STACK_OF_X509_CRL) ret = NULL; + + ret = Pv_X509_STORE_CTX_get1_crls(ctx, subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + + /* Workaround to fix the mismatch between issuer name of the * IBM + * signing CRLs and the IBM signing key subject name. Locality name has + * changed from Poughkeepsie to Armonk. + */ + fixed_subject = x509_armonk_locality_fixup(subject); + /* Was the locality replaced? */ + if (fixed_subject) { + X509_NAME *tmp; + + sk_X509_CRL_free(ret); + ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + + /* Workaround to fix the ordering mismatch between issuer name + * of the IBM signing CRLs and the IBM signing key subject name. + */ + tmp = fixed_subject; + fixed_subject = c2b_name(fixed_subject); + X509_NAME_free(tmp); + sk_X509_CRL_free(ret); + ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + X509_NAME_free(fixed_subject); + fixed_subject = NULL; + } + + /* Workaround to fix the ordering mismatch between issuer name of the + * IBM signing CRLs and the IBM signing key subject name. + */ + fixed_subject = c2b_name(subject); + sk_X509_CRL_free(ret); + ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + + g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL, _("no CRL found")); + return NULL; +} + /* Given a certificate @cert try to find valid revocation lists in @ctx. If no * valid CRL was found NULL is returned. */ @@ -927,20 +948,9 @@ STACK_OF_X509_CRL *store_ctx_find_valid_ return NULL; } - ret = X509_STORE_CTX_get1_crls(ctx, subject); - if (!ret) { - /* Workaround to fix the mismatch between issuer name of the - * IBM Z signing CRLs and the IBM Z signing key subject name. - */ - g_autoptr(X509_NAME) broken_subject = c2b_name(subject); - - ret = X509_STORE_CTX_get1_crls(ctx, broken_subject); - if (!ret) { - g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL, - _("no CRL found")); - return NULL; - } - } + ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, err); + if (!ret) + return NULL; /* Filter out non-valid CRLs for @cert */ for (gint i = 0; i < sk_X509_CRL_num(ret); i++) { @@ -1328,32 +1338,14 @@ gint check_chain_parameters(const STACK_ /* It's almost the same as X509_check_issed from OpenSSL does except that we * don't check the key usage of the potential issuer. This means we check: - * 1. issuer_name(cert) == subject_name(issuer) - * 2. Check whether the akid(cert) (if available) matches the issuer skid - * 3. Check that the cert algrithm matches the subject algorithm - * 4. Verify the signature of certificate @cert is using the public key of + * 1. Check whether the akid(cert) (if available) matches the issuer skid + * 2. Check that the cert algrithm matches the subject algorithm + * 3. Verify the signature of certificate @cert is using the public key of * @issuer. */ static gint check_host_key_issued(X509 *cert, X509 *issuer, GError **err) { - const X509_NAME *issuer_subject = X509_get_subject_name(issuer); - const X509_NAME *cert_issuer = X509_get_issuer_name(cert); - AUTHORITY_KEYID *akid = NULL; - - /* We cannot use X509_NAME_cmp() because it considers the order of the - * X509_NAME_Entries. - */ - if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) { - g_autofree char *issuer_subject_str = - X509_NAME_oneline(issuer_subject, NULL, 0); - g_autofree char *cert_issuer_str = - X509_NAME_oneline(cert_issuer, NULL, 0); - g_set_error(err, PV_CRYPTO_ERROR, - PV_CRYPTO_ERROR_CERT_SUBJECT_ISSUER_MISMATCH, - _("Subject issuer mismatch:\n'%s'\n'%s'"), - issuer_subject_str, cert_issuer_str); - return -1; - } + g_autoptr(AUTHORITY_KEYID) akid = NULL; akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL); if (akid && X509_check_akid(issuer, akid) != X509_V_OK) { Index: s390-tools-service/genprotimg/src/utils/crypto.h =================================================================== --- s390-tools-service.orig/genprotimg/src/utils/crypto.h +++ s390-tools-service/genprotimg/src/utils/crypto.h @@ -75,6 +75,7 @@ void x509_pair_free(x509_pair *pair); /* Register auto cleanup functions */ WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_INTEGER, ASN1_INTEGER_free) WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_OCTET_STRING, ASN1_OCTET_STRING_free) +WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(AUTHORITY_KEYID, AUTHORITY_KEYID_free) WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free) WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all) WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free) ++++++ s390-tools-sles15sp6-03-libpv-support-Armonk-in-IBM-signing-key-subject.patch ++++++ Index: s390-tools-service/include/libpv/cert.h =================================================================== --- s390-tools-service.orig/include/libpv/cert.h +++ s390-tools-service/include/libpv/cert.h @@ -16,7 +16,8 @@ #define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation" #define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US" -#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie" +#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie" +#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk" #define PV_IBM_Z_SUBJECT_ORGANIZATIONAL_UNIT_NAME_SUFFIX "Key Signing Service" #define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation" #define PV_IBM_Z_SUBJECT_STATE "New York" Index: s390-tools-service/libpv/cert.c =================================================================== --- s390-tools-service.orig/libpv/cert.c +++ s390-tools-service/libpv/cert.c @@ -857,7 +857,7 @@ static gboolean x509_name_data_by_nid_eq /* Checks whether the subject of @cert is a IBM signing key subject. For this we * must check that the subject is equal to: 'C = US, ST = New York, L = - * Poughkeepsie, O = International Business Machines Corporation, CN = + * Poughkeepsie or Armonk, O = International Business Machines Corporation, CN = * International Business Machines Corporation' and the organization unit (OUT) * must end with the suffix ' Key Signing Service'. */ @@ -879,7 +879,10 @@ static gboolean has_ibm_signing_subject( if (!x509_name_data_by_nid_equal(subject, NID_stateOrProvinceName, PV_IBM_Z_SUBJECT_STATE)) return FALSE; - if (!x509_name_data_by_nid_equal(subject, NID_localityName, PV_IBM_Z_SUBJECT_LOCALITY_NAME)) + if (!(x509_name_data_by_nid_equal(subject, NID_localityName, + PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) || + x509_name_data_by_nid_equal(subject, NID_localityName, + PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))) return FALSE; if (!x509_name_data_by_nid_equal(subject, NID_organizationName, @@ -1085,10 +1088,9 @@ static int check_signature_algo_match(co /* It's almost the same as X509_check_issed from OpenSSL does except that we * don't check the key usage of the potential issuer. This means we check: - * 1. issuer_name(cert) == subject_name(issuer) - * 2. Check whether the akid(cert) (if available) matches the issuer skid - * 3. Check that the cert algrithm matches the subject algorithm - * 4. Verify the signature of certificate @cert is using the public key of + * 1. Check whether the akid(cert) (if available) matches the issuer skid + * 2. Check that the cert algrithm matches the subject algorithm + * 3. Verify the signature of certificate @cert is using the public key of * @issuer. */ static int check_host_key_issued(X509 *cert, X509 *issuer, GError **error) @@ -1097,19 +1099,6 @@ static int check_host_key_issued(X509 *c const X509_NAME *cert_issuer = X509_get_issuer_name(cert); g_autoptr(AUTHORITY_KEYID) akid = NULL; - /* We cannot use X509_NAME_cmp() because it considers the order of the - * X509_NAME_Entries. - */ - if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) { - g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject); - g_autofree char *cert_issuer_str = pv_X509_NAME_oneline(cert_issuer); - - g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CERT_SUBJECT_ISSUER_MISMATCH, - _("Subject issuer mismatch:\n'%s'\n'%s'"), issuer_subject_str, - cert_issuer_str); - return -1; - } - akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL); if (akid && X509_check_akid(issuer, akid) != X509_V_OK) { g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_SKID_AKID_MISMATCH, @@ -1286,21 +1275,10 @@ int pv_verify_cert(X509_STORE_CTX *ctx, return 0; } -/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */ +/* Verify that SKID(issuer) == AKID(crl) */ static int check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **error) { - const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl); - const X509_NAME *issuer_subject = X509_get_subject_name(issuer); - AUTHORITY_KEYID *akid = NULL; - - if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) { - g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject); - g_autofree char *crl_issuer_str = pv_X509_NAME_oneline(crl_issuer); - - g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CRL_SUBJECT_ISSUER_MISMATCH, - _("issuer mismatch:\n%s\n%s"), issuer_subject_str, crl_issuer_str); - return -1; - } + g_autoptr(AUTHORITY_KEYID) akid = NULL; /* If AKID(@crl) is specified it must match with SKID(@issuer) */ akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL); @@ -1325,7 +1303,6 @@ int pv_verify_crl(X509_CRL *crl, X509 *c return -1; } - /* check that the @crl issuer matches with the subject name of @cert*/ if (check_crl_issuer(crl, cert, error) < 0) return -1; @@ -1393,6 +1370,93 @@ int pv_check_chain_parameters(const STAC return 0; } +/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return + * `NULL`. + */ +static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name) +{ + g_autoptr(X509_NAME) ret = NULL; + int pos; + + /* Check if ``L=Armonk`` */ + if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName, + PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)) + return NULL; + + ret = X509_NAME_dup(name); + if (!ret) + g_abort(); + + pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1); + if (pos == -1) + return NULL; + + X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos)); + + /* Create a new name entry at the same position as before */ + if (X509_NAME_add_entry_by_NID( + ret, NID_localityName, MBSTRING_UTF8, + (const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE, + sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1) + return NULL; + + return g_steal_pointer(&ret); +} + +/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL) + * issues. + */ +static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx, + const X509_NAME *subject, GError **err) +{ + g_autoptr(X509_NAME) fixed_subject = NULL; + g_autoptr(STACK_OF_X509_CRL) ret = NULL; + + ret = pv_X509_STORE_CTX_get1_crls(ctx, subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + + /* Workaround to fix the mismatch between issuer name of the * IBM + * signing CRLs and the IBM signing key subject name. Locality name has + * changed from Poughkeepsie to Armonk. + */ + fixed_subject = x509_armonk_locality_fixup(subject); + /* Was the locality replaced? */ + if (fixed_subject) { + X509_NAME *tmp; + + sk_X509_CRL_free(ret); + ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + + /* Workaround to fix the ordering mismatch between issuer name + * of the IBM signing CRLs and the IBM signing key subject name. + */ + tmp = fixed_subject; + fixed_subject = pv_c2b_name(fixed_subject); + X509_NAME_free(tmp); + sk_X509_CRL_free(ret); + ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + X509_NAME_free(fixed_subject); + fixed_subject = NULL; + } + + /* Workaround to fix the ordering mismatch between issuer name of the + * IBM signing CRLs and the IBM signing key subject name. + */ + fixed_subject = pv_c2b_name(subject); + sk_X509_CRL_free(ret); + ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject); + if (ret && sk_X509_CRL_num(ret) > 0) + return g_steal_pointer(&ret); + + g_set_error(err, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found")); + return NULL; +} + /* Given a certificate @cert try to find valid revocation lists in @ctx. If no * valid CRL was found NULL is returned. */ @@ -1412,21 +1476,9 @@ STACK_OF_X509_CRL *pv_store_ctx_find_val return NULL; } - ret = pv_X509_STORE_CTX_get1_crls(ctx, subject); - if (!ret) { - /* Workaround to fix the mismatch between issuer name of the - * IBM Z signing CRLs and the IBM Z signing key subject name. - */ - g_autoptr(X509_NAME) broken_subject = pv_c2b_name(subject); - - ret = pv_X509_STORE_CTX_get1_crls(ctx, broken_subject); - if (!ret) { - g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found")); - g_info("ERROR: %s", (*error)->message); - return NULL; - } - } - + ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, error); + if (!ret) + return NULL; /* Filter out non-valid CRLs for @cert */ for (int i = 0; i < sk_X509_CRL_num(ret); i++) { X509_CRL *crl = sk_X509_CRL_value(ret, i); ++++++ s390-tools-sles15sp6-04-pvattest-Fix-root-ca-parsing.patch ++++++ Index: s390-tools-service/pvattest/src/argparse.c =================================================================== --- s390-tools-service.orig/pvattest/src/argparse.c +++ s390-tools-service/pvattest/src/argparse.c @@ -190,13 +190,13 @@ static gboolean hex_str_toull(const char } /* NOTE REQUIRED */ -#define _entry_root_ca(__arg_data, __indent) \ - { \ - .long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \ - .arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \ - .description = "Use FILE as the trusted root CA instead the\n" __indent \ - "root CAs that are installed on the system (optional).\n", \ - .arg_description = "FILE", \ +#define _entry_root_ca(__arg_data, __indent) \ + { \ + .long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \ + .arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \ + .description = "Use FILE as the trusted root CA instead the\n" __indent \ + "root CAs that are installed on the system (optional).\n", \ + .arg_description = "FILE", \ } /* NOTE REQUIRED */
