xref: /netbsd-src/external/mpl/bind/dist/doc/arm/pkcs11.inc.rst (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
1.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
2..
3.. SPDX-License-Identifier: MPL-2.0
4..
5.. This Source Code Form is subject to the terms of the Mozilla Public
6.. License, v. 2.0.  If a copy of the MPL was not distributed with this
7.. file, you can obtain one at https://mozilla.org/MPL/2.0/.
8..
9.. See the COPYRIGHT file distributed with this work for additional
10.. information regarding copyright ownership.
11
12.. _pkcs11:
13
14PKCS#11 (Cryptoki) Support
15~~~~~~~~~~~~~~~~~~~~~~~~~~
16
17Public Key Cryptography Standard #11 (PKCS#11) defines a
18platform-independent API for the control of hardware security modules
19(HSMs) and other cryptographic support devices.
20
21PKCS#11 uses a "provider library": a dynamically loadable
22library which provides a low-level PKCS#11 interface to drive the HSM
23hardware. The PKCS#11 provider library comes from the HSM vendor, and it
24is specific to the HSM to be controlled.
25
26BIND 9 uses engine_pkcs11 for PKCS#11. engine_pkcs11 is an OpenSSL
27engine which is part of the `OpenSC`_ project. The engine is dynamically
28loaded into OpenSSL and the HSM is operated indirectly; any
29cryptographic operations not supported by the HSM can be carried out by
30OpenSSL instead.
31
32.. _OpenSC: https://github.com/OpenSC/libp11
33
34Prerequisites
35^^^^^^^^^^^^^
36
37See the documentation provided by the HSM vendor for information about
38installing, initializing, testing, and troubleshooting the HSM.
39
40Building SoftHSMv2
41^^^^^^^^^^^^^^^^^^
42
43SoftHSMv2, the latest development version of SoftHSM, is available from
44https://github.com/opendnssec/SoftHSMv2. It is a software library
45developed by the OpenDNSSEC project (https://www.opendnssec.org) which
46provides a PKCS#11 interface to a virtual HSM, implemented in the form
47of an SQLite3 database on the local filesystem. It provides less security
48than a true HSM, but it allows users to experiment with native PKCS#11
49when an HSM is not available. SoftHSMv2 can be configured to use either
50OpenSSL or the Botan library to perform cryptographic functions, but
51when using it for native PKCS#11 in BIND, OpenSSL is required.
52
53By default, the SoftHSMv2 configuration file is ``prefix/etc/softhsm2.conf``
54(where ``prefix`` is configured at compile time). This location can be
55overridden by the SOFTHSM2_CONF environment variable. The SoftHSMv2
56cryptographic store must be installed and initialized before using it
57with BIND.
58
59::
60
61   $  cd SoftHSMv2
62   $  configure --with-crypto-backend=openssl --prefix=/opt/pkcs11/usr
63   $  make
64   $  make install
65   $  /opt/pkcs11/usr/bin/softhsm-util --init-token 0 --slot 0 --label softhsmv2
66
67OpenSSL-based PKCS#11
68^^^^^^^^^^^^^^^^^^^^^
69
70OpenSSL-based PKCS#11 uses engine_pkcs11 OpenSSL engine from libp11 project.
71
72engine_pkcs11 tries to fit the PKCS#11 API within the engine API of OpenSSL.
73That is, it provides a gateway between PKCS#11 modules and the OpenSSL engine
74API.  One has to register the engine with OpenSSL and one has to provide the
75path to the PKCS#11 module which should be gatewayed to. This can be done by
76editing the OpenSSL configuration file, by engine specific controls, or by using
77the p11-kit proxy module.
78
79It is recommended, that libp11 >= 0.4.12 is used.
80
81For more detailed howto including the examples, we recommend reading:
82
83https://gitlab.isc.org/isc-projects/bind9/-/wikis/BIND-9-PKCS11
84
85Using the HSM
86^^^^^^^^^^^^^
87
88The canonical documentation for configuring engine_pkcs11 is in the
89`libp11/README.md`_, but here's copy of working configuration for
90your convenience:
91
92.. _`libp11/README.md`: https://github.com/OpenSC/libp11/blob/master/README.md#pkcs-11-module-configuration
93
94We are going to use our own custom copy of OpenSSL configuration, again it's
95driven by an environment variable, this time called OPENSSL_CONF.  We are
96going to copy the global OpenSSL configuration (often found in
97``etc/ssl/openssl.conf``) and customize it to use engines_pkcs11.
98
99::
100
101   cp /etc/ssl/openssl.cnf /opt/bind9/etc/openssl.cnf
102
103and export the environment variable:
104
105::
106
107   export OPENSSL_CONF=/opt/bind9/etc/openssl.cnf
108
109Now add following line at the top of file, before any sections (in square
110brackets) are defined:
111
112::
113
114   openssl_conf = openssl_init
115
116And make sure there are no other 'openssl_conf = ...' lines in the file.
117
118Add following lines at the bottom of the file:
119
120::
121
122   [openssl_init]
123   engines=engine_section
124
125   [engine_section]
126   pkcs11 = pkcs11_section
127
128   [pkcs11_section]
129   engine_id = pkcs11
130   dynamic_path = <PATHTO>/pkcs11.so
131   MODULE_PATH = <FULL_PATH_TO_HSM_MODULE>
132   init = 0
133
134Key Generation
135^^^^^^^^^^^^^^
136
137HSM keys can now be created and used.  We are going to assume that you already
138have a BIND 9 installed, either from a package, or from the sources, and the
139tools are readily available in the ``$PATH``.
140
141For generating the keys, we are going to use ``pkcs11-tool`` available from the
142OpenSC suite.  On both DEB-based and RPM-based distributions, the package is
143called opensc.
144
145We need to generate at least two RSA keys:
146
147::
148
149   pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type rsa:2048 --label example.net-ksk --pin <PIN>
150   pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type rsa:2048 --label example.net-zsk --pin <PIN>
151
152Remember that each key should have unique label and we are going to use that
153label to reference the private key.
154
155Convert the RSA keys stored in the HSM into a format that BIND 9 understands.
156The :iscman:`dnssec-keyfromlabel` tool from BIND 9 can link the raw keys stored in the
157HSM with the ``K<zone>+<alg>+<id>`` files.  You'll need to provide the OpenSSL
158engine name (``pkcs11``), the algorithm (``RSASHA256``) and the PKCS#11 label
159that specify the token (we asume that it has been initialized as bind9), the
160name of the PKCS#11 object (called label when generating the keys using
161``pkcs11-tool``) and the HSM PIN.
162
163Convert the KSK:
164
165::
166
167   dnssec-keyfromlabel -E pkcs11 -a RSASHA256 -l "token=bind9;object=example.net-ksk;pin-value=0000" -f KSK example.net
168
169and ZSK:
170
171::
172
173   dnssec-keyfromlabel -E pkcs11 -a RSASHA256 -l "token=bind9;object=example.net-zsk;pin-value=0000" example.net
174
175NOTE: you can use PIN stored on disk, by specifying ``pin-source=<path_to>/<file>``, f.e.:
176
177::
178
179   (umask 0700 && echo -n 0000 > /opt/bind9/etc/pin.txt)
180
181and then use in the label specification:
182
183::
184
185   pin-source=/opt/bind9/etc/pin.txt
186
187Confirm that you have one KSK and one ZSK present in the current directory:
188
189::
190
191   ls -l K*
192
193The output should look like this (the second number will be different):
194
195::
196
197   Kexample.net.+008+31729.key
198   Kexample.net.+008+31729.private
199   Kexample.net.+008+42231.key
200   Kexample.net.+008+42231.private
201
202A note on generating ECDSA keys: there is a bug in libp11 when looking up a key,
203that function compares keys only on their ID, not the label. So when looking up
204a key it returns the first key, rather than the matching key. The workaround for
205this is when creating ECDSA keys, you should specify a unique ID:
206
207::
208
209   ksk=$(echo "example.net-ksk" | openssl sha1 -r | awk '{print $1}')
210   zsk=$(echo "example.net-zsk" | openssl sha1 -r | awk '{print $1}')
211   pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type EC:prime256v1 --id $ksk --label example.net-ksk --pin <PIN>
212   pkcs11-tool --module <FULL_PATH_TO_HSM_MODULE> -l -k --key-type EC:prime256v1 --id $zsk --label example.net-zsk --pin <PIN>
213
214
215Specifying the Engine on the Command Line
216^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
217
218When using OpenSSL-based PKCS#11, the "engine" to be used by OpenSSL can be
219specified in :iscman:`named` and all of the BIND ``dnssec-*`` tools by using the ``-E
220<engine>`` command line option. Specifying the engine is generally not necessary
221unless a different OpenSSL engine is used.
222
223The zone signing commences as usual, with only one small difference.  We need to
224provide the name of the OpenSSL engine using the -E command line option.
225
226::
227
228   dnssec-signzone -E pkcs11 -S -o example.net example.net
229
230Running :iscman:`named` With Automatic Zone Re-signing
231^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
232
233The zone can also be signed automatically by named. Again, we need to provide
234the name of the OpenSSL engine using the :option:`-E <named -E>` command line option.
235
236::
237
238   named -E pkcs11 -c named.conf
239
240and the logs should have lines like:
241
242::
243
244   Fetching example.net/RSASHA256/31729 (KSK) from key repository.
245   DNSKEY example.net/RSASHA256/31729 (KSK) is now published
246   DNSKEY example.net/RSA256SHA256/31729 (KSK) is now active
247   Fetching example.net/RSASHA256/42231 (ZSK) from key repository.
248   DNSKEY example.net/RSASHA256/42231 (ZSK) is now published
249   DNSKEY example.net/RSA256SHA256/42231 (ZSK) is now active
250
251For :iscman:`named` to dynamically re-sign zones using HSM keys,
252and/or to sign new records inserted via nsupdate, :iscman:`named` must
253have access to the HSM PIN. In OpenSSL-based PKCS#11, this is
254accomplished by placing the PIN into the ``openssl.cnf`` file (in the above
255examples, ``/opt/pkcs11/usr/ssl/openssl.cnf``).
256
257The location of the openssl.cnf file can be overridden by setting the
258``OPENSSL_CONF`` environment variable before running :iscman:`named`.
259
260Here is a sample ``openssl.cnf``:
261
262::
263
264       openssl_conf = openssl_def
265       [ openssl_def ]
266       engines = engine_section
267       [ engine_section ]
268       pkcs11 = pkcs11_section
269       [ pkcs11_section ]
270       PIN = <PLACE PIN HERE>
271
272This also allows the ``dnssec-\*`` tools to access the HSM without PIN
273entry. (The ``pkcs11-\*`` tools access the HSM directly, not via OpenSSL, so
274a PIN is still required to use them.)
275