Skip to content

Handshake failing when client specifies custom certificate chain in its TLSConfiguration #46

@keithcorbs

Description

@keithcorbs

Hi all,

I have built an HTTP client using the Swift NIO and Swift NIO SSL framework, and my client needs to call a server endpoint that issues certificates signed with a private internal certificate authority. Because of this, my HTTP client needs to provide the internal public certificates needed to complete the SSL handshake and complete the request.

Given the current documentation, I tried doing this with swift-nio-ssl in two different ways, and neither of them worked. I tried the following:

  1. Providing each certificate individually in the certificate chain of the TLS configuration:
let cert1 = try OpenSSLCertificate(file: "/usr/local/share/ca-certificates/cert-1.pem", format: OpenSSLSerializationFormats.pem)
let cert2 = try OpenSSLCertificate(file: "/usr/local/share/ca-certificates/cert-2.pem", format: OpenSSLSerializationFormats.pem)
let cert3 = try OpenSSLCertificate(file: "/usr/local/share/ca-certificates/cert-3.pem", format: OpenSSLSerializationFormats.pem)
let certificateChain: [OpenSSLCertificateSource] = [.certificate(cert1), .certificate(cert2), .certificate(cert3)]
let tlsConfiguration = TLSConfiguration.forClient(certificateChain: certificateChain)
  1. Providing a single certificate, which is just all of the above certificates concatenated together:
let allCerts = try OpenSSLCertificate(file: "/usr/local/share/ca-certificates/allCerts.pem", format: OpenSSLSerializationFormats.pem)
let certificateChain: [OpenSSLCertificateSource] = [.certificate(allCerts)]
let tlsConfiguration = TLSConfiguration.forClient(certificateChain: certificateChain)

And both options caused my request to fail with the following Error in our errorCaught function of our ChannelInboundHandler protocol implementation:

Error received from HTTP connection: handshakeFailed(NIOOpenSSL.OpenSSLError.sslError([Error: 335573126 error:14007086:SSL routines:CONNECT_CR_CERT:certificate verify failed]))

Debugging further into this, it seems to go into the low level details of SSL and it might be beyond my high level comprehension of what's going on. Both seem to be failing in similar fashion.

To provide context into a related working way to call this manually - I was able to verify that I can get a response back with the following curl command by specifying the concatenated certificate file, and I was expecting similar behavior in swift-nio-ssl by providing the concatenated certificate file to the TLSConfiguration:

curl 'https://private-service.com:443/privateServiceOperation' -H 'Host https://private-service.com:443' -H 'User-Agent: CurlRequest' -H 'Accept: */*' --cacert /usr/local/share/ca-certificates/allCerts.pem

I was wondering if this was a supported feature by swift-nio-ssl, and if not, could it be a supported feature? Let me know if you need more details.

Thank you,
Keith

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions