# NervesKey.PKCS11

[![Hex version]( "Hex version")](

This is a minimal implementation of [PKCS #11](
for using the NervesKey with OpenSSL and other programs.  The NervesKey is a specific
configuration of the ATECC508A/ATECC608A chips that holds one private key in slot 0. If
you're using this chip in a similar configuration, this should work for you as well.

Supported features:


This library is organized to make it easy to integrate into Elixir and is
written with an expectation that provisioning, extracting certificates, etc. is done
via other means (like using [nerves_key]( If you're not
using Elixir, you can still run `make` and copy `priv/` to
a conveniently location. Elixir isn't needed to build the C library.

Another option is to look at
or [cryptoauthlib](

## Building

This library is self-contained with no compile-time dependencies. At runtime, it
isn't useful unless you have another program around that uses a PKCS #11 shared

If using it with Elixir, add a dependency to your `mix.exs`:

def deps do
    {:nerves_key_pkcs11, "~> 1.0"}

If not using Elixir, run `make`. You may need to set $(CC) or $(CFLAGS) if you're

## Slot definition

PKCS #11 uses the term slot to refer to cryptographic devices. This library can
use either slot ID (if called directly) or the slot's token ID (if called via
libp11) to find the NervesKey. Various parameters are mapped into the slot ID
according to the table below:

Slot range  | I2C bus   | Bus address              | Certificate
0-15        | slot      | 0x60 (ATECC default)     | Primary or auxiliary
16-31       | slot-16   | 0x35 (Trust&Go versions) | Primary or auxiliary

On Linux, the I2C bus number in the table above determines the device file. For
example, a bus number of "1" maps to `/dev/i2c-1`. NervesKey devices support a
primary and auxiliary set of certificates. Normally only the primary device
certificate is used. Under some conditions, it's useful to write a second set of
certificates to the device and those can be referenced by using the "Auxiliary"
rows in the table.  This library currently need to differentiate between primary
and auxiliary certificates so that's not represented in the slot ID. It may be
in the future.

The [PKCS #11 URI]( for addressing the
desired NervesKey has the form:


## OpenSSL integration

To use this with OpenSSL, you'll need ``. This library comes from
[OpenSC's libp11]( and can be installed on
Debian systems by running:

sudo apt install libengine-pkcs11-openssl1.1

## Invocation from Erlang and Elixir

Erlang's `crypto` application provides an API for loading OpenSSL engines. See
[the Erlang crypto User's Guide](
for details on this feature. `NervesKey.PKCS11.load_engine/0` is a helper method
to make the `:crypto.engine_load/3` call for you. It uses OpenSSL's `dynamic`
engine to load `` which in turn loads this PKCS #11 implementation.
Here's an example call in Elixir:

{:ok, engine} = NervesKey.PKCS11.load_engine()

If this doesn't work, you'll likely have to look at the implementation of
`load_engine/0` and fine tune the shared library paths or control commands.

After you load the engine, you'll eventually want to use it. The intended use
case is for delegate the ECDSA operation to the ATECC508A for use with TLS
connections. You'll need to obtain the X.509 certificate that corresponds to the
private key held in the ATECC508A through some mechanism. Then in your SSL
options, you'll have something like this:

  key: NervesKey.PKCS11.private_key(engine, i2c: 1, type: :nerves_key),
  certfile: "device-cert.pem",

The `NervesKey.PKCS11.private_key/2` helper method will create the appropriate
map so that Erlang's `:crypto` library can properly call into OpenSSL.

If you are using a pre-provisioned ATECC608B or similar that's labelled a Trust
and Go part, specify `:trust_and_go` for the `:type`.

## Sharing the NervesKey

If you have other code using the NervesKey, it might conflict with this library. There's
no lock file or mechanism to keep more than one process from accessing the ATECC508A
chip simultaneously. This is not expected to be an issue at runtime since the main
reason to access the NervesKey in another process is to provision it and that's not
something one would do when trying to use this library to assist a TLS negotiation.

## License

The Elixir and most C code is licensed under the 2-Clause BSD License.

The header file for the PKCS #11 function prototypes and structures, `pkcs11.h`,
has the following license:

/* pkcs11.h
   Copyright 2006, 2007 g10 Code GmbH
   Copyright 2006 Andreas Jellinghaus

   This file is free software; as a special exception the author gives
   unlimited permission to copy and/or distribute it, with or without
   modifications, as long as this notice is preserved.

   This file is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
   PURPOSE.  */