Trust caches
One of the objects included in the Secure Boot chain is the static trust cache, a trusted record of all the Mach-O binaries that are mastered into the signed system volume. Each Mach-O is represented by a code directory hash. For efficient searching, these hashes are sorted before being inserted into the trust cache. The code directory is the result of the signing operation performed by codesign(1)
. To enforce the trust cache, SIP must remain enabled. To disable trust cache enforcement on a Mac with Apple silicon, secure boot must be configured to Permissive Security.
When a binary is executed (whether as part of spawning a new process or mapping executable code into an existing process), its code directory is extracted and hashed. If the resulting hash is found in the trust cache, the executable mappings created for the binary will be granted platform privileges — that is, they may possess any entitlement and execute without further verification as to the authenticity of the signature. This is in contrast to an Intel-based Mac, where platform privileges are conveyed to operating system content by the Apple certificate that signs the binaries. (This certificate doesn’t constrain which entitlements the binary may possess).
Non-platform binaries (for example, notarised third-party code) must have valid certificate chains to execute, and the entitlements they may possess are constrained by the signing profile issued to the developer by the Apple Developer Program.
All binaries shipped within macOS are signed with a platform identifier. On a Mac with Apple silicon, this identifier is used to indicate that even though the binary is signed by Apple, its code directory hash must be present in the trust cache to execute. On an Intel-based Mac, the platform identifier is used to perform targeted revocation of binaries from an older release of macOS; this targeted revocation helps prevent those binaries from executing on newer versions.
The static trust cache completely locks a set of binaries to a given version of macOS. This behaviour helps prevent legitimately Apple-signed binaries from older operating systems from being introduced into newer ones for an attacker to gain advantage.
Platform code shipped outside the operating system
Apple ships some binaries — for example, Xcode and the development tools stack — that aren’t signed with a platform identifier. Even so, they’re still permitted to execute with platform privileges on a Mac with Apple silicon and a Mac with a T2 chip. Because this platform software is shipped independently of macOS, it isn’t subject to the revocation behaviours imposed by the static trust cache.
Loadable trust caches
Apple ships certain software packages with loadable trust caches. These caches have the same data structure as the static trust cache. But although there’s only one static trust cache — and its contents are always guaranteed to be locked into read-only ranges after the kernel’s early initialisation is complete — loadable trust caches are added to the system at runtime.
These trust caches are authenticated either through the same mechanism that authenticates boot firmware (personalisation using the Apple trusted signing service) or as globally signed objects (the signatures of which don’t bind them to a particular device).
One example of a personalised trust cache is the cache, shipped with the disk image that’s used to perform field diagnostics on a Mac with Apple silicon. This trust cache is personalised, along with the disk image and loaded into the subject Mac computer’s kernel while it’s booted into a diagnostic mode. The trust cache allows the software within the disk image to run with platform privilege.
An example of a globally signed trust cache is shipped with macOS software updates. This trust cache permits a chunk of code within the software update — the update brain — to run with platform privilege. The update brain performs any work to stage the software update that the host system lacks the capacity to perform in a consistent fashion across versions.