0

I'm trying to use SSL TCP connection between openssl on OS X and iOS(8.1 version). Exception Domains has 192.168.0.104.

Swift iOS code:

class SSLSocketLite {

    // The input stream.
    private var inStream: NSInputStream?
    // The output stream.
    private var outStream: NSOutputStream?
    // The host to connect to.
    private var host: String
    // The port to connect on.
    private var port: Int

    init(inHost:String, inPort:Int) {
        host = inHost
        port = inPort
        NSStream.getStreamsToHostWithName(host, port: port, inputStream: &inStream, outputStream: &outStream)
    }

    func Open() {
        inStream?.open()
        outStream?.open()

        inStream?.setProperty(NSStreamSocketSecurityLevelTLSv1, forKey: NSStreamSocketSecurityLevelKey)
        outStream?.setProperty(NSStreamSocketSecurityLevelTLSv1, forKey: NSStreamSocketSecurityLevelKey)

        inStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
        outStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
    }

    func Read() -> String! {
        var buffer = Array<UInt8>(count:1024, repeatedValue: 0)
        if inStream!.hasBytesAvailable {
            inStream!.read(&buffer, maxLength: 1024)
            let responseString = NSString(bytes: buffer, length: buffer.count, encoding: NSUTF8StringEncoding) as! String
            return responseString
        }
        return nil
    }

    func Write(msg:String) {
        let data:NSData = msg.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
        outStream!.write(UnsafePointer(data.bytes), maxLength: data.length)
    }

    func Close() {
        inStream?.close()
        outStream?.close()
    }
}


class ViewController: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()

        let sslsock = SSLSocketLite(inHost: "192.168.0.104", inPort: 1678)

        sslsock.Open()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

On the OS X side I created certificate and key using:

openssl req -x509 -newkey rsa:1024 -keyout key.key -out key.crt -days 365 -nodes

and launched TCP SSL server using:

openssl s_server -key key.key -cert key.crt -accept 1678

After that I got CFNetwork SSLHandshake failed (-9807) on the iOS side and bad gethostbyaddr on the OS X side. How can I solve this issue?

UPD:

1.touch openssl-ca.cnf

2.Copy-pasted in openssl-ca.cnf. One line changed:

commonName_default = localhost

3.openssl req -x509 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM

4.touch openssl-server.cnf

5.Copy-pasted in openssl-server.cnf. Two lines changed:

commonName_default = localhost

DNS.1 = localhost

6.openssl req -config openssl-server.cnf -newkey rsa:2048 -sha256 -nodes -out servercert.csr -outform PEM

7.Added 2 +1 sections in openssl-ca.cnf:

[ CA_default ]
    ...
    base_dir    = .
    certificate = $base_dir/cacert.pem  # The CA certifcate
    private_key = $base_dir/cakey.pem   # The CA private key
    new_certs_dir   = $base_dir     # Location for new certs after signing
    database    = $base_dir/index.txt   # Database index file
    serial      = $base_dir/serial.txt  # The current serial number

    unique_subject  = no            # Set to 'no' to allow creation of
                    # several certificates with same subject.

...

####################################################################
[ signing_policy ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

8.touch index.txt

9.echo '01' > serial.txt

10.openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr

11.openssl x509 -in servercert.pem -inform PEM -out servercert.der -outform DER

12.Added servercert.der in iOS project

13.let sslsock = SSLSocketLite(inHost: "localhost", inPort: 1678)

14.Exception Domains -> +localhost

15.openssl s_server -key serverkey.pem -cert servercert.pem -accept 1678

Final version of openssl-ca.cnf:

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ ca ]
default_ca  = CA_default        # The default ca section

[ CA_default ]

default_days    = 1000          # how long to certify for
default_crl_days= 30            # how long before next CRL
default_md  = sha256        # use public key default MD
preserve    = no            # keep passed DN ordering

x509_extensions = ca_extensions     # The extensions to add to the cert

email_in_dn = no            # Don't concat the email in the DN
copy_extensions = copy          # Required to copy SANs from CSR to cert

base_dir    = .
certificate = $base_dir/cacert.pem  # The CA certifcate
private_key = $base_dir/cakey.pem   # The CA private key
new_certs_dir   = $base_dir     # Location for new certs after signing
database    = $base_dir/index.txt   # Database index file
serial      = $base_dir/serial.txt  # The current serial number

unique_subject  = no            # Set to 'no' to allow creation of
                # several certificates with same subject.
####################################################################
[ req ]
default_bits        = 4096
default_keyfile     = cakey.pem
distinguished_name  = ca_distinguished_name
x509_extensions     = ca_extensions
string_mask         = utf8only

