Use System Keychain from System Extension

I need to store auth keys somewhere, previously app network extension would store them in a shared keychain. Now we're trying to move to system extensions, for out of appstore distribution, and shared keychain will no longer work.

Is it possible to write to system keychain from system extension? If yes, how do I specify that I want to use system keychain?

Our current code returns errSecNotAvailable if run in System Extension instead of App Extension. The code looks like this. If uncommented, it will work from the App Extension.

  NSString *teamID = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"Development Team"];
  NSString *groupID = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"App Group ID"];

  NSMutableDictionary *query = [NSMutableDictionary dictionaryWithDictionary:@{
    (id)kSecClass: (id)kSecClassGenericPassword,
//    (id)kSecAttrAccessGroup: [NSString stringWithFormat:@"%@.%@", teamID, groupID],
    (id)kSecAttrService: groupID,
//    (id)kSecAttrAccessible: (id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
  }];

  [query setObject:(id)kCFBooleanTrue forKey:(id)kSecUseDataProtectionKeychain];

  [query setObject:@(key) forKey:(id)kSecAttrAccount];
  [query setObject:[NSData dataWithBytes:buffer length:length] forKey:(id)kSecValueData];

SecItemAdd(cfQuery, NULL);

Replies

System extensions are effectively launchd daemons and, as such, the System keychain is the default option. Your code is failing because you’re trying to use the data protection keychain (kSecUseDataProtectionKeychain), which is only available to code running in a user context. See TN3137 On Mac keychain APIs and implementations.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

After removing kSecUseDataProtectionKeychain I started getting a different error - kPOSIXErrorEPERM I found this unresolved thread with the same issue https://developer.apple.com/forums/thread/710758 And same as there, after adding temporary read-write exception for path /Library/Keychains/ keychain started to work

Does it mean I cannot write to the keychain from System Network Extension using that read-write exception and publish to the the Appstore at the same time?

Does it mean I cannot write to the keychain from System Network Extension using that read-write exception and publish to the the App Store at the same time?

Only App Review can give you definitive answers about what will or won’t be allowed on the App Store. My advice is:

  1. File a bug explaining why your product needs this temporary exception entitlement.

  2. When you submit to the App Store, add a reviewer note that a) highlights your use of this temporary exception entitlement, and b) references your bug for all gory details.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

FB11916222 (Writing to keychain from Network System Extension fails with kPOSIXErrorEPERM)

Add a Comment

Oh, I just had cause to check on FB11916222 today and it’s reported as fixed in macOS 14. I don’t have time to check that right now, but if you have the opportunity to do so I’d appreciate you posting your results here.

IMPORTANT Once a bug like this is fixed, App Review typically requires you to conditionalise your workaround so that it only applies on older systems. If you find that you no longer need this temporary exception entitlement on macOS 14 and later, conditionalise it so that it only applies on older systems. For an example of how to do this, see here.

That example is for com.apple.security.temporary-exception.apple-events but the same process works for other temporary exception entitlements.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"