Skip to main content

OpenSSL 1.1.1 LTS

OpenSSL 1.1.1 LTS

On September 11th, 2018 the OpenSSL team released a Long Term Support (LTS) version (1.1.1) of OpenSSL which will be supported by the community and the core team for the next five years.  This LTS release includes many new features such as TLS 1.3, ABI version compatibility, new cryptography algorithms, and an overhaul in many areas to the random number generators included in OpenSSL.  And that is why I wanted to write this article; to highlight the new LTS release of OpenSSL, to illustrate some of the interesting network security aspects included in TLS 1.3, and to briefly discuss the new cryptographic algorithms included in this latest release.  So let’s not waste any time and jump right in!

NOTE: This post assumes a working knowledge of how secure socket connections are made and how previous versions of TLS work.  For an overview, please see my previous article on TLS 1.3.

 

TLS 1.3 Support

OpenSSL now provides full support for the newly implemented draft of TLS 1.3.  This is one of the top features of version 1.1.1. TLS 1.3 now offers security and networking performance enhancements that offer significant reductions in timing during connection setup between a client and a server. Two interesting features in OpenSSL that are responsible for these network performance gains are the use of pre-shared keys and 0-RTT data.

First let's discuss PSK's because this will set the foundation for 0-RTT data.  In the following example below, let’s take a looks at a client and server taking advantage of a PSK exchange using the TLS 1.3 protocol.  If you'll notice, the first exchange between the client and the server establishes a pre-shared-key (PSK) but sets up the connection normally.  Nothing too fancy here.  The real benefit comes from establishing future connections from the client to the server  because these connections can then take advantage of this pre-shared key expediting the handshake setup.

   Initial Handshake:
          ClientHello
          + key_share               -------->
                                                          ServerHello
                                                          + key_share
                                                {EncryptedExtensions}
                                                {CertificateRequest*}
                                                       {Certificate*}
                                                 {CertificateVerify*}
                                                           {Finished}
                                    <--------     [Application Data*]
          {Certificate*}
          {CertificateVerify*}
          {Finished}                -------->
                                    <--------      [NewSessionTicket]
          [Application Data]        <------->      [Application Data]
 
 
   Subsequent Handshake:
          ClientHello
          + key_share*
          + pre_shared_key          -------->
                                                          ServerHello
                                                     + pre_shared_key
                                                         + key_share*
                                                {EncryptedExtensions}
                                                           {Finished}
                                    <--------     [Application Data*]
          {Finished}                -------->
          [Application Data]        <------->      [Application Data]

From the OpenSSL vantage point, when the connection is going up, this PSK is detected and cipher suite can be picked up from the previous connection.  This can provide a latency reduction on these connections going forward.

The following code example from OpenSSL is the detection of the PSK in action to grab the previous cipher suite.  

int tls13_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
                                       const char *label, size_t llen,
                                       const unsigned char *context,
                                       size_t contextlen)
{
 
	...
 
    const SSL_CIPHER *sslcipher;
 
    if (ctx == NULL || !ossl_statem_export_early_allowed(s))
        goto err;
 
    if (!s->server && s->max_early_data > 0
            && s->session->ext.max_early_data == 0)
        sslcipher = SSL_SESSION_get0_cipher(s->psksession);
    else
        sslcipher = SSL_SESSION_get0_cipher(s->session);
 
 
    ...
}

Now that using PSK's have been discussed, let's talk about the option to take advantage of 0-RTT data.  This sequence is very similar to PSK's but instead of  waiting for the full handshake to go up before the client sends encrypted data, the client can attempt to send application data on the first round trip.  The server then has a couple of options to reuse the previous PSK and accept the encrypted data or reject it to establish a new handshake.

The following sequence below depicts how sending application data on the first trip is done from the client's perspective.  This has the opportunity to also greatly reduce latency.

         ClientHello
         + early_data
         + key_share*
         + psk_key_exchange_modes
         + pre_shared_key
         (Application Data*)     -------->
                                                         ServerHello
                                                    + pre_shared_key
                                                        + key_share*
                                               {EncryptedExtensions}
                                                       + early_data*
                                                          {Finished}
                                 <--------       [Application Data*]
         (EndOfEarlyData)
         {Finished}              -------->
         [Application Data]      <------->        [Application Data]

