Skip to content

oxidecomputer/dice-util

Repository files navigation

dice-utils

This repo hosts software supporting the DICE measured boot in Hubris. That mostly includes:

  • generating templates used by hubris stage0 to generate X.509 / PKCS#10 structures
  • tools to certify the DeviceId key that acts as the platform identity Components in this workspace are here mostly because they don't belong in the hubris repo.

Only a single script lives in to top level of the project. This script is discussed in detail below. More detailed docs are included in each subdirectory / crate as needed.

dice-ca-init.sh

This script is used to create and configure openssl certificate authorities (CAs). This includes creating the directory structure, configuration file, keys and certs. CAs created by this script may be useful in other contexts however they are specialized to this use-case.

Dependencies

Like most scripts, this one relies on other tools to do the heavy lifting. These dependencies must be installed before this script will work. Naming of packages is not consistent across OSs or distros so we use names from the upstream project here:

  • libp11
  • openssl
  • pkg-config
  • yubico-piv-tool

NOTE: We assume some common tools like tar, realpath and some compression libraries are installed as well. Any dependency problems encountered that aren't listed above should be reported in an issue.

NOTE: For development we also recommend installing the yubico ykman (yubikey manager) tool as well. In our experimentation we've found the yubico-piv-tool reset action to be unreliable. ykman piv reset however works as expected.

Examples

Often the best way to understand how a tool works is to see how it's used. This script has two main functions:

  1. creating a root (self-signed) certificate and CA
    $ ./dice-ca-init.sh \
        --archive-prefix dice-root-ca \
        --dir dice-root-ca \
        --self-signed
  2. creating an intermediate CA
    $ ./dice-ca-init.sh \
        --archive-prefix dice-intermediate-ca \
        --dir dice-intermediate-ca \
        --slot 9d

In both cases an OpenSSL CA is created in the directory provided by the --dir option. An archive of artifacts is also created (discussed in detail below) and named according to the --archive-prefix option. The openssl.cnf created in each CA dir is configured with defaults specific to their purpose:

  • root CAs have defaults for certifying intermediate CAs
  • intermediate CAs have defaults for certifying DICE DeviceId certs

When creating a root / self-signed cert in the first example the x.509 / RFC5280 certificate created is self signed. When creating an intermediate we instead create a PKCS#10 / RFD2986 certificate signing request (CSR). Before the intermediate CA can be used however the CSR must be evaluated and a cert generated by the parent CA. This can be done using an additional tool from the dice-mfg crate:

$ cargo run --bin dice-mfg -- \
    sign-cert \
    --openssl-cnf dice-root-ca/openssl.cnf \
    --csr-in dice-intermediate-ca/csr/ca.csr.pem \
    --cert-out dice-intermediate-ca/certs/ca.cert.pem

NOTE: Before signing a CSR, the CA should ensure the key holder meets some set of requirements. See key attestation below.

openssl.cnf

This script generates an "opinionated" openssl config files. The root directory for the CA files is included as an absolute path. Using relative paths makes the config more flexible but requires that invocations of the openssl ca command be done from the root of the CA directory.

NOTE: The down side of this approach is that if the CA directory is moved the openssl.cnf will need to have the dir entry in the CA config section updated accordingly.

Similarly we set defaults in openssl.cnf to prevent the need to provide any additional data to openssl on the command line. This makes each config special purpose and currently prevents us from creating multiple intermediate CAs for our PKI hierarchy.

Yubikey

In the examples above encryption keys for the CA are created on a yubikey. This is the default. We assume a key is present when the script is run. The default slot used is 9a and our example of a root CA uses this default. The second example of the intermediate CA explicitly selects slot 9d.

NOTE: The PIV spec (FIPS 201-3) defines specific requirements / uses for each key slot. Slot 9c is problematic for our use-case as it requires personal identification number (PIN) entry for each operation. We can provide the PIN in the openssl.cnf file but openssl will ignore this for operations on slot 9c to force PIN entry.

Key Attestation

Yubikeys are appealing as a way to prevent key exfiltration / duplication. By creating our CA keys in yubikeys we prevent simple key exfiltration as a yubikey is specifically designed to prevent key disclosure. Convincing ourselves that these keys were truly generated on a yubikey requires a significant amount of trust and communication between the parties involved. In a small enough group this may be feasible but convincing a 3rd party of this fact requires additional work.

Yubikeys implement an attestation mechanism intended to solve this problem. Key attestation works by yubico preloading every yubikey with an attestation signing key and a certificate signed by their attestation CA (both are in PIV slot f9). When an encryption key is created in the yubikey (not imported) the yubikey will generate a certificate attesting to the fact that it was created on the yubikey among other things. Assuming that the parties involved trust yubico and their devices these certificates can be used to prove that a given key was created on a legitimate yubikey.

When generating the keys for our CAs, dice-ca-init.sh collects the artifacts necessary to carry out this process. Additionally we include a script in this archive to validate the attestation cert chain. Before certifying an intermediate CA, the root CA should evaluate the attestation associated with the request.

About

utilities for cert template generation and manufacturing / certifying DeviceIds

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published