How to detect in iOS wether a user has secured device? [duplicate] - ios

I know the Touch ID on the iPhone 5S cannot be consumed by any other apps through the SDK, but I wanted to see if it was possible for an app to at least see if the Touch ID is enabled on the device. This can act as an additional security factor for an app to see if the Touch ID has been enabled on an iPhone 5S. I know MDM products can do this, is there a special API an app would need to use to determine this information?

The method you are looking for is LAContext's canEvaluatePolicy:error:.
It will return NO in the following cases :
Touch ID is not available on the device.
A passcode is not set on the device.
Touch ID has no enrolled fingers.
More infos here : Local Authentication Framework Reference
- (BOOL) isTouchIDAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
NSLog(#"%#", [authError localizedDescription]);
return NO;
}
return YES;
}

Since TouchID is only appeared in iPhone 5s, you can use the following code to determine hardware model:
- (NSString *) checkiPhone5s {
// Gets a string with the device model
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
free(machine);
if ([platform isEqualToString:#"iPhone6,1"]) {
// it is iPhone 5s !!!
}
}
Note that iPhone 5s may have new model, so that the platform string may be "iPhone6,2" , "iPhone6,3" in the future.
Alternatively, UIDeviceHardware class may provide useful information if that class is updated for iPhone 5s. Currently it shows "Unknown iPhone" for iPhone 5.

I check this by below stages.
iOS < 8.0:
self.touchIdAvailable = NO;
Then check if device is touchId available.
- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError **)error
if ("canEvaluatePolicy return YES"):{
self.touchIdAvailable = YES;
self.osTouchIdStatus = TouchIdSetOK;
}
check why this device is not touchID enable in error block
case LAErrorPasscodeNotSet:
case LAErrorTouchIDNotEnrolled:
self.touchIdAvailable = YES;
self.osTouchIdStatus = TouchIdNotSet;
break;
default:
self.touchIdAvailable = NO;
self.osTouchIdStatus = TouchIdNotSupported;
break;

There doesn't appear to be anything mentioned in the developer documentation about detecting if Touch ID is present on the device. There most definitely is a private API that can give you that information but using it would be grounds for Apple not approving your app.

Related

Detect if Secure Enclave is available on current device

