mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 01:59:26 +00:00
The OpenSSL 1.x Engines support has been deprecated in the OpenSSL 3.x and is going to be removed. Remove the OpenSSL Engine support in favor of OpenSSL Providers.
258 lines
9.2 KiB
ReStructuredText
258 lines
9.2 KiB
ReStructuredText
.. 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.
|
|
|
|
.. _pkcs11:
|
|
|
|
PKCS#11 (Cryptoki) Support
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Public Key Cryptography Standard #11 (PKCS#11) defines a
|
|
platform-independent API for the control of hardware security modules
|
|
(HSMs) and other cryptographic support devices.
|
|
|
|
PKCS#11 uses a "provider library": a dynamically loadable
|
|
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.
|
|
|
|
BIND 9 access PKCS#11 libraries via OpenSSL Providers. The provider for
|
|
OpenSSL 3 and newer is `pkcs11-provider`_.
|
|
|
|
.. _`pkcs11-provider`: https://github.com/latchset/pkcs11-provider
|
|
|
|
In both cases the extension 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.
|
|
|
|
Prerequisites
|
|
^^^^^^^^^^^^^
|
|
|
|
See the documentation provided by the HSM vendor for information about
|
|
installing, initializing, testing, and troubleshooting the HSM.
|
|
|
|
Building SoftHSMv2
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
SoftHSMv2, the latest development version of SoftHSM, is available from
|
|
https://github.com/opendnssec/SoftHSMv2. It is a software library
|
|
developed by the OpenDNSSEC project (https://www.opendnssec.org) which
|
|
provides a PKCS#11 interface to a virtual HSM, implemented in the form
|
|
of an SQLite3 database on the local filesystem. It provides less security
|
|
than a true HSM, but it allows users to experiment with native PKCS#11
|
|
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.
|
|
|
|
By default, the SoftHSMv2 configuration file is ``prefix/etc/softhsm2.conf``
|
|
(where ``prefix`` is configured at compile time). This location can be
|
|
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 3 with pkcs11-provider
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
OpenSSL provider-based PKCS#11 uses pkcs11-provider project.
|
|
|
|
pkcs11-provider tries to fit the PKCS#11 API within the Provider API of OpenSSL.
|
|
That is, it provides a gateway between PKCS#11 modules and the OpenSSL Provider
|
|
API. One has to register the provider 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, using provider specific controls, or
|
|
by using the p11-kit proxy module.
|
|
|
|
It is required to use pkcs11-provider version 0.3 or later. It is recommended
|
|
to use the lastest version available.
|
|
|
|
Configuring pkcs11-provider
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
The canonical documentation for configuring pkcs11-provider is in the
|
|
`provider-pkcs11.7`_ manual page, but here's copy of working configuration for
|
|
your convenience:
|
|
|
|
.. _`provider-pkcs11.7`: https://github.com/latchset/pkcs11-provider/blob/main/docs/provider-pkcs11.7.md
|
|
|
|
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 pkcs11-provider.
|
|
|
|
::
|
|
|
|
cp /etc/ssl/openssl.cnf /opt/bind9/etc/openssl.cnf
|
|
|
|
and export the environment variable:
|
|
|
|
::
|
|
|
|
export OPENSSL_CONF=/opt/bind9/etc/openssl.cnf
|
|
|
|
Now add the following line at the top of file, before any sections (in square
|
|
brackets) are defined:
|
|
|
|
::
|
|
|
|
openssl_conf = openssl_init
|
|
|
|
And make sure there are no other 'openssl_conf = ...' lines in the file.
|
|
|
|
Add following lines at the bottom of the file:
|
|
|
|
::
|
|
|
|
[openssl_init]
|
|
providers = provider_init
|
|
|
|
[provider_init]
|
|
default = default_init
|
|
pkcs11 = pkcs11_init
|
|
|
|
[default_init]
|
|
activate = 1
|
|
|
|
[pkcs11_init]
|
|
module = <PATHTO>/pkcs11.so
|
|
pkcs11-module-path = <FULL_PATH_TO_HSM_MODULE>
|
|
# bind uses the digest+sign api. this is broken with the default load behaviour,
|
|
# but works with early load. see: https://github.com/latchset/pkcs11-provider/issues/266
|
|
pkcs11-module-load-behavior = early
|
|
# no-deinit quirk is needed if you use softhsm2
|
|
#pkcs11-module-quirks = no-deinit
|
|
# if automatic logging to the token is needed, PIN can be specified as below
|
|
# the file referenced should contain just the PIN
|
|
#pkcs11-module-token-pin = file:/etc/pki/pin.txt
|
|
activate = 1
|
|
|
|
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``.
|
|
|
|
A zone that is configured with ``dnssec-policy`` can generate keys through
|
|
the PKCS#11 Provider API of OpenSSL.
|
|
|
|
If you want to create keys manually, the ``pkcs11-tool`` available from the
|
|
`OpenSC`_ suite can be used. On both DEB-based and RPM-based distributions,
|
|
the package is called opensc.
|
|
|
|
.. _OpenSC: https://github.com/OpenSC/libp11
|
|
|
|
We need to generate at least two RSA keys:
|
|
|
|
::
|
|
|
|
pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type rsa:2048 --label example.net-ksk --pin <PIN>
|
|
pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type rsa:2048 --label example.net-zsk --pin <PIN>
|
|
|
|
Remember that each key should have unique label and we are going to use that
|
|
label to reference the private key.
|
|
|
|
Convert the RSA keys stored in the HSM into a format that BIND 9 understands.
|
|
The :iscman:`dnssec-keyfromlabel` tool from BIND 9 can link the raw keys stored in the
|
|
HSM with the ``K<zone>+<alg>+<id>`` files.
|
|
|
|
You'll need to provide the algorithm (``RSASHA256``). The key is referenced with
|
|
the PKCS#11 URI scheme and it can contain the PKCS#11 token label (we asume that
|
|
it has been initialized as bind9), and the PKCS#11 object label (called label
|
|
when generating the keys using ``pkcs11-tool``) and the HSM PIN. Refer to
|
|
:rfc:`7512` for the full PKCS#11 URI specification.
|
|
|
|
Convert the KSK:
|
|
|
|
::
|
|
|
|
dnssec-keyfromlabel -a RSASHA256 -l "pkcs11:token=bind9;object=example.net-ksk;pin-value=0000" -f KSK example.net
|
|
|
|
and ZSK:
|
|
|
|
::
|
|
|
|
dnssec-keyfromlabel -a RSASHA256 -l "pkcs11:token=bind9;object=example.net-zsk;pin-value=0000" example.net
|
|
|
|
NOTE: you can use PIN stored on disk, by specifying ``pin-source=<path_to>/<file>``, f.e.:
|
|
|
|
::
|
|
|
|
(umask 0700 && echo -n 0000 > /opt/bind9/etc/pin.txt)
|
|
|
|
and then use in the label specification:
|
|
|
|
::
|
|
|
|
pin-source=/opt/bind9/etc/pin.txt
|
|
|
|
Confirm that you have one KSK and one ZSK present in the current directory:
|
|
|
|
::
|
|
|
|
ls -l K*
|
|
|
|
The output should look like this (the second number will be different):
|
|
|
|
::
|
|
|
|
Kexample.net.+008+31729.key
|
|
Kexample.net.+008+31729.private
|
|
Kexample.net.+008+42231.key
|
|
Kexample.net.+008+42231.private
|
|
|
|
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" | openssl sha1 -r | awk '{print $1}')
|
|
zsk=$(echo "example.net-zsk" | openssl sha1 -r | 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>
|
|
|
|
|
|
Running :iscman:`named` With Automatic Zone Re-signing
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Once the keys are created, the zone can also be signed automatically by named
|
|
without further requisites.
|
|
|
|
The logs should have lines like:
|
|
|
|
::
|
|
|
|
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
|
|
|
|
For :iscman:`named` to dynamically re-sign zones using HSM keys,
|
|
and/or to sign new records inserted via nsupdate, :iscman:`named` must
|
|
have access to the HSM PIN. In OpenSSL-based PKCS#11, this is
|
|
accomplished by placing the PIN into the ``openssl.cnf`` file (in the above
|
|
examples, ``/opt/pkcs11/usr/ssl/openssl.cnf``).
|
|
|
|
See OpenSSL extension specific documentation on how to configure the PIN on
|
|
global level. Doing so 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.)
|