Thank you very much for the clear explanation. It clarifies a lot for us.
Based on your response, we now understand that:
com.apple.token is a special system-managed group for CryptoTokenKit tokens
We cannot add credentials to it directly via kSecAttrAccessGroup
We need to create a persistent CryptoTokenKit token (not tied to smart card hardware)
We have a few follow-up questions to implement this correctly:
Question 1: Creating Persistent Virtual Token
How do we create a persistent CTK token that's not tied to physical smart card hardware?
Our current attempt:
private static func configureTokenForIdentity(_ identity: SecIdentity) throws {
var certRef: SecCertificate?
SecIdentityCopyCertificate(identity, &certRef)
guard let certificate = certRef else { return }
let driverClassID: TKTokenDriver.ClassID = "com.example.ExampleTokenExtension"
guard let driverConfig = TKTokenDriver.Configuration.driverConfigurations[driverClassID] else {
throw NSError(domain: NSCocoaErrorDomain, code: -1, userInfo: nil)
}
let instanceID = UUID().uuidString
let certItem = TKTokenKeychainCertificate(certificate: certificate, objectID: "com.example.cert1")
let keyItem = TKTokenKeychainKey(certificate: certificate, objectID: "com.example.key1")
keyItem?.canSign = true
keyItem?.isSuitableForLogin = true
let tokenConfig = TKToken.Configuration(instanceID: instanceID)
tokenConfig.keychainItems = [certItem, keyItem].compactMap { $0 }
// ❓ What is the correct API to persist this token configuration?
// In iOS SDK 26, these APIs don't exist:
// - driverConfig.addTokenConfiguration()
// - driverConfig.openTokenConfiguration()
}
What is the correct API in SDK 26 to register a persistent token configuration?
Question 2: Private Key Storage and Access
Our token extension implements TKTokenSessionDelegate:
func tokenSession(_ session: TKTokenSession, sign dataToSign: Data,
keyObjectID: Any, algorithm: TKTokenKeyAlgorithm) throws -> Data {
guard let privateKey = getPrivateKeyFromKeychain() else {
throw NSError(domain: TKErrorDomain, code: TKError.Code.objectNotFound.rawValue, userInfo: nil)
}
var error: Unmanaged<CFError>?
guard let signature = SecKeyCreateSignature(
privateKey,
.rsaSignatureMessagePKCS1v15SHA256,
dataToSign as CFData,
&error
) else {
throw error?.takeRetainedValue() as! Error
}
return signature as Data
}
private func getPrivateKeyFromKeychain() -> SecKey? {
let query: [String: Any] = [
kSecClass as String: kSecClassIdentity,
kSecAttrLabel as String: "com.example.clientcert",
kSecReturnRef as String: kCFBooleanTrue!,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard status == errSecSuccess, let identity = result as? SecIdentity else {
return nil
}
var privateKey: SecKey?
SecIdentityCopyPrivateKey(identity, &privateKey)
return privateKey
}
❓ How should the token session retrieve the private key imported from the PKCS#12 bundle?
Should the private key be stored in the app's keychain (current approach)?
Or should it be stored in the token's keychain items?
What's the correct data flow between the app and token extension?
Question 3: Microsoft Edge Integration
According to Microsoft's documentation, Edge for iOS can read from com.apple.token when the MDM policy ReadExtendedCertificateLocationsEnabled is enabled:
https://learn.microsoft.com/en-us/deployedge/microsoft-edge-browser-policies/readextendedcertificatelocationsenabled
❓ Will Edge be able to access certificates from a persistent CTK token created by a third-party app?
Question 4: Development Approach
You mentioned: "first prototype this with an actual smart card"
For development/testing purposes:
❓ Can we use a software-based virtual token instead of a physical smart card?
❓ Is there sample code or a template for creating persistent virtual tokens?
❓ What's the difference between a physical smart card token and a persistent virtual token (from the system's perspective)?
Our Goal
We want to understand the correct architecture to:
Import a PKCS#12 certificate in a third-party app
Create a persistent CryptoTokenKit virtual token that publishes this certificate
Make it available system-wide for managed apps like Microsoft Edge for iOS
Key Question: Is this use case supported for third-party apps, or is it restricted to specific Apple-approved scenarios?
Thank you again for your guidance!
Entitlements Configuration (for reference):
<!-- CertificateInstaller.entitlements -->
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.apple.token</string>
<string>$(AppIdentifierPrefix)com.example.app</string>
</array>
<!-- ExampleTokenExtension.entitlements -->
<key>com.apple.security.token</key>
<array>
<string>TEAMID.com.apple.token</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.apple.token</string>
</array>
Topic:
Privacy & Security
SubTopic:
General
Tags: