23 Jan

How to act as your own local CA and sign certificate request from ASA

There are several ways to operate on certificates. The widest spread method is by openssl library and associated command line tools. Library was not and probably is still not free of bugs. But it’s widely spread  among many operating systems which makes it a tool that easily can be used on most popular operating systems. If you are running Windows Server you can install Certificate Services component, Mac users can use Keychain Access which is core component of macOS.

While working with certificates and those tool remember about best practices. Points below are valid as of the end of 2016.

  • Use at least 2048-Bit Private Keys
  • Try to avoid wildcard certificates but remember to cover all FQDN’s in certificates
  • Use strong certificate signature algorithms – SHA256 is standard now,  SHA-1 has been deprecated
  • Use strong encryption for your connection – not really certificate related but worh notifying that TLSv1.2 is now a standard supporting strong cryptographic algorithms
  • Use complete certificate chains
  • Use strong key exchange and forward secrecy

If you want to know more about best practices you may refer to this short manual.

Creating CA

Self-signed certificate doesn’t mean it have to by signed by device itself. Actually that won’t work at all if you plan to connect from your iPhone application, but it will if you use Safari. Web browser looks to have a little relaxed requirements to provide backward compatibility with some older web pages. So you need to act as Certificate Authority (CA).

You can create CA certificate directly from your Keychain Access but unfortunately I found that during certification signing supporting application crashed all the time. So I was back to old good openssl.

If you are looking on good tutorial and usage example how to setup CA server and sign requests here is the good one. From it’s github repository you can get required configuration files and my lab CA server base on them. Before you start one major change you need to do is replace default hashing algorithm from insecure sha1 to sha256. You do this editing option default_md in root-ca.conf and signing-ca.conf files. Remember to change all occurrences because there is more than one! To simplify signing process and not generate request with many fields I also changed parameters domainComponent and organizationName from supplied to optional in signing-ca.conf. So the only mandatory field in our request will be commonName.

To create CA request we have to issue following command (of course after CA database is created as described on the page)

openssl req -new \
  -config etc/root-ca.conf \
  -out ca/root-ca.csr \
  -keyout ca/root-ca/private/root-ca.key

Normally, in usual production environments, this CA request is sent to authorized CA for signing but we self-sign this by following command

openssl ca -selfsign \
  -config etc/root-ca.conf \
  -in ca/root-ca.csr \
  -out ca/root-ca.crt \
  -extensions root_ca_ext

Now we can act as CA. Next step is to create request for Signing CA certificate – this one will be used for signing other CSR requests. We need to create separate database for signing process and then create Signing CA request

openssl req -new \
  -config etc/signing-ca.conf \
  -out ca/signing-ca.csr \
  -keyout ca/signing-ca/private/signing-ca.key

Then we sign the Signing CA CSR with our previously generated CA certificate

openssl ca \
  -config etc/root-ca.conf \
  -in ca/signing-ca.csr \
  -out ca/signing-ca.crt \
  -extensions signing_ca_ext

We get certificate signing requests in CSR format which we need to sign using Signing CA certificate using following command

openssl ca \
  -config etc/signing-ca.conf \
  -in certs/simple.org.csr \
  -out certs/simple.org.crt \
  -extensions server_ext

Please check the page I referred to for other examples how to use openssl.

Creating certificate request on ASA

I won’t get now deep into how the certificates are working and how ASA manage certificates, this is not the scope of this article. I will just focus on steps you need to follow.

If we don’t have it yet we need to generate general purpose key on the device. The most common and secure now is 4096-bit RSA key which provides strong encryption.

crypto key generate rsa modulus 4096 noconfirm

