== YubiHSM PKCS#11 Module

The YubiHSM PKCS#11 Module is a native library to interact with a
YubiHSM 2 device using the
link:http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html[PKCS#11
interface].

This library works as a translation layer between `libyubihsm` and
software using PKCS#11. For example, a function in this implementation
takes the input as specified by PKCS#11, translates it into the input
expected by the corresponding function in `libyubihsm`, calls that
function and then translates the result into the return value expected
by PKCS#11.

=== Connector Configuration

The
link:https://developers.yubico.com/YubiHSM2/Component_Reference/yubihsm-connector/[Connector]
is a component required by a YubiHSM 2 device that performs the
communication between the device and applications using it.

A connector can be either an external process communicating over HTTP
(by default `http://localhost:12345`), or directly linked in by
`libyubihsm` in the case of direct USB access.

The PKCS#11 module requires a configuration file containing the URL of
the Connector and other configuration options. The default location
for that file is the current directory and its default name is
`yubihsm_pkcs11.conf`. However, using the environment variable
`YUBIHSM_PKCS11_CONF`, one can point to a custom location and name.

Below is an example of a `yubihsm_pkcs11.conf` file:

[source, cfg]
----
connector=http://localhost:12345
debug
libdebug
dinout
----

This file will turn on debug messages for the PKCS#11 module
(`debug`), `libyubihsm` (`libdebug`) and functions call tracing
(`dinout`)

A full list of the configuration options can be found on the
link:https://developers.yubico.com/YubiHSM2/Component_Reference/PKCS_11/[developers
website].

==== Initialization Arguments

One of the possible parameters given to the PKCS#11 `C_Initialize`
function, `pReserved`, can also be used to provide configuration
options to the module. While this is technically in violation of the
PKCS#11 specifications which requires that field to be set to `NULL`,
some application such as OpenSSL support this behavior.

An example of using this technique can be found on the
link:https://developers.yubico.com/YubiHSM2/Component_Reference/PKCS_11/[developers
website].

=== Logging In

All interesting operations available through the PKCS#11 interface require
a logged-in session. There are two ways the credentials can be provided:
in plaintext or via YubiKey yubihsm-auth, and there are two types of
credentials: symmetric and asymmetric.

==== Plaintext symmetric credentials

This is the authentication mode for the default admin user available on
YubiHSM after factory reset. The 'Password' is fed into PBKDF2-HMAC-SHA256
to derive symmetric AES-128 encryption and MAC keys used in the SCP03
communication channel. The corresponding yubihsm-shell command to store
the credential on the YubiHSM is `put authkey`.

The format of the PKCS#11 PIN is as follows:

----
{AuthKeyID}{Password}
----

Where:

 `AuthKeyID` is Authentication Key ID of the YubiHSM, 16 bits,
            in hexadecimal, zero padded
 `Password` is the secret used as input to KDF, _MUST_ be at least `8` and
           at most `64` characters long.

For example, to use the default Authentication Key with ID `1` and password
`password`, the PKCS#11 PIN would then be `0001password`.

==== Plaintext asymmetric credentials

This is an authentication mode available starting from YubiHSM firmware
v2.3. The 'Password' is fed into PBKDF2-HMAC-SHA256 to derive a NIST
P-256 private key. This key, alongside the YubiHSM static public key
(configured via the `device-pubkey` option in `yubihsm_pkcs11.conf`), is
used to establish a dual ECDH key agreement (SCP11b), from which ephemeral
AES-128 encryption and MAC keys are derived. The corresponding yubihsm-shell
command to store the credential on the YubiHSM is `put authkey_asym`.

The format of the PKCS#11 PIN is as follows:

----
@{AuthKeyID}{Password}
----

Where:

 `AuthKeyID` is Authentication Key ID of the YubiHSM, 16 bits,
            in hexadecimal, zero padded
 `Password` is the secret used as input to KDF, _MUST_ be at least `8` and
           at most `64` characters long.

For example, to use the Authentication Key with ID `63` (decimal) and password
`DicewareGeneratedPassword`, the PKCS#11 PIN would then be
`@003fDicewareGeneratedPassword`.

==== Credentials from YubiKey yubihsm-auth applet

The YubiKey yubihsm-auth applet supports both symmetric and asymmetric
credentials stored in a non-exportable form in the YubiKey hardware. The
'Password' in this case is the yubihsm-auth PIN. Additionally, the
credential's label must be supplied. There is no distinction between
symmetric and asymmetric credentials from the PKCS#11 point of view, as
the authentication process is offloaded to the YubiKey.

The format of the PKCS#11 PIN is as follows:

----
#{YkAuthLabel}#{AuthKeyID}{Password}
----

Where:

 `YkAuthLabel` is a credential label in the YubiKey `yubihsm-auth`,
              _MUST_ be at least `1` and at most `64` characters long.
 `AuthKeyID` is Authentication Key ID of the YubiHSM, 16 bits,
            in hexadecimal, zero padded
 `Password` is the YubiKey `yubihsm-auth` credential PIN,
            _MUST_ be at least `8` and at most `16` characters long.

For example, to use the Authentication Key with ID `15` (decimal), with
credential label "ProdHsmAdmin" and YubiKey PIN `12345678`, the PKCS#11
PIN would then be `#ProdHsmAdmin#000f12345678`.

=== PKCS#11 Attributes

There are a number of settable attributes defined by PKCS#11 that do
not accurately translate to YubiHSM 2 Capabilities and are therefore
treated as always having a fixed value. A list of those attributes and
their values can be found on the
link:https://developers.yubico.com/YubiHSM2/Component_Reference/PKCS_11/[developers
website].

=== Capabilities and Domains

Objects created via the PKCS#11 module inherit the Domains of the
Authentication Key used to establish the session. The Domains can not
be changed or modified via the PKCS#11 module.

A table mapping PKCS#11 objects to YubiHSM 2 Capabilities can be found
on the
link:https://developers.yubico.com/YubiHSM2/Component_Reference/PKCS_11/[developers
website].

=== PKCS#11 Objects

Not all PKCS#11 Object Types are implemented. A list of what is
implemented is available
link:https://developers.yubico.com/YubiHSM2/Component_Reference/PKCS_11/[here].

=== Examples

==== C Code Example

Code examples of how to use the PKCS#11 module from C programs can be
found in the test link:tests/ecdh_derive_test.c

==== Pkcs11-tool Example

To derive an ECDH key using a public key in the file `peer.key` and a
private key in the YubiHSM 2 with OpenSC `pkcs11-tool`, the following
command can be used:

[source, sh]
----
pkcs11-tool -vvv --module yubihsm_pkcs11.so --derive -i peer.key --id 64 --login --pin 0001password
----

The private key in YubiHSM 2 has Object ID `0x0064` and the public key
in `peer.key` is expected to be in DER format. By default, this
command will expect to find a `yubihsm_pkcs11.conf` file in the
current directory.
