diff --git a/Sources/Packages/Sources/SmartCardSecretKit/Documentation.docc/Documentation.md b/Sources/Packages/Sources/SmartCardSecretKit/Documentation.docc/Documentation.md new file mode 100644 index 0000000..b17f751 --- /dev/null +++ b/Sources/Packages/Sources/SmartCardSecretKit/Documentation.docc/Documentation.md @@ -0,0 +1,3 @@ +# ````SmartCardSecretKit```` + +SmartCardSecretKit contains implementations of SecretKit protocols backed by a Smart Card. diff --git a/Sources/Packages/Sources/SmartCardSecretKit/SmartCard.swift b/Sources/Packages/Sources/SmartCardSecretKit/SmartCard.swift index db0eced..0ec866c 100644 --- a/Sources/Packages/Sources/SmartCardSecretKit/SmartCard.swift +++ b/Sources/Packages/Sources/SmartCardSecretKit/SmartCard.swift @@ -1 +1,2 @@ +/// Namespace for the Smart Card implementations. public enum SmartCard {} diff --git a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift index c8b6478..c5e9109 100644 --- a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift +++ b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift @@ -4,6 +4,7 @@ import SecretKit extension SmartCard { + /// An implementation of Secret backed by a Smart Card. public struct Secret: SecretKit.Secret { public let id: Data diff --git a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift index 57ce661..4ecd6b4 100644 --- a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift +++ b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift @@ -8,6 +8,7 @@ import SecretKit // ie, each token has its own Store. extension SmartCard { + /// An implementation of Store backed by a Smart Card. public class Store: SecretStore { @Published public var isAvailable: Bool = false @@ -17,6 +18,7 @@ extension SmartCard { private let watcher = TKTokenWatcher() private var tokenID: String? + /// Initializes a Store. public init() { tokenID = watcher.nonSecureEnclaveTokens.first watcher.setInsertionHandler { string in @@ -56,7 +58,7 @@ extension SmartCard { kSecAttrTokenID: tokenID, kSecUseAuthenticationContext: context, kSecReturnRef: true - ] as CFDictionary + ] as CFDictionary var untyped: CFTypeRef? let status = SecItemCopyMatching(attributes, &untyped) if status != errSecSuccess { @@ -91,11 +93,14 @@ extension SmartCard { extension SmartCard.Store { + /// Resets the token ID and reloads secrets. + /// - Parameter tokenID: The ID of the token that was removed. private func smartcardRemoved(for tokenID: String? = nil) { self.tokenID = nil reloadSecrets() } + /// Reloads all secrets from the store. private func reloadSecrets() { DispatchQueue.main.async { self.isAvailable = self.tokenID != nil @@ -104,6 +109,7 @@ extension SmartCard.Store { } } + /// Loads all secrets from the store. private func loadSecrets() { guard let tokenID = tokenID else { return } @@ -131,7 +137,7 @@ extension SmartCard.Store { kSecReturnRef: true, kSecMatchLimit: kSecMatchLimitAll, kSecReturnAttributes: true - ] as CFDictionary + ] as CFDictionary var untyped: CFTypeRef? SecItemCopyMatching(attributes, &untyped) guard let typed = untyped as? [[CFString: Any]] else { return } @@ -153,6 +159,7 @@ extension SmartCard.Store { extension TKTokenWatcher { + /// All available tokens, excluding the Secure Enclave. fileprivate var nonSecureEnclaveTokens: [String] { tokenIDs.filter { !$0.contains("setoken") } } @@ -161,11 +168,15 @@ extension TKTokenWatcher { extension SmartCard { + /// A wrapper around an error code reported by a Keychain API. public struct KeychainError: Error { + /// The status code involved. public let statusCode: OSStatus } + /// A signing-related error. public struct SigningError: Error { + /// The underlying error reported by the API, if one was returned. public let error: SecurityError? }