iosswiftcore-foundationsecurity-framework

SecAccessControlCreateWithFlags() in Swift


I am trying to call a function in the Security.framework, from swift code. Forgetting about the "error out" (last) parameter for a second, if I call the function like this:

let accessControlRef = SecAccessControlCreateFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
            SecAccessControlCreateFlags.UserPresence,
            nil
        )

I ge tht efollowing error:

Cannot find an initializer for type 'SecAccessControlCreateFlags' that accepts an argument list of type '(CFAllocator!, CFStringRef, SecAccessControlCreateFlags, nil)'

...however, if I reformat my code to the following:

let allocator:CFAllocatorRef! = kCFAllocatorDefault

let protection:AnyObject!     = kSecAttrAccessibleWhenUnlockedThisDeviceOnly

let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.UserPresence


let accessControlRef = SecAccessControlCreateWithFlags(
    allocator,
    protection,
    flags,
    nil
)

(specific types -e.g., CFAllocatorRef- taken from function prototype on Xcode's autocomplete)...it compiles with no problem. What's going on?

Next, the error parameter. What should I pass? Migrating my Objective-C code, I am tempted to pass the following variable (prepended with &, of course):

var accessControlError:CFErrorRef! = nil

...which gives the error:

Cannot invoke 'SecAccessControlCreateWithFlags' with an argument list of type '(CFAllocatorRef!, AnyObject!, SecAccessControlCreateFlags, inout CFErrorRef!)'

If, instead, I pass the following variable (again, prepended with the address-of operator):

var accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?>

(Same type as suggested by prototype autocomplete), I get:

Cannot invoke 'SecAccessControlCreateWithFlags' with an argument list of type '(CFAllocatorRef!, AnyObject!, SecAccessControlCreateFlags, inout UnsafeMutablePointer?>)'

...so, what gives?

EDIT: Forget about the error parameter. I seems I am taking the address twice (i.e., pointer to a pointer). Instead, I should do this:

var accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?> = nil
// ^ Already a 'pointer'

let allocator:CFAllocatorRef!         = kCFAllocatorDefault
let protection:AnyObject!             = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.UserPresence 

let accessControlRef = SecAccessControlCreateWithFlags(
        allocator,
        protection,
        flags,
        accessControlError // <- Notice the lack of '&'
)

Source: sample code within this answer.


Solution

  • (OK, so nobody has added any new insights in a while, so I will answer my own question with the contents of my last edit:)

    ANSWER: Forget about the error parameter. I seems I am taking the address twice (i.e., pointer to a pointer). Instead, I should do this:

    let accessControlError:UnsafeMutablePointer<Unmanaged<CFError>?> = nil
    // ^ Already a 'pointer'
    
    let allocator:CFAllocator!         = kCFAllocatorDefault
    let protection:AnyObject!             = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    let flags:SecAccessControlCreateFlags = SecAccessControlCreateFlags.userPresence 
    
    let accessControlRef = SecAccessControlCreateWithFlags(
            allocator,
            protection,
            flags,
            accessControlError // <- Notice the lack of '&'
    )