BIO_read/write and SSL_write/SSL_read APIs

2,478 views
Skip to first unread message

shikhach...@gmail.com

unread,
Dec 3, 2015, 11:34:56 AM12/3/15
to grpc.io
Hello , 

In grpc secuirty code  : 
1) SSL_write is followed by BIO_read & 
2) SSL_read  is followed by BIO_write 

Is this for some sort of cross checking ? Whether we have written correctly in SSL ?
Could you share when to use BIO_read & when to use SSL_read?I checked the openssl manual but the difference is not that clear.

-Shikha

Nicolas Noble

unread,
Dec 3, 2015, 1:33:45 PM12/3/15
to shikhach...@gmail.com, grpc.io
I didn't write that code, but I can answer that one. The SSL layer is setup to work in buffer mode. So doing SSL_write means we're sending unencrypted bytes to the SSL library, so that it can encrypt these bytes and put the resulting encrypted bytes in a buffer. Then we read from the buffer using BIO_read. Same thing in reverse for reading. We ACTUALLY do BIO_write then SSL_read in that case.


I am guessing that you're trying to plug your own SSL library into gRPC, hereby trying to read our implementation to know how to do that ?

--
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 grpc-io+u...@googlegroups.com.
To post to this group, send email to grp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/62cdfcc2-9cbe-4bee-9cfa-f4d258def642%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

shikhach...@gmail.com

unread,
Dec 4, 2015, 4:51:00 AM12/4/15
to grpc.io, shikhach...@gmail.com
Hey could you rephrase again , i am still not clear .

Let's consider client side code only : 

- Client is sending some data using SSL_write. Then in the server we  will do SSL_read/BIO_read. But here  BIO_read is done on the client side itself , client is trying to read what is written during SSL_write . So could you share the reason that?
- They are memory BIOs. Aware about the link b/w a SSL_writte & BIO_write ?


-Thanks

Nicolas Noble

unread,
Dec 4, 2015, 4:46:35 PM12/4/15
to Shikha Chowdhary, grpc.io
I think the portion of information you didn't understand is that https://github.com/grpc/grpc/blob/master/src/core/tsi/ssl_transport_security.c doesn't actually send or receive bytes from the tcp socket. All of what that code is doing is processing memory buffers.

When gRPC wants to send data down that need to be encrypted, we will eventually end up calling ssl_protector_protect. This gets one "in" buffer, which is the unencrypted bytes, and one "out" buffer, which needs to be filled with the encrypted bytes. So we call SSL_write (see https://github.com/grpc/grpc/blob/master/src/core/tsi/ssl_transport_security.c#L700) to transfer the gRPC input buffer into SSL's input buffer. Then we call BIO_read (see https://github.com/grpc/grpc/blob/master/src/core/tsi/ssl_transport_security.c#L704) to transfer the SSL's output buffer into gRPC's output buffer, which is the same data as the input, but encrypted. At that point, once the function exits, the upper network layer of gRPC will send the encrypted bytes over the network.

Symmetrically, when gRPC receives data that needs to be decrypted, we will eventually end up calling ssl_protector_unprotect. This gets one "in" buffer, which is the encrypted bytes, and one "out" buffer, which needs to be filled with the unencrypted bytes. So we call BIO_write (see https://github.com/grpc/grpc/blob/master/src/core/tsi/ssl_transport_security.c#L773) to transfer the gRPC input buffer into SSL's input buffer. Then we call SSL_read (see https://github.com/grpc/grpc/blob/master/src/core/tsi/ssl_transport_security.c#L783) to transfer the SSL's output buffer into gRPC's output buffer, which will then be the same data as the input, but decrypted. At that point, once the function exits, the upper layer of gRPC will process the output buffer.


In all cases, your questions are very OpenSSL-specific, and not really gRPC-specific. I would recommend asking them on the OpenSSL mailing list.

shikhach...@gmail.com

unread,
Dec 6, 2015, 11:45:01 AM12/6/15
to grpc.io, shikhach...@gmail.com
Thanks a ton Nicolas , Big help.
I was really confused about these API , i am new to all the SSL lib API stuff.

Again , Thank you so much.

shikhach...@gmail.com

unread,
Dec 9, 2015, 1:30:44 AM12/9/15
to grpc.io, shikhach...@gmail.com
Is there any specific reason for using memory BIOs in gRPC. gRPC is doing lot of processing in this case on its own. 
- On the other hand , socket BIO appears much simpler , you can simple transfer the fd to SSL layer.

I am assuming some performance gain for choosing memory BIOs, but still if you could share the reason.


-Shikha

Nicolas Noble

unread,
Dec 9, 2015, 3:05:04 AM12/9/15
to Shikha Chowdhary, grpc.io
Long story short, because our event model is quite incompatible with delegating the file descriptor to the SSL layer.

Remember that gRPC has non-SSL support as well, so all of the socket reading code needs to be present anyway. Meaning that all of the socket processing code had to be present anyway, so we're not doing much extra processing just to have memory BIOs. In case, this simplifies the code so that we can reuse the same socket reading code, and feed the results into an SSL processor. This also simplifies potential implementations of other SSL libraries, since not all of them might provide socket reading interfaces.

shikhach...@gmail.com

unread,
Dec 9, 2015, 4:05:47 AM12/9/15
to grpc.io, shikhach...@gmail.com
Ook , Thank you so much.

shikhach...@gmail.com

unread,
Dec 15, 2015, 8:44:57 AM12/15/15
to grpc.io, shikhach...@gmail.com
Hey , now i am clear about the security flow. 

Could you please share how to test the SSL layer using test/dummy  credentials.I am using the following version of client & server:

(A)SERVER

  std::string server_address("localhost:40000");
  GreeterServiceImpl service;
  SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key, test_server1_cert};
  SslServerCredentialsOptions ssl_opts;
  ssl_opts.pem_root_certs = test_root_cert;
  ssl_opts.pem_key_cert_pairs.push_back(pkcp);
  ServerBuilder builder;
  builder.AddListeningPort(server_address, grpc::SslServerCredentials(ssl_opts));
  builder.RegisterService(&service);
  std::unique_ptr<Server> server(builder.BuildAndStart());
  server->Wait();


(B) CLIENT

      SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
      Client greeter(grpc::CreateChannel("localhost:40000", SslCredentials(ssl_opts), ChannelArguments()));
      greeter.Run();


(C) ERRORS : I am getting the following error on server : 
 create_tsi_ssl_handshaker 
 ssl_handshaker_get_bytes_to_send_to_peer, BIO_read :-1
 ssl_handshaker_process_bytes_from_peer
 ssl_handshaker_process_bytes_from_peer, BIO_write :176
 SSL_do_handshake calling .
 No match found for server name: localhost.
 SSL_get_error :1.
 Handshake failed with fatal error SSL_ERROR_SSL: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher.
 Handshake failed with error TSI_PROTOCOL_FAILURE
 Secure transport failed with error 2


-Thanks

Julien Boeuf

unread,
Dec 16, 2015, 5:28:38 PM12/16/15
to grpc.io, shikhach...@gmail.com
Hello,

On the client-side, you need to set the SslTargetNameOverride on the ChannelArguments so that it matches the name that you have on your cert.
See:

Cheers,

    Julien.
Reply all
Reply to author
Forward
0 new messages