Is there a certain way to detect if storing in Secure Enclave is available on current device?
Here is another solution:
Device.h
#import <Foundation/Foundation.h>
#interface Device : NSObject
+(BOOL) hasSecureEnclave;
+(BOOL) isSimulator;
+(BOOL) hasBiometrics;
#end
Device.m
#import "Device.h"
#import <LocalAuthentication/LocalAuthentication.h>
#implementation Device
//To check that device has secure enclave or not
+(BOOL) hasSecureEnclave {
NSLog(#"IS Simulator : %d", [Device isSimulator]);
return [Device hasBiometrics] && ![Device isSimulator] ;
}
//To Check that this is this simulator
+(BOOL) isSimulator {
return TARGET_OS_SIMULATOR == 1;
}
//Check that this device has Biometrics features available
+(BOOL) hasBiometrics {
//Local Authentication Context
LAContext *localAuthContext = [[LAContext alloc] init];
NSError *error = nil;
/// Policies can have certain requirements which, when not satisfied, would always cause
/// the policy evaluation to fail - e.g. a passcode set, a fingerprint
/// enrolled with Touch ID or a face set up with Face ID. This method allows easy checking
/// for such conditions.
BOOL isValidPolicy = [localAuthContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
if (isValidPolicy) {
if (#available(ios 11.0, *)){
if (error.code != kLAErrorBiometryNotAvailable){
isValidPolicy = true;
} else{
isValidPolicy = false;
}
}else{
if (error.code != kLAErrorTouchIDNotAvailable){
isValidPolicy = true;
}else{
isValidPolicy = false;
}
}
return isValidPolicy;
}
return isValidPolicy;
}
#end
If you want solution in Swift 4, then refer this link.
Solution in Swift 4
For a developer, there is exactly one thing the Secure Enclave can do: Create and hold private keys for elliptic curve cryptography, and encrypt or decrypt data using these keys. On iOS 9, the attributes describing elliptic curve algorithms are not there - therefore, if you are running iOS 9, then you can assume the Secure Enclave is not there, because you cannot use it.
On iOS 10 and above, there is just one way to decide guaranteed correctly if the Secure Enclave is present: Create an elliptic curve encryption key in the Secure Enclave, as described by Apple's documentation. If this fails, and the error has a code of -4 = errSecUnimplemented, then there is no Secure Enclave.
If you insist on checking a list of devices, you only need the devices that are documented as having no Secure Enclave but are able to run iOS 10, because on iOS 9 it is never available.
I did it myself:
+ (BOOL) isDeviceOkForSecureEnclave
{
double OSVersionNumber = floor(NSFoundationVersionNumber);
UIUserInterfaceIdiom deviceType = [[UIDevice currentDevice] userInterfaceIdiom];
BOOL isOSForSecureEnclave = OSVersionNumber > NSFoundationVersionNumber_iOS_8_4 ? YES:NO;
//iOS 9 and up are ready for SE
BOOL isDeviceModelForSecureEnclave = NO;
switch (deviceType) {
case UIUserInterfaceIdiomPhone:
//iPhone
isDeviceModelForSecureEnclave = [self isPhoneForSE];
break;
case UIUserInterfaceIdiomPad:
//iPad
isDeviceModelForSecureEnclave = [self isPadForSE];
break;
default:
isDeviceModelForSecureEnclave = false;
break;
}
return (isOSForSecureEnclave && isDeviceModelForSecureEnclave) ? YES:NO;
}
/**
The arrays are models that we know not having SE in hardware, so if the current device is on the list it means it dosent have SE
*/
+ (BOOL) isPhoneForSE
{
NSString *thisPlatform = [self platform];
NSArray * oldModels = [NSArray arrayWithObjects:
#"x86_64",
#"iPhone1,1",
#"iPhone1,2",
#"iPhone2,1",
#"iPhone3,1",
#"iPhone3,3",
#"iPhone4,1",
#"iPhone5,1",
#"iPhone5,2",
#"iPhone5,3",
#"iPhone5,4", nil];
BOOL isInList = [oldModels containsObject: thisPlatform];
return !isInList;
}
+ (BOOL) isPadForSE
{
//iPad Mini 2 is the earliest with SE // "iPad4,4"
NSString *thisPlatform = [self platform];
NSArray * oldModels = [NSArray arrayWithObjects:
#"x86_64",
#"#iPad",
#"#iPad1,0",
#"#iPad1,1",
#"iPad2,1",
#"iPad2,2",
#"iPad2,3",
#"iPad2,4",
#"iPad2,5",
#"iPad2,6",
#"iPad2,7",
#"iPad3,1",
#"iPad3,2",
#"iPad3,3",
#"iPad3,4",
#"iPad3,5",
#"iPad3,6",nil];
BOOL isInList = [oldModels containsObject: thisPlatform];
return !isInList;
}
+ (NSString *)platform
{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithUTF8String:machine];
free(machine);
return platform;
}
#end
There is a more straightforward way to check if Secure Enclave is available using the CryptoKit framework. The following approach is iOS 13+ and Swift only.
import CryptoKit
if TARGET_OS_SIMULATOR == 0 && SecureEnclave.isAvailable {
// use Secure Enclave
}
Additional check for Simulator is needed since SecureEnclave.isAvailable returns true running on a Simulator (checked on iOS 14.4).

Is it possible to get the value of USE TOUCHID FOR iPhone unlock in default settings

Is it possible to Access Default settings > TouchID & Passcode > iPhone Unlock toggle value.
As far as I know, it's not possible.
NO. there is no way to know if user has opted for using TouchID for Unlocking phone.
There is method canEvaluatePolicy: error:
But this tells you if TouchId is configured / Enabled or Not Configured/Not Enabled. If you want to check for Availability of touch Id for your app, you can use canEvaluatePolicy: error:
-(void)canEvaluatePolicy {
LAContext *context = [[LAContext alloc] init];
__block NSString *message;
NSError *error;
BOOL success;
// test if we can evaluate the policy, this test will tell us if Touch ID is available and enrolled
success = [context canEvaluatePolicy: <BR>LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
if (success) {
message = [NSString stringWithFormat:#"Touch ID is available"];
}
else {
message = [NSString stringWithFormat:#"Touch ID is not available"];
}
[super printMessage:message inTextView:self.textView];
}
you can find fully working code from developer.apple.com website:
https://developer.apple.com/library/content/samplecode/KeychainTouchID/Listings/KeychainTouchID_AAPLLocalAuthenticationTestsViewController_m.html
I don't know why you would want to know that however, you can always check if the device supports TouchID and if it has been setup by the user. You do this by creating an LAContext (Local Authentication Context) and calling the function canEvaluatePolicy:error:. That is all I think you can find out about the TouchID settings on a given iPhone through an app. I hope this helps a little :)

How to call and get the current device version?

I am using this code to identify the iPhone Device. Can anyone explain to me how to call and get the current device version?
How to call one of these methods?
+ (DeviceHardwareSpecificPlatform)specificPlatform;
+ (DeviceHardwareGeneralPlatform)generalPlatform;
+ (DeviceHardwarePlatformType)platformType;
+ (NSString *)platformString;
I am calling them from another class.
According to the link you gave, there is a usage.txt file
UIDeviceHardware *h=[[UIDeviceHardware alloc] init];
[self setDeviceModel:[h platformString]];
[h release];
Actually, it's an old piece of code with manually managed memory. With ARC, you may want to use:
UIDeviceHardware *h=[[UIDeviceHardware alloc] init];
[self setDeviceModel:[h platformString]];
The UIDevice class provides all the information of the device on which your app is running.
UIDevice *deviceInfo = [UIDevice currentDevice];
NSLog(#“OS running on device: %#”, deviceInfo.systemName);
// OS running on device: iPhone OS
NSLog(#“OS Version running on device: %#”, deviceInfo.systemVersion);
//OS Version running on device: 7.1
NSLog(#“Device model: %#”, deviceInfo.model);
// Device model: iPod touch
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *deviceModelVersion = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
free(machine);
NSLog(#"Device model version: %#", deviceModelVersion);
//Device model version: iPhone4, 1
NSLog(#“Device name: %#”, deviceInfo.name);
//Device name: my iPod

See if Touch ID is enabled on iPhone 5s

I know the Touch ID on the iPhone 5S cannot be consumed by any other apps through the SDK, but I wanted to see if it was possible for an app to at least see if the Touch ID is enabled on the device. This can act as an additional security factor for an app to see if the Touch ID has been enabled on an iPhone 5S. I know MDM products can do this, is there a special API an app would need to use to determine this information?
The method you are looking for is LAContext's canEvaluatePolicy:error:.
It will return NO in the following cases :
Touch ID is not available on the device.
A passcode is not set on the device.
Touch ID has no enrolled fingers.
More infos here : Local Authentication Framework Reference
- (BOOL) isTouchIDAvailable {
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
if (![myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
NSLog(#"%#", [authError localizedDescription]);
return NO;
}
return YES;
}
Since TouchID is only appeared in iPhone 5s, you can use the following code to determine hardware model:
- (NSString *) checkiPhone5s {
// Gets a string with the device model
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *machine = malloc(size);
sysctlbyname("hw.machine", machine, &size, NULL, 0);
NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];
free(machine);
if ([platform isEqualToString:#"iPhone6,1"]) {
// it is iPhone 5s !!!
}
}
Note that iPhone 5s may have new model, so that the platform string may be "iPhone6,2" , "iPhone6,3" in the future.
Alternatively, UIDeviceHardware class may provide useful information if that class is updated for iPhone 5s. Currently it shows "Unknown iPhone" for iPhone 5.
I check this by below stages.
iOS < 8.0:
self.touchIdAvailable = NO;
Then check if device is touchId available.
- (BOOL)canEvaluatePolicy:(LAPolicy)policy error:(NSError **)error
if ("canEvaluatePolicy return YES"):{
self.touchIdAvailable = YES;
self.osTouchIdStatus = TouchIdSetOK;
}
check why this device is not touchID enable in error block
case LAErrorPasscodeNotSet:
case LAErrorTouchIDNotEnrolled:
self.touchIdAvailable = YES;
self.osTouchIdStatus = TouchIdNotSet;
break;
default:
self.touchIdAvailable = NO;
self.osTouchIdStatus = TouchIdNotSupported;
break;
There doesn't appear to be anything mentioned in the developer documentation about detecting if Touch ID is present on the device. There most definitely is a private API that can give you that information but using it would be grounds for Apple not approving your app.

How to detect if M7 is present, a.k.a it is an iPhone 5S or newer?

Trying to find a way to detect M7 being present.
Is it pointless to query CMStepCounter or CMMotionActivity class if M7 is not present? My guess is that on non M7 models having iOS 7.0, these classes get data but not that efficiently & use a lot more battery.
A crude way would be:
struct utsname systemInfo;
uname(&systemInfo);
model = [[NSString alloc] initWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
version = [[NSString alloc] initWithString:[[UIDevice currentDevice] systemVersion]];
if ([model compare:#"iPhone6,1"]) {
}
Use the APIs that Apple provides:
if ([CMStepCounter isStepCountingAvailable]) {
// The device supports step counting
} else {
// The device does not support step counting
}
if ([CMMotionActivityManager isActivityAvailable]) {
// You can use CMMotionActivity
} else {
// Nope, not supported
}
Of course this API is only on iOS 7 or later. So if you need to support iOS 5 or 6 then you need to wrap this code in a check for the CMStepCounter class too.

Resources