I am trying to do mTLS with a server using gRPC 1.46.0/OpenSSL 3.0.3 on 
Linux/C++

Below is a snippet of how I prepare `SSLChannelCredentials`:

std::shared_ptr<grpc::ChannelCredentials> GetChannelCredentials() {
  std::ifstream root_cert_path(GetRootCertPath());
  std::string root_cert(std::istreambuf_iterator<char>{root_cert_path}, {});

  std::ifstream client_key_path(GetClientKeyPath());
  std::string client_key(std::istreambuf_iterator<char>{client_key_path}, 
{});

  std::ifstream client_cert_path(GetClientCertPath());
  std::string client_cert(std::istreambuf_iterator<char>{client_cert_path}, 
{});

  grpc::SslCredentialsOptions cred_opts;

  cred_opts.pem_root_certs = root_cert;
  cred_opts.pem_private_key = client_key;
  cred_opts.pem_cert_chain = client_cert;

  return grpc::SslCredentials(cred_opts);
}

And this fails with the following debug log:

I0617 10:21:51.992245501 409 socket_utils_common_posix.cc:353] 
TCP_USER_TIMEOUT is available. TCP_USER_TIMEOUT will be used thereafter 
I0617 10:21:54.979146083 407 ssl_transport_security.cc:226] HANDSHAKE START 
- before SSL initialization - PINIT I0617 10:21:54.979203105 407 
ssl_transport_security.cc:226] LOOP - before SSL initialization - PINIT 
I0617 10:21:54.979849401 407 ssl_transport_security.cc:226] LOOP - 
SSLv3/TLS write client hello - TWCH I0617 10:21:59.975724008 409 
ssl_transport_security.cc:226] LOOP - SSLv3/TLS write client hello - TWCH 
I0617 10:21:59.975958355 409 ssl_transport_security.cc:226] LOOP - 
SSLv3/TLS read server hello - TRSH I0617 10:21:59.975972388 409 
ssl_transport_security.cc:226] LOOP - TLSv1.3 read encrypted extensi - TREE 
I0617 10:21:59.976032247 409 ssl_transport_security.cc:226] LOOP - 
SSLv3/TLS read server certific - TRCR E0617 10:21:59.976188482 409 
ssl_transport_security.cc:1495] Handshake failed with fatal error 
SSL_ERROR_SSL: error:1416F086:SSL 
routines:tls_process_server_certificate:certificate verify failed. D0617 
10:21:59.976230069 409 security_handshaker.cc:181] Security handshake 
failed: {"created":"@1655461319.976196203","description":"Handshake 
failed","file":"/grpc/src/core/lib/security/transport/security_handshaker.cc","file_line":377,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}
 
I0617 10:21:59.976453245 409 subchannel.cc:948] subchannel 0x619000064a80 
{address=ipv6:[2a05:d014:c4b:3500:bb49:5b5c:47c:5191]:443, 
args=grpc.client_channel_factory=0x602000001cb0, 
grpc.default_authority=mtls.gateway.nightowl.go-e.co:443, 
grpc.http2.max_pings_without_data=0, grpc.http2_scheme=https, 
grpc.internal.channel_credentials=0x606000005b40, 
grpc.internal.security_connector=0x60d000023280, 
grpc.internal.subchannel_pool=0x607000009b70, 
grpc.keepalive_permit_without_calls=1, grpc.keepalive_time_ms=86400000, 
grpc.keepalive_timeout_ms=86400000, 
grpc.primary_user_agent=grpc-c++/1.46.0, 
grpc.resource_quota=0x60400000fa90, 
grpc.server_uri=dns:///mtls.gateway.nightowl.go-e.co:443}: connect failed: 
{"created":"@1655461319.976196203","description":"Handshake 
failed","file":"/grpc/src/core/lib/security/transport/security_handshaker.cc","file_line":377,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}

This is really surprising, because I thought the prefix SSL in 
SSLChannelCredentials is only for historical purposes and it does not 
actually try to use SSLv3 any more.

To double check, I used the Python bindings to put together a simple 
example:

def certs():
    path = "certificate_file_path"
    with open(path + "ca.crt") as fd:
        ca = fd.read()
    with open(path + "client.crt") as fd:
        crt = fd.read()
    with open(path + "client.key") as fd:
        key = fd.read()
    return {
        "root_certificates": ca.encode("utf8"),
        "private_key": key.encode("utf8"),
        "certificate_chain": crt.encode("utf8"),
    }

async def main() -> None:
    credentials = grpc.ssl_channel_credentials(**certs())
    async with grpc.aio.secure_channel(
        "server_url:port", credentials
    ) as channel:
        stub = xxxxx(channel)
        await stream(stub)

And surely enough, this works like a charm with the following debug log:

D0617 12:25:37.611607359 5824 certificate_provider_registry.cc:33] 
registering certificate provider factory for "file_watcher" D0617 
12:25:37.611612059 5824 lb_policy_registry.cc:42] registering LB policy 
factory for "cds_experimental" D0617 12:25:37.611812743 5824 
lb_policy_registry.cc:42] registering LB policy factory for 
"xds_cluster_impl_experimental" D0617 12:25:37.611817173 5824 
lb_policy_registry.cc:42] registering LB policy factory for 
"xds_cluster_resolver_experimental" D0617 12:25:37.611824862 5824 
lb_policy_registry.cc:42] registering LB policy factory for 
"xds_cluster_manager_experimental" E0617 12:25:37.611829462 5824 
trace.cc:66] Unknown trace var: 'transport_security' I0617 
12:25:37.664472925 5825 ssl_transport_security.cc:226] HANDSHAKE START - 
TLS client start_connect - !!!!!! I0617 12:25:37.664616500 5825 
ssl_transport_security.cc:226] LOOP - TLS client enter_early_data - !!!!!! 
I0617 12:25:37.664622010 5825 ssl_transport_security.cc:226] LOOP - TLS 
client read_server_hello - !!!!!! I0617 12:25:37.694303510 5828 
ssl_transport_security.cc:226] LOOP - TLS 1.3 client read_hello_retr - 
!!!!!! I0617 12:25:37.694320800 5828 ssl_transport_security.cc:226] LOOP - 
TLS 1.3 client read_server_hel - !!!!!! I0617 12:25:37.694401058 5828 
ssl_transport_security.cc:226] LOOP - TLS 1.3 client read_encrypted_ - 
!!!!!! I0617 12:25:37.694410227 5828 ssl_transport_security.cc:226] LOOP - 
TLS 1.3 client read_certificat - !!!!!! I0617 12:25:37.694434267 5828 
ssl_transport_security.cc:226] LOOP - TLS 1.3 client read_server_cer - 
!!!!!! I0617 12:25:37.694463286 5828 ssl_transport_security.cc:226] LOOP - 
TLS 1.3 client read_server_cer - !!!!!! I0617 12:25:37.694742638 5828 
ssl_transport_security.cc:226] LOOP - TLS 1.3 client read_server_fin - 
!!!!!! I0617 12:25:37.694764417 5828 ssl_transport_security.cc:226] LOOP - 
TLS 1.3 client send_end_of_ear - !!!!!! I0617 12:25:37.694769907 5828 
ssl_transport_security.cc:226] LOOP - TLS 1.3 client send_client_enc - 
!!!!!! I0617 12:25:37.694773247 5828 ssl_transport_security.cc:226] LOOP - 
TLS 1.3 client send_client_cer - !!!!!! I0617 12:25:37.694779987 5828 
ssl_transport_security.cc:226] LOOP - TLS 1.3 client send_client_cer - 
!!!!!! I0617 12:25:37.695587273 5828 ssl_transport_security.cc:226] LOOP - 
TLS 1.3 client complete_second - !!!!!! I0617 12:25:37.695603763 5828 
ssl_transport_security.cc:226] LOOP - TLS 1.3 client done - !!!!!! I0617 
12:25:37.695607223 5828 ssl_transport_security.cc:226] LOOP - TLS client 
finish_client_hands - !!!!!! I0617 12:25:37.695614203 5828 
ssl_transport_security.cc:226] LOOP - TLS client done - !!!!!! I0617 
12:25:37.695616983 5828 ssl_transport_security.cc:226] HANDSHAKE DONE - TLS 
client done - !!!!!!