Next step is to generate certificate request using the key we just generated. There is small problem with this step if you are using ASDM.It looks like there is small bug in ASDM because FQDN field is never requested when certificate request is created, only CN is properly defined. This may result in several problems if particular application or operating system require FQDN to be valid and present. One of such example is iOS running on iPhones and iPads.  All discussions on developers forums or even Apple developers board focus on handshake problems, self-signed certificates etc. but none really said that even self-signed certificate or signed by own self-signed CA require certificate to contain two very important fields – CN and FQDN values. First one should contain all names that might be assigned to firewall, usually it’s limited to just hostname and FQDN record. But what we also have to attach is FQDN field of firewall that will be used in URLs inside of our application. If FQDN field in certificate is missing we will see following error message even if full signing path is correct and all certificates are trusted.

2017-01-14 23:16:44.485 ASAManagement[21917:24560543] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)
The certificate for this server is invalid. You might be connecting to a server that is pretending to be “asav-1.virl.lan” which could put your confidential information at risk.

The key information here is “(kCFStreamErrorDomainSSL, -9843)”, error number 9843 code name is “errSSLHostNameMismatch” which means that URL application tries to open is not matching FQDN in certificate or the field is missing.

If we generate Trustpoint using ASDM then FQDN parameter is not set. In advanced options we can define FQDN record but somehow this is ignored when commands are generated (ASDM 7.5(2) which is available on VIRL edition on ASAv 9.5(2)204). So we must create trustpoint and CSR manually from CLI

crypto ca trustpoint ASDM_TrustPoint15
revocation-check none
fqdn asav-1.virl.lan
subject-name CN=asav-1.virl.lan,CN=asav-1
id-usage ssl-ipsec
ip-address 172.16.1.51
enrollment terminal
!
crypto ca enroll ASDM_TrustPoint15

Please note that there are two CN names defined, one representing just hostname and second with FQDN name. Also, just for safety, I added ip-address field. Last command is used to start enrollment process.

Importing certificates to ASA

If you are not familiar with the whole PKI standard just remember the steps you need to follow:

  1. You need to import public CA certificate to firewall
  2. You need to import signing CA certificate to firewall
  3. You need to import signed certificate
  4. Certificate need to be assigned to interface

That will ensure that full certification path is present and valid. If any component is missing or invalid then certificate won’t be assigned to interface and won’t be used (but the command is still present in configuration)

CA and Signing CA certificates will use separate trustpoints but the commands are the same

crypto ca trustpoint ASDM_TrustPoint6
revocation-check none
no id-usage
enrollment terminal
!
crypto ca authenticate ASDM_TrustPoint6

At this stage in ASDM we should see two CA certificates we generated for our own CA Authority. Make use that “Usage” is displayed as “General Purpose” otherwise those CA certificates won’t be used for PKI path validation process.

When we create CSR and sign the certificate we need to upload it to firewall. We can easily do this using ASDM or by command

crypto ca import ASDM_TrustPoint15 certificate

Remember to refer to the same trustpoint that was used to create CSR.

ASAv on VIRL caveats

There is one particular problem with ASAv running on VIRL – it does not store keys we upload. That means the key as well as device certificate created using this key will be gone after every reboot. The CA and Signing CA keys will remain if we save the configuration into topology file as those are not dependent on device crypto key.

Of course we can create new CSR every time we launch simulation or reboot firewall but that’s not flexible – remember we have to import certificates to multiple devices

But we can export the certificate and keys to PCKS12 format that contain both certificate and private key. We do this using command

crypto ca export ASDM_TrustPoint15 pkcs12 test1234

The “test1234” is the password we set to protect PCKS12 package

Then after every firewall reboot we only need to import certificate to ASA

crypto ca import ASDM_TrustPoint15 pkcs12 "test1234"
!
crypto ca trustpoint ASDM_TrustPoint15
revocation-check none
id-usage ssl-ipsec

Links

You can find many resources about PKI, problems with self-signed certificate etc. I’d like to recommend few:

  • RPKI Tutorial describing basics if you are not familiar with keys and certificates, on same site you will find Simple PKI Example I’ve used for both my CA and commands for openssl
  • How to create CA certificate and sign other certificates using Keychain Access on macOS

Leave a Reply

%d bloggers like this: