13 Replies
      Latest reply on Mar 1, 2018 5:37 AM by eskimo
      mo.o Level 1 Level 1 (0 points)

        First of all, sorry for my english.

        i want iOS mutual authentication with client certificate.

        but when i make NSURLCredential for NSURLAuthenticationMethodClientCertificate,

        i have to need SecIdentityRef. but i cannot obtain identity from anywhere..

         

        1.

        i created keypair with SecKeyGeneratePair (RSA, 2048). and stored into keychain.

         

        2.

        send publickey to server. and get PEM type certificate (base64) from server, correctly.

         

        3.

        i decoded it. and make certificate with SecCertificateCreateWithData,

        store it keychain directly

        NSDictionary* certDic = @{
                                          (__bridge id)kSecClass : (__bridge id)kSecClassCertificate,
                                          (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
                                          (__bridge id)kSecValueRef : (__bridge id)savedCertRef,
                                          (__bridge id)kSecAttrLabel : cert_tag,
                                          };
        
        OSStatus status = SecItemAdd((__bridge CFDictionaryRef)certDic, NULL);
        

        perfectly work until here.

         

        4.

        now my keychain stored "Private Key", "Public Key","Certificate" from server

         

        5.

        when i try to access server, server request client certificate.

        so i have to send client certificate from my keychain

        but i have only SecCertificateRef. at that time. there is no SecIdentityRef


        //in NSURLAuthenticationMethodClientCertificate block...
        
        SecCertificateRef certificate = [DeviceCertificateControl getDeviceCertRef];
        SecIdentityRef identity = ??????????????????;
                   
        NSArray *certArray = [NSArray arrayWithObject:(__bridge id)certificate];
        * credential = [NSURLCredential credentialWithIdentity:identity certificates:certArray persistence:NSURLCredentialPersistencePermanent];
        

         

        :::::::::: question.

        1. how to make SecIdentityRef with SecCertificateRef with private key ref?

        (many other examples, they use P12 file (pkcs#12), but i don't use it)

         

        2. can i make pkcs#12 type data directly in iOS device?


        3. is there way to send certification without identity?


        many thanks.

        • Re: generate SecIdentityRef with SecCertificateRef, private key
          eskimo Apple Staff Apple Staff (10,295 points)

          I’m going to tackle your questions out of order:

          3. is there way to send certification without identity?

          This makes no sense.  My TLS for App Developers post explains why.

          2. can i make pkcs#12 type data directly in iOS device?

          Not via any iOS APIs.  A PKCS#12 is just a bag of bytes, so you could write or acquire code to create one, but it’s not a lot of fun.  It would be easier to fix your identity code.

          1. how to make SecIdentityRef with SecCertificateRef with private key ref?

          You need to do three things:

          • Before adding the certificate to the keychain, delete the public key from the keychain.  There are situations where the presence of the public key confuses the identity matching code (r. 15615260).

          • Identity matching is done via the public key hash, which should be stored in the kSecAttrLabel kSecAttrApplicationLabel attribute of the private key and the kSecAttrPublicKeyHash attribute of the certificate.  After you’ve got both items in the keychain, get these attributes to confirm that they match up.

          • Once the above is sorted out, you can get the identity by calling SecItemCopyMatching looking for items where the kSecClass is kSecClassIdentity.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"

            • Re: generate SecIdentityRef with SecCertificateRef, private key
              TirantFox Level 1 Level 1 (0 points)

              @eskimo Thank you for your contribution. This information is very difficult to find.

               

              I am in a similar predicament, in which I've created a key pair and CSR on my iOS app, sent the CSR to the server and received a PEM certificate back. So I have now at my disposal the Private Key, Public Key and the CA Signed Certificate.

               

              How do I determine the public key hash to follow your instructions here? How do I determine the ThumbprintAlgorithm used in the certificate without access to SecCertificateCopyValues?

               

              Any thoughts on why these functions are not included in the iOS API

                • Re: generate SecIdentityRef with SecCertificateRef, private key
                  eskimo Apple Staff Apple Staff (10,295 points)

                  How do I determine the public key hash to follow your instructions here?

                  You can actually the public key hash if necessary, but my experience is that it’s not necessary.  If you add the certificate to the keychain as a ref (that is, using kSecValueRef rather than kSecValueData), the system should set that attribute for you, at which point you can call SecItemCopyMatching to get an identity object.

                  Share and Enjoy

                  Quinn “The Eskimo!”
                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                  let myEmail = "eskimo" + "1" + "@apple.com"

                    • Re: generate SecIdentityRef with SecCertificateRef, private key
                      marekfromrzeszow Level 1 Level 1 (0 points)

                      Hi,

                       

                      My start situation is pretty much simillar to original mo.o post which means:
                      1. Generate pair of keys
                      2. Create CSR using keys from step 1

                      3. Do receive PEM in response to CSR post

                      4. Decode it

                      5. Store in same keychain as keys are

                      6. Trying to get the identity

                       

                      Thus I did follow @eskimo advices however at the end I still can not get the identity.

                       

                      Please find my sample code below and I would be very garatefull for any advice what I am doing wrong here? Did I use kSecAttrApplicationLabel and kSecAttrPublicKeyHash correctly? Maybe I have implemented something else incorectly?????

                       

                      Thanks in advance

                       

                       

                      
                      
                      
                      

                          let privKeyAttrApplicationLabel = "com.example.keys.privateKey.kSecAttrApplicationLabel".data(using: .utf8)!

                          let privKeyAttrApplicationTag = "com.example.keys.privateKey.kSecAttrApplicationTag".data(using: .utf8)!

                          let pubKeyAttrApplicationTag = "com.example.keys.publicKey.kSecAttrApplicationTag".data(using: .utf8)!

                       

                          let keyPairAttributes: [String: Any] =

                              [kSecAttrKeyType as String:            kSecAttrKeyTypeEC,

                               kSecAttrKeySizeInBits as String:      256,

                               kSecPrivateKeyAttrs as String:

                                  [kSecAttrIsPermanent as String:    true,

                                   kSecAttrApplicationLabel as String: privKeyAttrApplicationLabel,

                                   kSecAttrApplicationTag as String: privKeyAttrApplicationTag],

                               kSecPublicKeyAttrs as String:

                                  [kSecAttrIsPermanent: true,

                                   kSecAttrApplicationTag: pubKeyAttrApplicationTag]

                          ]

                       

                          var publicKeyRef: SecKey? = nil

                          var privateKeyRef: SecKey? = nil

                       

                          let keyPairGenerationStatus = SecKeyGeneratePair(keyPairAttributes as CFDictionary, &publicKeyRef, &privateKeyRef)

                          guard keyPairGenerationStatus == errSecSuccess else { return }

                       

                           // At this stage I create CSR using above pair of keys and do exchane it to PEM (X509) to finaly parse that to DER

                       

                          let pemCert: String = "MIO...A=="

                          let pemCertData = NSData(base64Encoded: pemCert, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters)!

                       

                           // Before adding the certificate to the keychain, delete the public key from the keychain.  There are situations where the presence of the public key confuses the identity matching code.

                       

                          let deletePublicKeyQuery: [String: Any] = [kSecClass as String: kSecClassKey,

                                                            kSecAttrKeyType as String: kSecAttrKeyTypeEC,

                                                            kSecAttrApplicationTag as String: pubKeyAttrApplicationTag,

                                                            kSecReturnRef as String: true]

                       

                          let deletePublicKeyStatus = SecItemDelete(deletePublicKeyQuery as CFDictionary)

                          guard deletePublicKeyStatus == errSecSuccess else { return }

                       

                          guard let cert = SecCertificateCreateWithData(kCFAllocatorDefault, pemCertData as CFData) else { return }

                       

                           // Add cer to keychain

                       

                          let addquery: [String: Any] = [kSecClass as String: kSecClassCertificate,

                                                         kSecValueRef as String: cert,

                                                         kSecAttrPublicKeyHash as String: privKeyAttrApplicationLabel,

                                                         kSecAttrLabel as String: "com.example.keys.mycert"]

                       

                          let certAddStatus = SecItemAdd(addquery as CFDictionary, nil)

                          guard certAddStatus == errSecSuccess else { return }

                       

                           // As I understand correctly at this moment Identity matching is done via the public key hash, which should be stored in the kSecAttrLabel           kSecAttrApplicationLabel attribute of the private key and the kSecAttrPublicKeyHash attribute of the certificate, but is it??????? Maybe I do it wrong????

                       

                           // This is final step where I am trying to get the Identity using kSecAttrApplicationTag same as I did use to generate privateKey

                       

                          let getIdentityQuery: [String: Any] = [kSecClass as String: kSecClassIdentity,

                                                                 kSecAttrApplicationTag as String: privKeyAttrApplicationTag]

                          var identityItem: CFTypeRef?

                          let status = SecItemCopyMatching(getIdentityQuery as CFDictionary, &identityItem)

                          guard status == errSecSuccess else { return }

                       

                          // At the final line here status is equal 0, however identityItem is nil! Why? Any idea what might be wrong??????

                        • Re: generate SecIdentityRef with SecCertificateRef, private key
                          eskimo Apple Staff Apple Staff (10,295 points)

                          For the keychain to ‘see’ an identity the kSecAttrApplicationLabel attribute of the private key and the kSecAttrPublicKeyHash attribute of the certificate must match.  So, the standard debugging step here is to dump these attributes and see whether they do in fact match.  Here’s what I recommend:

                          1. Create a small test app to explore this situation.

                          2. Write code to delete all keys and certificates from the keychain, so you start with a blank slate each time.

                          3. Then add in your test code.

                          4. Write code that dumps all the keys and certificates in the keychain, and specifically the above-mentioned attributes.

                          5. Run your app.

                          6. If things fail, check the output from step 4 to confirm that:

                            • There is a single key, the private key, and a single certificate

                            • The above-mentioned attributes have the same value

                          Share and Enjoy

                          Quinn “The Eskimo!”
                          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                          let myEmail = "eskimo" + "1" + "@apple.com"

                            • Re: generate SecIdentityRef with SecCertificateRef, private key
                              pmatas Level 1 Level 1 (0 points)

                              hey Quinn,

                               

                              I have a similar situation:

                              1. I receive a ca certificate, client certificate and a private key from our API as PEM Strings

                              2. Certificate and a private key are stored into the keychain

                              3. I need to pass this identity at a later stage to the secure transport as a MQTT networking library

                               

                              I'm following your advice and I got so far that I can verify the `SecAttrApplicationLabel` of my private key is equal to the `kSecAttrPublicKeyHash`.

                               

                              The problem is that when I query the keychain for an identity, i receive just `-25300`. Is there some manual way to combine them as an indentity?

                               

                              My code is below:

                               

                              // add the client certificate
                              guard let cert = SecCertificateCreateWithData(kCFAllocatorDefault, pemCertData as CFData) else {
                                    XCTAssert(false, "Failed creating a Ceriticate")
                                    return
                              }
                              let addCertQuery: [String: Any] = [kSecClass as String: kSecClassCertificate,
                                                                 kSecValueRef as String: cert,
                                                                 kSecAttrLabel as String: label]
                                 
                              let certAddStatus = SecItemAdd(addCertQuery as CFDictionary, nil)
                              
                              // add the private key
                              let addKeyQuery: [String: Any] = [
                                        kSecClass as String: kSecClassKey,
                                        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
                                        kSecAttrIsPermanent as String: true,
                                        kSecValueData as String: pemKeyData,
                                        kSecAttrApplicationLabel as String: publicHash,
                                        kSecAttrApplicationTag as String: tag
                                  ]
                                 
                              let privKeyAddStatus = SecItemAdd(addKeyQuery as CFDictionary, nil)
                              //
                              
                              // query for all avaiable identities
                              let getIdentityQuery: [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(getIdentityQuery as CFDictionary, &identityItem)
                              // the status returns -25300 
                              
                                • Re: generate SecIdentityRef with SecCertificateRef, private key
                                  eskimo Apple Staff Apple Staff (10,295 points)

                                  There’s two things I’d change here:

                                  • When you add your private key to the keychain (lines 13 through 22), don’t try to set up all the attributes yourself.  Rather, create the private key from pemKeyData yourself (SecKeyCreateWithData) and then add that via reference, much like do with the certificate.  That’ll make sure that the private key has all the necessary attributes set correctly.

                                  • When searching the identity, pass in just kSecReturnRef, not kSecReturnData and kSecReturnAttributes.  In the long term kSecReturnAttributes should be OK (so you can add it back into the mix once you’ve got past this hurdle) but kSecReturnData doesn’t really make any sense when talking about a synthetic construct like a digital identity.

                                  Share and Enjoy

                                  Quinn “The Eskimo!”
                                  Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                  let myEmail = "eskimo" + "1" + "@apple.com"

                                    • Re: generate SecIdentityRef with SecCertificateRef, private key
                                      pmatas Level 1 Level 1 (0 points)

                                      Thank you, Quinn! It worked as described.

                                       

                                       

                                      Initially, I assumed that the SecKeyCreateWithData also adds the certificate to the Keychain but after re-reading your answer I saw that I should add it manually.

                                       

                                       

                                      For those who might need it later, here's an example:

                                       

                                      
                                      func stripPemHeaders(_ pemString: String) -> String {
                                          var result = pemString
                                          //
                                          result = result.replacingOccurrences(of: "-----BEGIN RSA PRIVATE KEY-----\n", with: "")
                                          result = result.replacingOccurrences(of: "\n-----END RSA PRIVATE KEY-----\n", with: "")
                                          //
                                          result = result.replacingOccurrences(of: "-----BEGIN CERTIFICATE-----\n", with: "")
                                          result = result.replacingOccurrences(of: "\n-----END CERTIFICATE-----\n", with: "")
                                          return result
                                        }
                                      
                                      func storePrivateKey(for id: String, privateKeyString: String) -> OSStatus? {
                                          // cleanup key string from PEM headers
                                          let derPrivateKeyString = stripPemHeaders(privateKeyString)
                                          // we need to convert to Data before intitializing
                                          guard let pemKeyData = Data(base64Encoded: derPrivateKeyString, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters) else {
                                            print("Error: couldn't parse the privateKeyString, pls check if headers were removed: \(privateKeyString)")
                                            return nil
                                          }
                                          // create the SecKey before we can store it to the keychain
                                          let sizeInBits = pemKeyData.count * 8
                                          let tag = "\(id)-tag".data(using: .utf8)!
                                          let keyDict: [CFString: Any] = [
                                            kSecAttrKeyType: kSecAttrKeyTypeRSA,
                                            kSecAttrKeyClass: kSecAttrKeyClassPrivate,
                                            kSecAttrKeySizeInBits: NSNumber(value: sizeInBits),
                                            kSecReturnPersistentRef: true
                                          ]
                                          var error: Unmanaged<CFError>?
                                          guard let key = SecKeyCreateWithData(pemKeyData as CFData, keyDict as CFDictionary, &error) else {
                                            print("Failed creating a Certificate from data \(error.debugDescription)")
                                            return nil
                                          }
                                          /// add key reference to keychain
                                          let addKeyQuery: [String: Any] = [
                                            kSecClass as String: kSecClassKey,
                                            kSecAttrIsPermanent as String: true,
                                            kSecValueRef as String: key,
                                            kSecAttrApplicationTag as String: tag
                                          ]
                                        
                                          let privKeyAddStatus = SecItemAdd(addKeyQuery as CFDictionary, nil)
                                          return privKeyAddStatus
                                        }
                                      
                                  • Re: generate SecIdentityRef with SecCertificateRef, private key
                                    marekfromrzeszow Level 1 Level 1 (0 points)

                                    Hi @eskimo,

                                     

                                    Thank you very much for your tips it works for me like a charm!

                                     

                                    However I am facing now new issue and can not find anywhere clear enough answer to my problem. So briefly to remaind what I am trying to achieve:

                                     

                                    1. Generate pair of keys
                                    2. Create CSR using keys from step 1

                                    3. Do receive PEM in response to CSR post

                                    4. Decode it

                                    5. Store in same keychain as keys are

                                    6. Create digital identity credentials and use for URLAuthenticationChallenge for NSURLAuthenticationMethodClientCertificate

                                    7. When try to call final enpoint (https://192.168.XXX.YYY:8080/myrequest), veryfing serves with ca_self_signed_cert and use digital identity credentials from step 6 do receive error in URLSession dataTask completion handler as follows:

                                     

                                    NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."

                                    NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x1c0119740>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-1, NSErrorPeerCertificateChainKey=(...)


                                    Also in debbuger do notice following message:
                                    [BoringSSL] Function boringssl_context_parse_identity_certificate_chain: line 3781 The type of the leaf certificate is not that of `SecIdentityGetTypeID()`

                                     

                                    I am able to create now SecIdentity with success and add to URLSessionDelegate challange, however do receive error and it looks like ATS blocks something.

                                     

                                     


                                    FYI my url looks as follows and it is not a local one: https://192.168.XXX.YYY:8080/myrequest

                                     

                                     

                                    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

                                     

                                            if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate) {

                                     

                                                let getCertQuery: [String: Any] = [

                                                    kSecClass as String : kSecClassCertificate,

                                                    kSecReturnData as String  : kCFBooleanTrue,

                                                    kSecReturnAttributes as String : kCFBooleanTrue,

                                                    kSecReturnRef as String : kCFBooleanTrue

                                                ]

                                                var certItem: CFTypeRef?

                                                let certStatus = withUnsafeMutablePointer(to: &certItem) {

                                                    SecItemCopyMatching(getCertQuery as CFDictionary, UnsafeMutablePointer($0))

                                                }

                                                guard certStatus == errSecSuccess else { return }

                                                let certificate = certItem as! SecCertificate

                                     

                                     

                                                let getIdentityQuery: [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 identityStatus = withUnsafeMutablePointer(to: &identityItem) {

                                                    SecItemCopyMatching(getIdentityQuery as CFDictionary, UnsafeMutablePointer($0))

                                                }

                                                guard identityStatus == errSecSuccess else { return }

                                                let identity = identityItem as! SecIdentity

                                     

                                                // Create digital identity credentials

                                                let credentials = URLCredential(identity: identity, certificates: [certificate], persistence: .forSession)

                                                return completionHandler(.useCredential, credentials)

                                     

                                     

                                            } else if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {

                                     

                                                var localTrust: SecTrust?

                                                let policy = SecPolicyCreateBasicX509()

                                                let serverTrust = challenge.protectionSpace.serverTrust!

                                                for index in 0..<SecTrustGetCertificateCount(serverTrust) {

                                                    guard let cert = SecTrustGetCertificateAtIndex(serverTrust, index) else { break }

                                                    var servTrust: SecTrust?

                                                    SecTrustCreateWithCertificates(cert, policy, &servTrust)

                                                    let localServKey = SecTrustCopyPublicKey(servTrust!)!

                                     

                                                    let certificateData = NSData(contentsOfFile: Bundle.main.path(forResource: "ca_self_signed_cert", ofType: "der")!)

                                                    let localCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, certificateData!)

                                     

                                     

                                                    if SecTrustCreateWithCertificates(localCertificate!, policy, &localTrust) == errSecSuccess {

                                      

                                                        let localPublicKey = SecTrustCopyPublicKey(localTrust!)!

                                                        if (localPublicKey as AnyObject).isEqual(localServKey as AnyObject) {

                                                            print("trusted")

                                                            let credential = URLCredential(trust: serverTrust)

                                                            return completionHandler(.useCredential, credential)

                                                        }

                                                    }

                                                }

                                            }

                                        }

                                     

                                    I would be very gratefull for any tips here

                                     

                                    Cheers

                            • Re: generate SecIdentityRef with SecCertificateRef, private key
                              haosama Level 1 Level 1 (0 points)

                              Hi eskimo,

                               

                              I read already all topics about it, but I still can’t got identity from keychain.

                              I compare kSecAttrApplicationLabel of private key and kSecAttrPublicKeyHash of certificates, it’s same (value something like this: <fd92f1ee a28525668 … 28698ec3>)

                               

                              I using next pipeline:

                              1. Generate pair of RSA keys
                              2. Send public key to server and generate CSR, after signing it with private key on device we send it to server again for creating certificate
                              3. Load certificate to keychain on device
                              4. Tried to get identity

                               

                              I know that I miss step with deletion of public key, but I tried to get it from keychain and I can’t do it (I think that it not stored there, I always take it from private key)

                               

                              I using next code for creation keys, loading certificate and get’s Identity:

                               

                              Creation key pairs:

                               

                              let access = SecAccessControlCreateWithFlags(kCFAllocatorDefault,

                              kSecAttrAccessibleWhenUnlockedThisDeviceOnly,

                              .userPresence,

                              nil)!   /

                                    

                                      let attributes: [String: Any] =

                              [kSecAttrKeyType as String: kSecAttrKeyTypeRSA as String,

                              kSecAttrKeySizeInBits as String:      keySize,

                              kSecPrivateKeyAttrs as String:

                              [kSecAttrIsPermanent as String:    true,

                              kSecAttrApplicationTag as String: alias,

                              kSecAttrAccessControl as String:  access]

                                      ]

                               

                              var error: Unmanaged<CFError>?

                              privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)

                               

                                          if privateKey == nil{

                              var errorText = error!.takeRetainedValue() as Error

                              throw KeyGeneratorError.privateKeyNotDefined

                              }

                               

                                          publicKey = SecKeyCopyPublicKey(privateKey!)

                               

                                          if let cfdata = SecKeyCopyExternalRepresentation(publicKey!, &error) {

                              let data:Data = cfdata as Data

                              let key = self.format(keyData: data, withPemType: "RSA PUBLIC KEY")

                              return key

                              }

                               

                               

                              Import certificate:

                               

                              let derCert = self.convertToDerFrom(pem: pem)

                                    

                                      let certificate = SecCertificateCreateWithData(kCFAllocatorDefault, derCert)

                                    

                                      guard certificate != nil else {

                              throw KeychainError.certificateCreationFailed

                                      }

                                   

                                      let certificateQuery: [String: Any] = [kSecClass as String: kSecClassCertificate,

                              kSecValueRef as String: certificate!,

                              kSecAttrLabel as String: self.alias]

                                    

                                      let result = SecItemAdd(certificateQuery as CFDictionary, nil)

                                    

                                      guard result == errSecSuccess else {

                              throw KeychainError.unexpectedCertificateAddError

                                      }

                               

                               

                              Getting list of identity (tried to get one or many, same result):

                               

                              let identityQuery: [String: Any] = [kSecClass as String: kSecClassIdentity,

                              kSecMatchLimit as String: kSecMatchLimitAll,

                              kSecReturnRef as String: true]

                               

                                          var identityRef: CFTypeRef?

                               

                                          let result = SecItemCopyMatching(identityQuery as CFDictionary, &identityRef)

                               

                                          guard result == errSecSuccess else {

                              throw KeychainItem.KeychainError.unhandledError(status: result)

                              }

                               

                               

                              Mb I doing something wrong?