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.