From 779a1504cb87752f733b4388d1aba004c2a1606c Mon Sep 17 00:00:00 2001 From: Dan Federman Date: Mon, 22 Apr 2024 08:28:40 -0700 Subject: [PATCH] Make core types Sendable and @unchecked Sendable --- Sources/Valet/Accessibility.swift | 2 +- Sources/Valet/CloudAccessibility.swift | 2 +- Sources/Valet/Identifier.swift | 2 +- Sources/Valet/Internal/Configuration.swift | 2 +- Sources/Valet/Internal/Service.swift | 2 +- Sources/Valet/KeychainError.swift | 2 +- Sources/Valet/MigrationError.swift | 2 +- Sources/Valet/SecureEnclave.swift | 2 +- Sources/Valet/SecureEnclaveAccessControl.swift | 2 +- Sources/Valet/SecureEnclaveValet.swift | 7 ++++--- Sources/Valet/SharedGroupIdentifier.swift | 2 +- Sources/Valet/SinglePromptSecureEnclaveValet.swift | 4 ++-- Sources/Valet/Valet.swift | 7 ++++--- 13 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Sources/Valet/Accessibility.swift b/Sources/Valet/Accessibility.swift index e8f5fc68..0cd3d4dd 100644 --- a/Sources/Valet/Accessibility.swift +++ b/Sources/Valet/Accessibility.swift @@ -18,7 +18,7 @@ import Foundation @objc(VALAccessibility) -public enum Accessibility: Int, CaseIterable, CustomStringConvertible, Equatable { +public enum Accessibility: Int, CaseIterable, CustomStringConvertible, Equatable, Sendable { /// Valet data can only be accessed while the device is unlocked. This attribute is recommended for data that only needs to be accessible while the application is in the foreground. Valet data with this attribute will migrate to a new device when using encrypted backups. case whenUnlocked = 1 /// Valet data cannot be accessed after a restart until the device has been unlocked once; data is accessible until the device is next rebooted. This attribute is recommended for data that needs to be accessible by background applications. Valet data with this attribute will migrate to a new device when using encrypted backups. diff --git a/Sources/Valet/CloudAccessibility.swift b/Sources/Valet/CloudAccessibility.swift index 563e6ca9..c2fd8e40 100644 --- a/Sources/Valet/CloudAccessibility.swift +++ b/Sources/Valet/CloudAccessibility.swift @@ -18,7 +18,7 @@ import Foundation @objc(VALCloudAccessibility) -public enum CloudAccessibility: Int, CaseIterable, CustomStringConvertible, Equatable { +public enum CloudAccessibility: Int, CaseIterable, CustomStringConvertible, Equatable, Sendable { /// Valet data can only be accessed while the device is unlocked. This attribute is recommended for data that only needs to be accessible while the application is in the foreground. Valet data with this attribute will migrate to a new device when using encrypted backups. case whenUnlocked = 1 /// Valet data cannot be accessed after a restart until the device has been unlocked once; data is accessible until the device is next rebooted. This attribute is recommended for data that needs to be accessible by background applications. Valet data with this attribute will migrate to a new device when using encrypted backups. diff --git a/Sources/Valet/Identifier.swift b/Sources/Valet/Identifier.swift index b44d4f93..9a588f7f 100644 --- a/Sources/Valet/Identifier.swift +++ b/Sources/Valet/Identifier.swift @@ -17,7 +17,7 @@ import Foundation -public struct Identifier: CustomStringConvertible { +public struct Identifier: CustomStringConvertible, Sendable { // MARK: Initialization diff --git a/Sources/Valet/Internal/Configuration.swift b/Sources/Valet/Internal/Configuration.swift index 2ccff617..3355f4c6 100644 --- a/Sources/Valet/Internal/Configuration.swift +++ b/Sources/Valet/Internal/Configuration.swift @@ -17,7 +17,7 @@ import Foundation -internal enum Configuration: CustomStringConvertible { +internal enum Configuration: CustomStringConvertible, Sendable { case valet(Accessibility) case iCloud(CloudAccessibility) case secureEnclave(SecureEnclaveAccessControl) diff --git a/Sources/Valet/Internal/Service.swift b/Sources/Valet/Internal/Service.swift index df4bd4a2..ae3bc70b 100644 --- a/Sources/Valet/Internal/Service.swift +++ b/Sources/Valet/Internal/Service.swift @@ -17,7 +17,7 @@ import Foundation -internal enum Service: CustomStringConvertible, Equatable { +internal enum Service: CustomStringConvertible, Equatable, Sendable { case standard(Identifier, Configuration) case sharedGroup(SharedGroupIdentifier, Identifier?, Configuration) diff --git a/Sources/Valet/KeychainError.swift b/Sources/Valet/KeychainError.swift index 5289c044..affc549b 100644 --- a/Sources/Valet/KeychainError.swift +++ b/Sources/Valet/KeychainError.swift @@ -18,7 +18,7 @@ import Foundation @objc(VALKeychainError) -public enum KeychainError: Int, CaseIterable, CustomStringConvertible, Error, Equatable { +public enum KeychainError: Int, CaseIterable, CustomStringConvertible, Error, Equatable, Sendable { /// The keychain could not be accessed. case couldNotAccessKeychain /// User dismissed the user-presence prompt. diff --git a/Sources/Valet/MigrationError.swift b/Sources/Valet/MigrationError.swift index 832c0bbc..e57747d1 100644 --- a/Sources/Valet/MigrationError.swift +++ b/Sources/Valet/MigrationError.swift @@ -18,7 +18,7 @@ import Foundation @objc(VALMigrationResult) -public enum MigrationError: Int, CaseIterable, CustomStringConvertible, Error, Equatable { +public enum MigrationError: Int, CaseIterable, CustomStringConvertible, Error, Equatable, Sendable { /// Migration failed because the keychain query was not valid. case invalidQuery /// Migration failed because a key staged for migration was invalid. diff --git a/Sources/Valet/SecureEnclave.swift b/Sources/Valet/SecureEnclave.swift index e87d6a7b..9e3b4e37 100644 --- a/Sources/Valet/SecureEnclave.swift +++ b/Sources/Valet/SecureEnclave.swift @@ -17,7 +17,7 @@ import Foundation -public final class SecureEnclave { +public final class SecureEnclave: Sendable { // MARK: Internal Methods diff --git a/Sources/Valet/SecureEnclaveAccessControl.swift b/Sources/Valet/SecureEnclaveAccessControl.swift index 7242fc7b..2b47d3b3 100644 --- a/Sources/Valet/SecureEnclaveAccessControl.swift +++ b/Sources/Valet/SecureEnclaveAccessControl.swift @@ -18,7 +18,7 @@ import Foundation @objc(VALSecureEnclaveAccessControl) -public enum SecureEnclaveAccessControl: Int, CustomStringConvertible, Equatable { +public enum SecureEnclaveAccessControl: Int, CustomStringConvertible, Equatable, Sendable { /// Access to keychain elements requires user presence verification via Touch ID, Face ID, or device Passcode. On macOS 10.15 and later, this element may also be accessed via a prompt on a paired watch. Keychain elements are still accessible by Touch ID even if fingers are added or removed. Touch ID does not have to be available or enrolled. case userPresence = 1 diff --git a/Sources/Valet/SecureEnclaveValet.swift b/Sources/Valet/SecureEnclaveValet.swift index db91bd0b..019449dc 100644 --- a/Sources/Valet/SecureEnclaveValet.swift +++ b/Sources/Valet/SecureEnclaveValet.swift @@ -19,7 +19,7 @@ import Foundation /// Reads and writes keychain elements that are stored on the Secure Enclave using Accessibility attribute `.whenPasscodeSetThisDeviceOnly`. Accessing these keychain elements will require the user to confirm their presence via Touch ID, Face ID, or passcode entry. If no passcode is set on the device, accessing the keychain via a `SecureEnclaveValet` will fail. Data is removed from the Secure Enclave when the user removes a passcode from the device. @objc(VALSecureEnclaveValet) -public final class SecureEnclaveValet: NSObject { +public final class SecureEnclaveValet: NSObject, Sendable { // MARK: Public Class Methods @@ -92,7 +92,6 @@ public final class SecureEnclaveValet: NSObject { self.identifier = identifier self.service = service self.accessControl = accessControl - baseKeychainQuery = service.generateBaseQuery() } // MARK: Hashable @@ -232,7 +231,9 @@ public final class SecureEnclaveValet: NSObject { // MARK: Private Properties private let lock = NSLock() - private let baseKeychainQuery: [String : AnyHashable] + private var baseKeychainQuery: [String : AnyHashable] { + service.generateBaseQuery() + } } diff --git a/Sources/Valet/SharedGroupIdentifier.swift b/Sources/Valet/SharedGroupIdentifier.swift index 175b9895..d73aa804 100644 --- a/Sources/Valet/SharedGroupIdentifier.swift +++ b/Sources/Valet/SharedGroupIdentifier.swift @@ -17,7 +17,7 @@ import Foundation -public struct SharedGroupIdentifier: CustomStringConvertible { +public struct SharedGroupIdentifier: CustomStringConvertible, Sendable { // MARK: Initialization diff --git a/Sources/Valet/SinglePromptSecureEnclaveValet.swift b/Sources/Valet/SinglePromptSecureEnclaveValet.swift index 6f06e734..19eddd55 100644 --- a/Sources/Valet/SinglePromptSecureEnclaveValet.swift +++ b/Sources/Valet/SinglePromptSecureEnclaveValet.swift @@ -25,8 +25,8 @@ import Foundation /// Reads and writes keychain elements that are stored on the Secure Enclave using Accessibility attribute `.whenPasscodeSetThisDeviceOnly`. The first access of these keychain elements will require the user to confirm their presence via Touch ID, Face ID, or passcode entry. If no passcode is set on the device, accessing the keychain via a `SinglePromptSecureEnclaveValet` will fail. Data is removed from the Secure Enclave when the user removes a passcode from the device. @objc(VALSinglePromptSecureEnclaveValet) @available(watchOS 3, *) -public final class SinglePromptSecureEnclaveValet: NSObject { - +public final class SinglePromptSecureEnclaveValet: NSObject, @unchecked Sendable { + // MARK: Public Class Methods /// - Parameters: diff --git a/Sources/Valet/Valet.swift b/Sources/Valet/Valet.swift index 3ac2566c..a7db3099 100644 --- a/Sources/Valet/Valet.swift +++ b/Sources/Valet/Valet.swift @@ -19,7 +19,7 @@ import Foundation /// Reads and writes keychain elements. @objc(VALValet) -public final class Valet: NSObject { +public final class Valet: NSObject, Sendable { // MARK: Public Class Methods @@ -198,7 +198,6 @@ public final class Valet: NSObject { self.configuration = configuration self.service = service accessibility = configuration.accessibility - baseKeychainQuery = service.generateBaseQuery() } #if os(macOS) @@ -483,7 +482,9 @@ public final class Valet: NSObject { internal let configuration: Configuration internal let service: Service - internal let baseKeychainQuery: [String : AnyHashable] + internal var baseKeychainQuery: [String : AnyHashable] { + service.generateBaseQuery() + } // MARK: Private Properties