So this is how I used to do it
a) Create trusted app object of the app that is creating the ACL using
SecTrustedApplicationCreateFromPath
b) Then I would create a trusted app object that would grant access to all Microsoft-approved apps.
- create requirement using "SecRequirementCreateWithString" using pre-determined code sign requirement
- SecTrustedApplicationCreateFromRequirement("com.microsoft", requirement, &trustedApplicationRef);
c) Then add object from 1) and 2) in the array and create final accessRef using below API
SecAccessCreate((CFStringRef)accessLabel, (__bridge CFArrayRef)allTrustedApps, accessrefs);
Because SecTrustedApplicationCreateFromPath is deprecated and soon to be gone,
I was hoping to explore an alternative approach where
create login keychain first - since by default it still adds the creating app into the ACL
Then use above approach that I initially shared to add a new ACL containing the new trusted app ref object that was created from code sign requirement, and then append it to the existing access ref object for this login keychain object.
Post
Replies
Boosts
Views
Activity
Actually I figured it out. sorry :P
Hi Matt, could you help to answer my question above?
Thanks,
Peter
Thank you for your reply, Matt!
We are generating private-public RSA key pair programmatically in Objc-C. I don't think we are using an SSH session or other limited user context.
Just to confirm
-25307 is returned when the default Keychain is not found
Doesn't this mean when we try to write keychain objects into login keychain, and if keychain access doesn't have login keychain in the default keychain section? However, are there other scenarios that could lead to this? if the user already has login keychain as the default
-25295
I was not able to gather much information on this error. seems quite rare. is this related to above error? I am familiar with error -50 that happens when you pass in invalid params into the query dictionary, but -25295 seems different. I was talking to Eskimo a while ago, and he mentioned that SecKeyGeneratePair has some known bugs that cause public key to be treated as private keys and such. I wonder if this error code could be something that also happens due to some unknown bugs associated with SecKeyGeneratePair?
If it helps, this is how we currently generate key pairs in the legacy code base on MacOS
One weird thing I notice is that kSecAttrAccessible is being set, even thought it is only applicable to MacOS keychains that have iOS-style sharing enabled. I believe kSecAttrAccessible and kSecAttrAccess are mutually exclusive right? Could this also contribute to issues like -25295, -25307?
//private public key specific
[privateKeyAttr setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag];
[publicKeyAttr setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
[privateKeyAttr setObject:[NSNumber numberWithBool:NO] forKey:(__bridge id)kSecAttrIsExtractable];
[privateKeyAttr setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecAttrIsSensitive];
[publicKeyAttr setObject:(id)kCFBooleanFalse forKey:(__bridge id)kSecAttrIsExtractable];
[publicKeyAttr setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecAttrIsSensitive];
//actual dictionary that goes into SecKeyGeneratePair
[keyPairAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
[keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[keyPairAttr setObject:[NSNumber numberWithInt:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];
[keyPairAttr setObject:label forKey:(__bridge id)kSecAttrLabel];
[keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
[keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];
[keyPairAttr setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id)kSecAttrAccessible];
[keyPairAttr setObject:(__bridge id) [access reference object for ACL] forKey:(__bridge id)kSecAttrAccess];
// This does both generation and storing of the private and public key refs
status = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef);
Thank you, eskimo.
I tried both, and neither worked :(
Thanks, eskimo, but my understanding was that having kSecUseDataProtectionKeychain allows you to use iOS style keychain without being synced to the iCloud. would keychain items using this flag also appear on the iCloud section?
Just wanted to make sure I understood your response correctly.
Thanks,
Peter
Thank you, eskimo!
1) I don’t really understand what you mean by “the same” here.
Sorry for the confusion. what I meant was will there always be a 1-1 mapping between ECC private key and the public key retrieved from it through SecKeyCopyPublicKey? will it be the same object with the same data? - sorry I am not too familiar with ECC.
2) The good news here is that the workaround, don’t store the private key by switching to SecKeyCreateRandomKey, is also the best solution because:
Just to confirm - you meant "don't store the public key" here right?
Thank you! :)
Thank you so much, eskimo! Really appreciate your help.
In the future we might migrate from RSA to ECC (secure enclave storage) for our private keys and wanted to ask a couple of follow up questions
1) Will SecKeyCopyPublicKey always produce the same public key also for secure enclave ECC generated private key?
2) Could you provide some of the examples on the issues that you mentioned that could happen if we store public key in the keychain
(You mentioned above: ps You don’t need to add the public key to the keychain (and in some cases it can cause problems)
question 2) is just for my learning :) :)
Thank you again, eskimo!!
However, on MacOS, I was still wondering if I can use SecIdentityCreateWithCertificate on a x509 cert generated using above steps to dynamically create a Identity reference object, and then use it for
1)
NSURLCredential credentialWithidentity API for TLS challenge
2) Also with SecIdentitySetPreferred?
I'd really appreciate your response on these two questions also, although I really appreciate your answers on the proper way to use private keys as well :) :)
Aha I see!
Thank you so much for letting me know, eskimo! :) That sounds like a better practice indeed. we actually don't use public keys at all. Yep we do set kSecAttrIsPermanent.
This is what we did
1) First generate asymmetric RSA public and private keypair using SecKeyGeneratePair
2) Read private key data genearted from 1) using SecKeyCopyExternalRepresentation
3) Generate PKCS Certificate signing request using OpenSSL
4) Send to the server
5) Server returns signed x509 certificate
6) We write this x509 certificate into keychain :)
Once we have done all of that above, we currently retrieve a list of all identity objects and perform linear search to find the identity that we're interested in by looking at the issuer name using below code
NSDictionary *getQuery = @{ (id)kSecClass: (id)kSecClassIdentity,
(id)kSecReturnAttributes:(__bridge id)(kCFBooleanTrue),
(id)kSecMatchLimit : (__bridge id)kSecMatchLimitAll,
(id)kSecReturnRef: (__bridge id)(kCFBooleanTrue),
};
status = SecItemCopyMatching((__bridge CFDictionaryRef)getQuery, (CFTypeRef *)&identityArr);
Then uses this filtered identity for NSURLCredential - credentialWithIdentitiy API,
but I thought it would also be equally valid to simply generate Identity object using
SecIdentityCreateWithCertificate API and use it instead :)
I was wondering if you could help to confirm whether it is valid for me to use
1) SecIdentityCreateWithCertificate to generate Identity dynamically from x509 cert from above, and then use it with
NSURLCredential credentialWithidentity?
2) additionally, would it also be ok to use such a dynamically generated identity with SecIdentitySetPreferred ?
Thanks,
Peter
Hi @eskimo Thank you for your quick response. Yep I meant private key.
Nonetheless, can I generate Identity dynamically from such a cert using "SecIdentityCreateWithCertificate" and use that Identity for NSURLCredential credentialWithidentity?
Thank you,
Peter