Skip to content

Commit

Permalink
Keychain migration
Browse files Browse the repository at this point in the history
  • Loading branch information
flypaper0 committed Oct 30, 2023
1 parent aedef51 commit 34d5577
Showing 1 changed file with 38 additions and 2 deletions.
40 changes: 38 additions & 2 deletions Sources/WalletConnectKMS/Keychain/KeychainStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public final class KeychainStorage: KeychainStorageProtocol {
case errSecSuccess:
return item as? Data
case errSecItemNotFound:
return nil
// TODO: Replace with nil once migration period ends
return try tryMigrateAttrAccessible(key: key)
default:
throw KeychainError(status)
}
Expand Down Expand Up @@ -100,11 +101,46 @@ public final class KeychainStorage: KeychainStorageProtocol {
private func buildBaseServiceQuery(for key: String) -> [CFString: Any] {
return [
kSecClass: kSecClassGenericPassword,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
kSecAttrAccessible: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
kSecAttrIsInvisible: true,
kSecUseDataProtectionKeychain: true,
kSecAttrService: service,
kSecAttrAccount: key
]
}

private func tryMigrateAttrAccessible(key: String) throws -> Data? {
var query = buildBaseServiceQuery(for: key)
query[kSecReturnData] = true
query[kSecAttrAccessible] = kSecAttrAccessibleWhenUnlockedThisDeviceOnly

var item: CFTypeRef?
let status = secItem.copyMatching(query as CFDictionary, &item)

switch status {
case errSecSuccess: // Migration needed
guard let data = item as? Data else { return nil }

// Fetching old value
var deleteQuery = buildBaseServiceQuery(for: key)
deleteQuery[kSecAttrAccessible] = kSecAttrAccessibleWhenUnlockedThisDeviceOnly

// Deleting old value
let status = secItem.delete(deleteQuery as CFDictionary)

guard status == errSecSuccess || status == errSecItemNotFound else {
throw KeychainError(status)
}

// Replacing with new value
try add(data: data, forKey: key)

// Continue `readData` execution
return item as? Data
case errSecItemNotFound:
return nil
default:
throw KeychainError(status)
}
}
}

0 comments on commit 34d5577

Please sign in to comment.