Search code examples
iosobjective-ckeychainsecurity.framework

How to use Secure Enclave without TouchID and Passcode?


To generate key pair I am using Secure Enclave (kSecAttrTokenIDSecureEnclave). When trying to access generated key pair, iOS system, asks for TouchID. Below is code snapshot how I am generating and accessing key pair.

Is here a way to setup properties/attributes, that Secure Enclave functionality will be able to use without TouchID and Passcode?

Generate key pair:

SecAccessControlRef sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                                                kSecAttrAccessibleWhenUnlocked,
                                                kSecAccessControlUserPresence | kSecAccessControlPrivateKeyUsage, &error);

    NSDictionary *parameters = @{
        (__bridge id)kSecAttrTokenID: (__bridge id)kSecAttrTokenIDSecureEnclave,
        (__bridge id)kSecAttrKeyType: (__bridge id)kSecAttrKeyTypeEC,
        (__bridge id)kSecAttrKeySizeInBits: @256,
        (__bridge id)kSecPrivateKeyAttrs: @{
            (__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacObject,
            (__bridge id)kSecAttrIsPermanent: @YES,
            (__bridge id)kSecAttrLabel: @“SecKey”,
        },
    };
SStatus status = SecKeyGeneratePair((__bridge CFDictionaryRef)parameters, &publicKey, &privateKey);

Access key pair:

    NSDictionary *query = @{
        (__bridge id)kSecClass: (__bridge id)kSecClassKey,
        (__bridge id)kSecAttrKeyClass: (__bridge id)kSecAttrKeyClassPrivate,
        (__bridge id)kSecAttrLabel: @"SecKey",
        (__bridge id)kSecReturnRef: @YES
    };
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&privateKey);

Solution

  • This code is taken form Apple examples KeychainTouchID. By removing kSecAccessControlTouchIDAny it is possible to generate private key inside secure enclave and later use it without entering a passcode.

    SecAccessControlRef sacObject;
    
    // Should be the secret invalidated when passcode is removed? If not then use `kSecAttrAccessibleWhenUnlocked`.
    sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                                                kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
                                                /*kSecAccessControlTouchIDAny |*/ kSecAccessControlPrivateKeyUsage, &error);
    
    // Create parameters dictionary for key generation.
    NSDictionary *parameters = @{
        (__bridge id)kSecAttrTokenID: (__bridge id)kSecAttrTokenIDSecureEnclave,
        (__bridge id)kSecAttrKeyType: (__bridge id)kSecAttrKeyTypeEC,
        (__bridge id)kSecAttrKeySizeInBits: @256,
        (__bridge id)kSecPrivateKeyAttrs: @{
            (__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacObject,
            (__bridge id)kSecAttrIsPermanent: @YES,
            (__bridge id)kSecAttrLabel: @"my-se-key",
        },
    };