diff --git a/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift b/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift index f52f4c828..d354cad91 100644 --- a/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift +++ b/Sources/WalletConnectKMS/Keychain/KeychainStorage.swift @@ -55,7 +55,7 @@ public final class KeychainStorage: KeychainStorageProtocol { case errSecSuccess: return item as? Data case errSecItemNotFound: - return tryMigrateAttrAccessible(key: key) // TODO: Replace with nil once migration period ends + return tryMigrateAttrAccessibleOnRead(key: key) // TODO: Replace with nil once migration period ends default: throw KeychainError(status) } @@ -70,8 +70,13 @@ public final class KeychainStorage: KeychainStorageProtocol { let attributes = [kSecValueData: data] let status = secItem.update(query as CFDictionary, attributes as CFDictionary) - - guard status == errSecSuccess else { + + switch status { + case errSecSuccess: + return + case errSecItemNotFound: + try tryMigrateAttrAccessibleOnUpdate(data: data, key: key) // TODO: Remove once migration period ends + default: throw KeychainError(status) } } @@ -108,7 +113,7 @@ public final class KeychainStorage: KeychainStorageProtocol { ] } - private func tryMigrateAttrAccessible(key: String) -> Data? { + private func tryMigrateAttrAccessibleOnRead(key: String) -> Data? { var updateQuery = buildBaseServiceQuery(for: key) updateQuery[kSecAttrAccessible] = kSecAttrAccessibleWhenUnlockedThisDeviceOnly @@ -127,4 +132,25 @@ public final class KeychainStorage: KeychainStorageProtocol { return item as? Data } + + private func tryMigrateAttrAccessibleOnUpdate(data: Data, key: String) throws { + var updateAccessQuery = buildBaseServiceQuery(for: key) + updateAccessQuery[kSecAttrAccessible] = kSecAttrAccessibleWhenUnlockedThisDeviceOnly + + let accessAttributes = [kSecAttrAccessible: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly] + let accessStatus = secItem.update(updateAccessQuery as CFDictionary, accessAttributes as CFDictionary) + + guard accessStatus == errSecSuccess else { + throw KeychainError.itemNotFound + } + + let updateQuery = buildBaseServiceQuery(for: key) + let updateAttributes = [kSecValueData: data] + + let updateStatus = secItem.update(updateQuery as CFDictionary, updateAttributes as CFDictionary) + + guard updateStatus == errSecSuccess else { + throw KeychainError.itemNotFound + } + } }