Programmatically Checking If a Passcode Lock Is Set

Programmatically Checking if a Passcode Lock is Set

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.

Programatically Checking if a Passcode Lock is Set on iOS 7

No You cant.From the documentation:

kSecAttrAccessibleAfterFirstUnlock

The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.

After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute migrate to a new device when using encrypted backups.

Available in iOS 4.0 and later.

kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly

The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.

After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.

Available in iOS 4.0 and later.

kSecAttrAccessibleAlways

The data in the keychain item can always be accessed regardless of whether the device is locked.

This is not recommended for application use. Items with this attribute migrate to a new device when using encrypted backups.

Available in iOS 4.0 and later.

kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly

The data in the keychain can only be accessed when the device is unlocked. Only available if a passcode is set on the device.

This is recommended for items that only need to be accessible while the application is in the foreground. Items with this attribute never migrate to a new device. After a backup is restored to a new device, these items are missing. No items can be stored in this class on devices without a passcode. Disabling the device passcode causes all items in this class to be deleted.

Available in iOS 8.0 and later.

kSecAttrAccessibleAlwaysThisDeviceOnly

The data in the keychain item can always be accessed regardless of whether the device is locked.

This is not recommended for application use. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.

Available in iOS 4.0 and later.

kSecAttrAccessibleWhenUnlocked

The data in the keychain item can be accessed only while the device is unlocked by the user.

This is recommended for items that need to be accessible only while the application is in the foreground. Items with this attribute migrate to a new device when using encrypted backups.

This is the default value for keychain items added without explicitly setting an accessibility constant.

Available in iOS 4.0 and later.

kSecAttrAccessibleWhenUnlockedThisDeviceOnly

The data in the keychain item can be accessed only while the device is unlocked by the user.

This is recommended for items that need to be accessible only while the application is in the foreground. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.

Available in iOS 4.0 and later.

Programmatically detect whether iOS passcode is enabled or not

Update

As of iOS 9, you can achieve this using the LocalAuthentication.framework. If targeting iOS 9+ read the comments here or look at this answer.

If you still need to target iOS 8 then continue reading :)


Starting in iOS8, you can!

I've put together a simple category to easily check the status: https://github.com/liamnichols/UIDevice-PasscodeStatus

How it Works

This category works by using the new accessControl features added to the Security.Framework in iOS 8.
It attempts to add an item to the keychain using the kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly protection level.

The documentation states the following:

Item data can only be accessed while the device is unlocked. This class is only
available if a passcode is set on the device. This is recommended for
items that only need to be accessible while the application is in the
foreground. Items with this attribute will never migrate to a new
device, so after a backup is restored to a new device, these items
will be missing. No items can be stored in this class on devices
without a passcode.
Disabling the device passcode will cause all
items in this class to be deleted.

Because of this, an error is returned when you attempt to add or read an item in the keychain with this level of accessControl. If we see this error, the passcodeStatus returns as LNPasscodeStatusDisabled.
If we can successfully read or write to the keychain with this level of accessControl then we return LNPasscodeStatusEnabled.

If the device is unsupported or an unrelated error with the keychain is returned, we return LNPasscodeStatusUnknown.

Can I check whether the user has set a passcode?

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
}


Related Topics



Leave a reply



Submit