CFTypeRef HasSEKeyProtection()

in macos/macos.c [278:334]


CFTypeRef HasSEKeyProtection(
    const char* label,
    const char* tag,
    unsigned char* hash,
    CFStringRef value,
    CFStringRef* errorStr) {
  CFDataRef cfTag = StringToDataRef(tag);
  CFStringRef cfLabel = CFStringCreateWithCString(
      kCFAllocatorDefault, label, kCFStringEncodingUTF8);

  // Generate a query to return key attributes rather than key data.
  CFMutableDictionaryRef query = CFDictionaryCreateMutable(
      kCFAllocatorDefault,
      0,
      &kCFTypeDictionaryKeyCallBacks,
      &kCFTypeDictionaryValueCallBacks);
  CFDictionaryAddValue(query, kSecClass, kSecClassKey);
  CFDictionaryAddValue(query, kSecAttrApplicationTag, cfTag);
  CFDictionaryAddValue(query, kSecAttrLabel, cfLabel);
  CFDictionarySetValue(query, kSecReturnAttributes, kCFBooleanTrue);
  CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne);
  if (hash) {
    CFDataRef h = CFDataCreateWithBytesNoCopy(
        kCFAllocatorDefault, (UInt8*)hash, 20, kCFAllocatorNull);
    CFDictionaryAddValue(query, kSecAttrApplicationLabel, h);
  }

  CFTypeRef res = NULL;
  OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, &res);
  CFRelease((CFTypeRef)query);
  CFRelease((CFTypeRef)cfTag);
  CFRelease((CFTypeRef)cfLabel);
  if (!res)
    status = errSecBadReq;
  if (status != errSecSuccess) {
    *errorStr = SecCopyErrorMessageString(status, NULL);
    return NULL;
  }

  SecAccessControlRef ac =
      (SecAccessControlRef)CFDictionaryGetValue(res, kSecAttrAccessControl);

  if (!ac) {
    *errorStr = SecCopyErrorMessageString(errSecNoSuchAttr, NULL);
    return NULL;
  }

  CFTypeRef protection = SecAccessControlGetProtection(ac);
  if (!protection) {
    *errorStr = SecCopyErrorMessageString(errSecDataNotAvailable, NULL);
    return NULL;
  }

  CFRelease((CFTypeRef)ac);

  return protection;
}