From 546fe254163f56ac5cc022506a1a8c280c2b29ff Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Thu, 9 Nov 2023 09:23:04 +0800 Subject: [PATCH] apple-codesign: force subsequent binary identifiers to match earlier identifier This matches the behavior of Apple's tooling and prevents a validation error when the Mach-O is inside a bundle, as the requirements expression listed in the CodeResources file must match all binaries and that expression often contains the binary identifier. Closes #103, which tracks this issue. Closes #95, as the rcodesign signed bundle test case provided in that issue now validates with Apple's tooling. --- apple-codesign/CHANGELOG.md | 4 ++++ apple-codesign/src/signing_settings.rs | 14 +++++++++++++- .../cmd/sign-macho-reconcile-identifier.trycmd | 12 ++++++------ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/apple-codesign/CHANGELOG.md b/apple-codesign/CHANGELOG.md index c27df0a60..3d01699a8 100644 --- a/apple-codesign/CHANGELOG.md +++ b/apple-codesign/CHANGELOG.md @@ -37,6 +37,10 @@ Released on ReleaseDate. * `print-signature-info` now prints some integer values as strings containing both the integer and hex forms. Additional fields are added to help debug signature writing. +* Conflicting binary identifiers within a universal Mach-O are now reconciled + to the initially seen value. This matches the behavior of Apple's tooling + and fixes a bug where drift between the values could cause bundle validation + to fail. (#103) * cryptographic-message-syntax 0.25 -> 0.26. * x509-certificate 0.22 -> 0.23. diff --git a/apple-codesign/src/signing_settings.rs b/apple-codesign/src/signing_settings.rs index 0ead54dc4..50f9da4e4 100644 --- a/apple-codesign/src/signing_settings.rs +++ b/apple-codesign/src/signing_settings.rs @@ -772,6 +772,8 @@ impl<'key> SigningSettings<'key> { pub fn import_settings_from_macho(&mut self, data: &[u8]) -> Result<(), AppleCodesignError> { info!("inferring default signing settings from Mach-O binary"); + let mut seen_identifier = None; + for macho in MachFile::parse(data)?.into_iter() { let index = macho.index.unwrap_or(0); @@ -835,9 +837,19 @@ impl<'key> SigningSettings<'key> { || self.binary_identifier(&scope_arch).is_some() { info!("using binary identifier from settings"); + } else if let Some(initial_identifier) = &seen_identifier { + // The binary identifier should agree between all Mach-O within a + // universal binary. If we've already seen an identifier, use it + // implicitly. + if initial_identifier != cd.ident.as_ref() { + info!("identifiers within Mach-O do not agree (initial: {initial_identifier}, subsequent: {}); reconciling to {initial_identifier}", + cd.ident); + self.set_binary_identifier(scope_index.clone(), initial_identifier); + } } else { info!("preserving existing binary identifier in Mach-O"); - self.set_binary_identifier(scope_index.clone(), cd.ident); + self.set_binary_identifier(scope_index.clone(), cd.ident.to_string()); + seen_identifier = Some(cd.ident.to_string()); } if self.team_id.contains_key(&scope_main) diff --git a/apple-codesign/tests/cmd/sign-macho-reconcile-identifier.trycmd b/apple-codesign/tests/cmd/sign-macho-reconcile-identifier.trycmd index c9cb60d97..b9a154f99 100644 --- a/apple-codesign/tests/cmd/sign-macho-reconcile-identifier.trycmd +++ b/apple-codesign/tests/cmd/sign-macho-reconcile-identifier.trycmd @@ -33,7 +33,7 @@ signing exe as a Mach-O binary inferring default signing settings from Mach-O binary preserving existing binary identifier in Mach-O preserving code signature flags in existing Mach-O signature -preserving existing binary identifier in Mach-O +identifiers within Mach-O do not agree (initial: identifier-0, subsequent: identifier-1); reconciling to identifier-0 preserving code signature flags in existing Mach-O signature setting binary identifier to exe parsing Mach-O @@ -54,7 +54,7 @@ writing Mach-O to exe.signed $ rcodesign print-signature-info exe.signed - path: exe.signed file_size: 55312 - file_sha256: 1da13389e9c1b3c17eecffda607691e769b1b5a113fa600e19c380ccc35b5ca5 + file_sha256: ef5ec5345b8b70820cf5f207dcf57a6e59e26067098416a93feba927aaf71402 sub_path: macho-index:0 entity: mach_o: @@ -100,7 +100,7 @@ $ rcodesign print-signature-info exe.signed cms: null - path: exe.signed file_size: 55312 - file_sha256: 1da13389e9c1b3c17eecffda607691e769b1b5a113fa600e19c380ccc35b5ca5 + file_sha256: ef5ec5345b8b70820cf5f207dcf57a6e59e26067098416a93feba927aaf71402 sub_path: macho-index:1 entity: mach_o: @@ -119,8 +119,8 @@ $ rcodesign print-signature-info exe.signed - slot: CodeDirectory (0) magic: fade0c02 length: 325 - sha1: 030e89c3c24bd752e0b8036643067caa5a583176 - sha256: ddbc656f74f4073112ce4867671963c51fbef7b6f3a9b71e6e0e97453a9efb36 + sha1: c51f0d3272967beff74e25d1f0caedc9b6ed8229 + sha256: 5f7b84f4ce42b6237680fb5a15b7f6a58afe21a5ff73b6e1f1c826835d220d53 - slot: RequirementSet (2) magic: fade0c01 length: 12 @@ -134,7 +134,7 @@ $ rcodesign print-signature-info exe.signed code_directory: version: '0x20400' flags: CodeSignatureFlags(ADHOC) - identifier: identifier-1 + identifier: identifier-0 digest_type: sha256 platform: 0 signed_entity_size: 16400