I'm trying to add a generic password to the keychain and get back the persistent ID for it, and give it .userPresence access control. Unfortunately, if I include that, I get paramError back from SecItemAdd. Here's the code:
@discardableResult
func
set(username: String, hostname: String?, password: String, comment: String? = nil)
throws
-> PasswordEntry
{
// Delete any existing matching password…
if let existing = try? getEntry(forUsername: username, hostname: hostname)
{
try deletePassword(withID: existing.id)
}
// Store the new password…
var label = username
if let hostname
{
label = label + "@" + hostname
}
var item: [String: Any] =
[
kSecClass as String : kSecClassGenericPassword,
kSecAttrDescription as String : "TermPass Password",
kSecAttrGeneric as String : self.bundleID.data(using: .utf8)!,
kSecAttrLabel as String : label,
kSecAttrAccount as String : username,
kSecValueData as String : password.data(using: .utf8)!,
kSecReturnData as String : true,
kSecReturnPersistentRef as String: true,
]
if self.synchronizable
{
item[kSecAttrSynchronizable as String] = kCFBooleanTrue!
}
if let hostname
{
item[kSecAttrService as String] = hostname
}
if let comment
{
item[kSecAttrComment as String] = comment
}
// Apply access control to require the user to prove presence when
// retrieving this password…
var error: Unmanaged<CFError>?
guard
let accessControl = SecAccessControlCreateWithFlags(nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.userPresence,
&error)
else
{
let cfError = error!.takeUnretainedValue() as Error
throw cfError
}
item[kSecAttrAccessControl as String] = accessControl
item[kSecAttrAccessible as String] = kSecAttrAccessibleWhenUnlockedThisDeviceOnly
var result: AnyObject!
let status = SecItemAdd(item as CFDictionary, &result)
try Errors.throwIfError(osstatus: status)
load()
guard
let secItem = result as? [String : Any],
let persistentRef = secItem[kSecValuePersistentRef as String] as? Data
else
{
throw Errors.malformedItem
}
let entry = PasswordEntry(id: persistentRef, username: username, hostname: hostname, password: password, comment: comment)
return entry
}
(Note that I also tried it omitting kSecAttrAccessible, but it had no effect.)
This code works fine if I omit setting kSecAttrAccessControl.
Any ideas? TIA!
Topic:
Privacy & Security
SubTopic:
General