== YKCS11
This is a PKCS#11 module that allows external applications to communicate with the PIV
application running on a YubiKey.

This module is based on version 2.40 of the PKCS#11 (Cryptoki) specifications. The complete specifications are available at
https://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html[oasis-open.org].

=== Building
YKCS11 is automatically built as part of `yubico-piv-tool` and the
following command will suffice:

  $ mkdir build; cd build
  $ cmake ..
  $ make
  $ sudo make install

More info about building `yubico-piv-tool` can be found in the related
`README` file or in https://developers.yubico.com/yubico-piv-tool[yubico-piv-tool].

Once installed, the module will be found by default in
`/usr/local/lib/libykcs11.so` otherwise it will be built locally in
`yubico-piv-tool/build/ykcs11/libykcs11.so`

=== Portability
The module has been developed and tested using Ubuntu Linux, MacOS and Windows. Both MacOS and Windows use PCSC as
a backend.

=== YKCS11 on Windows
After installing yubico-piv-tool using the windows installer, the `Yubico PIV Tool\bin` directory needs to be added to
the system path in order for other applications to be able to load it. This is because the `libykcs11.dll` is dynamically
linked to `libykpiv.dll` and to `libcrypto-1_1.dll` and both of them need to be accessible for ykcs11 to be useful.

On Windows 10, setting the system path is done by following these steps:

1- Go to Control Panel → System and Security → System → Advanced system setting

2- Click “Environment Variables…“

3- Under System Variables, highlight “Path“ and click “Edit…“

4- Click “New“ and add the absolute path to `Yubico PIV Tool\bin` 

If setting the system path is not desirable, the `libykpiv.dll` and `libcrypto-1_1.dll` can be copied into the same
directory as the application that needs to access the ykcs11 module.

==== A Note for Developers
If `LoadLibrary` is called with an absolute path, it will *not* look for dependencies of the specified DLL in that
directory, but rather in the startup directory of the application that calls `LoadLibrary`. The solution is to either:

- Call `LoadLibraryEx` with the flag `LOAD_WITH_ALTERED_SEARCH_PATH` for absolute paths

- Add the directory where ykcs11 is located to the system PATH

- Or copy the dependencies into the application directory.

Please note that calling `LoadLibraryEx` with that flag for a non-absolute path is undefined behavior according to
MS docs. For example, the way Pkcs11Interop does it is to set a variable to `LOAD_WITH_ALTERED_SEARCH_PATH` if the
path looks absolute, and 0 otherwise; and then always calling `LoadLibraryEx`. If the flags is `0` then `LoadLibraryEx`
behaves exactly like `LoadLibrary`.

==== Key Mapping
The module provides access to all 25 keys that can be stored on the YubiKey PIV application. These keys correspond to the keys in the PIV slots as described in https://developers.yubico.com/PIV/Introduction/Certificate_slots.html[PIV Certificate Slots] and are accessible through `yubico-piv-tool`.

The mapping is as follows:

[cols="2*^", options="header"]
|===
|ykcs11 id|PIV
|1|9a
|2|9c
|3|9d
|4|9e
|5 - 24 | 82 - 95
|25|f9
|===

==== Key Generation
Key pair generation is a particular operation, in the sense that
within PIV this is the only moment where the newly created public key
is given back to the user. To prevent the key from being lost, it is
automatically stored within the YubiKey by wrapping it in an X.509
certificate.

=== Attestation Certificates
Attestation certificates are also accessible with the YKCS11 module. An attestation certificate is a regular X509 Certificates that has the same `CKA_ID` and public key as the key it is attesting. Attestation certificates, however, are not stored in the YubiKey (`CKA_TOKEN` is FALSE) and are generated when accessed.

For more details about attestation, see the link:../Attestation.adoc[Attestation] section.

=== User Types
YKCS11 defines two types of users: a regular user and a security
officer (SO). These have been mapped to perform regular usage of the
private key material (PIN-associated operations) and device management
(management-key associated operations).

==== PINs and Management Key
The default user PIN for the YubiKey is `123456`. +
The default management key is
`010203040506070801020304050607080102030405060708`. +

In order to perform operations involving the private keys, a regular
user must be logged in (i.e. using the PIN or fingerprint). However, given the
different PIN policies for different keys, subsequent operations might
require a new login. This is supported by the module through the `CONTEXT_SPECIFIC`
user in accordance with the specifications.

==== Fingerprint Authentication with YubiKey Bio

It is also possible to use the fingerprint reader on the YubiKey Bio to login. Attempting to login with an empty
PIN will trigger bio verification and the user is expected to scan their fingerprint then. Note that their might
not be an indication on the screen that a fingerprint scan is expected but the YubiKey will be blinking while it is
waiting for a fingerprint scan.

=== OpenSSL
The YubiKey only supports functions that require an asymmetrinc private key. Functions that do not, like encryption,
signature verification, hashing and generation of a random number, are done using OpenSSL.

Also, the YubiKey only performs raw decryption and signature. So when padding is used, for example OAEP and PSS padding,
applying and removing the padding is handled using OpenSSL functions.

=== Testing
Apart from the internal tests, the YKCS11 has also been tested with the Pkcs11Interop .NET library

==== Debugging
By default, the module has debugging disabled. This is _highly_ verbose
and might be confusing.

To enable debugging of the ykcs11 module, the variable `YKCS11_DBG` needs to be set to a numerical value `1` to `9`
(the value `0` indicates disabled debugging). `YKCS11_DBG` can be set in one of the following ways:

1. Set the environment variable `YKCS11_DBG`

2. Rebuild the project as follows (`2` here is an example):

  $ mkdir build; cd build
  $ cmake .. -DYKCS11_DBG=2
  $ make
  $ sudo make install

It is also possible to use https://github.com/OpenSC/OpenSC/wiki/Using-OpenSC[PKCS#11 Spy], as provided by OpenSC, to inspect the PKCS#11 communication.
