IOS - Software Trusted CA (Certificate Authority)

I am trying to use an application that should securely connect from an iPhone client to a TLS server through sockets / streams for general communication. For this purpose, I configured my own CA using the keychain tool for mac and included the certificate in the code set.

My application should now trust any server certificate issued by this CA. (I do not care how other applications relate to these certificates, I assume that they will not trust him because of the sandbox.)

I found several similar questions on the Internet, but it seems I got something wrong.

Connecting to the server seems to work fine if I drag the CA certificate into Simulator and agree to it manually.

However, when I try to establish trust in the CA certificate programmatically, my attempts to connect to the server later are rejected, despite the fact that the code below does not generate errors.

Therefore, I must have the wrong part of the certificate implementation ... Any ideas?

Thank you very much in advance!

NSString* certPath = [[NSBundle mainBundle] pathForResource:@"MyTestCA2" ofType:@"cer"]; //cer = CA certificate
NSData* certData = [NSData dataWithContentsOfFile:certPath];
SecCertificateRef cert;
if( [certData length] ) {
    cert = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certData);
    if( cert != NULL ) {
        CFStringRef certSummary = SecCertificateCopySubjectSummary(cert);
        NSString* summaryString = [[NSString alloc] initWithString:(__bridge NSString*)certSummary];
        NSLog(@"CERT SUMMARY: %@", summaryString);
        certSummary = nil;
    } else {
        NSLog(@" *** ERROR *** trying to create the SSL certificate from data located at %@, but failed", certPath);
    }
}

OSStatus err = noErr;
CFTypeRef result;
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
                      (__bridge id)kSecClassCertificate, kSecClass,
                      cert, kSecValueRef,
                      nil];
err = SecItemAdd((__bridge CFDictionaryRef)dict, &result);
if(err!=noErr) NSLog(@"error while importing");
if (err==errSecDuplicateItem) NSLog(@"Cert already installed");
NSLog(@":%i",(int)err);
assert(err==noErr||err==errSecDuplicateItem);   // accept no errors other than duplicate
err = noErr;
SecTrustRef trust;
err = SecTrustCreateWithCertificates(cert, SecPolicyCreateBasicX509() ,&trust);
assert(err==noErr);
err = noErr;
CFMutableArrayRef newAnchorArray = CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
CFArrayAppendValue(newAnchorArray,cert);
err = SecTrustSetAnchorCertificates(trust, newAnchorArray);
assert(err==noErr);
SecTrustResultType trustResult;
err=SecTrustEvaluate(trust,&trustResult);
assert(err==noErr);
cert=nil;
+4
source share
2 answers

I did not try to run partial code, but I have code (given below) that I know works. I use it to trust my internal CA.

err=SecTrustEvaluate(trust,&trustResult);
assert(err==noErr);

trustResult- this is what interests you, not a errreturn from SecTrustEvaluate. errTells you whether the API call was successful / failed; he does not tell you the result of the confidence assessment.

, . "" trustResult kSecTrustResultProceed kSecTrustResultUnspecified. "", "", " ", "".

- " " trustResult kSecTrustResultDeny, kSecTrustResultFatalTrustFailure kSecTrustResultOtherError. , trustResult , . , "".

, NSURLConnection delegate -didReceiveAuthenticationChallenge:. ASN.1/DER ( ca-cert.der). 1, . #ifdef 0, 2.

, Apple TLS, Apple Tech Note TN2232, HTTPS Server Trust Evaluation Apple Technical Q & A QA1360, kSecTrustResultUnspecified .


- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:
(NSURLAuthenticationChallenge *)challenge
{   
    SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
    return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
                  forAuthenticationChallenge: challenge];

    if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust])
    {
        do
        {
            SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
            NSCAssert(serverTrust != nil, @"serverTrust is nil");
            if(nil == serverTrust)
                break; /* failed */

            NSData* caCert = [NSData dataWithContentsOfFile:@"ca-cert.der"];
            NSCAssert(caCert != nil, @"caCert is nil");
            if(nil == caCert)
                break; /* failed */

            SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
            NSCAssert(caRef != nil, @"caRef is nil");
            if(nil == caRef)
                break; /* failed */

            NSArray* caArray = [NSArray arrayWithObject:(__bridge id)(caRef)];
            NSCAssert(caArray != nil, @"caArray is nil");
            if(nil == caArray)
                break; /* failed */

            OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
            NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
            if(!(errSecSuccess == status))
                break; /* failed */

            SecTrustResultType result = -1;
            status = SecTrustEvaluate(serverTrust, &result);
            if(!(errSecSuccess == status))
                break; /* failed */

            NSLog(@"Result: %d", result);

            /* https://developer.apple.com/library/ios/technotes/tn2232/_index.html */
            /* https://developer.apple.com/library/mac/qa/qa1360/_index.html */
            /* kSecTrustResultUnspecified and kSecTrustResultProceed are success */
            if(result != kSecTrustResultUnspecified && result != kSecTrustResultProceed)
                break; /* failed */

#if 0
            /* Treat kSecTrustResultConfirm and kSecTrustResultRecoverableTrustFailure as success */
            /*   since the user will likely tap-through to see the dancing bunnies */
            if(result == kSecTrustResultDeny || result == kSecTrustResultFatalTrustFailure || result == kSecTrustResultOtherError)
                break; /* failed to trust cert (good in this case) */
#endif

            // The only good exit point
            return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
                          forAuthenticationChallenge: challenge];

        } while(0);
    }

    // Bad dog
    return [[challenge sender] cancelAuthenticationChallenge: challenge];
}
+3

, NS/CF-Streams, , , NSURLConnection. ( , CA-cert , TLS , .)

aeternusrahl, Rob Napier:

... Heath Borders: Blog

, , , - !

: : "... - , , . socket.io, NSURLConnection. socket.io, .

, iOS, ! , , , , , .

, jll TLS, (. ). , Heath Borders/Rob Napier, , , ssl ( , .)

: A) jww NSURLConnections, , , NS/CF B) / Heath Borders C) !

A) , B)...

!

PS. , ... , , / , , , , . ( ), , , .

0

All Articles