Always EXC_BAD_ACCESS on SecTrustEvaluate

I am using Apple’s example code for evaluating a X509 certificate.
I have modified a bit to obtain a certificate from my bundle (only changed the file name).

When I run this it always crashes in the line with comment 5 status = SecTrustEvaluate(myTrust, &trustResult);. I get an always EXC_BAD_ACCESS there.

  • IOS9 SSL error with NSURLSession
  • CRL and OCSP behavior of iOS / Security.Framework?
  • MDM Server certificate to be used for SSL handshake with iPhone device
  • Retrieving data programmatically from a Configuration Profile in IOS
  • - (BOOL)validateCertificate
    {
        NSString *thePath = [[NSBundle mainBundle] pathForResource:@"user_signed_cert" ofType:@"crt"];
        NSData *certData = [[NSData alloc]
                            initWithContentsOfFile:thePath];
        CFDataRef myCertData = (__bridge_retained CFDataRef)certData; //1
        SecCertificateRef myCert;
        myCert = SecCertificateCreateWithData(NULL, myCertData); //2
        SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); //3
        SecCertificateRef certArray[1] = { myCert };
        CFArrayRef myCerts = CFArrayCreate(
                                           NULL, (void *)certArray,
                                           1, NULL);
        SecTrustRef myTrust;
        OSStatus status = SecTrustCreateWithCertificates(
                                                         myCerts,
                                                         myPolicy,
                                                         &myTrust); //4
        SecTrustResultType trustResult;
        if (status == noErr) {
            status = SecTrustEvaluate(myTrust, &trustResult); //5 }
    
            NSLog(@"Status: %d", status);
            //6 if (trustResult == kSecTrustResultRecoverableTrustFailure) {
        }
    
        if (myPolicy)
            CFRelease(myPolicy);
    }
    

    Does anyone know what is going wrong here?

    Thanks in advance!

    Update #1: I have changed it to the following but nothing changes. Same EXC_BAD_ACCESS on SecTrustEvaluate().

    NSMutableArray *temp = [[NSMutableArray alloc] init];
    [temp addObject:certData];
    OSStatus status = SecTrustCreateWithCertificates((__bridge CFArrayRef)temp, myPolicy, &myTrust);
    

    It seems that status is empty after SecTrustCreateWithCertificates() but does not contain an error.

    Any other suggestions whats wrong?

    Update #2: I have tried the solution mentioned below and receive always kSecTrustResultInvalid. I have only changed the CA certificate creation to store the private key in ca.key because when signing the request (client.csr) I got the following error message:

    Signature ok
    subject=/CN=foo-by-ZeeCA
    Getting CA Private Key
    unable to load CA Private Key
    

    Furthermore I had to change the signing request command to openssl x509 -CA ca.pem -in client.csr -CAkey ca.key -req -set_serial 1 -out client.pem. (added -CAkey ca.key)

    Then I have used the code in the solution below and added my paths from the bundle. Additionally, I have added a switch-case for the status.

    /*
     # CA
     openssl req -x509 -new -subj /CN=ZeeCA -keyout ca.key -nodes -set_serial 1 > ca.pem
     openssl x509 -outform DER -out ca.der -in ca.pem
    
     # create andsign client
     openssl req  -new -subj /CN=foo-by-ZeeCA -CAkey ca.key  -keyout client.key -nodes > client.csr
     openssl x509 -CA ca.pem -in client.csr -req -set_serial 1  -out client.pem
    
     # format for client identity import
     openssl pkcs12 -export -out client.12 -inkey client.key -in client.pem -CAfile ca.pem -password pass:1234
    
     # format for trust.
     openssl x509 -in client.pem -out client.der -outform der
    
     */
    
    NSString *clientPath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"der"];
    
    //NSString *thePath = @"XXXX/client.der";
    
    NSData *certData = [[NSData alloc]
                        initWithContentsOfFile:clientPath];
    CFDataRef myCertData = (__bridge_retained CFDataRef)certData; //1
    
    assert(myCertData);
    
    SecCertificateRef myCert;
    myCert = SecCertificateCreateWithData(NULL, myCertData); //2
    
    assert(myCert);
    
    SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); //3
    
    NSArray * certArray = [NSArray arrayWithObject:(__bridge id)(myCert)];
    
    SecTrustRef myTrust;
    OSStatus status = SecTrustCreateWithCertificates(
                                                     (__bridge CFArrayRef)certArray,
                                                     myPolicy,
                                                     &myTrust); //4
    
    NSString *caPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"der"];
    NSData *caData = [[NSData alloc]
                      initWithContentsOfFile:caPath];
    CFDataRef myCaData = (__bridge_retained CFDataRef)caData; 
    SecCertificateRef myCA = SecCertificateCreateWithData(NULL, myCaData); 
    assert(myCA);
    
    NSArray * myCAs = [NSArray arrayWithObject:(__bridge id)(myCA)];
    
    SecTrustResultType xxx = SecTrustSetAnchorCertificates(myTrust, (__bridge CFArrayRef)(myCAs));
    if (xxx != noErr) {
        NSLog(@"SecTrustSetAnchorCertificates failed: %d", xxx);
    }
    
    
    SecTrustResultType trustResult;
    if (status == noErr) {
        status = SecTrustEvaluate(myTrust, &trustResult); //5 }        
        NSLog(@"Status: %d", status);
    }
    
    if (myPolicy)
        CFRelease(myPolicy);
    
    if (status == noErr) {
        status = SecTrustEvaluate(myTrust, &trustResult); //5 }
    
        switch (status) {
            case kSecTrustResultProceed: // 1
                NSLog(@"Proceed");
                break;
            case kSecTrustResultConfirm: // 2
                NSLog(@"Confirm");
                break;
            case kSecTrustResultUnspecified: // 4
                NSLog(@"Unspecified");
                break;
            case kSecTrustResultRecoverableTrustFailure:  // 5
                NSLog(@"TrustFailure");
                break;
            case kSecTrustResultDeny: // 3
                NSLog(@"Deny");
                break;
            case kSecTrustResultFatalTrustFailure: // 6
                NSLog(@"FatalTrustFailure");
                break;
            case kSecTrustResultOtherError: // 7
                NSLog(@"OtherError");
                break;
            case kSecTrustResultInvalid: // 0
                NSLog(@"Invalid");
                break;
            default:
                NSLog(@"Default");
                break;
        }        
    }
    

    Solutions Collect From Internet About “Always EXC_BAD_ACCESS on SecTrustEvaluate”

    I think your issue is in the array of an array. I use the code below – i.e. pass a simple flat array of SecCertificateRef’s in what you call myCerts.

            NSMutableArray *serverChain = [NSMutableArray array];
            for(int i = 0; i < SecTrustGetCertificateCount(secTrustRef); i++)
                [serverChain addObject:(__bridge id)(SecTrustGetCertificateAtIndex(secTrustRef,i))];
    
            SecTrustRef noHostTrustRef = NULL;
            OSErr status = SecTrustCreateWithCertificates((__bridge CFArrayRef) serverChain, SecPolicyCreateSSL(NO, nil), &noHostTrustRef);
    
    
            if (status != noErr) {
                NSLog(@"SecTrustCreateWithCertificates failed: %hd", status);
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
    
            NSMutableArray *certRefs = [NSMutableArray arrayWithCapacity:[acceptableCAs count]];
            for(Certificate * cert in acceptableCAs)
                [certRefs addObject:(id)[cert secCertificateRef]];
    
            status = SecTrustSetAnchorCertificates(noHostTrustRef, (__bridge CFArrayRef)certRefs);
            if (status != noErr) {
                NSLog(@"SecTrustSetAnchorCertificates failed: %hd", status);
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
    
            status = SecTrustEvaluate(noHostTrustRef, &result);
            if (status != noErr) {
                NSLog(@"SecTrustEvaluate failed: %hd", status);
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
            CFRelease(noHostTrustRef);
    

    If I take your code and put it in a simple cmd line wrapper:

    import

    int main(int argc, const char * argv[])
    {

    @autoreleasepool {
    
        //  openssl req -x509 -new -subj /CN=foo -out user_signed_cert.crt \
        //      -keyout /dev/null -outform DER -nodes -set_serial 1
        //
        NSString *thePath = @"XXXXX/user_signed_cert.crt";
    
        NSData *certData = [[NSData alloc]
                            initWithContentsOfFile:thePath];
        CFDataRef myCertData = (__bridge_retained CFDataRef)certData; //1
    
        assert(myCertData);
    
        SecCertificateRef myCert;
        myCert = SecCertificateCreateWithData(NULL, myCertData); //2
        SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); //3
        SecCertificateRef certArray[1] = { myCert };
        CFArrayRef myCerts = CFArrayCreate(
                                           NULL, (void *)certArray,
                                           1, NULL);
        SecTrustRef myTrust;
        OSStatus status = SecTrustCreateWithCertificates(
                                                         myCerts,
                                                         myPolicy,
                                                         &myTrust); //4
        SecTrustResultType trustResult;
        if (status == noErr) {
            status = SecTrustEvaluate(myTrust, &trustResult); //5 }
    
            NSLog(@"Status: %d", status);
            //6 if (trustResult == kSecTrustResultRecoverableTrustFailure) {
        }
    
        if (myPolicy)
            CFRelease(myPolicy);
    
    }
    return 0;
    

    and with an explicit cert:

    @autoreleasepool {
    
        /*
    
         # CA
         openssl req -x509 -new -subj /CN=ZeeCA -keyout /dev/stdout -nodes -set_serial 1 > ca.pem
         openssl x509 -outform DER -out ca.der -in ca.pem
    
         # create andsign client
         openssl req  -new -subj /CN=foo-by-ZeeCA   -keyout client.key -nodes > client.csr
         openssl x509 -CA ca.pem -in client.csr -req -set_serial 1  -out client.pem
    
         # format for client identity import
         openssl pkcs12 -export -out client.12 -inkey client.key -in client.pem -CAfile ca.pem -password pass:1234
    
         # format for trust.
         openssl x509 -in client.pem -out client.der -outform der
    
         */
        NSString *thePath = @"XXXX/client.der";
    
        NSData *certData = [[NSData alloc]
                            initWithContentsOfFile:thePath];
        CFDataRef myCertData = (__bridge_retained CFDataRef)certData; //1
    
        assert(myCertData);
    
        SecCertificateRef myCert;
        myCert = SecCertificateCreateWithData(NULL, myCertData); //2
    
        assert(myCert);
    
        SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); //3
    
        NSArray * certArray = [NSArray arrayWithObject:(__bridge id)(myCert)];
    
        SecTrustRef myTrust;
        OSStatus status = SecTrustCreateWithCertificates(
                                                         (__bridge CFArrayRef)certArray,
                                                         myPolicy,
                                                         &myTrust); //4
    
    
        NSData *caData = [[NSData alloc]
                           initWithContentsOfFile:@"XXXXX/ca.der"];
        CFDataRef myCaData = (__bridge_retained CFDataRef)caData; 
        SecCertificateRef myCA = SecCertificateCreateWithData(NULL, myCaData); 
        assert(myCA);
    
        NSArray * myCAs = [NSArray arrayWithObject:(__bridge id)(myCA)];
    
        SecTrustResultType xxx = SecTrustSetAnchorCertificates(myTrust, (__bridge CFArrayRef)(myCAs));
        if (xxx != noErr) {
            NSLog(@"SecTrustSetAnchorCertificates failed: %d", xxx);
        }
    
    
        SecTrustResultType trustResult;
        if (status == noErr) {
            status = SecTrustEvaluate(myTrust, &trustResult); //5 }
    
            NSLog(@"Status: %d", status);
            //6 if (trustResult == kSecTrustResultRecoverableTrustFailure) {
        }
    
        if (myPolicy)
            CFRelease(myPolicy);
    
    }
    

    both seem to do the trick for me ?