ABI Compatibility and new Cryptography Algorithms

Two other very important features to note on this latest release of OpenSSL is ABI and API compatibility and all the new cryptographic libraries.  First, let's start with ABI and API stability.  For certain downstream applications that are taking advantage of OpenSSL 1.1.0, let's use CPython as an example, it may safe to simply drop in version 1.1.1 of OpenSSL and your application will still receive backward compatibility support.  All of this will need to be tested of course, but for downstream applications using Python this could see a big win because this has always been a pain point of using Python.  If you updated to a new version that shipped with a newer copy of OpenSSL, that could break your application.

Next, before we talk about cryptography algorithms, I want to make it clear that I am not a cryptography expert but I do have a general interest so I wanted to mention the robust set of cryptography updates included in OpenSSL 1.1.1.  One in-particular that I find interesting is the SipHash algorithm due to the efficiency in size and the utility of the algorithm to authenticate network packets without using hash tables.  While this is not a new or robust update I find it to be a useful utility and one that I am glad is included in OpenSSL.  Below is a snippet for the init() method in the OpenSSL crypto library.

/* hash_size = crounds = drounds = 0 means SipHash24 with 16-byte output */
int SipHash_Init(SIPHASH *ctx, const unsigned char *k, int crounds, int drounds)
{
    uint64_t k0 = U8TO64_LE(k);
    uint64_t k1 = U8TO64_LE(k + 8);
 
    /* If the hash size wasn't set, i.e. is zero */
    ctx->hash_size = siphash_adjust_hash_size(ctx->hash_size);
 
    if (drounds == 0)
        drounds = SIPHASH_D_ROUNDS;
    if (crounds == 0)
        crounds = SIPHASH_C_ROUNDS;
 
    ctx->crounds = crounds;
    ctx->drounds = drounds;
 
    ctx->len = 0;
    ctx->total_inlen = 0;
 
    ctx->v0 = 0x736f6d6570736575ULL ^ k0;
    ctx->v1 = 0x646f72616e646f6dULL ^ k1;
    ctx->v2 = 0x6c7967656e657261ULL ^ k0;
    ctx->v3 = 0x7465646279746573ULL ^ k1;
 
    if (ctx->hash_size == SIPHASH_MAX_DIGEST_SIZE)
        ctx->v1 ^= 0xee;
 
    return 1;
}

Here also is the complete list of new cryptography algorithms included in OpenSSL 1.1.1:

SHA3
SHA512/224 and SHA512/256
EdDSA (including Ed25519 and Ed448)
X448 (adding to the existing X25519 support in 1.1.0)
Multi-prime RSA
SM2
SM3
SM4
SipHash
ARIA (including TLS support)

In Summary ⌛️

In summary the release of OpenSSL 1.1.1 marks a major release of the SSL engine in terms of network security and performance.  I think there will be a lot that the information security community learns as these new cryptography algorithms and network techniques are applied throughout the industry.  I myself, am interested in learning more about how to test 0-RTT and to utilize SipHash in authentication projects.  I also hope that API and ABI stability releases are something that downstream languages like Python can continue to expect as new release of OpenSSL are put out.  I am very excited to see where we go from here and what is next in terms of network security and performance.  Thank you for reading and if you have a question, comment, or concern, please leave a comment and I will do my best to respond as soon as possible.

 

References:

  1. IETF TLS Protocol 1.3
  2. OpenSSL Github Project
  3. OpenSSL Release Page
  4. SipHash Research Paper
  5. OpenSSL 1.1.1 Release Notes

Member for

3 years
Matt Eaton

Long time iOS and server side team lead with a love for Python, Swift, ObjC, C, C++, networking, testing, network debugging, embedded development, technical writing, and research.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.