0

I am trying to figure out what about my TLS handshake is failing. I am not exactly sure what this error code means. Can someone provide more context here?

2000-00-00T00:00:00-0000 error [[GRPC-LOGG]] : error=handshakeFailed(NIOSSL.BoringSSLError.sslError([Error: 268436496 error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE at /Users/username/Library/Developer/Xcode/DerivedData/ios-dc-bocetydygnmhxsdxqxaivnvasghk/SourcePackages/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/tls_record.cc:592])) grpc.conn.addr_local=10.220.93.246 grpc.conn.addr_remote=23.98.156.101 grpc_connection_id=C1C6376D-9F74-48AF-9D7A-D903BB68D716/0 [GRPC] grpc client error

I did take a look at the tls_record.cc file; which is reporting SSL3_AL_FATAL. The tls_record.cc can be seen below.

tls_record.cc

f (alert_level == SSL3_AL_FATAL) {
    OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
    ERR_add_error_dataf("SSL alert number %d", alert_descr);
    *out_alert = 0;  // No alert to send back to the peer.
    return ssl_open_record_error;
  }



I am using gRPC-Swift to make this call.

        var clientConnection: ClientConnection.Builder

        var tlsConfig = TLSConfiguration.makeClientConfiguration()
        tlsConfig.certificateVerification = .noHostnameVerification
        tlsConfig.trustRoots = .certificates([nioCert!])
        
        let clientConfig = GRPCTLSConfiguration.makeClientConfigurationBackedByNIOSSL(configuration: tlsConfig, hostnameOverride: sniName)
        
        clientConnection = ClientConnection.usingTLS(with: clientConfig, on: eventLoopGroup)
                .withTLSCustomVerificationCallback({ ... })

        clientConnection.connect(host: hostName, port: port)
    



When running curl -v https://hostname:port/foo command, this is what I get back from the server:

*   Trying 12.43.425.642:443...
* Connected to q003.ed14.ws.samplecloud.dogi (12.43.425.642) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
* LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to q003.ed14.ws.samplecloud.dogi:443 
* Closing connection 0
curl: (35) LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to q003.ed14.ws.samplecloud.dogi:443

I have added a ClientError Logger to the gRPC connection and this is what I am getting:

[!! GRPC-CLIENT-ERROR]: handshakeFailed(NIOSSL.BoringSSLError.sslError([Error: 268435581 error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED at /Users/username/Library/Developer/Xcode/DerivedData/ios-dc-bocetydygnmhxsdxqxaivnvasghk/SourcePackages/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/handshake.cc:393])) file:[<unknown>] line:[0]]



The error in the log above points back to the tls_record:

 if (alert_level == SSL3_AL_FATAL) {
    OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr); // << this line
    ERR_add_error_dataf("SSL alert number %d", alert_descr);
    *out_alert = 0;  // No alert to send back to the peer.
    return ssl_open_record_error;
  }

I think there is an issue with how I am attaching my certificates. When I view the network traffic, I do not see any client certificate showing up in the TLS handshake:

Client Certificates: -
Server Certificates: 3

It seems as though I was attaching my certificates to swift-grpc's server part of the framework and not the client, this is how you attach them for the client-side:

        tlsConfig.certificateChain = [.certificate(nioCert!)]
        
        let privateKeyNIO = try? NIOSSLPrivateKey.init(bytes: privateKeyByteAry, format: .der)
        tlsConfig.privateKey = NIOSSLPrivateKeySource.privateKey(privateKeyNIO!)

Note that I am still getting the same error as reported above.

Update:

I have confirmed that the client certificates are not showing up in the request. I am not sure why this is the case; I am clearly attaching a client cert.


    tlsConfig.certificateChain = [NIOSSLCertificateSource.certificate(nioCert!)]
    let privateKeyNIO = try? NIOSSLPrivateKey.init(bytes: privateKeyByteAry, format: .der)
    tlsConfig.privateKey = NIOSSLPrivateKeySource.privateKey(privateKeyNIO!)
wizeOnes
  • 119
  • 16
  • Two questions: 1. What happens if you `curl -v https://hostname:port/foo` ? 2. What’s inside your custom verification callback? – Johannes Weiss Feb 04 '23 at 20:46
  • Also, what’s in `sniName`? Are you passing the correct hostname there? Because the remote side will see the SNI name and potentially serve you different certs depending on what you send there. – Johannes Weiss Feb 04 '23 at 20:48
  • I have updated the post to display results from `curl`. – wizeOnes Feb 04 '23 at 20:58
  • The sni name contains: `PORT.hostname` to route through to the correct port when routing through the proxy. – wizeOnes Feb 04 '23 at 21:05
  • The verification callback is basically taking the certs from the server and comparing them to the cert on the client (comparing their public keys) to see if we have any of the certs from the server. I am actually forcing a successful validation in the callback to figure out find out why I am receiving this error; this way I know its not failing because of the verification callback. – wizeOnes Feb 04 '23 at 21:13
  • Note that the sni contains the same `hostname` that is originally called in `curl` – wizeOnes Feb 04 '23 at 21:15
  • Hmm, I don't think the `curl` command had a `https://` URL, this looks like `curl` tried to speak plaintext HTTP to the server on port 443 (which the server rejected). This looks like a `curl -v http://server:port/foo` and not the `curl -v https://server:port/foo` that we need. Mind double-checking? – Johannes Weiss Feb 05 '23 at 21:22
  • @JohannesWeiss Yes, looks like I ran it with `http`. I have updated the `curl` results to display the proper output. I also left out `tlsConfig.trustRoots = .certificates([nioCert!])` ; which has now been added. – wizeOnes Feb 05 '23 at 23:41
  • I have added a bit more context, I think there is something wrong with the way the client `NIOSSLCertificate` is being added. Is this not the way you add them? – wizeOnes Feb 05 '23 at 23:51
  • Okay thank you, curl is seeing the same issue and the TLS handshake doesn’t complete. Are you sure you have the right hostname/port? This server doesn’t appear to speak TLS. So this looks like a configuration problem with host/port or how the server is set up. – Johannes Weiss Feb 07 '23 at 07:20
  • @JohannesWeiss I have confirmed with my backend dev that the client certificates are in-fact missing. I see the client cert missing in the network traffic as well. Why do you question the host/port? Is it possible that the certs are not being attached correctly? – wizeOnes Feb 07 '23 at 21:05

0 Answers0