A CLI to manage PKCS#11 tokens for use with Sequoia PGP.

This tool helps users manage [PKCS#11 tokens] (aka Cryptokis) for use
in the OpenPGP ecosystem generally, and for use with Sequoia PGP in
particular.  Well known Cryptokis include those by [Nitrokey] and
[YubiKey].  Most HSMs also implement the PKCS#11 standard.

  [PKCS#11 tokens]: https://en.wikipedia.org/wiki/PKCS_11
  [Nitrokey]: https://www.nitrokey.com/products/nitrokeys
  [YubiKey]: https://www.yubico.com

The primary goal of this tool is to simplify the use of Crytokis with
Sequoia-based programs.  Although the exposed functionality may be
useful beyond this use case, an explicit non-goal is support for
everything that [PKCS#11 specifies].  For that, the `pkcs11-tool`,
which is part of [OpenSC], is more appropriate.

  [PKCS#11 specifies]: https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=pkcs11
  [OpenSC]: https://github.com/OpenSC/OpenSC/wiki

# Getting Started

This tool has currently only been tested with the [Kryoptic] soft
token.

  [Kryoptic]: https://github.com/latchset/kryoptic

## Building Kryoptic

You'll first need to build the Kryoptic soft token.  See the project's
`README` for more details.  One way is to run:

```shell
$ git clone https://github.com/latchset/kryoptic.git
$ cd kryoptic \
  && export CARGO_TARGET_DIR=/tmp/kryoptic-build \
  && mkdir -p $CARGO_TARGET_DIR \
  && FEATURES="--features pqc" \
  && cargo build --release $FEATURES \
  && cargo test $FEATURES \
```

This will place the PKCS#11 library in
`/tmp/kryoptic-build/release/libkryoptic_pkcs11.so`.

To configure Kryoptic, add something like the following to
`$HOME/.config/kryoptic/token.conf`:

```yaml
[[slots]]
slot = 1
dbtype = "sqlite"
dbargs = "/tmp/kryoptic/token.sql"
[[slots]]
slot = 3
dbtype = "sqlite"
dbargs = "/tmp/kryoptic/token3.sql"
```

## Building `sq-cryptoki`

To build `sq-cryptoki`, you can do:

```shell
$ git clone https://gitlab.com/sequoia-pgp/sequoia-cryptoki.git
$ cd sequoia-cryptoki
$ export CARGO_TARGET_DIR=/tmp/sequoia-cryptoki-build \
  && mkdir -p $CARGO_TARGET_DIR \
  && FEATURES="--no-default-features --features sequoia-openpgp/crypto-openssl,sequoia-openpgp/compression" \
  && cargo build --release --all $FEATURES
```

To run the test suite, you need to specify a PKCS#11 module using the
`SEQUOIA_CRYPTOKI_MODULE` environment variable, and the backend type
using the `SEQUOIA_CRYPTOKI_BACKEND` environment variable.  To use
Kryoptic with PQC support, do:

```shell
$ SEQUOIA_CRYPTOKI_BACKEND=kryoptic-pqc \
  SEQUOIA_CRYPTOKI_MODULE=/tmp/kryoptic-build/release/libkryoptic_pkcs11.so \
  cargo test --all $FEATURES
```

You can also test against `Kryoptic` compiled without PQC support
using the `kryoptic-no-pqc` backend.  This backend skips tests that
use PQC.

Using the Kryoptic backend, the test suite uses ephemeral tokens; it
does not touch any configured tokens.

## Listing Tokens and Keys

You can now use use the following to list the configured tokens and
any keys:

```shell
$ /tmp/sequoia-cryptoki-build/release/sq-cryptoki \
  --module /tmp/kryoptic-build/release/libkryoptic_pkcs11.so \
  token list
Slot #1
  - Slot:
    - Description: Kryoptic Slot
    - Manufacturer: Kryoptic Project
    - Hardware version: 0.0
    - Firmware version: 1.1
    - Hardware token: no
    - Removable token: no
    - Token present: yes
  - Token:
    - Label: "Kryoptic Soft Token"
    - Manufacturer: "Kryoptic Project"
    - Model: "v1"
    - Serial number: ""
    - Initialized: no
    - Clock: not present
    - Has a protected authentication path: no
Slot #3
  - Slot:
    - Description: Kryoptic Slot
...
```

It is possible to specify multiple modules to work with multiple
tokens at once.

## Token Initialization

Before generating a key, you need to initialize the token.  This can
be done as follows:

```shell
$ /tmp/sequoia-cryptoki-build/release/sq-cryptoki \
  --module /tmp/kryoptic-build/release/libkryoptic_pkcs11.so \
  token init --slot 1 --new-token-label extra-secure
 Config::select_internal: /tmp/kryoptic-build/release/libkryoptic_pkcs11.so has 2 slots
Token not yet initialized.  Performing initial initialization.
Please enter a PIN to protect the SO PIN: 
                   Please repeat the PIN: 
Please enter a PIN to protect the user PIN: 
                     Please repeat the PIN: 
```

`--slot` is a selector.  For tokens the following selectors are
available: `--backend`, `--slot`, `--token-label`, and
`--token-serial-number`.  These selectors can be combined if none of
the selectors are unambiguous.

When selecting a key, the above selectors can be used as well as the
`--key-label`, and `--key-id` selectors.

With the exception of `--backend` and `--slot`, selectors also match
against the hex encoded value.  For instance, if a token label is
`foo`, then both `--token-label foo` and `--token-label 666f6f` will
match.  This is helpful if the value contains unprintable characters.

# License

This project is licensed under the GNU Library General Public License
version 2 or later.

The file [dicewords.rs] includes the words listed in the [EFF short
wordlist].  See the [blog post from the EFF] for more details.  The
blog post doesn't mention a license, but [the website's content] is
published under the [CC-BY-4.0 International].

  [dicewords.rs]: src/common/dicewords.rs
  [EFF short wordlist]: https://www.eff.org/files/2016/09/08/eff_short_wordlist_1.txt
  [blog post from the EFF]: https://www.eff.org/dice
  [the website's content]: https://www.eff.org/copyright
  [CC-BY-4.0 International]: https://creativecommons.org/licenses/by/4.0/
