Does SecTrustEvaluate() look for root certificates in the application keychain?

后端 未结 3 2114
逝去的感伤
逝去的感伤 2021-01-03 13:45

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

相关标签:
3条回答
  • 2021-01-03 13:50

    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
    
    0 讨论(0)
  • 2021-01-03 14:01

    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.

    0 讨论(0)
  • 2021-01-03 14:06

    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

    0 讨论(0)
提交回复
热议问题