Trying to use kSecACLAuthorizationPartitionID

Hi,


I am trying to figure out how I can set the kSecACLAuthorizationPartitionID when creating a private key that will later be used by the macOS system ("apple:"). This key is to be used for things like Wi-Fi (eapolagent) and so on.


I have been experimenting with the below code, the private key is created correctly, ACL is set and it is added to the keychain, however it seems it is overwritten when I add the key to the keychain:


    // create standard access
    SecAccessRef access = SecAccessCreateWithOwnerAndACL(0, 0, kSecUseOnlyUID, NULL, &error);

    // build partitions list
    NSMutableArray* partitions = [[NSMutableArray alloc] init];

    // we want the apple system to be able to sign with this key
    [partitions addObject:@"apple:"];

    NSMutableDictionary *descriptionDict = [[NSMutableDictionary alloc] init];

    [descriptionDict setObject:(__bridge id)partitions
                        forKey:(__bridge id)@"Partitions"];

    NSData *xmlData = [NSPropertyListSerialization dataFromPropertyList:descriptionDict
                                                                 format:NSPropertyListXMLFormat_v1_0
                                                       errorDescription:&error];

    SecACLRef newAcl = NULL;

    status = SecACLCreateWithSimpleContents(access, NULL, (CFStringRef)[self hexStringValue:xmlData], kSecKeychainPromptRequirePassphase, &newAcl);

    NSArray* authorizations = @[(__bridge id)kSecACLAuthorizationPartitionID];

    // update ACL
    status = SecACLUpdateAuthorizations(newAcl, (__bridge CFArrayRef) authorizations);


At this point, if I loop through the access ACLS, all look well.And I proceed to create the key:


SecKeyRef privateKey = SecKeyCreateFromData((CFDictionaryRef)attributes, (CFDataRef)encodedKeyData, &error);


And then add this to the keychain with the access I created above


            NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init];
            [attributes setObject:(__bridge id)privateKey
                           forKey:(id)kSecValueRef];
            [attributes setObject:(id)kSecClassKey
                           forKey:(id)kSecClass];
            [attributes setObject:tag
                           forKey:(id)kSecAttrApplicationTag];
            [attributes setObject:(__bridge id)access
                           forKey:(__bridge id)kSecAttrAccess ];

             err = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);


All this runs without error, however dumping the keychain, I can see the ACL as follows:


    entry 0:
        authorizations (1): any
        don't-require-password
        description: <NULL>
        applications: <null>
    entry 1:
        authorizations (1): partition_id
        don't-require-password
        description: unsigned:
        applications: <null>
    entry 2:
        authorizations (1): change_acl
        don't-require-password
        description: <NULL>
        applications: <null>

The "unsigned:" is I assume due to me running the app in debug mode, but it looks like the ACL I set is ignored and the keychain API hardcodes this to the caller partition_id.

I have also tried to set the partition_id after adding the key to the keychain, but this requires the password of the User, something we do not want to request for obvious reasons.


Is what I am trying even possible? Can you set the partition_id when creating a key?


Thanks,


S.

Answered by DTS Engineer in 298751022

Is what I am trying even possible?

No it is not. I recently explored this in a different context (r. 33635514) and the response I got from keychain engineering is that there’s no supported way for you to create keychain items which will be silently used by other apps (or the system). User consent must be acquired.

Share and Enjoy

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

let myEmail = "eskimo" + "1" + "@apple.com"

it seems the circumstance and issue (above) has not changed on macOS 11.4

Yes.

What’s your specific goal here? Many tasks related to keychain partitioning have no supported solution because they run counter to the reason why we added keychain partitioning in the first place (that is, to prevent unmediated transfer of credentials between unrelated code). If you explain more about your situation, I should be able to give you an idea as to whether there’s a way forward or not.

Share and Enjoy

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

unmediated transfer of credentials between unrelated code

Just to make sure I understand it correctly, the next version of the same app (installed via brew) would be considered unrelated code, right?

Just to make sure I understand it correctly, the next version of the same app (installed via brew) would be considered unrelated code, right?

That depends on how it’s signed. My advice is that you sign your code with a stable signing identity, which means it has a consistent designated requirement (DR), which means it’s considered the ‘same code’. See TN3127 Inside Code Signing: Requirements for more about that.

I suspect that brew leaves the code unsigned (or ad hoc signed for Apple silicon) which means there’s no way to for the system to tell that it’s the same code.

However, that’s just a guess. I don’t use brew and have no idea whether it has any support for code signing. To get a definitive answer, I recommend that you escalate this via its support channel.

Share and Enjoy

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

Trying to use kSecACLAuthorizationPartitionID
 
 
Q