Setup: Server with X.509 Certificates¶
The most-used form of server authentication uses X.509 certificates, also known as PKIX certificates. This section explains how to set them up for the TLS Pool.
They bind a public key with an algorithm such as RSA or ECDSA to an identity, which includes the web server name. The binding is confirmed by a trusted third party, or certificate authority. This may be a paid party, or one providing certificates for free, such as Let’s Encrypt or CAcert.
Generally, a certificate authority will explain the hoops that you must jump through:
- Generate a private key of a certain algorithm and size, for example 2048 bits RSA or 256 bits ECDSA. As a side-effect, a public key is usually derived from the private key as well.
- Using that, generate a certificate request, which incorporates the public
key and your intended identity, notably
CN=www.example.com
and perhaps one or more DNS names also explicitly mentioned. A special form is a wildcard certificate, such asCN=*.example.com
, which would cover any name under the domain name. - Then you upload only the certificate request. The certificate authority is
likely to scrutinise your request, strip parts that it won’t allow and
perhaps provide alternative forms of a name, such as the domain name without
the
www
prefix label. - The certificate authority should now do some hard work to validate that you are the owner of the website. In practice, a flimsy test such as the ability to receive email is considered sufficient to grant you a certificate for 1 up to 3 years. Sarcasm intended.
- You now receive the certificate over email, or can download it somewhere. Used together with the private key that you kept to yourself, you can now instruct your server to secure its connections with TLS. The way to do that is completely dependent on the server program, but often comes down to mentioning the paths of the two files somewhere in a configuration file.
This path is still the same with the TLS Pool, except that we use PKCS #11 and so our private keys are better protected — at least that is possible, but it depends on the precise PKCS #11 implementation chosen. But even the basic SoftHSMv2 that we advise to newcomers already encrypts the certificate with a PIN, thereby improving over what most servers do. Also, the design of the TLS Pool as a separate process means that access to this file is not required from the same server that may be running scripts of mediocre quality and often dubious maintenance status.
To create a private key with the TLS Pool, we need to run a tool that is
versed in PKCS #11. Instead of openssl rsa
that quickly becomes cryptic when
handling PKCS #11, we recommend using the tools that come with GnuTLS:
P11LIB=`tlspool-configvar -c /etc/tlspool.conf pkcs11_path`
P11URI=`tlspool-configvar -c /etc/tlspool.conf pkcs11_token`
p11tool --provider "$P11LIB" --login --generate-rsa --bits 2048 --label=Label --id=30303031 --outfile=/dev/null "$P11URI"
OBJURI="$P11URI;id=%30%30%30%31;label=Label;type=private"
echo "PKCS #11 Object URI: $OBJURI"
The --id=30303031
form is a bit awkward; it represents the identity, which
often is a binary identity, in hexadecimal form, so the identity given here
would be 0001
when interpreted as ASCII. The main use of the identity is
matches private keys to public keys and perhaps certificates. The --label
on
the other hand, is intended for human consumption.
Neither the --id
nor the --label
needs to be unique — other than for
practical purposes of finding back the one object that you are looking for, of
course. Assuming that at least their combination is unique, the printed
pkcs11:
URI should help to locate the generated private key in the future;
note how the hexadecimal content is percent-escaped in the URI form.
For the upcoming request, we should write a template file holding the
details of how we would like our certificate to look. We will assume below that
the template is saved in request.template
. An example can be found in the
certtool(1)
manual page, but a short form that should work mostly is
organization = "Snake Oil, Ltd"
state = "Bliss"
country = US
cn = "www.example.com"
dns_name = "www.example.com"
dns_name = "example.com"
We now create a certificate request using the concealed private key. For this, we use another tool from GnuTLS:
certtool --provider "$P11LIB" --generate-request --outfile request.pem --template=request.template
The result in request.pem
is what you should ship to your certificate
authority.
We now twiddle our thumbs until our certificate authority has done its work. This may involves jumping through some hoops, such as clicking on a link in an email sent to your domain administrator’s address.
Upon arrival, save the certificate to a file named new.pem
— or at least,
that will be the name assumed below. We shall also assume that you got the
textual form, as that is common. We however, need the binary form so we need to
transform it from PEM to DER notation:
certtool --infile new.pem --outfile new.der --outder
We now hold a file named new.der
that we can use to import into the TLS Pool.
And remember the pkcs11:
URI for the object? We saved it in $OBJURI
when
generating the private key, as well as printed it on the output. We will need
that too, because now we bring the signed certificate and the private key
together.
To import the certificate and private key as a pair into the TLS Pool, we run the following command:
set_localid /etc/tlspool.conf www.example.com X.509,server "$OBJURI" new.der
The arguments on this line are:
- A reference to the configuration file for the TLS Pool; this is used to find
the database environment and the
localid.db
locations. If the database and/or its environment have not been created yet, this tool will do it for us. - The name for which the newly imported credential can be used. You may
additionally want to import it without the
www
prefix label. If you hold a wildcard certificate, please understand that the TLS Pool does not search itslocalid.db
in that way; you should import each covered name separately. - The flags indicate that the type of this entry is an X.509 certificate, meant to be used in a server.
- The
pkcs11:
URI and the filename of the DER file with the certificate are all that’s left.
Variations exist. For instance, you might have added anything but the root
certificate to new.der
, in the order of escalating the hierarchy. In that
case, you should add the chained
flag as well. This is how non-standard
certificate authorities (those that are not in trust.db
or another certificate
authority list on the remote end) can be supported;
CAcert is probably the best-known example of that.
After this, your done. If you ever need to remove the certificate, for
example because its due date has passed, you can either overwrite it with a new
one (using the same flags) or you can rerun the command but leave out the
pkcs11:
URI and DER file name.
You do not need to restart the TLS Pool after having modified the database; it should pickup automatically. This is the main reason for using databases to configure these things.