The docs say: “If not all the certificates needed to verify the leaf certificate are included in the trust management object, then SecTrustEvaluate searches for certificates
Seems like it's been a while since you posted so I'm not sure if you still need the answer. If your use case is "I'm getting hit with connection:didReceiveAuthenticationChallenge:
, and I'd like to make sure that exact certificate is being evaluated, then you can either use iOS built-in trust methods or do a bit more work via the Foundation APIs: (note that SecTrustEvaulate is not being called specifically here, but it could be added in quite easily)
#import <Security/Security.h>
#import <CommonCrypto/CommonDigest.h>
From there, you can iterate the full array of certs, and compare it to something like a SHA1 of the challenge's server trust reference:
// way #1 - iOS built-in ================================================ //
SecTrustRef trust = challenge.protectionSpace.serverTrust;
CFIndex cnt = SecTrustGetCertificateCount(trust);
// way #2 - build it in yourself from a file ============================ //
OSErr err;
NSString *path = [[NSBundle mainBundle] pathForResource:@"my.cert"
ofType:@"der"];
NSData *derData = [NSData dataWithContentsOfFile:path];
SecCertificateRef myCert =
SecCertificateCreateWithData(NULL, (CFDataRef)derData);
CFMutableArrayRef array = CFArrayCreateMutable(NULL, 1, NULL);
CFArrayInsertValueAtIndex(array, 0, myCert);
err = SecTrustSetAnchorCertificates(trust, array);
if (err != errSecSuccess) {
// do something smarter here, obviously, logging would be a start
abort();
}
CFArrayRef certs = NULL;
err = SecTrustCopyCustomAnchorCertificates(trust, &certs);
if (err != errSecSuccess) {
// again, better choices needed
abort();
}
CFIndex cnt = CFArrayGetCount(certs);
// loop and compare 'em
for (int i = 0; i < cnt; i++) {
SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
CFDataRef cdata = SecCertificateCopyData(cert);
NSData *data = [[NSData alloc] initWithData:(NSData *)cdata];
unsigned char digest_result[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, data.length, digest_result);
// compare each byte with your in-code SHA1 bytes
if (allBytesMatch) {
NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];
[challenge.sender useCredential:cred
forAuthenticationChallenge:challenge];
}
}
// don't forget to release & CFRelease all the alloc'ed stuff from above
eskimo1 from Apple Devforums answered this so:
- Does SecTrustEvaluate() look for root certificates in the application keychain?
Not by default. However, it's easy to make it do this by getting the certificates out of your keychain (or from wherever) and applying them to the SecTrust object using SecTrustSetAnchorCertificates.
SecTrustEvaluation /will/ find intermediate certificates in your keychain.
It's written in the doc now:
Note: Although this function searches the user’s keychain (or the application keychain in iOS) for intermediate certificates, it does not search those keychains for anchor (root) certificates. To add an anchor certificate, you must call SecTrustSetAnchorCertificates.
Source: SecTrustEvaluate documentation