I'm banging my head trying to generate a private-public key pair with kSecAttrTokenIDSecureEnclave
so that the private key is generated in the secure enclave.
Where is kSecAttrTokenIDSecureEnclave
documented? Below is my code, which fails with status code -50.
- (void)generateKeyPair {
const UInt8 publicTagString[] = "public";
const UInt8 privateTagString[] = "private";
publicTag = CFDataCreate(0, publicTagString, sizeof(publicTagString));
privateTag = CFDataCreate(0, privateTagString, sizeof(privateTagString));
CFMutableDictionaryRef publicAttr = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
CFDictionaryAddValue(publicAttr, kSecAttrApplicationTag, publicTag);
// CFDictionaryAddValue(publicAttr, kSecAttrIsPermanent, kCFBooleanTrue);
CFDictionaryAddValue(publicAttr, kSecAttrCanEncrypt, kCFBooleanFalse);
CFDictionaryAddValue(publicAttr, kSecAttrCanDecrypt, kCFBooleanFalse);
CFDictionaryAddValue(publicAttr, kSecAttrCanDerive, kCFBooleanFalse);
CFDictionaryAddValue(publicAttr, kSecAttrCanSign, kCFBooleanFalse);
CFDictionaryAddValue(publicAttr, kSecAttrCanVerify, kCFBooleanTrue);
CFDictionaryAddValue(publicAttr, kSecAttrCanUnwrap, kCFBooleanFalse);
CFMutableDictionaryRef privateAttr = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
CFDictionaryAddValue(privateAttr, kSecAttrApplicationTag, privateTag);
// CFDictionaryAddValue(privateAttr, kSecAttrIsPermanent, kCFBooleanTrue);
CFDictionaryAddValue(privateAttr, kSecAttrCanEncrypt, kCFBooleanFalse);
CFDictionaryAddValue(privateAttr, kSecAttrCanDecrypt, kCFBooleanFalse);
CFDictionaryAddValue(privateAttr, kSecAttrCanDerive, kCFBooleanFalse);
CFDictionaryAddValue(privateAttr, kSecAttrCanSign, kCFBooleanTrue);
CFDictionaryAddValue(privateAttr, kSecAttrCanVerify, kCFBooleanFalse);
CFDictionaryAddValue(privateAttr, kSecAttrCanUnwrap, kCFBooleanFalse);
const void* parameterKeys[] = {
kSecAttrKeyType,
kSecAttrKeySizeInBits,
kSecAttrTokenID,
kSecPublicKeyAttrs,
kSecPrivateKeyAttrs
};
int intKeySize = 512;
CFNumberRef keySize = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &intKeySize);
const void* parameterValues[] = {
kSecAttrKeyTypeRSA,
keySize,
kSecAttrTokenIDSecureEnclave,
publicAttr,
privateAttr
};
CFDictionaryRef parameters = CFDictionaryCreate(
kCFAllocatorDefault,
parameterKeys,
parameterValues,
5, // ??? Make this programmatic
NULL,
NULL
);
OSStatus status = SecKeyGeneratePair(parameters, &publicKey, &privateKey);
if(status != errSecSuccess) {
[self logError:[NSString stringWithFormat:@"SecKeyGeneratePair status %d", (int)status] :nil];
return;
}
}
The error you are getting, -50
, indicates a parameter error. A parameter you are passing to the function is incorrect or inappropriate for the operation. If you look at the SecItem
header or the you will see:
kSecAttrTokenIDSecureEnclave Specifies well-known identifier of the token implemented using device's Secure Enclave. The only keychain items supported by the Secure Enclave token are 256-bit elliptic curve keys (kSecAttrKeyTypeEC). Keys must be generated on the secure enclave using SecKeyGenerateKeyPair call with kSecAttrTokenID set to kSecAttrTokenIDSecureEnclave in the parameters dictionary, it is not possible to import pregenerated keys to kSecAttrTokenIDSecureEnclave token.
RSA is not currently a supported cipher when generating a private key in the secure enclave. Switch to a 256 bit EC key.
This was covered in the WWDC 2015 session 706 Security And Your Apps. The Apple sample project "KeychainTouchID" shows the correct parameters for generating and using a key using the secure enclave.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With