0

The problem:

I have an iOS 8 application with a framework for keychain access and a share extension.

enter image description here

Both, the host application and the share extension link the keychain access framework and they both share a keychain.

Everything works in Debug configuration. But when I use the Release configuration the value dataTypeRef is always nil when I try to receive a password from the keychain.

I have already tried to add an App Group but without luck.

Has anyone an idea why it doesn't work for Release builds? Thanks

The code for the keychain access:

In the keychain access framework I add a password to the keychain like this:

public class func setPassword(password: String, account: String, service: String = "kDDHDefaultService") {
    var secret: NSData = password.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
    let objects: Array = [secClassGenericPassword(), service, account, secret]
    
    let keys: Array = [secClass(), secAttrService(), secAttrAccount(), secValueData()]
    
    let query = NSDictionary(objects: objects, forKeys: keys)
    
    SecItemDelete(query as CFDictionaryRef)
    
    let status = SecItemAdd(query as CFDictionaryRef, nil)
}

To receive the password I do this:

 public class func passwordForAccount(account: String, service: String = "kDDHDefaultService") -> String? {
    
    let keys: [AnyObject] = [secClass(), secAttrService(), secAttrAccount(), secReturnData()]
    let objects: [AnyObject] = [secClassGenericPassword(), service, account, true]
    
    println("keys \(keys), objects \(objects)")
    
    let queryAttributes = NSDictionary(objects: objects, forKeys: keys)

    var dataTypeRef : Unmanaged<AnyObject>?
    let status = SecItemCopyMatching(queryAttributes, &dataTypeRef);
    if status == errSecItemNotFound {
        println("not Found")
        return nil
    }
    
    if dataTypeRef == nil {  // dataTypeRef is always nil in Release builds
        println("dataTypeRef == nil")
        return nil
    }
    
    let retrievedDataRef : CFDataRef = dataTypeRef!.takeRetainedValue() as CFDataRef
    let retrievedData : NSData = retrievedDataRef
    
    let password = NSString(data: retrievedData, encoding: NSUTF8StringEncoding)

    return password as? String
}

Note: This has nothing to do with the share extension it even doesn't work for the host application.

Update: For a test I have added the KeychainAccess class to the target of the host application. But I still can't access the keychain in Release builds.

Community
  • 1
  • 1
dasdom
  • 13,975
  • 2
  • 47
  • 58

1 Answers1

-1

I think I found a temporary fix. As suggested in a comment to this answer I set the optimization of the Swift compiler to None[-Onone] in the keychain access target and it seems to work now.

Community
  • 1
  • 1
dasdom
  • 13,975
  • 2
  • 47
  • 58