So, the python bindings try nothing but TLS 1.3, which is exactly what I 
expected.

I figured, perhaps the SSL in SSLChannelCredentials in C++ is taken 
literally by the gRPC team and I am supposed to use the experimental 
TLSCredentials. So I tried something like this:

std::shared_ptr<grpc::ChannelCredentials> GetChannelCredentials() {
  std::ifstream root_cert_path(GetRootCertPath());
  std::string root_cert(std::istreambuf_iterator<char>{root_cert_path}, {});

  std::ifstream client_key_path(GetClientKeyPath());
  std::string client_key(std::istreambuf_iterator<char>{client_key_path}, 
{});

  std::ifstream client_cert_path(GetClientCertPath());
  std::string client_cert(std::istreambuf_iterator<char>{client_cert_path}, 
{});

  std::vector<grpc::experimental::IdentityKeyCertPair> keypairs = 
{{client_key, client_cert}};
  auto certificate_provider = 
std::make_shared<grpc::experimental::StaticDataCertificateProvider>(root_cert, 
keypairs);
  grpc::experimental::TlsChannelCredentialsOptions cred_opts;
  cred_opts.set_certificate_provider(certificate_provider);
  cred_opts.
  cred_opts.set_verify_server_certs(true);
  return grpc::experimental::TlsCredentials(cred_opts);
}

