Post

Replies

Boosts

Views

Activity

Reply to Secure enclave protected private key in CryptoKit vs Security framework
We are having similar challenge. It seems, that something ist missing in the API. Use Case Only registered App-Instances are allowed to connect to the API (we use DCAppAttest durcing the registration, out of scope here) Communication between App and the API is authenticated using mutual TLS The private Key is held in the Secure Enclave and is not transferable Certificate ist issued by the Backend API upon the successful registration Implementation Keypair is generated in the Secure Enclave: var error: Unmanaged<CFError>? = nil; guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, [.privateKeyUsage], &error) else { throw error!.takeRetainedValue() as Error } self.privateKey = try SecureEnclave.P256.Signing.PrivateKey.init( accessControl: accessControl ); Certificate Signing Request ist created using CryptoKit Certificates: let privateKeyCertificate = Certificate.PrivateKey(privateKey) let attributes = CertificateSigningRequest.Attributes() let csr = try CertificateSigningRequest(version: .v1, subject: subject, privateKey: privateKeyCertificate, attributes: attributes, signatureAlgorithm: .ecdsaWithSHA256) let csrAsPEM = try csr.serializeAsPEM(discriminator: CertificateSigningRequest.defaultPEMDiscriminator).pemString CSR is then sent to Backend für validation, if everything checks up server signs the CSR and returns the certificate. We then store the SecureEnclave.P256.Signing.PrivateKey in the Keychain as described here: Storing CryptoKit Keys in the Keychain using GenericPasswordConvertible. The Certificate is also stored in the Keychain: let addQuery: [String: Any] = [ kSecClass as String: kSecClassCertificate, kSecValueRef as String: cert, kSecAttrLabel as String: "My Certificate" ] let status = SecItemAdd(addQuery as CFDictionary, nil) We are stuck in the last Step: retrieve the SecIdentity from the KeyChain. We get Error -25300, no matter what. Lates query is like this: let query: [String: Any] = [ kSecClass as String: kSecClassIdentity, kSecReturnData as String: kCFBooleanTrue, kSecReturnAttributes as String: kCFBooleanTrue, kSecReturnRef as String: kCFBooleanTrue, kSecMatchLimit as String: kSecMatchLimitAll ] var identityItem: CFTypeRef? let status = SecItemCopyMatching(query as CFDictionary, &identityItem)
Jan ’24