title: iOS SecTrustRef Always NULL
body: <p>I'm trying to connect an iOS app to a Windows C# sever using TLS over TCP/IP.</p>
  
  <p>The TLS connection is using <em>untrusted certificates</em> created from an <em>untrusted CA root certificate</em> using the <em>makecert</em> utility.</p>
  
  <p>To test these certificates I created a simple C# client and using those certificates it was able to connect and communicate with the server.</p>
  
  <p>I'm not skilled at iOS development, but I did manage to find some code that connects me to the server, as follows:</p>
  
  <pre><code>-(bool)CreateAndConnect:(NSString *) remoteHost withPort:(NSInteger) serverPort
  {
      CFReadStreamRef readStream;
      CFWriteStreamRef writeStream;
  
      CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(remoteHost),
                                         serverPort, &amp;readStream, &amp;writeStream);
  
      CFReadStreamSetProperty(readStream, kCFStreamPropertySocketSecurityLevel,
                              kCFStreamSocketSecurityLevelNegotiatedSSL);
  
      NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
      NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
  
      [inputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey:NSStreamSocketSecurityLevelKey];
  
      // load certificate from servers exported p12 file
      NSArray *certificates = [[NSArray alloc] init];
      [self loadClientCertificates:certificates];
  
      NSDictionary *sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                   (id)kCFBooleanFalse, (id)kCFStreamSSLValidatesCertificateChain,
                                   certificates,(id)kCFStreamSSLCertificates,
                                   nil];
  
      [inputStream setProperty:sslSettings forKey:(__bridge NSString *)kCFStreamPropertySSLSettings];
  
      [inputStream setDelegate:self];
      [outputStream setDelegate:self];
  
      [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
      [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  
      CFReadStreamOpen(readStream);
      CFWriteStreamOpen(writeStream);
  
      return true;
  }
  </code></pre>
  
  <p>The code also seems to do some form of TLS negotiation, as the C# server rejects the connection if the p12 certificates are not provided as part of the NSStream settings.</p>
  
  <p>So it appears like the first stage of the TLS negotiation is working.</p>
  
  <p>To validate the server certificate I have this function, which gets called by the NSStream delegate on the NSStreamEventHasSpaceAvailable event:</p>
  
  <pre><code>// return YES if certificate verification is successful, otherwise NO
  -(BOOL) VerifyCertificate:(NSStream *)stream
  {
      NSData *trustedCertData = nil;
      BOOL result             = NO;
      SecTrustRef trustRef    = NULL;
      NSString *root_certificate_name      = @"reference_cert";
      NSString *root_certificate_extension = @"der";
  
      /* Load reference cetificate */
      NSBundle *bundle = [NSBundle bundleForClass:[self class]];
      trustedCertData = [NSData dataWithContentsOfFile:[bundle pathForResource: root_certificate_name ofType: root_certificate_extension]];
  
      /* get trust object */
      /* !!!!! error is here as trustRef is NULL !!!! */
      trustRef = (__bridge SecTrustRef)[stream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust];
  
      /* loacate the reference certificate */
      NSInteger numCerts = SecTrustGetCertificateCount(trustRef);
      for (NSInteger i = 0; i &lt; numCerts; i++) {
          SecCertificateRef secCertRef = SecTrustGetCertificateAtIndex(trustRef, i);
          NSData *certData = CFBridgingRelease(SecCertificateCopyData(secCertRef));
          if ([trustedCertData isEqualToData: certData]) {
              result = YES;
              break;
          }
      }
      return result;
  }
  </code></pre>
  
  <p>Now the problem is, no matter what I try, the <strong>trustRef</strong> object is always null.</p>
  
  <p>From this Apple developer link: <a href="https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html" rel="noreferrer">https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html</a></p>
  
  <p>There is this quote that suggest this should not be the case:</p>
  
  <blockquote>
    <p>By the time your stream delegate’s event handler gets called to
    indicate that there is space available on the socket, the operating
    system has already constructed a TLS channel, obtained a certificate
    chain from the other end of the connection, and created a trust object
    to evaluate it.</p>
  </blockquote>
  
  <p>Any hints on how to fix this?</p>
  
  <p>How can I get access to that <em>trustRef</em> object for the NSStream?</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>Thanks for the reply 100phole.</p>
  
  <p>In trying to get this to work, I thought this might have something to do with the issue and in one of my many attempts I moved all of those socket related items into a class: </p>
  
  <p>Something like this:</p>
  
  <pre><code>@interface Socket
      CFReadStreamRef readStream;
      CFWriteStreamRef writeStream;
  
      NSInputStream *inputStream;
      NSOutputStream *outputStream;
  @end
  </code></pre>
  
  <p>But that came up with the same results :(</p>
  
  <p>I only reverted back to the version shown above because, based on my Google searching, that appears to be a fairly code common pattern.</p>
  
  <p>For example, even this code from the Apple Developer site uses a very similar style:</p>
  
  <p><a href="https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html#//apple_ref/doc/uid/20002277-BCIDFCDI" rel="noreferrer">https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html#//apple_ref/doc/uid/20002277-BCIDFCDI</a></p>
  
  <p>As I mentioned earlier, I'm no expert in Objective-C (far from it), so I might be wrong, but from what I have seen, moving those items into a class and having them persist did not seem to make any difference. </p>