Local Authentication par Pierre-Alban Toth

23
Local Authentication & Keychain CocoaHeads Paris - 09/04/15

Transcript of Local Authentication par Pierre-Alban Toth

Local Authentication & Keychain

CocoaHeads Paris - 09/04/15

#DIGITALE

Touch ID

• iOS 7

• iPhone 5s / iPad Air 2 / iPad Mini 3

• Unlock device (Passcode)

• iTunes/AppStore purchases, Pay

• Passcode at restart / after 48hrs idle

• 5 fingerprints max.

• No iCloud/Backup sync

• SECURE ENCLAVE

Secure ?

• Native encryption

• On top of the chip (Isolation == Trust)

• Cryptographic Operations Center

• Touch ID Operations Center

• Touch ID security APIs \o/

‣ LAContext (new)

‣ secItem (updated)

• App needs to be foreground

• Simplest Touch ID implementation

• Yes/No answer

• No Keychain interaction

• Parental check, unlock app feature…

LAContext

• Make sure Touch ID is available

• canEvaluatePolicy:error:

LAContext

#import <LocalAuthentication/LocalAuthentication.h>

LAContext *context = [LAContext new];

NSError *error; if([context canEvaluatePolicy: LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) { // Touch ID authentication available }

• Ask for an access

• evaluatePolicy:localizedReason:reply:

LAContext

[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"CocoaHeads sessions access" reply:^(BOOL success, NSError *authenticationError) { if (success) { // Access granted ! } else { // Access refused. See authenticationError }}];

LAContext

• LocalAuthentication errors

‣ LAErrorUserCancel

‣ LAErrorUserSystemCancel

‣ LAErrorUserFallback…

LAContext

• Keychain item access with Passcode

• Touch ID used when available

• Acknowledge access to sensitive data

‣ password, token, credit card…

secItem

• Keychain 101 : Store an item

• Simple ? :)

secItem

NSData *secretKey = [self secretKey]; NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"CocoaHeads", (__bridge id)kSecAttrAccount: @“admin", (__bridge id)kSecValueData: secretKey, (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAlways};

OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, nil);

• New attribute : kSecAttrAccessControl

• kSecAttrAccessible + kSecAccessControlUserPresence

secItem

NSError *error;

SecAccessControlRef accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAccessControlUserPresence, &error);

• kSecAttrAccessible…

• …WhenPasscodeSetThisDeviceOnly

‣ No Passcode == item is erased

• …WhenUnlockedThisDeviceOnly

‣ No Passcode == item not accesible

secItem

• All together

secItem

NSData *secretKey = [self secretKey]; NSError *error;

SecAccessControlRef accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAccessControlUserPresence, &error);

NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"CocoaHeads", (__bridge id)kSecAttrAccount: @"admin", (__bridge id)kSecValueData: secretKey, (__bridge id)kSecAttrAccessControl: (__bridge id)accessControl};

OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, nil);

• Keychain 101 : Read an item

secItem

NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"CocoaHeads", (__bridge id)kSecAttrAccount: @"admin", (__bridge id)kSecReturnData: @YES};

CFTypeRef dataTypeRef = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef);

NSData *secretKey = CFBridgingRelease(dataTypeRef);

• Read an item with ACLs

secItem

NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"CocoaHeads", (__bridge id)kSecAttrAccount: @"admin", (__bridge id)kSecReturnData: @YES, (__bridge id)kSecUseOperationPrompt: @"CocoaHeads sessions access"};

dispatch_async(dispatch_get_main_queue(), ^{ CFTypeRef dataTypeRef = NULL; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataTypeRef); NSData * secretKey = CFBridgingRelease(dataTypeRef); });

APIs comparisonLAContext secItem

Simplicity

Passcode fallback

Store data

Detect Touch ID

Real life use cases

• To learn more… ‣ WWDC 2014 - Session 711 ‣ KeychainTouchID sample code

• Pierre-Alban Toth (@patoth) ‣ iOS dev @ Capitaine Train ‣ https://www.capitainetrain.com/jobs

Thank you !

Q&A