Определите, доступен ли Secure Enclave на текущем устройстве
Есть ли определенный способ определить, доступно ли сохранение в Secure Enclave на текущем устройстве?
4 ответа
Вот еще одно решение:
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
Если вам нужно решение в Swift 4, то перейдите по этой ссылке.
Для разработчика есть только одна вещь, которую может сделать Secure Enclave: создавать и хранить закрытые ключи для криптографии на эллиптических кривых, а также шифровать или дешифровать данные с помощью этих ключей. В iOS 9 атрибуты, описывающие алгоритмы эллиптической кривой, отсутствуют - поэтому, если вы работаете в iOS 9, вы можете предположить, что Secure Enclave там нет, потому что вы не можете его использовать.
В iOS 10 и более поздних версиях существует только один способ правильно определить, присутствует ли Secure Enclave: создайте ключ шифрования эллиптической кривой в Secure Enclave, как описано в документации Apple. Если это не удается, и ошибка имеет код -4 = secErrUnimplemented, тогда Secure Enclave не существует.
Если вы настаиваете на проверке списка устройств, вам нужны только те устройства, для которых задокументировано, что они не имеют безопасного анклава, но могут работать с iOS 10, потому что в iOS 9 оно никогда не доступно.
Я сам это сделал:
+ (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
Существует более простой способ проверить, доступен ли Secure Enclave, используя инфраструктуру CryptoKit. Следующий подход предназначен только для iOS 13+ и Swift.
import CryptoKit
if TARGET_OS_SIMULATOR == 0 && SecureEnclave.isAvailable {
// use Secure Enclave
}
Требуется дополнительная проверка симулятора, т.к.
SecureEnclave.isAvailable
возвращается
true
работает на Симуляторе (проверено на iOS 14.4).