Crate tugger_apple_codesign[−][src]
Binary code signing for Apple platforms.
This crate provides a pure Rust implementation of binary code signing
for Apple operating systems (like macOS and iOS). A goal of this crate
is to facilitate reimplementing functionality from Apple’s codesign
and other similar tools without a dependency on an Apple machine or
operating system: you should be able to sign Apple binaries from Linux
or Windows if you wanted to.
This crate is in its early stages of development and there are many
rough edges. Use at your own risk. Always validate signed binaries
with Apple’s codesign
tool to ensure correctness.
Features and Capabilities
This crate can:
- Find code signature data embedded in Mach-O binaries (both single and multi-arch/fat/universal binaries). (See find_signature_data, parse_signature_data.)
- Deeply parse code signature data into Rust structs. (See EmbeddedSignature, BlobData, and e.g. CodeDirectoryBlob.
- Parse and verify the RFC 5652 Cryptographic Message Syntax (CMS)
signature data. This includes using a Time-Stamp Protocol (TSP) / RFC 3161
server for including a signed time-stamp token for that signature.
(Functionality provided by the
cryptographic-message-syntax
crate, developed in the same repository as this crate.) - Generate new embedded signature data, including cryptographically signing that data using any signing key and X.509 certificate chain you provide. (See MachOSigner and [MachOSignatureBuilder].)
- Writing a new Mach-O file containing new signature data. (See MachOSigner.)
- Parse
CodeResources
XML plist files defining information on nested/signed resources within bundles. This includes parsing and applying the filtering rules defining in these files. - Sign bundles. Nested bundles will automatically be signed. Additional
Mach-O binaries outside the main executable will also be signed. Non
Mach-O/code files will be digested. A
CodeResources
XML file will be produced.
There are a number of missing features and capabilities from this crate that we hope are eventually implemented:
- Only embedded signatures are supported. (No support for detached signatures.)
- No parsing of the Code Signing Requirements DSL. We support parsing the binary
requirements to Rust structs, serializing back to binary, and rendering to the
human friendly DSL. You will need to use the
csreq
tool to compile an expression to binary and then give that binary blob to this crate. Alternatively, you can write Rust code to construct a code requirements expression and serialize that to binary. - No turnkey support for signing keys. We want to make it easier for obtaining signing keys (and their X.509 certificate chain) for use with this crate. It should be possible to easily integrate with the OS’s key store or hardware based stores (such as Yubikeys). We also don’t look for necessary X.509 certificate extensions that Apple’s verification likely mandates, which we should do and enforce.
- Notarization support. The notarization ticket appears to be part of the embedded signature data. We don’t support parsing this blob. It should be possible to coerce this crate into emitting a notarization blob in the signature data. But this isn’t currently implemented as part of our high-level signing primitives.
There is missing features and functionality that will likely never be implemented:
- Binary verification compliant with Apple’s operating systems. We are capable of verifying the digests of code and other embedded signature data. We can also verify that a cryptographic signature came from the annotated public key in that signature. We can also write heuristics to look for certain common problems with signatures. But we can’t and likely never will implement all the rules Apple uses to verify a binary for execution because we perceive there to be little value in doing this. This crate could be used to build such functionality elsewhere, however.
Getting Started
This crate is still in early phases of development. Until things are more mature,
a good place to start with the source code is main.rs
to get a feel for what
CLI commands do.
The MachOSigner type is your gateway to how code signing is performed.
find_signature_data and parse_signature_data are useful for finding and then parsing signature data into an EmbeddedSignature instance for examination.
If you’d like to learn about the technical underpinnings of code signing on Apple platforms, see specification.
Re-exports
pub use code_requirement::*; |
Modules
code_requirement | Code requirement language primitives. |
specification | Apple code signing technical specifications |
Structs
BlobEntry | Represents a single blob as defined by a SuperBlob index entry. |
BlobWrapperBlob | Represents a generic blob wrapper. |
BundleSigner | A primitive for signing an Apple bundle. |
CodeDirectoryBlob | Represents a code directory blob entry. |
CodeResources | Represents a |
CodeResourcesBuilder | Interface for constructing a |
CodeResourcesRule | Represents an abstract rule in a |
CodeSignatureFlags | Code signature flags. |
DetachedSignatureBlob | A detached signature. |
Digest | |
EmbeddedSignature | Represents embedded signature data in a Mach-O binary. |
EmbeddedSignatureBlob | Represents an embedded signature. |
EmbeddedSignatureOldBlob | An old embedded signature. |
EntitlementsBlob | Represents an Entitlements blob. |
ExecutableSegmentFlags | Flags that influence behavior of executable segment. |
MachOSignatureData | Describes signature data embedded within a Mach-O binary. |
MachOSigner | Mach-O binary signer. |
OtherBlob | Represents an unknown blob type. |
ParsedBlob | Represents the parsed content of a blob entry. |
RequirementBlob | Represents a Requirement blob. |
RequirementSetBlob | Represents a Requirement set blob. |
Scatter | |
SignedMachOInfo | Metadata about a signed Mach-O file or bundle. |
SigningSettings | Represents code signing settings. |
SingleBundleSigner | A primitive for signing a single Apple bundle. |
VerificationContext | Context for a verification issue. |
VerificationProblem |
Enums
AppleCodesignError | Unified error type for Apple code signing. |
BlobData | Represents a single, parsed Blob entry/slot. |
CodeDirectoryVersion | Version of Code Directory data structure. |
CodeSigningMagic | Defines header magic for various payloads. |
CodeSigningSlot | Defines a typed slot within code signing data. |
DigestType | Represents a digest type from a CS_HASHTYPE_* constants. |
RequirementType | Denotes type of code requirements. |
SettingsScope | Denotes the scope for a setting. |
VerificationProblemType | Describes a problem with verification. |
Traits
Blob | Provides common features for a parsed blob type. |
BundleFileHandler | Used to process individual files within a bundle. |
Functions
check_signing_capability | Determines whether this crate is capable of signing a given Mach-O binary. |
compute_code_hashes | Compute code hashes for a Mach-O binary. |
compute_paged_hashes | Compute paged hashes. |
create_code_directory_hashes_plist | Obtain the XML plist containing code directory hashes. |
create_self_signed_code_signing_certificate | Create a new self-signed X.509 certificate suitable for signing code. |
create_superblob | Create the binary content for a SuperBlob. |
find_signature_data | Attempt to extract a reference to raw signature data in a Mach-O binary. |
parse_signature_data | Parse raw Mach-O signature data into a data structure. |
verify_macho | Verifies a parsed Mach-O binary. |
verify_macho_data | Verifies unparsed Mach-O data. |
verify_path | Verifies a binary in a given path. |