mirror of
https://github.com/maxgoedjen/secretive.git
synced 2024-11-24 14:37:08 +00:00
Smart card working
This commit is contained in:
parent
9ebb14d1cf
commit
610bcfe023
@ -5,7 +5,7 @@ import OSLog
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
let store = SecureEnclave.Store()
|
||||
let store = SmartCard.Store()
|
||||
let notifier = Notifier()
|
||||
lazy var agent: Agent = {
|
||||
Agent(store: store, notifier: notifier)
|
||||
|
@ -4,6 +4,10 @@
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
|
||||
<array>
|
||||
<string>com.apple.ctkd.watcher-client</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.maxgoedjen.Secretive</string>
|
||||
|
@ -12,25 +12,102 @@ extension SmartCard {
|
||||
public let name = NSLocalizedString("Smart Card", comment: "Smart Card")
|
||||
@Published public fileprivate(set) var secrets: [Secret] = []
|
||||
fileprivate let watcher = TKTokenWatcher()
|
||||
fileprivate var id: String?
|
||||
|
||||
public init() {
|
||||
watcher.setInsertionHandler { (string) in
|
||||
id = watcher.tokenIDs.filter { !$0.contains("setoken") }.first
|
||||
watcher.setInsertionHandler { string in
|
||||
guard self.id == nil else { return }
|
||||
guard !string.contains("setoken") else { return }
|
||||
let driver = TKSmartCardTokenDriver()
|
||||
let token = TKToken(tokenDriver: driver, instanceID: string)
|
||||
let session = TKSmartCardTokenSession(token: token)
|
||||
print(session)
|
||||
|
||||
self.id = string
|
||||
self.secrets.removeAll()
|
||||
self.loadSecrets()
|
||||
}
|
||||
print(watcher.tokenIDs)
|
||||
loadSecrets()
|
||||
}
|
||||
|
||||
public func sign(data: Data, with secret: SmartCard.Secret) throws -> Data {
|
||||
fatalError()
|
||||
// MARK: Public API
|
||||
|
||||
public func create(name: String) throws {
|
||||
fatalError("Keys must be created on the smart card.")
|
||||
}
|
||||
|
||||
public func delete(secret: SmartCard.Secret) throws {
|
||||
public func delete(secret: Secret) throws {
|
||||
fatalError("Keys must be deleted on the smart card.")
|
||||
}
|
||||
|
||||
public func sign(data: Data, with secret: SecretType) throws -> Data {
|
||||
guard let id = id else { fatalError() }
|
||||
let attributes = [
|
||||
kSecClass: kSecClassKey,
|
||||
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
|
||||
kSecAttrApplicationLabel: secret.id as CFData,
|
||||
kSecAttrTokenID: id,
|
||||
kSecReturnRef: true
|
||||
] as CFDictionary
|
||||
var untyped: CFTypeRef?
|
||||
let status = SecItemCopyMatching(attributes, &untyped)
|
||||
if status != errSecSuccess {
|
||||
throw KeychainError(statusCode: status)
|
||||
}
|
||||
guard let untypedSafe = untyped else {
|
||||
throw KeychainError(statusCode: errSecSuccess)
|
||||
}
|
||||
let key = untypedSafe as! SecKey
|
||||
var signError: SecurityError?
|
||||
guard let signature = SecKeyCreateSignature(key, .ecdsaSignatureMessageX962SHA256, data as CFData, &signError) else {
|
||||
throw SigningError(error: signError)
|
||||
}
|
||||
return signature as Data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SmartCard.Store {
|
||||
|
||||
fileprivate func loadSecrets() {
|
||||
guard let id = id else { return }
|
||||
let attributes = [
|
||||
kSecClass: kSecClassKey,
|
||||
kSecAttrTokenID: id,
|
||||
kSecReturnRef: true,
|
||||
kSecMatchLimit: kSecMatchLimitAll,
|
||||
kSecReturnAttributes: true
|
||||
] as CFDictionary
|
||||
var untyped: CFTypeRef?
|
||||
let status = SecItemCopyMatching(attributes, &untyped)
|
||||
print(status)
|
||||
guard let typed = untyped as? [[CFString: Any]] else { return }
|
||||
let wrapped: [SmartCard.Secret] = typed.map {
|
||||
let name = $0[kSecAttrLabel] as? String ?? "Unnamed"
|
||||
let id = $0[kSecAttrApplicationLabel] as! Data
|
||||
let publicKeyRef = $0[kSecValueRef] as! SecKey
|
||||
let publicKeySecRef = SecKeyCopyPublicKey(publicKeyRef)!
|
||||
let publicKeyAttributes = SecKeyCopyAttributes(publicKeySecRef) as! [CFString: Any]
|
||||
let publicKey = publicKeyAttributes[kSecValueData] as! Data
|
||||
return SmartCard.Secret(id: id, name: name, publicKey: publicKey)
|
||||
}
|
||||
secrets.append(contentsOf: wrapped)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SmartCard {
|
||||
|
||||
public struct KeychainError: Error {
|
||||
public let statusCode: OSStatus
|
||||
}
|
||||
|
||||
public struct SigningError: Error {
|
||||
public let error: SecurityError?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension SmartCard {
|
||||
|
||||
public typealias SecurityError = Unmanaged<CFError>
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user