Using OpenSSL for making a network TLS server

Hi, Ruby EventMachine has some issues in its TLS implementation (coded
in C++ using OpenSSL) as noted in
Memory leak with start_tls · Issue #266 · eventmachine/eventmachine · GitHub.

I’ve been suggested by the author of the project to make a TLS stack
on pure Ruby (by using OpenSSL) and I want to start with it. I’d like
to ask some very basic questions so I can investigate how to achieve
it:

  • Imagine that a Ruby server receives a TLS connection from a client.
    I assume that my server must implement the TLS handshake protocol at
    pure Ruby level, this is, OpenSSL will not help me with this, am I
    right?

  • Once such TLS handshake is started, I could receive a certificate
    from the client, such certificate must be parsed “manually” at Ruby
    level in the server (OpenSSL will not help me with this),am I right?

  • I must also send my certificate(s) to the peer (again at Ruby level).

  • After previous steps, I expect that TLS connection is done so I will
    receive data from the client. And I should process/decrypt such data
    by using some OpenSSL::XXXXXXX instance and method, am I right?

  • And in case I reply data to the client, I must first encrypt the
    data using some OpenSSL::XXXXXXXX instance and method, and then send
    the generated data to the client, am I right?

Thanks a lot for any input that helps me starting with this stuff.

Ruby’s OpenSSL library has an SSLServer class that will do exactly what
you’re asking. Here is just some quick example code (most of the code is
just building a self-signed cert, you could just as easily load this
from a
file):

require ‘openssl’
require ‘socket’

tcp_server = TCPServer.new 8080

ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new 2048
ctx.cert = OpenSSL::X509::Certificate.new
ctx.cert.subject = OpenSSL::X509::Name.new [[‘CN’, ‘localhost’]]
ctx.cert.issuer = ctx.cert.subject
ctx.cert.public_key = ctx.key
ctx.cert.not_before = Time.now
ctx.cert.not_after = Time.now + 60 * 60 * 24
ctx.cert.sign ctx.key, OpenSSL::Digest::SHA1.new

server = OpenSSL::SSL::SSLServer.new tcp_server, ctx
socket = server.accept
puts socket.gets

With anything having to do with crypto I would highly recommend not
trying
to create the solution yourself (it is far to easy to screw up). Instead
you should take time to review existing solutions that have been “battle
hardened.”

2011/12/2 Iñaki Baz C. [email protected]:

server = OpenSSL::SSL::SSLServer.new tcp_server, ctx
socket = server.accept
puts socket.gets

With anything having to do with crypto I would highly recommend not trying
to create the solution yourself (it is far to easy to screw up). Instead
you should take time to review existing solutions that have been “battle
hardened.”

Hi, unfortunatelly the above solution is not valid for me. What I want
to do is using OpenSSL on top of a EventMachine TCP connection.

EventMachine manages all the sockets and connections internally (at
C++ level), and creates an instance of EM::Connection Ruby class for
each TCP connection (a server connection). Such EM::Connection class
provides some callbacks:


class MyTcpServer < EM::Connection
def receive_data data
puts “data reveiced on this connection: #{data}”
end
end

And includes a method “send_data(data)” to send data over the
connection.

So I don’t have a Ruby Socket instance. Instead I receive the raw TCP
data in that connection. In my case, such TCP data initially contains
the client’s SSL handshake, so I need a way to pass such handshake to
a Ruby OpenSSL::XXX instance. I also need a way to encrypt data based
on the SSL handshake and write it into a raw string, so I can call
EM::Connection#send_data(data) over the TLS connection.

Unfortunatelly it seems that Ruby OpenSSL does not provide a mechanism
for that, and it requires passing a real Ruby Socket as argument for
OpenSSL::SSL::SSLSocket and OpenSSL::SSL::SSLServer. Any suggestion
please?

A workaround I’m thinking about is using an intermediary like-socket,
so when I receive TCP data over the EM::Connection#receive_data(data)
method, I send such raw data to the intermediary socket, and
previously I passed such intermediary socket during the initialitation
of the OpenSSL::SSL::SSLSocket instance (so the SSL handshake and
decryption is done by OpenSSL as usual). But I don’t know how to
implement this “concept”, and I would prefer not to deal with an
“intermediary socket”.

Thanks a lot for any suggestion.

Any suggestion about this please? Maybe the only response is that
“there is no way” (hope not) :slight_smile:

Thanks a lot.

2011/12/5 Iñaki Baz C. [email protected]:

2011/12/2 John D. [email protected]:

ctx = OpenSSL::SSL::SSLContext.new
socket = server.accept
puts socket.gets

With anything having to do with crypto I would highly recommend not trying
to create the solution yourself (it is far to easy to screw up). Instead
you should take time to review existing solutions that have been “battle
hardened.”

Really thanks a lot.

2011/12/7 Brian C. [email protected]:

Definitely don’t write a TLS implementation yourself.

You can use a SocketPair (in ruby: Socket.pair) to buffer the
EventMachine data.

http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/26d3538da0410b8b/fdc3c5c6686ceb49?lnk=gst&q=Socket.pair&rnum=2&hl=en&pli=1

Really interesting, thanks a lot, I will use it.

“Iñaki Baz C.” [email protected] wrote in post #1035430:

Any suggestion about this please? Maybe the only response is that
“there is no way” (hope not) :slight_smile:

Definitely don’t write a TLS implementation yourself.

You can use a SocketPair (in ruby: Socket.pair) to buffer the
EventMachine data.

http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/26d3538da0410b8b/fdc3c5c6686ceb49?lnk=gst&q=Socket.pair&rnum=2&hl=en&pli=1