2

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.

Plumenator
  • 1,682
  • 3
  • 20
  • 49

3 Answers3

3

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
Scott Corscadden
  • 2,831
  • 1
  • 25
  • 43
  • Thanks for the answer! However, I was actually trying to see if I could use the keychain as a cert store. I ended up using openssl and implementing an on disk cert store like openssl does on Linux. – Plumenator Dec 10 '11 at 14:55
  • And I think (I don't remember) I actually *did* get the answer to this from a helpful Apple employee on the iOS forum. I'll probably add it here some time later. – Plumenator Dec 10 '11 at 14:57
  • … some time later … has come @Plumenator? – Scott Corscadden Mar 31 '12 at 10:17
  • Thanks for the reminder. :-) I'm adding the answer as I type. – Plumenator Apr 03 '12 at 22:12
  • How do you create SecTrustRef in the second way you have described ? – RandomGuy Jul 16 '15 at 18:49
  • I never needed to create one in the second path. After comparing the SHA bytes for a match I could use the `[challenge.sender useCredential:cred forAuthenticationChallenge:challenge]` call to signal "all's good". – Scott Corscadden Jul 18 '15 at 11:39
2

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

gregschlom
  • 4,825
  • 4
  • 28
  • 23
0

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.

Plumenator
  • 1,682
  • 3
  • 20
  • 49