CFStream with TLS

890 Views Asked by At

Is it possible to communicate on a CFStream with TLS 1.2? If yes, what is the best way? Setting a SSLContext or setting the CFReadStreamSetProperty? Unfortunately I cannot find any example for this.

1

There are 1 best solutions below

1
On

Here is my code, if someone is also searching for this:

var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
var inputStream: InputStream!
var outputStream: OutputStream!

func connectToServer(host: String, port: Int, ssl: Bool=true) throws {
    self.ssl = ssl

    // Create StreamPair
    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host as CFString, UInt32(port), &readStream, &writeStream)

    // CFStreamCreatePairWithSocketToHost creates unmanaged CFReadStreams. So let's take the retained value
    // we have to release those values!
    inputStream = readStream!.takeRetainedValue()
    outputStream = writeStream!.takeRetainedValue()

    if ssl == true {
        let dict = [
            kCFStreamSSLValidatesCertificateChain: kCFBooleanFalse,     // allow self-signed certificate
            kCFStreamSSLLevel: "kCFStreamSocketSecurityLevelTLSv1_2"    // don't understand, why there isn't a constant for version 1.2
            ] as CFDictionary

        let sslSetRead = CFReadStreamSetProperty(inputStream, CFStreamPropertyKey(kCFStreamPropertySSLSettings), dict)
        let sslSetWrite = CFWriteStreamSetProperty(outputStream, CFStreamPropertyKey(kCFStreamPropertySSLSettings), dict)

        if sslSetRead == false || sslSetWrite == false {
            throw ConnectionError.sslConfigurationFailed
        }
    }

    // set the delegate of the streams
    inputStream.delegate = self
    outputStream.delegate = self

    // schedule the streams for the runLoop
    inputStream.schedule(in: .current, forMode: .commonModes)
    outputStream.schedule(in: .current, forMode: .commonModes)

    // open the streams
    inputStream.open()
    outputStream.open()
}