1 Reply
      Latest reply: Feb 2, 2017 3:02 PM by eskimo RSS
      Henning_DEV Level 1 Level 1 (0 points)

        Hi,

         

        I tried to implement a connection between a iOS-App (iOS 9 /10) and a TCP-server with TLS 1.2 by using a real certificate for testing, not a self signed.

         

        As you can see in the code, I use NSStream for the data transfer between the server and the app.

            CFReadStreamRef readStream;
            CFWriteStreamRef writeStream;
            CFDictionaryRef sslSettingsDict;
        
            CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)ns_IP, ui_Port, &readStream, &writeStream);
        
            inputStream = (__bridge NSInputStream *)readStream;
            outputStream = (__bridge NSOutputStream *)writeStream;
        
            [inputStream setDelegate:(id)self];
            [outputStream setDelegate:(id)self];
        
            [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            
            const void* keys[] = {  kCFStreamSSLLevel, kCFStreamPropertyShouldCloseNativeSocket};
            const void* values[] = { CFSTR("kCFStreamSocketSecurityLevelTLSv1_2"), CFSTR("kCFBooleanTrue") };
            
            sslSettingsDict = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 2,
                                                                    &kCFTypeDictionaryKeyCallBacks,
                                                                    &kCFTypeDictionaryValueCallBacks);
        
            CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, sslSettingsDict);
            CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, sslSettingsDict);
            CFRelease(sslSettingsDict);
        
            [inputStream open];
            [outputStream open];
        

         

        We tried several settings on the server. First step was that the client verifies the certificate from the server. That was ok with my code.

        In the second step the server expects a certificate from the client. But now I get the error CFNetwork SSLHandshake failed (-9824 -> -9829).

         

        I added NSAllowsArbitraryLoads to my Info.plist, but that doesn't make a difference.

         

          <key>NSAppTransportSecurity</key>
          <dict>
          <key>NSAllowsArbitraryLoads</key>
          <true/>
          </dict>
        

         

        Thanks for the help

        • Re: CFNetwork SSLHandshake failed (-9824 -> -9829) in iOS-App
          eskimo Apple Staff Apple Staff (6,490 points)

          Let’s start with some random things:

          • There's no need to monkey with kCFStreamPropertyShouldCloseNativeSocket when you create a stream pair with CFStreamCreatePairWithSocketToHost; it defaults to true in that case.

          • You don’t need to set kCFStreamPropertySSLSettings on both streams; the streams form a pair, so setting properties on one applies those properties to both.

          • Life is much easier if you learn to love toll-free bridging.  Personally, I never use CFDictionary, I just work with the much nicer NSDictionary (or Swift Dictionary) type and then toll-free bridge to CFDictionary at the last minute.

          • It’s best to avoid kCFStreamSocketSecurityLevelTLSv1_2.  CFSocketStream will use TLS 1.2 by default.  If you want to constrain it to only use TLS 1.2, use kCFStreamPropertySSLContext to get the SSLContext and set the minimum TLS version via SSLSetProtocolVersionMin.

          • App Transport Security only applies to high-level HTTP[S] APIs (NSURLSession, NSURLConnection, and things layered on top of those).  It has no effect on CFSocketStream.

          You should check out my TLSTool sample code, which shows these techniques in action.


          As to your actual problem, you wrote:

          First step was that the client verifies the certificate from the server. That was ok with my code.

          Cool.

          In the second step the server expects a certificate from the client.

          You set that via the kCFStreamSSLCertificates subkey of kCFStreamPropertySSLSettings.  Again, TLSTool shows an example of this.

          Share and Enjoy

          Quinn “The Eskimo!”
          Apple Developer Relations, Developer Technical Support, Core OS/Hardware
          let myEmail = "eskimo" + "1" + "@apple.com"