Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically Checking if a Passcode Lock is Set

Tags:

Since my app would be dealing with sensitive data of the user, I would like to know if there is a way I can check from my app whether there is a Passcode Lock set in iOS.

The reason I need to check this is because say if the user has in the app some information and then keeps it on the table and goes out for a couple of minutes. The iPad/iPhone by default, goes to standby mode. If a passcode lock had been set, only when the correct passcode is entered, would anyone be able to use the ipad. This would provide an additional security measure to prevent any passerby to view the sensitive data from the app.

So basically, I would like my app to check whether the passcode lock is set and if not prompt the user to do it.

Is this possible?

like image 805
learner2010 Avatar asked May 31 '11 18:05

learner2010


3 Answers

With iOS 8, there is now a way to check that the user has a passcode set. This code will crash on iOS 7.

Objective-C:

-(BOOL) deviceHasPasscode {
    NSData* secret = [@"Device has passcode set?" dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *attributes = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"LocalDeviceServices",  (__bridge id)kSecAttrAccount: @"NoAccount", (__bridge id)kSecValueData: secret, (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly };

    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
    if (status == errSecSuccess) { // item added okay, passcode has been set            
        SecItemDelete((__bridge CFDictionaryRef)attributes);

        return true;
    }

    return false;
}

Swift:

func deviceHasPasscode() -> Bool {
    let secret = "Device has passcode set?".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    let attributes = [kSecClass as String:kSecClassGenericPassword, kSecAttrService as String:"LocalDeviceServices", kSecAttrAccount as String:"NoAccount", kSecValueData as String:secret!, kSecAttrAccessible as String:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly]

    let status = SecItemAdd(attributes, nil)
    if status == 0 {
        SecItemDelete(attributes)
        return true
    }

    return false
}
like image 76
Aaron Bratcher Avatar answered Oct 07 '22 22:10

Aaron Bratcher


Since iOS 9, there is a flag LAPolicyDeviceOwnerAuthentication in LocalAuthentication framework.

+ (BOOL)isPasscodeEnabled
{
    NSError *error = nil;
    LAContext *context = [[LAContext alloc] init];

    BOOL passcodeEnabled = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];

    if(passcodeEnabled) {
        NSLog(@"Passcode enabled.");
        return YES;
    }

    NSLog(@"Passcode NOT enabled: %@", error.localizedDescription);
    return NO;
}

Since iOS 8 there have been another flag for checking if TouchID is enabled:

+ (BOOL)isTouchIdEnabled
{
    NSError *error = nil;
    LAContext *context = [[LAContext alloc] init];

    BOOL touchIDEnabled = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];

    if(touchIDEnabled) {
        NSLog(@"TouchID enabled.");
        return YES;
    }

    NSLog(@"TouchID NOT enabled: %@", error.localizedDescription);
    return NO;
}
like image 45
Heikki Hautala Avatar answered Oct 07 '22 21:10

Heikki Hautala


Take a look at the File Protection section on The Application Runtime Environment. File protection requires the user to have passcode lock setting enabled and a valid passcode set. If you your application writes/creates and file, use the NSDataWritingFileProtectionComplete option. If your application doesn't use any files, then create a dummy file and enable the protection.

like image 40
Black Frog Avatar answered Oct 07 '22 21:10

Black Frog