AMFI: checking file integrity on your Mac

Digging around looking at signature checking for apps in Mojave brought me in contact with a part of macOS with which I wasn’t familiar: AMFI. Although very little seems to be known about this important subsystem in macOS security, I thought it might be useful to share what I have been able to discover. Please feel free to correct any errors, and cast light on dark corners where I have missed information.

Judging by its name, Apple Mobile File Integrity (AMFI) originated in iOS, where it blocks any attempt to run unsigned code. It seems to have been migrated to macOS in Sierra or before, possibly with the changes in Gatekeeper and code signing in 2012.

It consists of two components: the daemon or service amfid, which runs from /usr/libexec/amfid. This is very small, only around 51 KB, and is run as a root Launch Daemon by /System/Library/LaunchDaemons/com.apple.MobileFileIntegrity.plist. It normally starts after loginwindow and sandboxd (a relative), and before syspolicyd and trustd (on which it relies).

Its client is the AppleMobileFileIntegrity extension (in /System/Library/Extensions), which is rather larger at 151 KB of executable code. Its current version is 1.0.5.

The AMFI extension loads trusted keys from NVRAM and is also involved with rootless and DataVault controllers. amfid checks the integrity of files running on the system by calling trustd to do its checking. trustd is a Launch Agent daemon which provides services for evaluating trust in certificates for all processes, including with Static Code Checks.

The AMFI extension and amfid form the com.apple.MobileFileIntegrity subsystem, but as of macOS 10.14.2 they don’t use that subsystem identifier in the unified log, which suggests that their code hasn’t yet been revised to take full advantage of that feature of the new log.

AMFI checks in with launchd, and as well as checking signatures and their certificates, it checks entitlements and provisioning profiles, producing a filtered entitlement dictionary for an app. amfid refers to related files /Library/Preferences/com.apple.security.coderequirements.plist and com.apple.security.libraryvalidation.plist, neither of which is normally present on standalone Macs, but may be related to provisioning on managed systems.

AMFI and amfid log entries are quite common, even when a Mac is apparently idle (but not asleep), occurring when apps are launched. Typical entries for an amfid check are brief:
00.444085 amfid Security SecTrustEvaluateIfNecessary
amfid calls for a Trust Evaluation
00.445546 com.apple.securityd rvc trustd trustd asynchronously fetching CRL (http://crl.apple.com/root.crl) for client (amfid[124]/0#-1 LF=0)
trustd announces that it is performing that asynchronously
00.445639 com.apple.securityd policy trustd trustd cert[2]: AnchorTrusted =(leaf)[force]> 0
trustd reports the certificate is trusted.

When a validation fails, the error is normally reported first, and that failure returns to amfid and the AMFI extension:
00.461066 com.apple.MobileFileIntegrity amfid amfid amfid Basic requirement validation failed, error: (null)
00.461145 amfid amfid /Users/hoakley/Documents/test2/SignetTest5.app/Contents/MacOS/Signet signature not valid: -67030

That is normally taken back to the kernel:
00.461160 kernel AppleMobileFileIntegrity AMFI: code signature validation failed.
and the app or process will fail to start, or be aborted immediately.

For AMFI, a broken signature is normally fatal for the app or process, but it may be allowed when an old SDK has been used, or SDK information is missing or malformed. AMFI may also prevent access to a graphics bundle because the path to the app or process is untrusted.