From 24ddaf301a66c13ae5177a583aaae83887eab4ff Mon Sep 17 00:00:00 2001 From: Tim Trippel Date: Tue, 3 Dec 2024 15:22:21 -0800 Subject: [PATCH] [provisioning] enable SIVAL cert endorsement with Nitrokeys The DICE CA key is stored on a Nitrokey, which can be used in a benchtop provisioning flow to endorse DICE certificates. Signed-off-by: Tim Trippel --- sw/device/silicon_creator/manuf/base/BUILD | 22 ++++++++- .../manuf/base/provisioning_inputs.bzl | 7 +-- .../manuf/keys/{fake => }/dice_ca.conf | 0 .../manuf/keys/{fake => }/ext_ca.conf | 0 .../silicon_creator/manuf/keys/fake/README.md | 11 +++-- .../manuf/keys/fake/gen_fake_ca.sh | 8 +-- .../silicon_creator/manuf/keys/sival/BUILD | 16 ++++++ .../manuf/keys/sival/README.md | 49 +++++++++++++++++++ .../manuf/keys/sival/ca_config.json | 14 ++++++ .../manuf/keys/sival/dice_ca.csr | 9 ++++ .../manuf/keys/sival/dice_ca.pem | 17 +++++++ sw/host/provisioning/cert_lib/src/lib.rs | 6 ++- .../orchestrator/configs/skus/emulation.hjson | 2 - .../orchestrator/configs/skus/sival.hjson | 21 ++++---- 14 files changed, 154 insertions(+), 28 deletions(-) rename sw/device/silicon_creator/manuf/keys/{fake => }/dice_ca.conf (100%) rename sw/device/silicon_creator/manuf/keys/{fake => }/ext_ca.conf (100%) create mode 100644 sw/device/silicon_creator/manuf/keys/sival/BUILD create mode 100644 sw/device/silicon_creator/manuf/keys/sival/README.md create mode 100644 sw/device/silicon_creator/manuf/keys/sival/ca_config.json create mode 100644 sw/device/silicon_creator/manuf/keys/sival/dice_ca.csr create mode 100644 sw/device/silicon_creator/manuf/keys/sival/dice_ca.pem diff --git a/sw/device/silicon_creator/manuf/base/BUILD b/sw/device/silicon_creator/manuf/base/BUILD index 30519b9eafcd97..2e5d4411d97a0a 100644 --- a/sw/device/silicon_creator/manuf/base/BUILD +++ b/sw/device/silicon_creator/manuf/base/BUILD @@ -415,7 +415,7 @@ filegroup( tags = [ "lc_test_locked0", "manuf", - ], + ] + ["manual"] if config.get("offline", False) else [], test_cmd = _FT_PROVISIONING_CMD_ARGS, test_harness = _FT_PROVISIONING_HARNESS.format(sku), ), @@ -449,6 +449,16 @@ filegroup( test_suite( name = "ft_provision_cw310", tags = ["manual"], + tests = [ + ":ft_provision_{}_fpga_hyper310_rom_with_fake_keys".format(sku) + for sku, config in EARLGREY_SKUS.items() + if not config.get("offline", False) + ], +) + +test_suite( + name = "ft_provision_including_offline_cw310", + tags = ["manual"], tests = [ ":ft_provision_{}_fpga_hyper310_rom_with_fake_keys".format(sku) for sku in EARLGREY_SKUS.keys() @@ -458,6 +468,16 @@ test_suite( test_suite( name = "ft_provision_cw340", tags = ["manual"], + tests = [ + ":ft_provision_{}_fpga_cw340_rom_with_fake_keys".format(sku) + for sku, config in EARLGREY_SKUS.items() + if not config.get("offline", False) + ], +) + +test_suite( + name = "ft_provision_including_offline_cw340", + tags = ["manual"], tests = [ ":ft_provision_{}_fpga_cw340_rom_with_fake_keys".format(sku) for sku in EARLGREY_SKUS.keys() diff --git a/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl b/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl index 42844289d5c235..36124bf15192c9 100644 --- a/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl +++ b/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl @@ -67,8 +67,8 @@ EARLGREY_SKUS = { }, "sival": { "otp": "sival", - "ca_config": "//sw/device/silicon_creator/manuf/keys/fake:ca_config.json", - "ca_data": ["//sw/device/silicon_creator/manuf/keys/fake:ca_data"], + "ca_config": "//sw/device/silicon_creator/manuf/keys/sival:ca_config.json", + "ca_data": ["//sw/device/silicon_creator/manuf/keys/sival:ca_data"], "dice_libs": ["//sw/device/silicon_creator/lib/cert:dice"], "host_ext_libs": ["@provisioning_exts//:default_ft_ext_lib"], "device_ext_libs": ["@provisioning_exts//:default_perso_fw_ext"], @@ -79,7 +79,8 @@ EARLGREY_SKUS = { "owner_fw": "//sw/device/silicon_owner/bare_metal:bare_metal_slot_b", "ecdsa_key": {"//hw/ip/otp_ctrl/data/earlgrey_skus/sival/keys:keyset": "sv00-earlgrey-a1-root-ecdsa-prod-0"}, "perso_bin": "//sw/device/silicon_creator/manuf/base/binaries:ft_personalize_sival", - "orchestrator_cfg": "//sw/host/provisioning/orchestrator/configs/skus:emulation.hjson", + "orchestrator_cfg": "//sw/host/provisioning/orchestrator/configs/skus:sival.hjson", + "offline": True, }, } | EXT_EARLGREY_SKUS diff --git a/sw/device/silicon_creator/manuf/keys/fake/dice_ca.conf b/sw/device/silicon_creator/manuf/keys/dice_ca.conf similarity index 100% rename from sw/device/silicon_creator/manuf/keys/fake/dice_ca.conf rename to sw/device/silicon_creator/manuf/keys/dice_ca.conf diff --git a/sw/device/silicon_creator/manuf/keys/fake/ext_ca.conf b/sw/device/silicon_creator/manuf/keys/ext_ca.conf similarity index 100% rename from sw/device/silicon_creator/manuf/keys/fake/ext_ca.conf rename to sw/device/silicon_creator/manuf/keys/ext_ca.conf diff --git a/sw/device/silicon_creator/manuf/keys/fake/README.md b/sw/device/silicon_creator/manuf/keys/fake/README.md index 5861db653aff63..1bf35d7c3e1da4 100644 --- a/sw/device/silicon_creator/manuf/keys/fake/README.md +++ b/sw/device/silicon_creator/manuf/keys/fake/README.md @@ -33,17 +33,18 @@ $ openssl ec -in sk.pem -text -noout To generate a Root CA certificate using the earlier generated private EC key, you can use the CSR (Certificate Signing Request) configuration file checked in -to this directory (`ca.conf`) as in input to the following OpenSSL commands: +to this repo (`dice_ca.conf` or `ext_ca.conf`) as in input to the following +OpenSSL commands: ```sh # Generate the CSR: -$ openssl req -new -key sk.pem -out ca.csr -config ca.conf +$ openssl req -new -key sk.pem -out dice_ca.csr -config ../dice_ca.conf # Generate the X.509 certificate in PEM format: -$ openssl x509 -req -in ca.csr -signkey sk.pem -out ca.pem -days 3650 \ - -extfile ca.conf -extensions v3_ca +$ openssl x509 -req -in dice_ca.csr -signkey sk.pem -out dice_ca.pem \ + -days 3650 -extfile ../dice_ca.conf -extensions v3_ca # Examine the generated certificate: -$ openssl x509 -in ca.pem -text +$ openssl x509 -in dice_ca.pem -text ``` # Generating the RMA unlock token encryption keypair with OpenSSL diff --git a/sw/device/silicon_creator/manuf/keys/fake/gen_fake_ca.sh b/sw/device/silicon_creator/manuf/keys/fake/gen_fake_ca.sh index 5f92a942dd4bea..d66f78ddba5090 100755 --- a/sw/device/silicon_creator/manuf/keys/fake/gen_fake_ca.sh +++ b/sw/device/silicon_creator/manuf/keys/fake/gen_fake_ca.sh @@ -16,16 +16,16 @@ EXT_CA_KEY="$DICE_CA_KEY" echo "Generating fake key DICE CA cert ..." openssl req -new -key "$DICE_CA_KEY" -keyform der \ - -out dice_ca.csr -config dice_ca.conf + -out dice_ca.csr -config ../dice_ca.conf openssl x509 -req -in dice_ca.csr -signkey "$DICE_CA_KEY" \ - -keyform der -out dice_ca.pem -days 3650 -extfile dice_ca.conf \ + -keyform der -out dice_ca.pem -days 3650 -extfile ../dice_ca.conf \ -extensions v3_ca echo "Done." echo "Generating fake key Personalization Extension CA cert ..." openssl req -new -key "$EXT_CA_KEY" -keyform der \ - -out ext_ca.csr -config ext_ca.conf + -out ext_ca.csr -config ../ext_ca.conf openssl x509 -req -in ext_ca.csr -signkey "$EXT_CA_KEY" \ - -keyform der -out ext_ca.pem -days 3650 -extfile ext_ca.conf \ + -keyform der -out ext_ca.pem -days 3650 -extfile ../ext_ca.conf \ -extensions v3_ca echo "Done." diff --git a/sw/device/silicon_creator/manuf/keys/sival/BUILD b/sw/device/silicon_creator/manuf/keys/sival/BUILD new file mode 100644 index 00000000000000..2cc3e2fa2041d4 --- /dev/null +++ b/sw/device/silicon_creator/manuf/keys/sival/BUILD @@ -0,0 +1,16 @@ +# Copyright lowRISC contributors (OpenTitan project). +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +package(default_visibility = ["//visibility:public"]) + +exports_files(glob(["**"])) + +filegroup( + name = "ca_data", + srcs = [ + ":ca_config.json", + ":dice_ca.pem", + "//sw/device/silicon_creator/manuf/keys/fake:rma_unlock_enc_rsa3072.pub.der", + ], +) diff --git a/sw/device/silicon_creator/manuf/keys/sival/README.md b/sw/device/silicon_creator/manuf/keys/sival/README.md new file mode 100644 index 00000000000000..11a6bc2d32b816 --- /dev/null +++ b/sw/device/silicon_creator/manuf/keys/sival/README.md @@ -0,0 +1,49 @@ +# CA Endorsement Keys + +Certificate Authority endorsement keys are are used to endorse the following +certificate chains during personalization: +1. DICE attestation certificate chains, and +2. SKU specific certificate chains. + +The real (private) keys used for the SIVAL SKU are stored on offline HSMs. The +matching public keys and certificates are checked into the repository. + +To use the private keys to endorse the certificates in benchtop provisioning +flow, one must set the following envars: + - `PKCS11_MODULE_PATH`: to point to the PKCS#11 shared library for the + hardware token they are using, and + - `PKCS11_TOKEN_PIN`: to the PIN used for hardware token authentication. + +For example, if the SIVAL private keys are stored on a Nitrokey, and you wanted +to test the SIVAL FT provisioning flow, you would issue the following Bazel +command: +```sh +bazel test --test_output=streamed \ + //sw/device/silicon_creator/manuf/base:ft_provision_sival_fpga_hyper310_rom_with_fake_keys \ + --action_env=PKCS11_MODULE_PATH=/opt/nitrokey/lib/libsc-hsm-pkcs11.so \ + --action_env=PKCS11_TOKEN_PIN= +``` + +## Generating a Root CA Certificate from a Token Held ECDSA Key + +To generate a Root CA certificate from a public key held on a hardware token, +e.g., Nitrokey, you may use the CSR (Certificate Signing Request) configuration +file checked in to this repo (`dice_ca.conf`) as in input to the following +commands: +```sh +# Set the PKCS11_MODULE_PATH envar to point to the shared library for the +# hardware token you are using, e.g.: +export PKCS11_MODULE_PATH=/opt/nitrokey/lib/libsc-hsm-pkcs11.so + +# Generate the CSR: +openssl req -new -engine pkcs11 -keyform engine -config ../dice_ca.conf -out dice_ca.csr \ + -key "pkcs11:pin-value=;object=sv00-earlgrey-a1-ca-dice-0" + +# Generate the X.509 certificate in PEM format: +openssl x509 -req -engine pkcs11 -keyform engine -in dice_ca.csr -out dice_ca.pem \ + -days 3650 -extfile ../dice_ca.conf -extensions v3_ca \ + -signkey "pkcs11:pin-value=694201;object=sv00-earlgrey-a1-ca-dice-0" + +# Examine the generated certificate: +openssl x509 -in dice_ca.pem -text +``` diff --git a/sw/device/silicon_creator/manuf/keys/sival/ca_config.json b/sw/device/silicon_creator/manuf/keys/sival/ca_config.json new file mode 100644 index 00000000000000..14f9d7455d0ec1 --- /dev/null +++ b/sw/device/silicon_creator/manuf/keys/sival/ca_config.json @@ -0,0 +1,14 @@ +{ + "dice": { + "certificate": "sw/device/silicon_creator/manuf/keys/sival/dice_ca.pem", + "key_id": "0x5398A4F090F2A95C3D52FC98DEB9F2F9AF042F6E", + "key_type": "Token", + "key": "sv00-earlgrey-a1-ca-dice-0" + }, + "ext": { + "certificate": "sw/device/silicon_creator/manuf/keys/sival/dice_ca.pem", + "key_id": "0x5398A4F090F2A95C3D52FC98DEB9F2F9AF042F6E", + "key_type": "Token", + "key": "sv00-earlgrey-a1-ca-dice-0" + } +} diff --git a/sw/device/silicon_creator/manuf/keys/sival/dice_ca.csr b/sw/device/silicon_creator/manuf/keys/sival/dice_ca.csr new file mode 100644 index 00000000000000..caef2e8004d47e --- /dev/null +++ b/sw/device/silicon_creator/manuf/keys/sival/dice_ca.csr @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBHjCBxAIBADBiMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDzANBgNVBAoM +Bkdvb2dsZTEUMBIGA1UECwwLRW5naW5lZXJpbmcxHzAdBgNVBAMMFkdvb2dsZSBF +bmdpbmVlcmluZyBJQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATu4HkgAzRX +PJAhMw9E/qXZzoQ+Kx3awtKAPk29herxqr7d/bEYWVjKBpMg9QzTjQHQBswmU/H3 +GTr5FCjfas2foAAwCgYIKoZIzj0EAwIDSQAwRgIhAP14uGJ6C2g2lAl06oRrODme +yjQviuSdqIaszMxFknHtAiEAszHbVPKgTtSnSggw0jFkIx8pZnUJD4cOFJ5EUGOV +Sk4= +-----END CERTIFICATE REQUEST----- diff --git a/sw/device/silicon_creator/manuf/keys/sival/dice_ca.pem b/sw/device/silicon_creator/manuf/keys/sival/dice_ca.pem new file mode 100644 index 00000000000000..e5957515e02bcf --- /dev/null +++ b/sw/device/silicon_creator/manuf/keys/sival/dice_ca.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICqDCCAk+gAwIBAgIUFDAsPzL14w6/jKAtysPUTcGRgM4wCgYIKoZIzj0EAwIw +YjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQKDAZHb29nbGUxFDAS +BgNVBAsMC0VuZ2luZWVyaW5nMR8wHQYDVQQDDBZHb29nbGUgRW5naW5lZXJpbmcg +SUNBMB4XDTI0MTIwNDAzNTgwOFoXDTM0MTIwMjAzNTgwOFowYjELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMQ8wDQYDVQQKDAZHb29nbGUxFDASBgNVBAsMC0VuZ2lu +ZWVyaW5nMR8wHQYDVQQDDBZHb29nbGUgRW5naW5lZXJpbmcgSUNBMFkwEwYHKoZI +zj0CAQYIKoZIzj0DAQcDQgAE7uB5IAM0VzyQITMPRP6l2c6EPisd2sLSgD5NvYXq +8aq+3f2xGFlYygaTIPUM040B0AbMJlPx9xk6+RQo32rNn6OB4jCB3zAdBgNVHQ4E +FgQUU5ik8JDyqVw9UvyY3rny+a8EL24wgZ8GA1UdIwSBlzCBlIAUU5ik8JDyqVw9 +UvyY3rny+a8EL26hZqRkMGIxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEPMA0G +A1UECgwGR29vZ2xlMRQwEgYDVQQLDAtFbmdpbmVlcmluZzEfMB0GA1UEAwwWR29v +Z2xlIEVuZ2luZWVyaW5nIElDQYIUFDAsPzL14w6/jKAtysPUTcGRgM4wDwYDVR0T +AQH/BAUwAwEB/zALBgNVHQ8EBAMCAYYwCgYIKoZIzj0EAwIDRwAwRAIgQmIdM2Mv +KI70Huk3zWbukclONM9dAJ8n9qiD0HFnypICIBeaUmZZ1FQtsa0i0KNb7+KH5EvV +g3u7GESPQU2jEnCj +-----END CERTIFICATE----- diff --git a/sw/host/provisioning/cert_lib/src/lib.rs b/sw/host/provisioning/cert_lib/src/lib.rs index 513179fabda483..d85ab0e256396c 100644 --- a/sw/host/provisioning/cert_lib/src/lib.rs +++ b/sw/host/provisioning/cert_lib/src/lib.rs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +use std::env; use std::fs::{self, OpenOptions}; use std::io::{Read, Write}; use std::path::PathBuf; @@ -137,7 +138,8 @@ fn parse_and_endorse_x509_cert_token(tbs: Vec, key_id: &str) -> Result, key_id: &str) -> Result