2021-06-03 08:37:05 +02:00
|
|
|
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
|
|
..
|
|
|
|
.. SPDX-License-Identifier: MPL-2.0
|
|
|
|
..
|
|
|
|
.. This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
.. License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
..
|
|
|
|
.. See the COPYRIGHT file distributed with this work for additional
|
|
|
|
.. information regarding copyright ownership.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
.. _pkcs11:
|
|
|
|
|
2020-06-08 15:33:45 +00:00
|
|
|
PKCS#11 (Cryptoki) Support
|
2019-03-31 12:49:47 +02:00
|
|
|
--------------------------
|
|
|
|
|
2020-06-08 15:33:45 +00:00
|
|
|
Public Key Cryptography Standard #11 (PKCS#11) defines a
|
2019-03-31 12:49:47 +02:00
|
|
|
platform-independent API for the control of hardware security modules
|
|
|
|
(HSMs) and other cryptographic support devices.
|
|
|
|
|
2020-06-08 15:33:45 +00:00
|
|
|
PKCS#11 uses a "provider library": a dynamically loadable
|
2019-03-31 12:49:47 +02:00
|
|
|
library which provides a low-level PKCS#11 interface to drive the HSM
|
|
|
|
hardware. The PKCS#11 provider library comes from the HSM vendor, and it
|
|
|
|
is specific to the HSM to be controlled.
|
|
|
|
|
2021-10-11 14:39:06 +02:00
|
|
|
BIND 9 uses engine_pkcs11 for PKCS#11. engine_pkcs11 is an OpenSSL
|
|
|
|
engine which is part of the `OpenSC`_ project. The engine is dynamically
|
|
|
|
loaded into OpenSSL and the HSM is operated indirectly; any
|
|
|
|
cryptographic operations not supported by the HSM can be carried out by
|
|
|
|
OpenSSL instead.
|
|
|
|
|
|
|
|
.. _OpenSC: https://github.com/OpenSC/libp11
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
Prerequisites
|
|
|
|
~~~~~~~~~~~~~
|
|
|
|
|
2020-06-08 15:33:45 +00:00
|
|
|
See the documentation provided by the HSM vendor for information about
|
|
|
|
installing, initializing, testing, and troubleshooting the HSM.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
Building SoftHSMv2
|
|
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
|
|
SoftHSMv2, the latest development version of SoftHSM, is available from
|
|
|
|
https://github.com/opendnssec/SoftHSMv2. It is a software library
|
2020-09-14 21:04:19 +00:00
|
|
|
developed by the OpenDNSSEC project (https://www.opendnssec.org) which
|
2019-03-31 12:49:47 +02:00
|
|
|
provides a PKCS#11 interface to a virtual HSM, implemented in the form
|
2020-12-16 10:24:01 +01:00
|
|
|
of an SQLite3 database on the local filesystem. It provides less security
|
2020-06-08 15:33:45 +00:00
|
|
|
than a true HSM, but it allows users to experiment with native PKCS#11
|
2019-03-31 12:49:47 +02:00
|
|
|
when an HSM is not available. SoftHSMv2 can be configured to use either
|
|
|
|
OpenSSL or the Botan library to perform cryptographic functions, but
|
|
|
|
when using it for native PKCS#11 in BIND, OpenSSL is required.
|
|
|
|
|
2020-06-08 15:33:45 +00:00
|
|
|
By default, the SoftHSMv2 configuration file is ``prefix/etc/softhsm2.conf``
|
|
|
|
(where ``prefix`` is configured at compile time). This location can be
|
2019-03-31 12:49:47 +02:00
|
|
|
overridden by the SOFTHSM2_CONF environment variable. The SoftHSMv2
|
|
|
|
cryptographic store must be installed and initialized before using it
|
|
|
|
with BIND.
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
$ cd SoftHSMv2
|
|
|
|
$ configure --with-crypto-backend=openssl --prefix=/opt/pkcs11/usr
|
|
|
|
$ make
|
|
|
|
$ make install
|
|
|
|
$ /opt/pkcs11/usr/bin/softhsm-util --init-token 0 --slot 0 --label softhsmv2
|
|
|
|
|
|
|
|
OpenSSL-based PKCS#11
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2020-05-27 15:53:44 +00:00
|
|
|
OpenSSL-based PKCS#11 uses engine_pkcs11 OpenSSL engine from libp11 project.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
engine_pkcs11 tries to fit the PKCS#11 API within the engine API of OpenSSL.
|
|
|
|
That is, it provides a gateway between PKCS#11 modules and the OpenSSL engine
|
|
|
|
API. One has to register the engine with OpenSSL and one has to provide the
|
|
|
|
path to the PKCS#11 module which should be gatewayed to. This can be done by
|
|
|
|
editing the OpenSSL configuration file, by engine specific controls, or by using
|
|
|
|
the p11-kit proxy module.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
It is recommended, that libp11 >= 0.4.12 is used.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
For more detailed howto including the examples, we recommend reading:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
https://gitlab.isc.org/isc-projects/bind9/-/wikis/BIND-9-PKCS11
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
Using the HSM
|
|
|
|
~~~~~~~~~~~~~
|
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
The canonical documentation for configuring engine_pkcs11 is in the
|
|
|
|
`libp11/README.md`_, but here's copy of working configuration for
|
|
|
|
your convenience:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
.. _`libp11/README.md`: https://github.com/OpenSC/libp11/blob/master/README.md#pkcs-11-module-configuration
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
We are going to use our own custom copy of OpenSSL configuration, again it's
|
|
|
|
driven by an environment variable, this time called OPENSSL_CONF. We are
|
|
|
|
going to copy the global OpenSSL configuration (often found in
|
|
|
|
``etc/ssl/openssl.conf``) and customize it to use engines_pkcs11.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
cp /etc/ssl/openssl.cnf /opt/bind9/etc/openssl.cnf
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
and export the environment variable:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
export OPENSSL_CONF=/opt/bind9/etc/openssl.cnf
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
Now add following line at the top of file, before any sections (in square
|
|
|
|
brackets) are defined:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
openssl_conf = openssl_init
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2022-01-14 11:30:06 +01:00
|
|
|
And make sure there are no other 'openssl_conf = ...' lines in the file.
|
|
|
|
|
|
|
|
Add following lines at the bottom of the file:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
[openssl_init]
|
|
|
|
engines=engine_section
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
[engine_section]
|
|
|
|
pkcs11 = pkcs11_section
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
[pkcs11_section]
|
|
|
|
engine_id = pkcs11
|
|
|
|
dynamic_path = <PATHTO>/pkcs11.so
|
|
|
|
MODULE_PATH = <FULL_PATH_TO_HSM_MODULE>
|
|
|
|
init = 0
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
Key Generation
|
|
|
|
~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
HSM keys can now be created and used. We are going to assume that you already
|
|
|
|
have a BIND 9 installed, either from a package, or from the sources, and the
|
|
|
|
tools are readily available in the ``$PATH``.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
For generating the keys, we are going to use ``pkcs11-tool`` available from the
|
|
|
|
OpenSC suite. On both DEB-based and RPM-based distributions, the package is
|
|
|
|
called opensc.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
We need to generate at least two RSA keys:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type rsa:2048 --label example.net-ksk --pin <PIN>
|
2022-01-11 09:04:55 +01:00
|
|
|
pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type rsa:2048 --label example.net-zsk --pin <PIN>
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
Remember that each key should have unique label and we are going to use that
|
|
|
|
label to reference the private key.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
Convert the RSA keys stored in the HSM into a format that BIND 9 understands.
|
2022-03-03 22:17:04 +01:00
|
|
|
The :iscman:`dnssec-keyfromlabel` tool from BIND 9 can link the raw keys stored in the
|
2021-05-20 16:26:53 +02:00
|
|
|
HSM with the ``K<zone>+<alg>+<id>`` files. You'll need to provide the OpenSSL
|
|
|
|
engine name (``pkcs11``), the algorithm (``RSASHA256``) and the PKCS#11 label
|
|
|
|
that specify the token (we asume that it has been initialized as bind9), the
|
|
|
|
name of the PKCS#11 object (called label when generating the keys using
|
|
|
|
``pkcs11-tool``) and the HSM PIN.
|
|
|
|
|
|
|
|
Convert the KSK:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
dnssec-keyfromlabel -E pkcs11 -a RSASHA256 -l "token=bind9;object=example.net-ksk;pin-value=0000" -f KSK example.net
|
|
|
|
|
|
|
|
and ZSK:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
dnssec-keyfromlabel -E pkcs11 -a RSASHA256 -l "token=bind9;object=example.net-zsk;pin-value=0000" example.net
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
NOTE: you can use PIN stored on disk, by specifying ``pin-source=<path_to>/<file>``, f.e.:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
(umask 0700 && echo -n 0000 > /opt/bind9/etc/pin.txt)
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
and then use in the label specification:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
pin-source=/opt/bind9/etc/pin.txt
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
Confirm that you have one KSK and one ZSK present in the current directory:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
ls -l K*
|
|
|
|
|
|
|
|
The output should look like this (the second number will be different):
|
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
Kexample.net.+008+31729.key
|
|
|
|
Kexample.net.+008+31729.private
|
|
|
|
Kexample.net.+008+42231.key
|
|
|
|
Kexample.net.+008+42231.private
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2022-01-11 09:04:55 +01:00
|
|
|
A note on generating ECDSA keys: there is a bug in libp11 when looking up a key,
|
|
|
|
that function compares keys only on their ID, not the label. So when looking up
|
|
|
|
a key it returns the first key, rather than the matching key. The workaround for
|
|
|
|
this is when creating ECDSA keys, you should specify a unique ID:
|
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
ksk=$(echo "example.net-ksk" | sha1sum - | awk '{print $1}')
|
|
|
|
zsk=$(echo "example.net-zsk" | sha1sum - | awk '{print $1}')
|
|
|
|
pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type EC:prime256v1 --id $ksk --label example.net-ksk --pin <PIN>
|
|
|
|
pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type EC:prime256v1 --id $zsk --label example.net-zsk --pin <PIN>
|
|
|
|
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2020-06-08 15:33:45 +00:00
|
|
|
Specifying the Engine on the Command Line
|
2019-03-31 12:49:47 +02:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
When using OpenSSL-based PKCS#11, the "engine" to be used by OpenSSL can be
|
2022-03-03 22:17:04 +01:00
|
|
|
specified in :iscman:`named` and all of the BIND ``dnssec-*`` tools by using the ``-E
|
2021-05-20 16:26:53 +02:00
|
|
|
<engine>`` command line option. Specifying the engine is generally not necessary
|
|
|
|
unless a different OpenSSL engine is used.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
The zone signing commences as usual, with only one small difference. We need to
|
|
|
|
provide the name of the OpenSSL engine using the -E command line option.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
dnssec-signzone -E pkcs11 -S -o example.net example.net
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2022-03-03 22:17:04 +01:00
|
|
|
Running :iscman:`named` With Automatic Zone Re-signing
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
The zone can also be signed automatically by named. Again, we need to provide
|
2022-03-02 16:54:31 +01:00
|
|
|
the name of the OpenSSL engine using the :option:`-E <named -E>` command line option.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
named -E pkcs11 -c named.conf
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
and the logs should have lines like:
|
|
|
|
|
|
|
|
::
|
2021-10-11 14:39:06 +02:00
|
|
|
|
2021-05-20 16:26:53 +02:00
|
|
|
Fetching example.net/RSASHA256/31729 (KSK) from key repository.
|
|
|
|
DNSKEY example.net/RSASHA256/31729 (KSK) is now published
|
|
|
|
DNSKEY example.net/RSA256SHA256/31729 (KSK) is now active
|
|
|
|
Fetching example.net/RSASHA256/42231 (ZSK) from key repository.
|
|
|
|
DNSKEY example.net/RSASHA256/42231 (ZSK) is now published
|
|
|
|
DNSKEY example.net/RSA256SHA256/42231 (ZSK) is now active
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2022-03-03 22:17:04 +01:00
|
|
|
For :iscman:`named` to dynamically re-sign zones using HSM keys,
|
|
|
|
and/or to sign new records inserted via nsupdate, :iscman:`named` must
|
2019-03-31 12:49:47 +02:00
|
|
|
have access to the HSM PIN. In OpenSSL-based PKCS#11, this is
|
2020-05-27 15:53:44 +00:00
|
|
|
accomplished by placing the PIN into the ``openssl.cnf`` file (in the above
|
2019-03-31 12:49:47 +02:00
|
|
|
examples, ``/opt/pkcs11/usr/ssl/openssl.cnf``).
|
|
|
|
|
|
|
|
The location of the openssl.cnf file can be overridden by setting the
|
2022-03-03 22:17:04 +01:00
|
|
|
``OPENSSL_CONF`` environment variable before running :iscman:`named`.
|
2019-03-31 12:49:47 +02:00
|
|
|
|
2020-05-27 15:53:44 +00:00
|
|
|
Here is a sample ``openssl.cnf``:
|
2019-03-31 12:49:47 +02:00
|
|
|
|
|
|
|
::
|
|
|
|
|
|
|
|
openssl_conf = openssl_def
|
|
|
|
[ openssl_def ]
|
|
|
|
engines = engine_section
|
|
|
|
[ engine_section ]
|
|
|
|
pkcs11 = pkcs11_section
|
|
|
|
[ pkcs11_section ]
|
|
|
|
PIN = <PLACE PIN HERE>
|
|
|
|
|
2020-06-08 15:33:45 +00:00
|
|
|
This also allows the ``dnssec-\*`` tools to access the HSM without PIN
|
|
|
|
entry. (The ``pkcs11-\*`` tools access the HSM directly, not via OpenSSL, so
|
|
|
|
a PIN is still required to use them.)
|