####################################################################
[ ca_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = Maryland

localityName            = Locality Name (eg, city)
localityName_default        = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test CA, Limited

organizationalUnitName  = Organizational Unit (eg, division)
organizationalUnitName_default  = Server Research Department

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = localhost

emailAddress            = Email Address
emailAddress_default        = test@example.com

####################################################################
[ ca_extensions ]

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign

####################################################################
[ signing_policy ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

Final version of openssl-server.cnf:

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ req ]
default_bits        = 2048
default_keyfile     = serverkey.pem
distinguished_name  = server_distinguished_name
req_extensions      = server_req_extensions
string_mask         = utf8only

####################################################################
[ server_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = MD

localityName            = Locality Name (eg, city)
localityName_default        = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test CA, Limited

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = localhost

emailAddress            = Email Address
emailAddress_default        = test@example.com

####################################################################
[ server_req_extensions ]

subjectKeyIdentifier        = hash
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

####################################################################
[ alternate_names ]

DNS.1       = localhost

iOS output:

SwiftPlayground[917:31077] CFNetwork SSLHandshake failed (-9807)

OpenSSL s_server output(nothing happened):

Using default temp DH parameters  
Using default temp ECDH parameters 
ACCEPT
konstantin_doncov
  • 2,725
  • 4
  • 40
  • 100
  • *`openssl req -x509 ...`* - What hostname did you use when you created the certificate? What is the `host, port` used in the Objective C code? Also see [How do you sign Certificate Signing Request with your Certification Authority](http://stackoverflow.com/a/21340898/608639) and [How to create a self-signed certificate with openssl?](http://stackoverflow.com/q/10175812/608639) It provides a lot of background information on X.509 server certificates, and where the various rules come from. – jww Aug 28 '16 at 03:38
  • @jww thanks. I did everything as said in [How do you sign Certificate Signing Request with your Certification Authority](http://stackoverflow.com/a/21340898/608639), after that I converted certificate: `openssl x509 -in servercert.pem -inform PEM -out servercert.der -outform DER`, added servercert.der in iOS application and started `sudo openssl s_server -key serverkey.pem -cert servercert.pem -accept 1678`. But got `SSLHandshake failed (-9807)` on the iOS side, and nothing on the OS X server side. What did I do wrong? – konstantin_doncov Aug 29 '16 at 18:06
  • If the X.509 and certificate and hostnames are OK, then turn to this next: `sudo openssl s_server ...` - Are you using Apple's OpenSSL 0.9.8? If so, you probably have to use OpenSSL 1.0.1 or higher. OpenSSL 1.0.2 would be a good choice. – jww Aug 29 '16 at 18:11
  • If you are using OpenSSL 1.0.1 or higher, then also be aware of Apple's `SecureTransport`/`ECDHE-ECDSA` bug. Its unpatched on a number of iOS and OS X hosts. Also see [`SSL_OP_SAFARI_ECDHE_ECDSA BUG`](http://wiki.openssl.org/index.php/SSL_OP_SAFARI_ECDHE_ECDSA_BUG) on the OpenSSL wiki. – jww Aug 29 '16 at 18:14
  • @jww `openssl version` out: `OpenSSL 0.9.8zg 14 July 2015`. I installed openssl using homebrew, so am I need to install version from another vendor? And are you sure that all commands in the my previous comment are valid? Is it ok to use `pem` version of servercert on the server side and `der` on the client side? – konstantin_doncov Aug 29 '16 at 18:22
  • @"I installed openssl using homebrew ..."* - But you don't seem to be using it... – jww Aug 29 '16 at 18:28
  • @jww what do you mean? – konstantin_doncov Aug 29 '16 at 18:31
  • @jww I tried all night to do what you wrote, but still have no progress. So I added in the question sequence of commands which I used for these attempt, final versions of files and output(you can see it in the **UPD** section). – konstantin_doncov Aug 30 '16 at 02:59
  • @jww I understood what you said about `homebrew` and `openssl`. I really used openssl instance which was installed not using `brew`. Now I all the way used `/usr/local/Cellar/openssl/1.0.2g/bin/openssl` file with `1.0.2g` version. But iOS still throws `CFNetwork SSLHandshake failed (-9807)`. Do you have any suggestions? – konstantin_doncov Aug 30 '16 at 15:11
  • @jww now I used tested Objective-C sample code from another StackOverflow answer and it threw the same error([you can check it](http://stackoverflow.com/questions/39239817/cfnetwork-sslhandshake-failed-9807-on-ios-simulator-with-localhost)). Still don't know what I do wrong – konstantin_doncov Aug 31 '16 at 03:01

1 Answers1

0

I wrote a package to help with handling this problem, unfortunately for you it is Obj-C, but I do have resources on there namely for creating certificates that will work with the new iOS 13 TLS restrictions. Here is a link to a tutorial for creating a CA, intermediate CA, and server/user certificates.

https://jamielinux.com/docs/openssl-certificate-authority/introduction.html

If you follow it exactly you will have working certificates, except that the tutorial doesn't take into account one of the most recent changes. However, if you use my configuration files, I made the necessary small changes to make it so that the certificates will work, if you just follow the process of the tutorial - here you can find those configuration files:

https://github.com/eamonwhiter73/IOSObjCWebSockets

You will have to make a few small changes to the configuration files - your base path, and the DNS names all the way at the bottom of each file.

ewizard
  • 2,801
  • 4
  • 52
  • 110