CFBooleanRef CreateSEKey()

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;
}