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:
-servername <name>
- Set SNI servername.
-cert <file>
- Certificate to present to server.
- Useful for testing client certs.
-key <file>
- The private key file to use.
- Necessary for testing client certs.
-verify_return_error
- Return errors, aborting handshake if any found.
-CAfile <file>
- Certificates to use for server certification.
- Use this when using a self-signed certificate.
-state
- Print SSL session states (incl. handshake steps) - very useful for debugging or tinkering.
-debug
- Print debugging info + hex dump of traffic.
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:
- Key exchange algorithm
- Authentication algorithm
- Encryption algorithm
- Encryption algorithm strength
- 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:
- Exchange capabilities and agree on connection parameters.
- Validate the presented certificates or authenticate using other means.
- Agree on a shared master secret that will be used to protect the session.
- 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:
- dh_anon -> Diffie-Hellman key exchange without authentication
- dhe_rsa -> Diffie-Hellman exchange with RSA auth
- ecdh_naon -> elliptic curve exchange without auth
- ecdh_rsa -> EC exchange with RSA auth
- ecdhe_ecdsa -> EC exchange with ECDSA auth
- rsa -> RSA exchange with RSA auth
Best Practices
- Use ciphersuites that use authenaticated encryption, ie. GCM
- Use at least 2048 bit RSA keys.
- Use at least 128 bit ECDSA keys.
- SSLv2 and SSLv3 are ancient protocols and insecure.
- TLSv1.0 and TLSv1.1 are legacy protocols, do not use them.
- TLSv1.2 and TLSv1.3 are secure protocols.
- Perfect forward secrecy is assued by ciphersuites with either ECDHE or DHE in the name. All TLSv1.3 ciphersuites provide forward secrecy.
- Use authenticated encryption with associated data (AEAD) ciper suites: CHACHA20_POLY1305 or GCM. CBC is weak.
- Whereas TLSv1.2 requires two roundtrips to complete the handshake, TLSv1.3 requires only one.
Misc
TLS includes extensions that add special functionality. Useful extensions:
- 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
- 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.
- Similar to the
Comments
Add new comment