macOS SecAccessControlRef throws errors and crashes

Dear Developer,


I’m a little confused about passwordhandling with TouchID in macOS and need help.

According to Pages or Numbers, a password that is TouchID 'controlled‘ isn’t visible in the keychain.app. I think I’m right, that therefore I have to call ‚SecItemAdd‘ with a SecAccessControlRef. Am I?


So I implemented the following Code:


NSData *secret = [@"top secret" dataUsingEncoding: NSUTF8StringEncoding];
CFErrorRef *error = nil;
   SecAccessControlRef sacObject =
   SecAccessControlCreateWithFlags(kCFAllocatorDefault,
                                   kSecAttrAccessibleWhenUnlocked,
                                   kSecAccessControlBiometryAny,
                                   error);
   if(error)
   {
      CFStringRef errorstring = CFErrorCopyFailureReason( *error);
     
   }
  
  
   NSDictionary *query = @{
                           (id)kSecClass : (id)kSecClassGenericPassword,
                           (id)kSecAttrService : @"the.bundle.identifier",
                           (id)kSecAttrAccount : @"myAccount",
                           (id)kSecValueData : secret,
                           (id)kSecAttrAccessControl : (__bridge id) sacObject
                           };
   CFTypeRef* returnref = nil;
   OSStatus status = SecItemAdd((CFDictionaryRef)query, returnref);
   if (status != errSecSuccess)
   {
      CFStringRef errorstatus = SecCopyErrorMessageString( status, NULL);
      NSLog((__bridge NSString *)errorstatus);
     
   }


which throws an error in console.app

‚Error Domain=NSOSStatusErrorDomain Code=-34018 "Client has neither com.apple.application-identifier, com.apple.security.application-groups nor keychain-access-groups entitlements" UserInfo={NSDescription=Client has neither com.apple.application-identifier, com.apple.security.application-groups nor keychain-access-groups entitlements}'


So I added


<key>com.apple.application-identifier</key>

<string>TeamID.bundle.identifier</string>

<key>keychain-access-groups</key>

<array>

<string>TeamID.groupname</string>

</array>


That was already set:

<key>com.apple.security.application-groups</key>

<array>

<string>TeamID.groupname</string>

</array>


and the app crashes at start (in and outside the debugger)

with

Exception Type: EXC_CRASH (Code Signature Invalid)

Exception Codes: 0x0000000000000000, 0x0000000000000000

Exception Note: EXC_CORPSE_NOTIFY


Termination Reason: Namespace CODESIGNING, Code 0x1


It doesn’t crash when I remove ‚keychain-access-groups‘, but then again I got error 34018.

Do I need a provisioning profile to manage keychain-access-groups (we don’t need it for anything else in our apps)?


And last but important: What about Apps outside the sandbox? We’ve got entitlements to enable hardened-Runtime for Notarization. Can I add the same entitlements as in sandboxed apps?


macOS: 10.14.2, Xcode 10.1

Adding Passwords to keychain without SecAccessControlRef works perfect.



Thank you for your help!


Brigitte

The implemented of Touch ID is intimately connected to the iOS-style database keychain. And to use the database keychain the app must be securely identified to macOS, that is, in a way that’s guaranteed by a provisioning profile. This sets the

com.apple.application-identifier
entitlement, which is what macOS is using to securely identify your app.

How you proceed here depends on how you plan to ship your app:

  • If you plan to ship your app via the Mac App Store (MAS), you should enable standard MAS Development code signing. This will set the

    com.apple.application-identifier
    entitlement and you’re good to go.
  • If you plan to ship outside of the MAS, you’ll need to enable Developer ID code siging and then associate a provisioning profile with your app. The easiest way to do that is to use the Capabilities editor in Xcode to temporarily enable a service that requires a provisioning profile.

Regardless, you can double check this with the

codesign
tool. Once you’ve built your app, dump its entitlements like so:
$ codesign -d --entitlements :- /path/to/your.app

You should expect to see the

com.apple.application-identifier
entitlement. If you don’t, you have more work to do.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
macOS SecAccessControlRef throws errors and crashes
 
 
Q