This commit is contained in:
Max Goedjen 2021-11-07 12:47:51 -08:00
parent af52c60ebf
commit 80a2bd42a3
No known key found for this signature in database
GPG Key ID: E58C21DD77B9B8E8
2 changed files with 19 additions and 10 deletions

View File

@ -12,7 +12,7 @@ public protocol SecretStore: ObservableObject, Identifiable {
func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> SignedData func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> SignedData
// TODO: MOVE TO SEPARATE PROTOCOL? // TODO: MOVE TO SEPARATE PROTOCOL?
func persistAuthentication(secret: SecretType, forDuration: TimeInterval) throws func persistAuthentication(secret: SecretType, forDuration duration: TimeInterval) throws
} }

View File

@ -98,14 +98,12 @@ extension SecureEnclave {
public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> SignedData { public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> SignedData {
let context: LAContext let context: LAContext
// TODO: RESTORE
if let existing = persistedAuthenticationContexts[secret], existing.valid { if let existing = persistedAuthenticationContexts[secret], existing.valid {
context = existing.context context = existing.context
} else { } else {
let newContext = LAContext() let newContext = LAContext()
newContext.localizedCancelTitle = "Deny" newContext.localizedCancelTitle = "Deny"
// TODO: FIX pendingAuthenticationContext = PersistentAuthenticationContext(secret: secret, context: newContext, expiration: Date(timeIntervalSinceNow: Constants.authenticationPersistenceOptInWindow))
pendingAuthenticationContext = PersistentAuthenticationContext(secret: secret, context: newContext, expiration: Date(timeIntervalSinceNow: 100))
context = newContext context = newContext
} }
context.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\"" context.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\""
@ -136,15 +134,26 @@ extension SecureEnclave {
} }
let signatureDuration = Date().timeIntervalSince(signingStartTime) let signatureDuration = Date().timeIntervalSince(signingStartTime)
// Hack to determine if the user had to authenticate to sign. // Hack to determine if the user had to authenticate to sign.
// Since there's now way to inspect SecAccessControl to determine. // Since there's now way to inspect SecAccessControl to determine (afaict).
let requiredAuthentication = signatureDuration > Constants.unauthenticatedThreshold let requiredAuthentication = signatureDuration > Constants.unauthenticatedThreshold
return SignedData(data: signature as Data, requiredAuthentication: requiredAuthentication) return SignedData(data: signature as Data, requiredAuthentication: requiredAuthentication)
} }
public func persistAuthentication(secret: Secret, forDuration: TimeInterval) throws { public func persistAuthentication(secret: Secret, forDuration duration: TimeInterval) throws {
guard secret == pendingAuthenticationContext?.secret else { throw AuthenticationPersistenceError() } let newContext = LAContext()
persistedAuthenticationContexts[secret] = pendingAuthenticationContext newContext.localizedCancelTitle = "Deny"
newContext.localizedReason = "sign requests without reprompting"
newContext.evaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometricsOrWatch, localizedReason: newContext.localizedReason) { x, y in
print(x, y)
}
guard let pending = pendingAuthenticationContext,
secret == pending.secret,
pending.valid
else { throw AuthenticationPersistenceExpiredError() }
let rewrapped = PersistentAuthenticationContext(secret: secret, context: newContext, expiration: Date(timeIntervalSinceNow: duration))
persistedAuthenticationContexts[secret] = rewrapped
pendingAuthenticationContext = nil pendingAuthenticationContext = nil
} }
@ -215,8 +224,7 @@ extension SecureEnclave {
public let error: SecurityError? public let error: SecurityError?
} }
public struct AuthenticationPersistenceError: Error { public struct AuthenticationPersistenceExpiredError: Error {}
}
} }
@ -232,6 +240,7 @@ extension SecureEnclave {
static let keyTag = "com.maxgoedjen.secretive.secureenclave.key".data(using: .utf8)! as CFData static let keyTag = "com.maxgoedjen.secretive.secureenclave.key".data(using: .utf8)! as CFData
static let keyType = kSecAttrKeyTypeECSECPrimeRandom static let keyType = kSecAttrKeyTypeECSECPrimeRandom
static let unauthenticatedThreshold: TimeInterval = 0.05 static let unauthenticatedThreshold: TimeInterval = 0.05
static let authenticationPersistenceOptInWindow: TimeInterval = 30
} }
} }