# `NervesKey`
[🔗](https://github.com/nerves-hub/nerves_key/blob/v1.3.0/lib/nerves_key.ex#L10)

This is a high level interface to provisioning and using the NervesKey
or any ATECC508A/608A that can be configured similarly.

# `certificate_pair`

```elixir
@type certificate_pair() :: :primary | :aux
```

Which device/signer certificate pair to use

# `device_type`

```elixir
@type device_type() :: :nerves_key | :trust_and_go
```

Which type of device to use

# `clear_aux_certificates`

```elixir
@spec clear_aux_certificates(ATECC508A.Transport.t()) :: :ok
```

Clear out the auxiliary certificates

This function overwrites the auxiliary certificate slots with

# `create_signing_key_pair`

```elixir
@spec create_signing_key_pair(keyword()) ::
  {X509.Certificate.t(), X509.PrivateKey.t()}
```

Create a signing key pair

This returns a tuple that contains a new signer certificate and private key.
It is compatible with the ATECC508A certificate compression.

Options:

* :years_valid - how many years this key is valid for

# `default_info`

```elixir
@spec default_info(ATECC508A.Transport.t()) :: NervesKey.ProvisioningInfo.t()
```

Return default provisioning info for a NervesKey

This function is used for pre-programmed NervesKey devices. The
serial number is a Base32-encoded version of the ATECC508A/608A's globally unique
serial number. No additional care is needed to keep the number unique.

# `detected?`

```elixir
@spec detected?(ATECC508A.Transport.t()) :: boolean()
```

Detect if a NervesKey is available on the transport

# `device_cert`

```elixir
@spec device_cert(ATECC508A.Transport.t(), certificate_pair(), device_type()) ::
  X509.Certificate.t()
```

Read the device certificate from the slot

The device must be programmed for this to work.

Examples:

```
iex> NervesKey.device_cert(transport, :primary, :nerves_key)
{:OTPCertificate, ...}

iex> NervesKey.device_cert(transport, :primary, :trust_and_go)
{:OTPCertificate, ...}
```

# `get_raw_settings`

```elixir
@spec get_raw_settings(ATECC508A.Transport.t(), device_type()) ::
  {:ok, binary()} | {:error, atom()}
```

Return the settings block as a binary

# `get_settings`

```elixir
@spec get_settings(ATECC508A.Transport.t(), device_type()) ::
  {:ok, map()} | {:error, atom()}
```

Return all of the setting stored in the NervesKey as a map

# `has_aux_certificates?`

```elixir
@spec has_aux_certificates?(ATECC508A.Transport.t()) :: boolean()
```

Check whether the auxiliary certificates were programmed

# `manufacturer_mac`

IEEE EUI-48 MAC address that can be used as a unique identifier in LAN networking
This is only available on `:trust_and_go`

# `manufacturer_sn`

```elixir
@spec manufacturer_sn(ATECC508A.Transport.t(), device_type()) :: binary()
```

Read the manufacturer's serial number

# `max_settings_len`

```elixir
@spec max_settings_len(device_type()) :: integer()
```

Return the max length of settings

# `provision`

```elixir
@spec provision(
  ATECC508A.Transport.t(),
  NervesKey.ProvisioningInfo.t(),
  X509.Certificate.t(),
  X509.PrivateKey.t()
) :: :ok
```

Provision a NervesKey in one step.

See the README.md for how to use this. This function locks the
ATECC508A down, so you'll want to be sure what you pass it is
correct.

This function does it all. It requires the signer's private key so
handle that with care. Alternatively, please consider sending a PR
for supporting off-device signatures so that HSMs can be used.

# `provision_aux_certificates`

```elixir
@spec provision_aux_certificates(
  ATECC508A.Transport.t(),
  X509.Certificate.t(),
  X509.PrivateKey.t(),
  device_type()
) :: :ok
```

Provision the auxiliary device/signer certificates on a NervesKey.

This function creates and saves the auxiliary certificates. These
are only needed if the ones written by `provision/4` are not
usable. They are not used unless explicitly requested. See the
README.md for details.

You may call this function multiple times after the ATECC508A
has been provisioned.

# `provisioned?`

```elixir
@spec provisioned?(ATECC508A.Transport.t()) :: boolean()
```

Check whether the NervesKey has been provisioned

# `put_raw_settings`

```elixir
@spec put_raw_settings(ATECC508A.Transport.t(), binary(), device_type()) :: :ok
```

Store raw settings on the Nerves Key

This overwrites all of the settings and should be used with care since there's
no protection against race conditions with other users of this API.

# `put_settings`

```elixir
@spec put_settings(ATECC508A.Transport.t(), map(), device_type()) :: :ok
```

Store settings on the NervesKey

This overwrites all of the settings that are currently on the key and should
be used with care since there's no protection against a race condition with
other NervesKey users.

# `sign_digest`

```elixir
@spec sign_digest(ATECC508A.Transport.t(), binary()) ::
  {:ok, binary()} | {:error, atom()}
```

Sign a SHA256 digest

# `signer_cert`

```elixir
@spec signer_cert(ATECC508A.Transport.t(), certificate_pair(), device_type()) ::
  X509.Certificate.t()
```

Read the signer certificate from the slot

# `ssl_opts`

```elixir
@spec ssl_opts(ATECC508A.Transport.t(), certificate_pair(), device_type()) ::
  keyword()
```

Return ssl_opts for using the NervesKey

Pass an engine and optionally which certificate that you'd like to use.

# `volatile_provision`

```elixir
@spec volatile_provision(
  ATECC508A.Transport.t(),
  NervesKey.ProvisioningInfo.t(),
  X509.Certificate.t(),
  X509.PrivateKey.t(),
  binary(),
  binary()
) :: :ok
```

Provision a NervesKey for the volatile key config in one step.

See the README.md for how to use this. This function locks the
ATECC508A down, so you'll want to be sure what you pass it is
correct. Ensure you have the activation key in safe storage, it
will be required to use the NervesKey.

This function does it all. It requires the signer's private key so
handle that with care. Alternatively, please consider sending a PR
for supporting off-device signatures so that HSMs can be used.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
