title: Objective-C TCP Server with SSL / TLS support
body: <p>I have a simple TCP Server / Client setup. This connection actually works great.</p>
  
  <p>Now I wanted to implement SSL / TLS encryption for the socket connections. I created a PKCS12 certificate using keychain access. In my server I have the following code inside the accept callback:</p>
  
  <pre><code>NSString *certificatePath = [[NSBundle mainBundle] pathForResource:@"TCPServerCertificate" ofType:@"p12"];
  NSData *certificateData = [NSData dataWithContentsOfFile:certificatePath];
  
  CFArrayRef keyRef;
  OSStatus status = SecPKCS12Import((__bridge CFDataRef)certificateData, (__bridge CFDictionaryRef)@{(__bridge NSString *)kSecImportExportPassphrase: @"1234"}, &amp;keyRef);
  
  if (status != noErr) {
      NSLog(@"PKCS12 import error %i", status);
      return;
  }
  
  CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyRef, 0);
  SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
  
  SecCertificateRef certificate;
  status = SecIdentityCopyCertificate(identityRef, &amp;certificate);
  
  if (status != noErr) {
      NSLog(@"sec identity copy failed: %i", status);
      return;
  }
  
  NSArray *certificates = [NSArray arrayWithObjects:(__bridge id)identityRef, (__bridge id)certificate, nil];
  
  NSDictionary *settings = @{(NSString *)kCFStreamPropertyShouldCloseNativeSocket:    [NSNumber numberWithBool:YES],
                             (NSString *)kCFStreamSSLValidatesCertificateChain:       [NSNumber numberWithBool:YES],
                             (NSString *)kCFStreamSSLAllowsExpiredCertificates:       [NSNumber numberWithBool:NO],
                             (NSString *)kCFStreamSSLAllowsExpiredRoots:              [NSNumber numberWithBool:NO],
                             (NSString *)kCFStreamSSLAllowsAnyRoot:                   [NSNumber numberWithBool:YES],
                             (NSString *)kCFStreamSSLCertificates:                    certificates,
                             (NSString *)kCFStreamSSLIsServer:                        [NSNumber numberWithBool:YES],
                             (NSString *)kCFStreamSSLLevel:                           (NSString *)kCFStreamSocketSecurityLevelTLSv1};
  
  CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
  CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
  </code></pre>
  
  <p>Then I create <code>NSStream</code> instances of the streams and handle them in another class.</p>
  
  <p>When I run the server and connect a client, I'm getting the regular <code>NSStreamEventOpenCompleted</code> in my delegate. When I then try to write to the stream or event if I just close the connection, I'm getting the following errors:</p>
  
  <pre><code>2013-10-25 13:27:08.584 TCPServer[6435:303] CFNetwork SSLHandshake failed (-9800)
  2013-10-25 13:27:08.584 TCPServer[6435:303] NSStreamEventOpenCompleted
  2013-10-25 13:27:08.585 TCPServer[6435:303] NSStreamEventErrorOccurred
  </code></pre>
  
  <p>I wonder what I have to implement on the client side. Also I wonder why I'm getting the handshake failure when sending data or disconnecting from the client side. Whenever this error occurs, the client thinks it's still connected.</p>
  
  <p>Are there any good TCP SSL/TLS tutorials or other material that covers both, the client and the server side?</p>