iOS - SecKeyCreateSignature iOS 13 CryptoTokenKit code = -2

Hi,


I am using SecKeyCreateSignature to sign the data. It works for most users but for some iOS 13 users we are getting following error:


Error Domain=CryptoTokenKit Code=-2 "Failed to get externalizedContext from LAContext" UserInfo={NSLocalizedDescription=Failed to get externalizedContext from LAContext}


The error is only happening on iOS 13 devices and happens intermittently. I have copied the relevant code below:


-(NSData*) signData:(NSString*) textData withAuthenticator:(SANDKSecurityDeviceAuthenticator) auth andUID:(NSString*) userID error:(NSInteger*) errorCode {
 
  Authenticator *authenticator = [AuthenticatorManager getAuthenticator:auth];
 
  // Get private key selected for signing
  NSString *alias = [NSString stringWithFormat:@"%@%@", userID,authenticator.type];
 
  SecKeyRef privateKey = (SecKeyRef)[authenticator getPrivateKeyRef:alias];
 
  // Generate digest
  NSData* dataToSign =  [textData dataUsingEncoding:NSUTF8StringEncoding];
  NSData* hashedDataToSign = [HashUtils hasData:dataToSign withAlgorithm:SANDKSecurityDevice_SHA_256 andError:NULL];
 
  NSData* signature = nil;
  CFErrorRef error = NULL;
  signature = (NSData*) CFBridgingRelease(SecKeyCreateSignature(privateKey,
                                                                kSecKeyAlgorithmECDSASignatureDigestX962SHA256,
                                                                (__bridge CFDataRef)hashedDataToSign,
                                                                &error));
  if (!signature) {
    NSError *err = CFBridgingRelease(error);
    *errorCode = err.code;
  }
  return signature;
}

I would appreciate if someone can provide any insight on the issue.


Thanks.

Replies

This error means that you’re running out of

LAContext
objects. Due to the way that the Security framework talks to the Secure Enclave, there’s a relative low limit here.

I have a couple of recommendations:

  • Check your code to ensure that you’re not holding on to key objects (

    SecKey
    ) for a long time. A key object that represents an SE key consumes an
    LAContext
    [1], and thus keeping a lot of key objects around could run you out of those resources.

    I recommend that you rely on the keychain to store your SE keys and then only create a key object for that key when you need to use it. This reduces the above-mentioned resource usage and has other benefits (for example, it limits your exposure to any recoverable SE infrastructure errors).

  • Use Instruments to check your code for leaks of either

    SecKey
    or
    LAContext
    objects.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] The mechanics of this vary by OS; iOS 13 is supposed to make more efficient use of these resources.

I got the same error, and what helped me is viewing the CTK log with log stream --process setoken. This showed me the internal error the CryptoTokenKit got in initialisation, which helped me debugging the issue.