in macos/macos.c [143:214]
CFBooleanRef CreateSEKey(
const char* label,
const char* tag,
CFBooleanRef useBiometrics,
CFBooleanRef accessibleWhenUnlockedOnly,
CFDataRef* pubKey,
CFStringRef* errorStr) {
CFErrorRef error = NULL;
CFTypeRef protection = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
SecAccessControlCreateFlags flags = kSecAccessControlPrivateKeyUsage;
if (useBiometrics == kCFBooleanTrue)
flags |= kSecAccessControlUserPresence;
if (accessibleWhenUnlockedOnly == kCFBooleanTrue)
protection = kSecAttrAccessibleWhenUnlockedThisDeviceOnly;
SecAccessControlRef access = SecAccessControlCreateWithFlags(
kCFAllocatorDefault, protection, flags, &error);
if (error) {
*errorStr = CFErrorCopyDescription(error);
CFRelease((CFTypeRef)error);
return kCFBooleanFalse;
}
CFDataRef cfTag = StringToDataRef(tag);
CFStringRef cfLabel = CFStringCreateWithCString(
kCFAllocatorDefault, label, kCFStringEncodingUTF8);
CFMutableDictionaryRef privKeyAttrs = CFDictionaryCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(privKeyAttrs, kSecAttrApplicationTag, cfTag);
CFDictionaryAddValue(privKeyAttrs, kSecAttrAccessControl, access);
CFDictionaryAddValue(privKeyAttrs, kSecAttrIsPermanent, kCFBooleanTrue);
CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(attrs, kSecAttrLabel, cfLabel);
CFDictionaryAddValue(attrs, kSecAttrTokenID, kSecAttrTokenIDSecureEnclave);
CFDictionaryAddValue(attrs, kSecAttrKeyType, kSecAttrKeyTypeEC);
CFDictionaryAddValue(attrs, kSecPrivateKeyAttrs, privKeyAttrs);
SecKeyRef privKey = SecKeyCreateRandomKey(attrs, &error);
CFRelease((CFTypeRef)access);
CFRelease((CFTypeRef)privKeyAttrs);
CFRelease((CFTypeRef)attrs);
CFRelease((CFTypeRef)cfTag);
CFRelease((CFTypeRef)cfLabel);
if ((!privKey) || (error)) {
*errorStr = CFSTR("error generating random private key");
if (error) {
*errorStr = CFErrorCopyDescription(error);
CFRelease((CFTypeRef)error);
}
return kCFBooleanFalse;
}
SecKeyRef publicKey = SecKeyCopyPublicKey(privKey);
CFRelease((CFTypeRef)privKey);
if (publicKey)
*pubKey = ExtractPubKey(publicKey);
CFRelease((CFTypeRef)publicKey);
return kCFBooleanTrue;
}