Post

Replies

Boosts

Views

Activity

Reply to Keychain Identity backed by key generated in secure enclave
Hey @eskimo thank you for your reply! I followed your instructions, but identity does not appear in a keychain. I manually compared public portion of a key generated in Secure Enclave with a public key of a certificate surfaced in Keychain Access. They match, but I cannot see the certificate in a list of all available identities. I also tried to manually create and add identity to the keychain. In this case SecItemAdd fails with -50 errSecParam. Here is the code I'm using: func run() {  let key = genKey()     let publicKey = SecKeyCopyPublicKey(key!)  let d = Data(referencing: SecKeyCopyExternalRepresentation(publicKey!, nil)!)  print("publicKey:", d.hexEncodedString()) // compare with a public key of a cert in Keychain Access app     let certificate = genCert(key: key!)  addCertificateToKeychain(certificate: certificate!)  // addIdentityToKeychain(certificate: certificate!)  listIdentities() } func genKey() -> SecKey? {  let access = SecAccessControlCreateWithFlags(   kCFAllocatorDefault,   kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,   .privateKeyUsage,   nil)!     let attributes: NSDictionary = [   kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,   kSecAttrKeySizeInBits: 256,   kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,   kSecPrivateKeyAttrs: [    kSecAttrIsPermanent: true,    kSecAttrAccessControl: access   ]  ]     return SecKeyCreateRandomKey(attributes, nil) } func genCert(key: SecKey) -> SecCertificate? { // generate and return x509 certificate } func addCertificateToKeychain(certificate: SecCertificate) {  let addquery: [String: Any] = [kSecClass as String: kSecClassCertificate,                  kSecValueRef as String: certificate]  let status = SecItemAdd(addquery as CFDictionary, nil)  print("SecItemAdd Certificate", status) // status 0 } func addIdentityToKeychain(certificate: SecCertificate) {  var identity: SecIdentity?  let statusIDCreate = SecIdentityCreateWithCertificate(nil, certificate, &identity)  print("SecItemIdentityCreate", statusIDCreate) // status 0     let addquery: [String: Any] = [kSecClass as String: kSecClassIdentity,                  kSecValueRef as String: identity!]  let status = SecItemAdd(addquery as CFDictionary, nil)  print("SecItemAdd Identity", status) // status -50 errSecParam } func listIdentities() {  let query: [String: Any] = [kSecClass as String: kSecClassIdentity,                kSecMatchLimit as String: kSecMatchLimitAll,                kSecReturnRef as String: true]  var item: CFTypeRef?  SecItemCopyMatching(query as CFDictionary, &item)     for id in item as! Array<SecIdentity> {   var certificate: SecCertificate?   SecIdentityCopyCertificate(id, &certificate)   let desc = SecCertificateCopyLongDescription(kCFAllocatorDefault, certificate!, nil)   print(desc!)  } } extension Data {  func hexEncodedString() -> String {   return self.map { String(format: "%02hhX ", $0) }.joined()  } } Am I doing something wrong? Thank you
Topic: Privacy & Security SubTopic: General Tags:
Jan ’23
Reply to Keychain Identity backed by key generated in secure enclave
Hey! Yes, I'm developing an app for mac, with no intentions to run it on iOS ever. My bad, should've mentioned that in the beginning. Is it even possible to add a certificate to the data protection keychain? SecItemAdd attributes do not allow to specify a keychain. There is SecItemImport method that has importKeychain: SecKeychain? attribute, but I didn't find a way to get a reference to data protection keychain. Besides, most methods in SecKeychain are deprecated. Thank you!
Topic: Privacy & Security SubTopic: General Tags:
Jan ’23
Reply to Keychain Identity backed by key generated in secure enclave
Hey @eskimo thank you for your reply! I followed your instructions, but identity does not appear in a keychain. I manually compared public portion of a key generated in Secure Enclave with a public key of a certificate surfaced in Keychain Access. They match, but I cannot see the certificate in a list of all available identities. I also tried to manually create and add identity to the keychain. In this case SecItemAdd fails with -50 errSecParam. Here is the code I'm using: func run() {  let key = genKey()     let publicKey = SecKeyCopyPublicKey(key!)  let d = Data(referencing: SecKeyCopyExternalRepresentation(publicKey!, nil)!)  print("publicKey:", d.hexEncodedString()) // compare with a public key of a cert in Keychain Access app     let certificate = genCert(key: key!)  addCertificateToKeychain(certificate: certificate!)  // addIdentityToKeychain(certificate: certificate!)  listIdentities() } func genKey() -> SecKey? {  let access = SecAccessControlCreateWithFlags(   kCFAllocatorDefault,   kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,   .privateKeyUsage,   nil)!     let attributes: NSDictionary = [   kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,   kSecAttrKeySizeInBits: 256,   kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,   kSecPrivateKeyAttrs: [    kSecAttrIsPermanent: true,    kSecAttrAccessControl: access   ]  ]     return SecKeyCreateRandomKey(attributes, nil) } func genCert(key: SecKey) -> SecCertificate? { // generate and return x509 certificate } func addCertificateToKeychain(certificate: SecCertificate) {  let addquery: [String: Any] = [kSecClass as String: kSecClassCertificate,                  kSecValueRef as String: certificate]  let status = SecItemAdd(addquery as CFDictionary, nil)  print("SecItemAdd Certificate", status) // status 0 } func addIdentityToKeychain(certificate: SecCertificate) {  var identity: SecIdentity?  let statusIDCreate = SecIdentityCreateWithCertificate(nil, certificate, &identity)  print("SecItemIdentityCreate", statusIDCreate) // status 0     let addquery: [String: Any] = [kSecClass as String: kSecClassIdentity,                  kSecValueRef as String: identity!]  let status = SecItemAdd(addquery as CFDictionary, nil)  print("SecItemAdd Identity", status) // status -50 errSecParam } func listIdentities() {  let query: [String: Any] = [kSecClass as String: kSecClassIdentity,                kSecMatchLimit as String: kSecMatchLimitAll,                kSecReturnRef as String: true]  var item: CFTypeRef?  SecItemCopyMatching(query as CFDictionary, &item)     for id in item as! Array<SecIdentity> {   var certificate: SecCertificate?   SecIdentityCopyCertificate(id, &certificate)   let desc = SecCertificateCopyLongDescription(kCFAllocatorDefault, certificate!, nil)   print(desc!)  } } extension Data {  func hexEncodedString() -> String {   return self.map { String(format: "%02hhX ", $0) }.joined()  } } Am I doing something wrong? Thank you
Topic: Privacy & Security SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’23
Reply to Keychain Identity backed by key generated in secure enclave
Hey! Yes, I'm developing an app for mac, with no intentions to run it on iOS ever. My bad, should've mentioned that in the beginning. Is it even possible to add a certificate to the data protection keychain? SecItemAdd attributes do not allow to specify a keychain. There is SecItemImport method that has importKeychain: SecKeychain? attribute, but I didn't find a way to get a reference to data protection keychain. Besides, most methods in SecKeychain are deprecated. Thank you!
Topic: Privacy & Security SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’23
Reply to Keychain Identity backed by key generated in secure enclave
Found kSecUseDataProtectionKeychain, it is not listed in SecItemAdd attributes section, but it works! Thank you
Topic: Privacy & Security SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’23
Reply to CryptoTokenKit persistent token extension + SSH PKCS#11 authentication doesn't work
AFAIK you cannot use CTK app extension does not implement pkcs11 interface. The simplest way to use key generated in secure enclave for SSH I can think of is implementing of SSH Agent that will leverage Secure Enclave.
Topic: Privacy & Security SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’23