Files
openhaystack/OpenHaystack/OpenHaystack/HaystackApp/KeychainController.swift
2021-03-11 11:02:24 +01:00

87 lines
2.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// OpenHaystack Tracking personal Bluetooth devices via Apple's Find My network
//
// Copyright © 2021 Secure Mobile Networking Lab (SEEMOO)
// Copyright © 2021 The Open Wireless Link Project
//
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
import OSLog
import Security
struct KeychainController {
static func loadAccessoriesFromKeychain(test: Bool = false) -> [Accessory] {
var query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrLabel: "FindMyAccessories",
kSecAttrService: "SEEMOO-FINDMY",
kSecMatchLimit: kSecMatchLimitOne,
kSecReturnData: true,
]
if test {
query[kSecAttrService] = "SEEMOO-Test"
}
var result: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard status == errSecSuccess,
let resultData = result as? Data
else {
return []
}
// Convert from PropertyList to an array of accessories
do {
let accessories = try PropertyListDecoder().decode([Accessory].self, from: resultData)
return accessories
} catch {
os_log("Could not decode accessories %@", String(describing: error))
}
return []
}
static func storeInKeychain(accessories: [Accessory], test: Bool = false) throws {
// Store or update
var attributes: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrLabel: "FindMyAccessories",
kSecAttrService: "SEEMOO-FINDMY",
kSecValueData: try PropertyListEncoder().encode(accessories),
]
if test {
attributes[kSecAttrService] = "SEEMOO-Test"
}
// Try to store the item
let storeStatus = SecItemAdd(attributes as CFDictionary, nil)
if storeStatus == errSecDuplicateItem {
var query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrLabel: "FindMyAccessories",
kSecAttrService: "SEEMOO-FINDMY",
]
if test {
query[kSecAttrService] = "SEEMOO-Test"
}
// Update the existing item
let updateStatus = SecItemUpdate(query as CFDictionary, attributes as CFDictionary)
guard updateStatus == errSecSuccess else {
throw KeychainError.updatingItemFailed
}
}
}
}
enum KeychainError: Error {
case updatingItemFailed
}