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.
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"