README.md

# NervesKey.PKCS11

[![CircleCI](https://circleci.com/gh/nerves-hub/nerves_key_pkcs11.svg?style=svg)](https://circleci.com/gh/nerves-hub/nerves_key_pkcs11)
[![Hex version](https://img.shields.io/hexpm/v/nerves_key_pkcs11.svg "Hex version")](https://hex.pm/packages/nerves_key_pkcs11)

This is a minimal implementation of [PKCS #11](https://en.wikipedia.org/wiki/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:

* ECDSA

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](https://hex.pm/nerves_key).) If you're not
using Elixir, you can still run `make` and copy `priv/nerves_key_pkcs11.so` to
a conveniently location. Elixir isn't needed to build the C library.

Another option is to look at
[cryptoauth-openssl-engine](https://github.com/MicrochipTech/cryptoauth-openssl-engine)
or [cryptoauthlib](https://github.com/MicrochipTech/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
library.

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

```elixir
def deps do
  [
    {:nerves_key_pkcs11, "~> 0.1.0"}
  ]
end
```

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

## 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. The following table shows the mapping
from slot to device.

Slot range  | Description
------------|------------
0-15        | I2C bus 0-15 (i.e. /dev/i2c-0, etc.), ATECC508A at address 0x60 (the default)

The [PKCS #11 URI](https://tools.ietf.org/html/rfc7512) for addressing the
desired NervesKey has the form:

```text
pkcs11:id=1
```

## OpenSSL integration

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

```sh
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](http://erlang.org/doc/apps/crypto/engine_load.html)
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 `libpkcs11.so` which in turn loads this PKCS #11 implementation.
Here's an example call in Elixir:

```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:

```elixir
[
  key: NervesKey.PKCS11.private_key(engine, {:i2c, 1}),
  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.

## 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:

```text
/* 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
   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
   PURPOSE.  */
```