Question

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 in the keychain search list (see SecTrustSetKeychains) and in the system’s store of anchor certificates (see SecTrustSetAnchorCertificates).”

However, since SecTrustSetKeychains() is not available on iOS, it’s not clear whether this function will also look in the application’s keychain.

Was it helpful?

Solution 3

eskimo1 from Apple Devforums answered this so:

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

OTHER TIPS

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

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top