5

I have a Linux process that needs to act as an SSL server (accept and service connections from other clients) but also needs to - in the same process - initiate client sessions with other SSL servers.

I intend to create two separate SSL_CTX handles using two SSL_CTX_new() function calls, one invoked with server methods and the other with client methods. Is such dual-use of OpenSSL within a single process supported? My hope is that OpenSSL uses the SSL_CTX handle - and does not rely on global or static local variables - for all context information it may need to create and service new sessions. Is this a good assumption?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
perplexed
  • 422
  • 4
  • 12
  • [OpenSSL docs](https://www.openssl.org/docs/man1.1.1/man7/ssl.html) seem to be somewhat misleading on SSL_CTX description: _This is the **global context structure** which is created by a server or client **once per program life-time** and which holds mainly default values for the SSL structures which are later created for the connections._ (emphasis mine). According to the answers below this is not actually the case (or maybe OpenSSL devs meant something else by the words _global_ and _once per program life-time_). – Alex Che Oct 18 '22 at 20:47

2 Answers2

11

Does OpenSSL allow multiple SSL_CTX per process, one SSL_CTX used for server sessions ...

Yes, and this is quite common. Its common when using Server Name Indication. In the case of SNI, you have a default SSL_CTX and then a SSL_CTX for each server. You then return the default SSL_CTX or a specialized SSL_CTX in the SNI callback if the client included the server name extension in its ClientHello.

SSL_CTX are referenced counted by the library, so they are not truly freed until the reference count drops to 0 in one of the SSL_CTX_free calls.

Here are some related questions on SNI, if interested:

The first even provides you with the callback code. GetServerContext returns a new (or existing) context based on the server name:

/* Need a new certificate for this domain */
SSL_CTX* ctx = GetServerContext(servername);
if(ctx == NULL) handleFailure();
...

/* Set new context */
SSL_CTX* v = SSL_set_SSL_CTX(ssl, ctx); 

Does OpenSSL allow multiple SSL_CTX per process, ... other SSL_CTX for client sessions?

Yes, but you usually don't use it. The client does not usually change its SSL_CTX like the server does.

In the case that a client connects to multiple servers, usually you set your channel parameters with SSL_CTX_set_options and use that for every connection to every server (even different ones). Parameters would be things like protocols (TLS 1.1, TLS 1.2), cipher suites (removing anonymous cipher suites) and compression. See the discussion below surrounding SSL/TLS Client for more details.

The client does need to set the server's hostname, but that's done on the SSL* using SSL_set_tlsext_host_name, and not the SSL_CTX*.

Or, if you are using BIO's, it would look like this. Notice the BIO effectively wraps a SSL*, so you're not modifying the SSL_CTX*:

BIO* web = BIO_new_ssl_connect(ctx);
if(web == NULL) handleFailure();

res = BIO_set_conn_hostname(web, HOST_NAME ":" HOST_PORT);
if(res != 1) handleFailure();

... one invoked with server methods and the other with client methods

Not needed. The only difference between them (like SSLv23_client_method and SSLv23_server_method), is a couple of function pointers for functions like connect and accept in unseen structures. Clients call connect and servers call accept.

Instead, just use the generic SSLv23_method and everything will be fine. You still have to tune the context with SSL_CTX_set_options because the default context provided by SSL_CTX_new includes weak/wounded/broken protocols and ciphers.

OpenSSL's wiki page SSL/TLS Client shows you how to tune a SSL_CTX object. It performs the following, and its can be used by both clients and servers:

  • Disable SSLv2
  • Disable SSLv3
  • Disable Compression
  • Disable anonymous protocols
  • Use "strong" ciphers

Using a custom cipher list like "HIGH: ... : !SRP:!PSK" removes many weak/wounded ciphers, and removes a bunch of cipher suites that are probably not supported at the server (so there's no reason for the client to advertise them). SRP is Thomas Wu's Secure Remote Password, and PSK is Preshared Key. IANA reserves 87 cipher suites based on them, so it saves nearly 180 bytes in the ClientHello.


Is such dual-use of OpenSSL within a single process supported?

Yes.


My hope is that OpenSSL uses the SSL_CTX handle - and does not rely on global or static local variables

Well, you're out of luck there. There are a lot of globals, some of them are dynamically allocated, and some of them are not freed.

And if you're working in Java or C#, they are leaked each time the shared object is loaded/unloaded. So your Java or C# program accumulates more and more memory over time. The OpenSSL devs don't feel its worthy of their time. See, for example, Small memory leak on multithreaded server on the OpenSSL mailing list.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • Comprehensive answer. Thanks! I had to read up on SNI a little bit. Sounds like a single SSL_CTX_new(SSL_v23_method) is all I need for use as a client (using connect() calls) and server (using accept()) calls. Correct? – perplexed Dec 31 '14 at 10:55
  • Use of globals and static variables in OpenSSL is really an implementation detail I shouldn't be worrying about. I mentioned them only due to my apprehension that global variables might carry context-specific info that would prevent the use of more than one SSL_CTX. – perplexed Dec 31 '14 at 11:02
  • I'm curious, what about the case of using a single SSL_CTX from multiple threads to multiple hosts as a client? Tell if I'm too off-topic but this thread seems to be the closest to my question/issue. Say if I were using openSSL in a reverse proxy situation, would it be safe/work for be to use a single CTX that's been configured with the necessary verification certs/paths shared across multiple threads/hosts? I'm trying to determine if my newly found "decryption failed or bad record mac" has something to do with this. –  Apr 06 '15 at 16:34
  • Reading the previous comments, seems the OP is looking to confirm the same thing. –  Apr 06 '15 at 16:35
1

From my experience: you can freely create several contexts as long as you properly initialized OpenSSL library. I have used two different contexts in the same application with no problems after having set up threading locks as described in OpenSSL man page: http://www.openssl.org/docs/crypto/threads.html. If your app doesn't use threads you won't need such setup at all.

Vladimir Kunschikov
  • 1,735
  • 1
  • 16
  • 16