• caglararli@hotmail.com
  • 05386281520

OpenSSL "method" picking between TLS 1.2 and 1.3 [duplicate]

Çağlar Arlı      -    38 Views

OpenSSL "method" picking between TLS 1.2 and 1.3 [duplicate]

To summarize my question: How can a client support both TLS 1.2 and 1.3 ?

I have looked at How browsers pick TLS... Which summarized is: if a client connects to a server, it negotiates the handshake as to whether it will handle TLS 1.3 or TLS 1.2. I know that the server can reply with an "Okay, I'll upgrade you to 1.3" if it supports 1.3

However it doesn't explain my question in OpenSSL code. So here it is.

OpenSSL seems to require that the client decide which TLS version before it tries to connect to the server, based on this thing called "method". Here is what how I've been testing.

This is a tale of two cipher suites (although there are many more, these will suffice to demonstrate my question).

The two cipher suites I am using are

TLS13-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256

I am using OpenSSL (WolfSSL as well, since it's pretty much portable back and forth)

But before the client starts, it doesn't know what the server can handle yet, so how does it know what "method" to load?

To elaborate on this, here's what I've been testing with:

I created an SSL server with TLS1.3 enabled and using this when I create the context:

method = TLS_server_method();

And has those two ciphers loaded using:

SSL_CTX_set_cipher_list();

All good from the server side.

The client loads the "method" (still not clear on what this thing is) one of several ways.

First, on the client I use the following (pasted fragments, not intended as full example). It loads only ONE cipher at a time:

void InitializeSSL( const char * cipher) {
    meth = TLSv1_3_client_method();

    if ((m_sslCtx = SSL_CTX_new(meth)) == NULL) {
        printf("ERROR: failed to create SSL CTX\n");
        return 1;
    }
    result = SSL_CTX_set_cipher_list(m_sslCtx, cipher); // <-- ONLY ONE CIPHER PER ITERATION
    if (result != SSL_SUCCESS) {
        SSLCleanup();
        return MISSING_NOT_PRESENT;
    }
    SSL_CTX_set_verify(m_sslCtx, SSL_VERIFY_NONE, 0); //not worried about certs for this test
    m_socket = ConnectToHost();    
    m_dataSsl = SSL_new(m_sslCtx);
    SSL_set_fd(m_dataSsl, m_socket);
    result = SSL_connect(m_dataSsl);
    . . . 

Then the connection is closed and cleaned. Then do it all over again with the other cipher.

It ONLY connects with the TLS1.3 cipher, as one might expect. The other cipher fails.

When I use

meth = TLSv1_2_client_method();

it ONLY connected with the TLS 1.2 cipher, and the TLS1.3 cipher fails. Okay.

However, when I don't specify a version, and use the more "generic" named functions:

meth = TLS_method();
meth = TLS_client_method();

When it sets "SSL_CTX_set_cipher_list()" to TLS13-AES128-GCM-SHA256 it connects. Then it closes and frees everything as intended.

Then it again does a "SSL_CTX_set_cipher_list()" to ECDHE-RSA-AES128-GCM-SHA256. However it fails to connect to the server. I get what appears to be a "record layer version error"

This implies that the client has to know what the server expects and has to load the correct method BEFORE it creates the SSL context.

A browser doesn't know ahead of time if a server is supporting TLS 1.2 or 1.3. So how does it know which "method" it needs to load? Without just bailing and starting over, having to perform a different meth = {some alternate method}_method();

The goal here is a tool that hammers on a server one cipher at a time, testing to see if it will accept specific ciphers. Because customers tend to come back and say "Your server still has AES128_FRED_FLINTSTONE which is too old and not secure". So I need to know how our embedded server is handling ciphers from the third party library.

And the cipher names aren't very conducive to knowing which TLS version they work with, except the ones that begin with "TLS_..." are generally TLS 1.3

Or am I missing something entirely?

Any advice is appreciated. Thanks in advance.

-Scott