And at least this tries to do TLS 1.3, but fails with the following message:

I0617 19:26:21.349515081   81267 ssl_utils.cc:422]           No root 
certificates specified; use ones stored in system default locations instead
I0617 19:26:21.360184162   81267 ssl_utils.cc:422]           No root 
certificates specified; use ones stored in system default locations instead
I0617 19:26:21.360424123   81267 ssl_utils.cc:422]           No root 
certificates specified; use ones stored in system default locations instead
I0617 19:26:21.360607314   81267 ssl_utils.cc:422]           No root 
certificates specified; use ones stored in system default locations instead
I0617 19:26:21.360816715   81267 ssl_utils.cc:422]           No root 
certificates specified; use ones stored in system default locations instead
I0617 19:26:21.361017545   81267 ssl_utils.cc:422]           No root 
certificates specified; use ones stored in system default locations instead
I0617 19:26:21.361262535   81267 socket_utils_common_posix.cc:353] 
TCP_USER_TIMEOUT is available. TCP_USER_TIMEOUT will be used thereafter
I0617 19:26:24.348350517   81265 ssl_transport_security.cc:226]     
 HANDSHAKE START -      before SSL initialization  - PINIT 
I0617 19:26:24.348468056   81265 ssl_transport_security.cc:226]             
    LOOP -      before SSL initialization  - PINIT 
I0617 19:26:24.348747673   81265 ssl_transport_security.cc:226]             
    LOOP -   SSLv3/TLS write client hello  -  TWCH
I0617 19:26:29.347766352   81267 ssl_transport_security.cc:226]             
    LOOP -   SSLv3/TLS write client hello  -  TWCH
I0617 19:26:29.348116633   81267 ssl_transport_security.cc:226]             
    LOOP -    SSLv3/TLS read server hello  -  TRSH
I0617 19:26:29.348155419   81267 ssl_transport_security.cc:226]             
    LOOP - TLSv1.3 read encrypted extensi  -  TREE
I0617 19:26:29.348220587   81267 ssl_transport_security.cc:226]             
    LOOP - SSLv3/TLS read server certific  -  TRCR
E0617 19:26:29.348505470   81267 ssl_transport_security.cc:1495] Handshake 
failed with fatal error SSL_ERROR_SSL: error:1416F086:SSL 
routines:tls_process_server_certificate:certificate verify failed.
D0617 19:26:29.348590787   81267 security_handshaker.cc:181] Security 
handshake failed: 
{"created":"@1655486789.348516884","description":"Handshake 
failed","file":"/home/ssengupta/git/grpc/src/core/lib/security/transport/security_handshaker.cc","file_line":377,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}
I0617 19:26:29.348826737   81267 subchannel.cc:948]          subchannel 
0x619000065480 {address=ipv6:[2a05:d014:c4b:3500:bb49:5b5c:47c:5191]:443, 
args=grpc.client_channel_factory=0x602000001cb0, 
grpc.default_authority=mtls.gateway.nightowl.go-e.co:443, 
grpc.http2.max_pings_without_data=0, grpc.http2_scheme=https, 
grpc.internal.channel_credentials=0x60300001e010, 
grpc.internal.security_connector=0x613000040700, 
grpc.internal.subchannel_pool=0x6070000099b0, 
grpc.keepalive_permit_without_calls=1, grpc.keepalive_time_ms=86400000, 
grpc.keepalive_timeout_ms=86400000, 
grpc.primary_user_agent=grpc-c++/1.46.0-dev, 
grpc.resource_quota=0x60400000fa90, 
grpc.server_uri=dns:///mtls.gateway.nightowl.go-e.co:443}: connect failed: 
{"created":"@1655486789.348516884","description":"Handshake 
failed","file":"/home/ssengupta/git/grpc/src/core/lib/security/transport/security_handshaker.cc","file_line":377,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"}

I am confused now what I should do. What is the preferred method to use TLS 
with a gRPC client for C++?

-- 
You received this message because you are subscribed to the Google Groups 
"grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/grpc-io/9e694bf9-264b-4104-a06c-71ab73ef9fc6n%40googlegroups.com.

Reply via email to