SSL Certificate Agility with Postfix

RFC 4492 and RFC 6460 introduced a number of TLS ciphers based on elliptic curve cryptography (ECC). While some of them are designed to work with RSA keys (which is what most encrypted website on the Internet are using at this point of time) others are designed to be used with a new type of keys which use the ECDSA algorithm. The advantage of using ECDSA keys instead of RSA keys is the superior performance and hopefully superior security.

But as with all new standards it takes a while before ECDSA got widely adopted. Almost 10 years later most modern browsers support this crypto algorithm. But there are still browsers (often running under outdated operating systems) and even web search engine crawlers in use that only support RSA. It is therefore still desirable to support both ECDSA and RSA keys in parallel. This approach is called certificate agility because the server is configured with multiple key/certificate pairs and automatically chooses one depending on the capabilities of the client.

Inspired by this blog article I recently created an ECDSA key (using the secp384r1 curve for compatibility with Google’s browser Chrome) for my Apache web server, got it signed by a certificate authority and enabled certificate agility. If you use Firefox or Chrome you can click on the pad lock next to the URL bar to check which of my two keys your browsers used during the key exchange. Encouraged by this quick win I wanted to enable certificate agility for more services. The obvious next target was Postfix, the mail server software that handles all the e-mail from and to my domains.

Modern versions of Postfix feature full support for certificate agility. They can be configured to use any combination of RSA, DSA and ECDSA keys. If you want to use an RSA and an ECDSA key you only need four configuration statements similar to these:

# RSA key and certificate chain
smtpd_tls_key_file = /etc/ssl/private/smtpd-key.pem
smtpd_tls_cert_file = /etc/ssl/certs/smtpd-cert.pem
# ECDSA key and certificate chain
smtpd_tls_eckey_file = /etc/ssl/private/smtpd-key-ecdsa.pem
smtpd_tls_eccert_file = /etc/ssl/certs/smtpd-cert-ecdsa.pem

The devil is however in the detail, at least if your system uses OpenSSL 1.0.1 and not 1.0.2. While OpenSSL 1.0.1 supports multiple keys for a TLS server endpoint it only supports a single intermediate certificate chain. And without the correct intermediate certificates SMTP clients won’t be able to verify the validity of your servers certificate. To work around this limitation you need to create the certificate files from the above configuration example like this:

  1. /etc/ssl/certs/smtpd-cert.pem contains the certificate for the RSA key stored in /etc/ssl/private/smtpd-key.pem followed by the intermediate certificate for both keys.
  2. /etc/ssl/certs/smtpd-cert-ecdsa.pem contains the certificate for the ECDSA key stored in /etc/ssl/private/smtpd-key-ecdsa.pem again followed by the intermediate certificate for both keys.

With this configuration SMTP clients will always receive all the necessary certificates to validate your server certificate. The only downside is that they will also receive two certificate that they don’t need. That should however not have any noticeable consequences. You can now test certificate agility using the OpenSSL command line client:

openssl s_client -cipher ECDHE-RSA-AES128-SHA -connect <your server>:25 -starttls smtp
openssl s_client -cipher ECDHE-ECDSA-AES128-SHA -connect <your server>:25 -starttls smtp

Both commands should result in a successful connection. Certificate validation should also work but you might have to supply an extra command line argument like -CApath /etc/ssl/certs to specify the location of the certificate authority catalog.

There is however still one problem with such a setup: although Postfix now supports certificate agility it is still going to use the RSA key most if not all the time. The reason is that OpenSSL still prefers RSA over ECDSA by default. And as (almost?) all SMTP clients support RSA it is always going to be used in preference of ECDSA. To change this behaviour you need to modify the cipher lists used by Postfix. This is however a change which is usually discouraged. So please consider it carefully. On my setup I’ve configured Postfix’s TLS settings as follows:

tls_high_cipherlist = ECDSA+AESGCM:ECDSA+AES:ECDH+AESGCM:DH+AESGCM:ECDH+AES:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
smtpd_tls_ciphers = high
smtpd_tls_exclude_ciphers = aNULL, RC4
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3

The cipher exclusion list is probably not necessary anymore. But I leave it in there just to be hundred percent sure. After this change certificate agility finally works as desired:

Jul 24 19:31:37 colwyn postfix/smtpd[22130]: Anonymous TLS connection established from mail-la0-x244.google.com[2a00:1450:4010:c03::244]: TLSv1.2 with cipher ECDHE-ECDSA-AES128-GCM-SHA256 (128/128 bits)

I haven’t noticed any problems with such a setup since I deployed it on my mail server two weeks ago.