Options for providing a pin
===========================

The obvious ways to provide user and security officer pin are to write a secret
into p11nethsm.conf, pass it on command line to frontend tools interactively,
or pass it as command line argument like pkcs11-tool --pin.

In automation scenarios this may not be flexible or secure enough. A better
option can be to include the pin-source attribute in a PKCS#11 URI as
defined in RFC 7512 [1]. For example,

  pkcs11:token=NetHSM;object=mykey;type=private&pin-source=/secure/place/.pin

is understood by both pkcs11-provider and the libp11 engine which will read the
secret from a text file that was previously prepared in a secure context.

[1] https://www.rfc-editor.org/rfc/rfc7512.html


Testing with Nitrokey's public online demo instance
===================================================

nethsm-pkcs11 can be tested with Nitrokey's online demo instance at
nethsmdemo.nitrokey.com. This example shows how to use it to sign a text
message through PKCS#11 using openssl as frontend.

First copy the demo instance example configuration in place

  mkdir -p $HOME/.config/nitrokey
  cp /usr/share/doc/nethsm-pkcs11/examples/p11nethsm.demoinstance.conf \
    $HOME/.config/nitrokey/p11nethsm.conf

Since the demo instance is periodically reset, we must provision it first to
get a key and user known to us. Provisioning can be done with the pynitrokey
tool, or through REST API with plain curl as shown further on.

  # unlock - may fail if already unlocked
  curl -H "Content-Type: application/json" --data '{
      "passphrase": "unlockunlock"
    }' \
    https://admin:adminadmin@nethsmdemo.nitrokey.com/api/v1/unlock

  # provision - may fail if already provisioned
  curl -H "Content-Type: application/json" --data '{
      "unlockPassphrase": "unlockunlock",
      "adminPassphrase": "adminadmin",
      "systemTime": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
    }' \
    https://admin:adminadmin@nethsmdemo.nitrokey.com/api/v1/provision

  # create operator user
  curl -X "PUT" -H "Content-Type: application/json" --data '{
      "realName": "Debian User",
      "role": "Operator",
      "passphrase": "operatoroperator"
    }' \
    https://admin:adminadmin@nethsmdemo.nitrokey.com/api/v1/users/operator

  # generate signign key
  curl -H "Content-Type: application/json" --data '{
      "mechanisms": [
        "RSA_Signature_PKCS1"
      ],
      "type": "RSA",
      "length": 2048,
      "id": "myFirstKey"
    }' \
    https://admin:adminadmin@nethsmdemo.nitrokey.com/api/v1/keys/generate

Install pkcs11-provider and p11-kit to let openssl find the nethsm-pkcs11 module.
Then verify the connection.

sudo apt install nethsm-pkcs11 pkcs11-provider p11-kit-modules
p11-kit list-modules

The output should contain following lines (excerpt)

  module: nethsm_pkcs11
      token: NetHSMdemo
          uri: pkcs11:model=NetHSM;manufacturer=Nitrokey%20GmbH;serial=0000000000;token=NetHSMdemo

For CMS signign, we'll also need a signer certificate along with the key.
It can be created and uploaded as follows.

  openssl req -provider pkcs11 -provider default \
    -x509 -new -batch -subj /CN=myFirstKey -text -days 365 \
    -key "pkcs11:token=NetHSMdemo;object=myFirstKey;type=private" \
    -outform PEM \
    -out /tmp/cert.pem

  curl -v -H "Content-Type: application/octet-stream" \
    --upload-file /tmp/cert.pem \
    https://admin:adminadmin@nethsmdemo.nitrokey.com/api/v1/keys/myFirstKey/cert

Finally, we can sign our message and create a detached CMS signature:

  echo "my message" > /tmp/message.txt

  openssl cms -provider pkcs11 -provider default -sign \
    -inkey "pkcs11:token=NetHSMdemo;object=myFirstKey;type=private" \
    -signer "pkcs11:token=NetHSMdemo;object=myFirstKey;type=cert" \
    -md SHA256 -outform DER -binary \
    -in /tmp/message.txt \
    -out /tmp/message.txt.sig
