Note: This no longer works due to SIP protection on macOS after Big Sur
A common activity when deploying Macs in Enterprise and Education environments is trusted a certificate in the System keychain. Before macOS 11 Big Sur, this was done using the security command.
However, macOS 11 Big Sur changed this:
macOS Big Sur 11 beta improves system security by requiring an administrator password when a certificate trust settings change is made in the admin trust domain. Running as the root user alone is no longer sufficient to modify certificate trust. User trust domain settings continue to require confirmation by entering the password for the user’s account. This change may affect you if one of the following is true: You have written scripts which call /usr/bin/security add-trusted-cert -d ... as root. Your process runs as root and calls the SecTrustSettingsSetTrustSettings function to trust a certificate.
In Big Sur, when you use the security command to add / trust a certificate, you get prompted:
sudo security add-trusted-cert -r trustRoot /tmp/web.twocanoes.com.cer
sudo security trust-settings-import -d /tmp/settings
Adding a certificate to the System keychain doesn’t prompt:
sudo security add-certificates -k /Library/Keychains/System.keychain /tmp/web.twocanoes.com.cer
However, that last command doesn’t trust the certificate. It just imports it.
The trust information on both the user and system keychain is stored in /Library/Security/Trust Settings. The System keychain trust setting are in a file named “Admin.plist” and looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>trustList</key>
<dict>
<key>1F9575A7FDCE56AB5461E89C0738841C94F02C81</key>
<dict>
<key>issuerName</key>
<data>
MEAxEzARBgoJkiaJk/IsZAEZFgNjb20xGTAXBgoJkiaJk/IsZAEZ
Fgl0d29jYW5vZXMxDjAMBgNVBAMTBVRDU0NB
</data>
<key>modDate</key>
<date>2021-08-20T14:15:32Z</date>
<key>serialNumber</key>
<data>
EwAAAF+zxdRuiaLqIAAAAAAAXw==
</data>
<key>trustSettings</key>
<array>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAED
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147408896</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAED
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEI
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>SMIME</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147408872</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEI
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>SMIME</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEJ
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>eapServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEL
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>ipsecServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEQ
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>CodeSigning</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEU
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>AppleTimeStamping</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEC
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>basicX509</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
</array>
</dict>
<key>A93342811590725BF3EDB290545EBF3BD40814B0</key>
<dict>
<key>issuerName</key>
<data>
MEAxEzARBgoJkiaJk/IsZAEZFgNjb20xGTAXBgoJkiaJk/IsZAEZ
Fgl0d29jYW5vZXMxDjAMBgNVBAMTBVRDU0NB
</data>
<key>modDate</key>
<date>2021-08-20T01:29:18Z</date>
<key>serialNumber</key>
<data>
WPQVDB1u0KFKnBg34gSxkw==
</data>
<key>trustSettings</key>
<array>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAED
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147408896</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAED
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEI
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>SMIME</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147408872</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEI
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>SMIME</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEJ
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>eapServer</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEL
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>ipsecServer</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEQ
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>CodeSigning</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEU
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>AppleTimeStamping</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEC
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>basicX509</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
</array>
</dict>
</dict>
<key>trustVersion</key>
<integer>1</integer>
</dict>
</plist>
Each trusted certificate has a entry in the trustList. For example, there is the trust for the certificate web.twocanoes.com:
<key>1F9575A7FDCE56AB5461E89C0738841C94F02C81</key>
<dict>
<key>issuerName</key>
<data>
MEAxEzARBgoJkiaJk/IsZAEZFgNjb20xGTAXBgoJkiaJk/IsZAEZ
Fgl0d29jYW5vZXMxDjAMBgNVBAMTBVRDU0NB
</data>
<key>modDate</key>
<date>2021-08-20T14:15:32Z</date>
<key>serialNumber</key>
<data>
EwAAAF+zxdRuiaLqIAAAAAAAXw==
</data>
<key>trustSettings</key>
<array>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAED
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147408896</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAED
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEI
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>SMIME</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147408872</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEI
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>SMIME</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEJ
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>eapServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEL
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>ipsecServer</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEQ
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>CodeSigning</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEU
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>AppleTimeStamping</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
<dict>
<key>kSecTrustSettingsAllowedError</key>
<integer>-2147409654</integer>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEC
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>basicX509</string>
<key>kSecTrustSettingsResult</key>
<integer>2</integer>
</dict>
</array>
</dict>
The key of 1F9575A7FDCE56AB5461E89C0738841C94F02C81 is the sha1 has of the certificate.
The issuername is base64 of the asn1 of the issue from the cert:
echo MEAxEzARBgoJkiaJk/IsZAEZFgNjb20xGTAXBgoJkiaJk/IsZAEZFgl0d29jYW5vZXMxDjAMBgNVBAMTBVRDU0NB | base64 -D|openssl asn1parse -inform der
0:d=0 hl=2 l= 64 cons: SEQUENCE
2:d=1 hl=2 l= 19 cons: SET
4:d=2 hl=2 l= 17 cons: SEQUENCE
6:d=3 hl=2 l= 10 prim: OBJECT :domainComponent
18:d=3 hl=2 l= 3 prim: IA5STRING :com
23:d=1 hl=2 l= 25 cons: SET
25:d=2 hl=2 l= 23 cons: SEQUENCE
27:d=3 hl=2 l= 10 prim: OBJECT :domainComponent
39:d=3 hl=2 l= 9 prim: IA5STRING :twocanoes
50:d=1 hl=2 l= 14 cons: SET
52:d=2 hl=2 l= 12 cons: SEQUENCE
54:d=3 hl=2 l= 3 prim: OBJECT :commonName
59:d=3 hl=2 l= 5 prim: PRINTABLESTRING :TCSCA
The serial number is the base64 of the cert serial:
echo EwAAAF+zxdRuiaLqIAAAAAAAXw== | base64 -D |xxd -p
The trustSettings do not seem to change for different certificates and see to be constants. For instance:
Adding and Trusting without Prompting
Knowing this information makes it easy to add in trusted certificate. If you are deploying a bunch of Macs that need a set up root certificates trusted, do this:
- Add the certificate the System Keychain in Keychain Utility, and mark it as trusted.
- Copy the /Library/Security/Trust Settings/Admin.plist and the certificate file to the target macs. Note that this will overwrite the current trust setting so be aware you may need to merge if you want to keep the old settings.
- Import the certificate by running:
sudo security add-certificates -k /Library/Keychains/System.keychain /tmp/web.twocanoes.com.cer
- Move Admin.plist to /Library/Security/Trust Settings and set the permissions to read and write only by root:wheel.
- Reboot