Everything I Know About TLS

Published: 2021-09-03
Tagged: guide linux networking

This is a brain-dump of everything I know about working with TLS. It will start with useful commands, then move to more theoretical areas.

Tools & Commands

openssl

Connect to server and retrieve certificate information:

openssl s_client -showcerts -connect mattscodecave.com:443

Some useful s_client flags:

List supported elliptic curve names:

openssl ecparam -list_curves

Create ECDSA key:

openssl ecparam -name secp256k1 -genkey -noout -out server.key

Create RSA private key:

openssl genrsa -out server.key 2048

Create CSR using server.key for CN=localhost:

openssl req -new -key server.key -subj '/CN=localhost' -out server.csr

Sign CSR using CA cert and key:

openssl x509 -req server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.crt

Create self-signed cert:

openssl req -x509 -sha256 -newkey rsa:4096 -days 365 -keyout key.pem -out cert.pem

Show certificate details

openssl x509 -in cert.pem -noout -text

Bash function to read a .pem file that contains multiple certificates:

function x509read() {
    openssl crl2pkcs7 -nocrl -certfile ultimate.pem | openssl pkcs7 -print_certs -text -noout
}

cfssl

cfssl is a tool created by cloudfare for managing certificates. It has a lot more functionality than what I cover here, but it's great for getting a simple TLS setup. The way I use it is to create json files that cfssl then turns into x509 certificates. This way, instead of running openssl commands to create certificates, I can check the json files into vcs, and recreate any certificates at any time.

I picked this tool up from Distributed Services with Go (great, highly recommend).

Create a CA

Create a CA CSR json file, eg. ca-csr.json:

{
    "CN": "CA NAME",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "OU": "Matt's Raspberry Pi"
        }
    ]
}

Create a CA config json file, eg. ca:

{
    "signing": {
        "profiles": {
            "server": {
                "expiry": "8760h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth"
                ]
            },
            "client": {
                "expiry": "8760h",
                "usages": [
                    "signing",
                    "key encipherment",
                    "client auth"
                ]
            }
        }
    }
}

Now, generate the CA key and certificate:

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

This will create a ca-key.pem, ca.pem, and ca.csr.

Create and Sign Server Certificate

Create a server CSR json file, eg. server-csr.json:

{
    "CN": "192.168.1.99",
    "hosts": [
        "raspberrypi.local",
        "192.168.1.99"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "OU": "The Server"
        }
    ]
}

Now, use the ca files to sign the CSR and create server.csr, server-key.pem, server.pem files:

cfssl gencert -ca=ca.pem -ca-key=ca.key -config=ca-config.json -profile=server server-csr.json | cfssljson -bare server

Create and Sign Client Certificate

Create a client CSR json file, eg. client-csr.json:

{
    "CN": "client",
    "hosts": [""],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "OU": "Client 1"
        }
    ]
}

Now, use the ca files to sign the CSR and create client.key and client.pem files:

cfssl gencert -ca=ca.pem -ca-key=ca.key -config=ca-config.json -profile=client client-csr.json | cfssljson -bare client

TLS Bits and Pieces

Cipher Suites

Cipher suites are composed of:

  1. Key exchange algorithm
  2. Authentication algorithm
  3. Encryption algorithm
  4. Encryption algorithm strength
  5. MAC (message authentication code) or PRF (pseudorandom function)

All these properties are encoded in the name:

TLS_key-exchange_authentication_WITH_encryption-algorithm_strength_mode_MACorPRF

An example ciphersuite:

TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

The Handshake

The aim of the handshake is to:

  1. Exchange capabilities and agree on connection parameters.
  2. Validate the presented certificates or authenticate using other means.
  3. Agree on a shared master secret that will be used to protect the session.
  4. Verify that the handshake messages haven't been modified by a third party.

The handshake looks like this:

-> ClientHello
<- ServerHello
<- Certificate
<- ServerKeyExchange
<- ServerHelloDone
-> ClientKeyExchange
-> ChangeCipherSpec
-> Finished
<- ChangeCipherSpec
<- Finished

ChangeCipherSpec is the signal that the sending side obtained enough information to setup the secure connection and is switching to encryption.

When a client cert is used, the server also requests the client cert via a CertificateRequest message.

The Key Exchange phase is when TLS establishes a shared secret. There are a few ways this can be done:

Best Practices

Misc

TLS includes extensions that add special functionality. Useful extensions:

  1. ALPN: Application Layer Protocol Negotiation
    • Includes layer 7 information in TLS. It can be used by the server to switch protocols, ie. HTTP/1.1 -> H2
  2. SNI: Server Name Indication
    • Similar to the Host header in HTTP.
    • It can be used on servers to serve multiple TLS servers on the same port by routing traffic according to SNI.

Comments

There aren't any comments here.

Add new comment