OCSP and X.509 NSS upgrade
Libreswan now has support for OCSP and certificate verification through NSS. Prior to [update] pluto contained its own x509 certificate/crl structures and validation code, now replaced with the NSS CERT* structures and functions. Any pluto functions that previously accessed x509cert_t and x509crl_t structures have been converted to use CERTCertificate and CERTCrl. Pluto still contains a generalName structure and conversion functions are used to work with CERTGeneralName.
The NSS database format used is now the SQL type. You should always append sql: to the database path when using certutil/crlutil. Alternately you can set the NSS_DEFAULT_DB_TYPE environment variable to 'sql:' and use certutil/crlutil as normal.
During the IKEv1 and IKEv2 exchanges, any certificate or certificate chain that is received is passed directly to NSS for decoding and verification. An in-memory NSS cache is used to hold the decoded chain and combines with the on-disk NSS database, which contains the CA certificate that completes the trust.
Assuming that the certificate verified succesfully, the end certificate is cached and used for the rest of the exchange. The end certificate will not be imported to the NSS database permanently and only remain in memory until released by a connection deletion, or a restart of pluto. At the moment, these certificates do not show up in 'ipsec auto --listall', but the RSA public key and ID information of the certificate will.
Before verifying the certificate there is a check for the issuer's CRL. As long as a CRL is in place it will be used automatically by NSS. The behavior of pluto's CRL handling has not changed. If a CRL is expired (nextUpdate has lapsed), or missing, pluto queues a crl fetch request to be processed during the next check interval (crlcheckinterval). The fetch thread uses curl to retrieve the current CRL at the CA's CRL URI. The fetched blob is passed to a helper program '_import_crl', which is essentially a stripped down crlutil, that imports the CRL to the NSS database if valid. This caches the new CRL, available for any subsequent exchanges.
A CRL can be added using crlutil before starting pluto, or placed in /etc/ipsec.d/crls for pluto to call _import_crl on startup against the crl files in the directory.
The configuration option "strictcrlpolicy" has been renamed to "crl_strict"
In strict mode (crl_strict), a missing or expired CRL results in a rejection. If a peer's exchange fails while using a good certificate due to the CRL expiring in strict mode, setting a crlcheckinterval that triggers between the peer's retransmit attempts will allow a fetch to update the CRL and authorize the exchange. The peer will then only notice a delay in connection.
Previously pluto allowed CRLs with an MD5 signature algorithm. These are now rejected by NSS. You must use CRLs with a signature algorithm of at least SHA-1.
The use of NSS certificates now considers the database trust arguments. Before, this did not matter to pluto as the NSS certificates were only converted to the internal pluto certificate when loaded.
The following trust strings should be used:
- End cert with private key: u,u,u
- Root CA: CT,,
- Intermediate CA: ,,
- Trusted Peer cert (no private key), OCSP responder cert: P,,
[root@east ~]# certutil -L -d sql:/etc/ipsec.d Certificate Nickname Trust Attributes SSL,S/MIME,JAR/XPI east u,u,u Libreswan test CA for mainca - Libreswan CT,, north P,, hashsha2 P,, west-ec P,, nic P,,
The SSL 'T' flag on the Root CA is important as NSS requires a usage profile to verify against. This flag allows NSS to verify an end certificate as 'certUsageSSLClient', meaning enforcing the digitalSignature KU extension on the end certificate, adhering to RFC 4945's section on KeyUsage.
18.104.22.168. KeyUsage Since we are talking about using the public key to validate a signature, if the KeyUsage extension is present, then at least one of the digitalSignature or the nonRepudiation bits in the KeyUsage extension MUST be set (both can be set as well). It is also fine if other KeyUsage bits are set.
An example of a Libreswan test end certificate:
[root@east ~]# certutil -L -d sql:/etc/ipsec.d -n east | grep -A1 -B1 'Usages' Name: Certificate Key Usage Usages: Digital Signature Non-Repudiation
To configure OCSP support, the following 'config setup' options are provided:
- enable or disable OCSP checks within NSS. yes/no. Default == no
- set a "default responder" uri: ex. "http://nic.testing.libreswan.org:2560". Default == unset
- set to the NSS nickname of the certificate used by the OCSP responder to sign the responses. Default == unset
- this option goes together with ocsp_uri to enable a default responder.
- set to the maximum time (in seconds) that pluto will block waiting on the OCSP response. Default == 2 seconds.
- 'yes' sets OCSP checking to "strict" which configures CERT_SetOCSPFailureMode with ocspMode_FailureIsVerification
- 'no' (the default) sets it to ocspMode_FailureIsNotAVerificationFailure (perhaps this should not be default)
The following comment from NSS sources explains the failure modes:
/* * ocspMode_FailureIsVerificationFailure: * This is the classic behaviour of NSS. * Any OCSP failure is a verification failure (classic mode, default). * Without a good response, OCSP networking will be retried each time * it is required for verifying a cert. * * ocspMode_FailureIsNotAVerificationFailure: * If we fail to obtain a valid OCSP response, consider the * cert as good. * Failed OCSP attempts might get cached and not retried until * minimumSecondsToNextFetchAttempt. * If we are able to obtain a valid response, the cert * will be considered good, if either status is "good" * or the cert was not yet revoked at verification time. * * Additional failure modes might be added in the future. */
When enabling OCSP it is recommended to set ocsp_uri and ocsp_trust_name together in order to enable a default responder. Without it, NSS will rely solely on OCSP information contained in the certificates. Similar to the problem of configuring CRL fetches that rely on the IPsec connectivity, configuring an OCSP URI with an address that is only reachable through the IPsec tunnel can be problematic.
An OCSP responder certificate can be a CA, or a seperate certificate issued just for the responder's OCSP service, and it must be pre-loaded into the NSS database before starting pluto. The OCSP responder certificate should have the OCSP Responder Certificate EKU extension, and an OCSP authInfo ext. with the URI of the OCSP responder.
For example, the test harness has a certificate 'nic' used for OCSP. Its extensions are:
Signed Extensions: Name: Certificate Basic Constraints Data: Is not a CA. Name: Certificate Key Usage Usages: Digital Signature Non-Repudiation Certificate Signing CRL Signing Name: Extended Key Usage TLS Web Server Authentication Certificate TLS Web Client Authentication Certificate Code Signing Certificate OCSP Responder Certificate Name: Authority Information Access Method: PKIX Online Certificate Status Protocol Location: URI: "http://nic.testing.libreswan.org:2560" Name: CRL Distribution Points Distribution point: URI: "http://nic.testing.libreswan.org/revoked.crl"
The CRL Signing/Certificate Signing KU extensions and Code Signing EKU may also be required. This text should be updated when this is confirmed.
1. Requires ocspd installed on nic (available in fedora repo)
- testing/x509/ocspd.conf needs to be copied to /etc/ocspd/ocspd.conf
- For CRL tests a fetch URL is provided by nic through launching a python SimpleHTTPServer from nicinit
2. pyOpenSSL on testing _host_ system needs a patch to support creating SHA-1 signed CRL. See note at top of dist_certs.py. dist_certs.py should be run before running the nss-cert* tests