We are building a NETransparentProxyProvider system extension on macOS. The extension needs a certificate identity provisioned by MDM for cryptographic operations at runtime (signing and/or mTLS). We have hit a wall where a PKCS#12-delivered identity resolves correctly inside the extension but an ACME-delivered identity does not, and we want to understand whether this is a known limitation, a gap, or whether there is a supported path we are missing. We understand the implications of the data protection keychain on macOS but wonder if there is a carveout here that may not be documented well.
We deploy the extension via MDM (profile traditionally but could be via DDM on macOS27). A VPN profile delivers an identity reference to the extension at runtime via PayloadCertificateUUID which surfaces an identity reference within protocolConfiguration.identityReference.
When referencing a PKCS#12 identity (com.apple.security.pkcs12 payload): the identityReference is 196 bytes, beginning with the 4-byte prefix 73737569 (ASCII "ssui"). The reference is self-describing — it embeds the keychain path (/Library/Keychains/System.keychain), the certificate subject (in our case, "Delegate Test CA"), the team ID, and a 20-byte SHA-1 hash at the tail. This format carries everything the Security framework needs to locate the item.
Full reference (our test, redacted to structure):
73737569 00000020 <uuid-bytes> 00000000000000000000000000000006
64626e6d 00000023 2f4c696272…53797374656d2e6b6579636861696e00 ← /Library/Keychains/System.keychain
6974656d 00000069 80001000… ← item data incl. DER subject
…
00000014 48b494ae47d1b7b07ed8c77a681337a3af8e92a8 ← 20-byte SHA-1 hash
When referencing a ACME identity (com.apple.security.acme payload, ECSECPrimeRandom P-384, SE-backed): the identityReference is 20 bytes, beginning with the 4-byte prefix 63657274 (ASCII "cert"). The remaining 16 bytes are opaque — they do not embed a keychain path, certificate subject, or any other locator.
Full reference (our test):
63657274 a4c7e569737944b1 ad464dc3bb398f14
Searching for the SecIdentity
The PKCS#12 reference resolves using SecItemCopyMatching with kSecValuePersistentRef set to the 196-byte reference and kSecMatchSearchList pointing at System.keychain succeeds immediately, returning a SecIdentity with both SecIdentityCopyCertificate and SecIdentityCopyPrivateKey succeeding - this is obviously expected for an exportable software key type.
The ACME reference fails using every path that we tried to search/load it as a SecIdentity. Primarily:
kSecValuePersistentRef with kSecUseDataProtectionKeychain: true (no explicit keychain): -25291 (errSecNoDefaultKeychain)
kSecValuePersistentRef with an explicit kSecMatchSearchList pointing at System.keychain: -50 (errSecParam) — combining kSecValuePersistentRef with an explicit keychain search list is an invalid parameter combination for the compact cert-format reference.
kSecMatchItemList with an explicit kSecMatchSearchList: -25300 (errSecItemNotFound)
SecKeychainItemCopyFromPersistentReference (legacy API): -25300 (errSecItemNotFound)
kSecValuePersistentRef with no keychain qualifier at all: -25291 (errSecNoDefaultKeychain)
com.apple.managed.vpn.shared access group (which i know has had entitled use on iOS): -34018 (errSecMissingEntitlement)
Next steps
The cert-format kSecValuePersistentRef produced by an ACME identity cannot be resolved in a root daemon context using any API path we can find. The ssui-format reference from a PKCS#12 identity works.
With macOS 27, com.apple.configuration.network.vpn.vpn-plugin DDM declarations accept an Authentication.IdentityAssetReference which can point at an ACME identity asset. Traditional VPN profiles also support PayloadCertificateUUID referencing an ACME payload. Both paths result in the extension receiving a cert-format reference that it cannot resolve.
Is there a supported API to resolve a cert-format kSecValuePersistentRef in a daemon context without a default keychain? Or is this just the reality of the DPK on macOS where ACME/SE-backed identities are not usable from system extensions, and the IdentityAssetReference and PayloadCertificateUUID fields only work for PKCS#12 or SCEP identity types in this context?
For completeness: we have also explored ManagedApp.framework and ManagedAppIdentitiesProvider as an alternative delivery path, and believe this is the better method, but that hits a separate issue where managedappsd fails to verify the code signature of a system extension caller (filed separately as feedback FB23484530). Similar to this, we need to understand if the ExtensionConfigs in ManagedApp.framework are for appex user space app extensions only, and don't extend to System Extensions.
Topic:
Business & Education
SubTopic:
Device Management
0
0
18