1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! 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].

mod bundle_signing;
pub use bundle_signing::*;
mod certificate;
pub use certificate::*;
mod code_directory;
pub use code_directory::*;
mod code_hash;
pub use code_hash::*;
pub mod code_requirement;
pub use code_requirement::*;
mod code_resources;
pub use code_resources::*;
mod error;
pub use error::*;
mod macho;
pub use macho::*;
mod macho_signing;
pub use macho_signing::*;
mod signing;
pub use signing::*;
pub mod specification;
mod verify;
pub use verify::*;