From de283f7e8aad24dda3edc9bf2b1fb383092e8c44 Mon Sep 17 00:00:00 2001 From: Tim Trippel Date: Mon, 28 Oct 2024 14:54:54 -0700 Subject: [PATCH] [manuf] refactor FT flows to enable downstream OTP definitions This refactors the FT provisioning Bazel build binary and test targets to enable defining downstream OTP configurations and ingesting them into FT provisioning flows. Additionally, this removes the reliance on build configurations to select which personalization extension to use, and simply builds and tests all FT provisioning flows that can be enumerated at build time. This makes it easier to run and test all flows upstream only, with: `bazel test //sw/device/silicon_creator/manuf/base:ft_provision_cw310`, or all flows upstream and downstream with: `PROV_EXTS_DIR=... bazel test //sw/device/silicon_creator/manuf/base:ft_provision_cw310`. As a result, this also simplifies the build graph by removing configuration transistions. Signed-off-by: Tim Trippel (cherry picked from commit 87e0070443d0220424f078bdfeaee981afae1d32) --- rules/otp.bzl | 2 +- sw/device/silicon_creator/manuf/base/BUILD | 21 ++--- .../manuf/base/provisioning_inputs.bzl | 34 +++++--- .../manuf/extensions/BUILD.bazel | 49 ------------ .../manuf/extensions/README.md | 80 ++++++++++++------- .../silicon_creator/manuf/extensions/cfg.bzl | 26 +++++- .../manuf/extensions/example_ft_ext_lib.rs | 11 --- .../extensions/example_personalize_ext.c | 23 ------ sw/device/silicon_creator/manuf/lib/BUILD | 4 +- sw/host/provisioning/ft/BUILD | 48 ++++++----- sw/host/provisioning/ft_lib/BUILD | 54 +++++++------ 11 files changed, 161 insertions(+), 191 deletions(-) delete mode 100644 sw/device/silicon_creator/manuf/extensions/example_ft_ext_lib.rs delete mode 100644 sw/device/silicon_creator/manuf/extensions/example_personalize_ext.c diff --git a/rules/otp.bzl b/rules/otp.bzl index 2634fa4ffd027..9a504a48f96be 100644 --- a/rules/otp.bzl +++ b/rules/otp.bzl @@ -379,7 +379,7 @@ otp_image_consts = rule( # keys. This is useful for testing in dv_sim, fpga and verilator # environments. OTP_SIGVERIFY_FAKE_KEYS = [ - "//sw/device/silicon_creator/rom/keys/fake/otp:json_rot_keys", + "@//sw/device/silicon_creator/rom/keys/fake/otp:json_rot_keys", ] # This is a set of overlays to generate a generic, standard OTP image. diff --git a/sw/device/silicon_creator/manuf/base/BUILD b/sw/device/silicon_creator/manuf/base/BUILD index ac1f20e057472..8269fe5928585 100644 --- a/sw/device/silicon_creator/manuf/base/BUILD +++ b/sw/device/silicon_creator/manuf/base/BUILD @@ -206,7 +206,7 @@ opentitan_test( "//sw/device/silicon_creator/manuf/lib:individualize_sw_cfg_{}".format(cfg), ], ) - for cfg in EARLGREY_OTP_CFGS + for cfg in EARLGREY_OTP_CFGS.keys() ] filegroup( @@ -214,7 +214,7 @@ filegroup( testonly = True, srcs = [ ":sram_ft_individualize_{}".format(cfg) - for cfg in EARLGREY_OTP_CFGS + for cfg in EARLGREY_OTP_CFGS.keys() ], ) @@ -322,20 +322,11 @@ manifest(d = { "//sw/device/silicon_creator/manuf/lib:flash_info_fields", "//sw/device/silicon_creator/manuf/lib:individualize_sw_cfg_{}".format(config["otp"]), "//sw/device/silicon_creator/manuf/lib:personalize", - ] + config["dice_libs"] + config["ext_libs"], + ] + config["dice_libs"] + config["device_ext_libs"], ) for sku, config in EARLGREY_SKUS.items() ] -filegroup( - name = "ft_personalize_all", - testonly = True, - srcs = [ - ":ft_personalize_{}".format(sku) - for sku in EARLGREY_SKUS.keys() - ], -) - config_setting( name = "ckms_cert_endorsement_params", flag_values = {":endorse_certs_with_ckms": "True"}, @@ -354,7 +345,7 @@ _FT_PROVISIONING_CMD_ARGS = """ "//conditions:default": LOCAL_CERT_ENDORSEMENT_PARAMS, }) -_FT_PROVISIONING_HARNESS = "//sw/host/provisioning/ft" +_FT_PROVISIONING_HARNESS = "//sw/host/provisioning/ft:ft_{}" [ opentitan_test( @@ -380,7 +371,7 @@ _FT_PROVISIONING_HARNESS = "//sw/host/provisioning/ft" "manuf", ], test_cmd = _FT_PROVISIONING_CMD_ARGS, - test_harness = _FT_PROVISIONING_HARNESS, + test_harness = _FT_PROVISIONING_HARNESS.format(sku), ), silicon = silicon_params( binaries = @@ -393,7 +384,7 @@ _FT_PROVISIONING_HARNESS = "//sw/host/provisioning/ft" interface = "teacup", needs_jtag = True, test_cmd = _FT_PROVISIONING_CMD_ARGS, - test_harness = _FT_PROVISIONING_HARNESS, + test_harness = _FT_PROVISIONING_HARNESS.format(sku), ), ) for sku, config in EARLGREY_SKUS.items() diff --git a/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl b/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl index c33589d1382bc..3d7f4e9aa304d 100644 --- a/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl +++ b/sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl @@ -2,30 +2,45 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -EARLGREY_OTP_CFGS = [ - "sival", - "prodc", -] +load( + "@provisioning_exts//:cfg.bzl", + "EXT_EARLGREY_OTP_CFGS", + "EXT_EARLGREY_SKUS", +) + +# A list of OTP configurations that will be used to autogenerate FT +# individualization binaries that configure OTP with the constants defined in +# these bazel targets. +EARLGREY_OTP_CFGS = { + "sival": "//hw/ip/otp_ctrl/data/earlgrey_skus/sival:otp_consts", + "prodc": "//hw/ip/otp_ctrl/data/earlgrey_skus/prodc:otp_consts", +} | EXT_EARLGREY_OTP_CFGS +# A dictionary of SKU configurations that will be used to generate FT +# personalization binaries that configure OTP and flash info pages as defined +# in these bazel targets. EARLGREY_SKUS = { # OTP Config: SIVAL; DICE Certs: X.509; Additional Certs: None "sival": { "otp": "sival", "dice_libs": ["//sw/device/silicon_creator/lib/cert:dice"], - "ext_libs": ["@provisioning_exts//:perso_fw_ext"], + "host_ext_libs": ["@provisioning_exts//:default_ft_ext_lib"], + "device_ext_libs": ["@provisioning_exts//:default_perso_fw_ext"], }, # OTP Config: SIVAL; DICE Certs: CWT; Additional Certs: None # TODO(#24281): uncomment when DICE CWT cert flows are fully supported # "sival_dice_cwt": { # "otp": "sival", # "dice_libs": ["//sw/device/silicon_creator/lib/cert:dice_cwt"], - # "ext_libs": ["@provisioning_exts//:perso_fw_ext"], + # "host_ext_libs": ["@provisioning_exts//:default_ft_ext_lib"], + # "device_ext_libs": ["@provisioning_exts//:default_perso_fw_ext"], # }, # OTP Config: SIVAL; DICE Certs: X.509; Additional Certs: TPM EK "sival_tpm": { "otp": "sival", "dice_libs": ["//sw/device/silicon_creator/lib/cert:dice"], - "ext_libs": [ + "host_ext_libs": ["@provisioning_exts//:default_ft_ext_lib"], + "device_ext_libs": [ "//sw/device/silicon_creator/lib/cert:tpm_ek_template_library", "//sw/device/silicon_creator/manuf/base:tpm_perso_fw_ext", ], @@ -34,9 +49,10 @@ EARLGREY_SKUS = { "prodc": { "otp": "prodc", "dice_libs": ["//sw/device/silicon_creator/lib/cert:dice"], - "ext_libs": ["@provisioning_exts//:perso_fw_ext"], + "host_ext_libs": ["@provisioning_exts//:default_ft_ext_lib"], + "device_ext_libs": ["@provisioning_exts//:default_perso_fw_ext"], }, -} +} | EXT_EARLGREY_SKUS _DEVICE_ID_AND_TEST_TOKENS = """ --device-id="0x11111111_22222222_33333333_44444444_55555555_66666666_77777777_88888888" diff --git a/sw/device/silicon_creator/manuf/extensions/BUILD.bazel b/sw/device/silicon_creator/manuf/extensions/BUILD.bazel index 08c4c93bd7b39..d1962b625a279 100644 --- a/sw/device/silicon_creator/manuf/extensions/BUILD.bazel +++ b/sw/device/silicon_creator/manuf/extensions/BUILD.bazel @@ -2,38 +2,10 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -load("@bazel_skylib//rules:common_settings.bzl", "bool_flag") load("@rules_rust//rust:defs.bzl", "rust_library") package(default_visibility = ["//visibility:public"]) -bool_flag( - name = "use_example_perso_ext", - build_setting_default = False, -) - -config_setting( - name = "example_perso_ext_cfg", - flag_values = { - ":use_example_perso_ext": "True", - }, -) - -cc_library( - name = "example_perso_fw_ext", - srcs = ["example_personalize_ext.c"], - deps = [ - "@//sw/device/lib/dif:flash_ctrl", - "@//sw/device/lib/runtime:log", - "@//sw/device/lib/testing/json:provisioning_data", - "@//sw/device/lib/testing/test_framework:status", - "@//sw/device/lib/testing/test_framework:ujson_ottf", - "@//sw/device/silicon_creator/lib/cert", - "@//sw/device/silicon_creator/manuf/base:personalize_ext", - "@//sw/device/silicon_creator/manuf/lib:flash_info_fields", - ], -) - cc_library( name = "default_perso_fw_ext", srcs = ["default_personalize_ext.c"], @@ -48,16 +20,6 @@ cc_library( ], ) -_DEVICE_PERSO_EXTS = select({ - "example_perso_ext_cfg": [":example_perso_fw_ext"], - "//conditions:default": [":default_perso_fw_ext"], -}) - -cc_library( - name = "perso_fw_ext", - deps = _DEVICE_PERSO_EXTS, -) - rust_library( name = "default_ft_ext_lib", srcs = ["default_ft_ext_lib.rs"], @@ -67,14 +29,3 @@ rust_library( "@crate_index//:arrayvec", ], ) - -rust_library( - name = "example_ft_ext_lib", - srcs = ["example_ft_ext_lib.rs"], - crate_name = "ft_ext_lib", - deps = [ - "@crate_index//:anyhow", - "@crate_index//:arrayvec", - "@crate_index//:log", - ], -) diff --git a/sw/device/silicon_creator/manuf/extensions/README.md b/sw/device/silicon_creator/manuf/extensions/README.md index 4789856ca84f8..0454f09fa48ae 100644 --- a/sw/device/silicon_creator/manuf/extensions/README.md +++ b/sw/device/silicon_creator/manuf/extensions/README.md @@ -1,35 +1,55 @@ # Provisioning Flow Extensions -Various components of the reference provisioning flow provided can be extended -to satisfy the requirements of various SKUs. This describes the infrastructure -in place that enables extending reference provisioning flows with code managed -outside this repo. +Provisioning an Earlgrey chip requires executing code on devivce during two core +phases: +1. Chip Probe (CP): when the wafer is still intact, and +2. Final Test (FT): when each chip has been packaged and loaded into a socket. +For the most part, the CP process is the same across all Earlgrey chips, +regardless of the SKU. However, the FT process can differ based on the target +SKU. + +## FT Provisioning Overview + +There are two main phases during FT provisioning: +1. individualization, and +2. personalization. + +## Customizing FT Provisioning Flows + +Various components of the reference FT provisioning flow can be extended to +satisfy the requirements of various SKUs. Specifically, there is Bazel +infrastructure, and example code, in place to demonstrate how one can define: +1. downstream OTP configurations for a custom SKU, and +2. downstream personalization firmware and host harness extensions for a custom SKU. + +Defining both start by defining an additional Bazel repo location on your system +that resembles the directory this README.md is located in, and pointing Bazel +at it via the `PROV_EXTS_DIR` envar. This tells Bazel to instantiate a local +repo called `@provisioning_exts`. + +## OTP Image Definitions + +To define additional OTP configurations downstream, one must add OTP targets +to the `EXT_EARLGREY_OTP_CFGS` and `EXT_EARLGREY_SKUS` dictionaries in their +downstream `@provisioning_exts` Bazel repo. ## Personalization Firmware -The personalization firmware `ft_personalize.c` defines an `extern` extension -function that is invoked as the final step in the personalization flow. - -`status_t personalize_extension(ujson_t *uj)` - -The example function provided in this example external Bazel repo does nothing, -except print a message to the console. However, this provides a mechanism for -SKU owners / customers to develop closed-source personalization FW extensions, -that can easily make use of open-source code. - -This feature is implemented with the help of some custom Bazel repository rules. -Specifically, in this directory we define a secondary Bazel -repository (`@perso_exts`) that is designed to be used in -conjunction with the main OpenTitan Bazel repository. Within this repository, we -define a single `perso_ext` library that is linked with the reference -`ft_personalize` binary. The `perso_ext` library itself just contains an -implementation of the `personalize_extension(...)` function described above. -However, the `perso_ext` library is linked with other libraries -based on a Bazel `config_setting` that allows you to toggle which personalize -extension library should be used (if you are building binaries for several SKU -owners). - -Note, the Bazel configuration settings and example personalization extension -library (`perso_ext`) provided in this -repository are merely examples, as the `personalize_extension(...)` function -implemented does nothing, except print a message. +The personalization firmware `ft_personalize.c` defines two `extern` C functions +that are invoked before and after certificates are endorsed off-device, +respectively: +`status_t personalize_extension_pre_cert_endorse(...)` +`status_t personalize_extension_post_cert_endorse(...)` + +Additionally, the FT provisioning test harness provides an hook function to call +during the certificate endorsement operation: +`pub fn ft_ext(endorsed_cert_concat: ArrayVec) -> Result>` + +The default functions provided in this example external Bazel repo do nothing. +However, this provides a mechanism for SKU owners / customers to develop +closed-source personalization FW extensions, that can make use of open-source +code. + +To configure a SKU to use downstream hooks, on must update their SKUs +configuration definition in the `EXT_EARLGREY_SKUS` dictionary in the +`@provisioning_exts` repo. diff --git a/sw/device/silicon_creator/manuf/extensions/cfg.bzl b/sw/device/silicon_creator/manuf/extensions/cfg.bzl index bf4692e837347..883e70310203e 100644 --- a/sw/device/silicon_creator/manuf/extensions/cfg.bzl +++ b/sw/device/silicon_creator/manuf/extensions/cfg.bzl @@ -2,7 +2,25 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -HOST_FT_EXTS = select({ - "@provisioning_exts//:example_perso_ext_cfg": ["@provisioning_exts//:example_ft_ext_lib"], - "//conditions:default": ["@provisioning_exts//:default_ft_ext_lib"], -}) +# This enables downstream integrators to define external Earlgrey OTP +# configurations to be used during provisioning for downstream SKUs. See the +# upstream Earlgrey OTP configurations list defined in the `EARLGREY_OTP_CFGS` +# dict in `sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl` for +# more details. +EXT_EARLGREY_OTP_CFGS = { + # : +} + +# This enables downstream integrators to define external Earlgrey SKU +# configurations to be used during provisioning. See the upstream Earlgrey SKU +# configurations defined in the `EARLGREY_SKUS` dictionary in +# `sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl` for more +# details. +EXT_EARLGREY_SKUS = { + # : { + # "otp": , + # "dice_libs": [] + # "host_ext_libs": [] + # "device_ext_libs": [] + # } +} diff --git a/sw/device/silicon_creator/manuf/extensions/example_ft_ext_lib.rs b/sw/device/silicon_creator/manuf/extensions/example_ft_ext_lib.rs deleted file mode 100644 index 3a58e6d98be22..0000000000000 --- a/sw/device/silicon_creator/manuf/extensions/example_ft_ext_lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright lowRISC contributors (OpenTitan project). -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::Result; -use arrayvec::ArrayVec; - -pub fn ft_ext(endorsed_cert_concat: ArrayVec) -> Result> { - log::info!("Running example host FT extension ..."); - Ok(endorsed_cert_concat) -} diff --git a/sw/device/silicon_creator/manuf/extensions/example_personalize_ext.c b/sw/device/silicon_creator/manuf/extensions/example_personalize_ext.c deleted file mode 100644 index 4bfbc8be9a99b..0000000000000 --- a/sw/device/silicon_creator/manuf/extensions/example_personalize_ext.c +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright lowRISC contributors (OpenTitan project). -// Licensed under the Apache License, Version 2.0, see LICENSE for details. -// SPDX-License-Identifier: Apache-2.0 - -#include "sw/device/lib/dif/dif_flash_ctrl.h" -#include "sw/device/lib/runtime/log.h" -#include "sw/device/lib/testing/json/provisioning_data.h" -#include "sw/device/lib/testing/test_framework/status.h" -#include "sw/device/lib/testing/test_framework/ujson_ottf.h" -#include "sw/device/silicon_creator/lib/cert/cert.h" -#include "sw/device/silicon_creator/manuf/base/personalize_ext.h" - -status_t personalize_extension_pre_cert_endorse( - personalize_extension_pre_endorse_t *pre_params) { - LOG_INFO("Running example pre-cert-endorsement perso extension ..."); - return OK_STATUS(); -} - -status_t personalize_extension_post_cert_endorse( - personalize_extension_post_endorse_t *post_params) { - LOG_INFO("Running example post-cert-endorsement perso extension ..."); - return OK_STATUS(); -} diff --git a/sw/device/silicon_creator/manuf/lib/BUILD b/sw/device/silicon_creator/manuf/lib/BUILD index b536d94996f7c..4c40789fcd416 100644 --- a/sw/device/silicon_creator/manuf/lib/BUILD +++ b/sw/device/silicon_creator/manuf/lib/BUILD @@ -193,10 +193,10 @@ cc_library( name = "individualize_sw_cfg_{}".format(cfg), deps = [ ":individualize_sw_cfg", - "//hw/ip/otp_ctrl/data/earlgrey_skus/{}:otp_consts".format(cfg), + "{}".format(target), ], ) - for cfg in EARLGREY_OTP_CFGS + for cfg, target in EARLGREY_OTP_CFGS.items() ] opentitan_test( diff --git a/sw/host/provisioning/ft/BUILD b/sw/host/provisioning/ft/BUILD index 7769d9892643f..35b8755d73e3a 100644 --- a/sw/host/provisioning/ft/BUILD +++ b/sw/host/provisioning/ft/BUILD @@ -5,6 +5,7 @@ load("@rules_rust//rust:defs.bzl", "rust_binary") load( "//sw/device/silicon_creator/manuf/base:provisioning_inputs.bzl", + "EARLGREY_SKUS", "FT_PERSONALIZE_ENDORSEMENT_KEYS", ) @@ -12,25 +13,28 @@ package(default_visibility = ["//visibility:public"]) # Additional data dependencies on this rust binary allow the provisioning # orchestration scripts to invoke this binary with bazel run. -rust_binary( - name = "ft", - testonly = True, - srcs = ["src/main.rs"], - data = [ - "//sw/device/silicon_creator/manuf/base:ft_personalize_all", - "//sw/device/silicon_creator/manuf/base:sram_ft_individualize_all", - "//third_party/openocd:jtag_cmsis_dap_adapter_cfg", - "//third_party/openocd:jtag_olimex_cfg", - "//third_party/openocd:openocd_bin", - ] + FT_PERSONALIZE_ENDORSEMENT_KEYS, - deps = [ - "//sw/host/opentitanlib", - "//sw/host/provisioning/ft_lib", - "//sw/host/provisioning/ujson_lib", - "//sw/host/provisioning/util_lib", - "@crate_index//:anyhow", - "@crate_index//:clap", - "@crate_index//:humantime", - "@crate_index//:log", - ], -) +[ + rust_binary( + name = "ft_{}".format(sku), + testonly = True, + srcs = ["src/main.rs"], + data = [ + "//sw/device/silicon_creator/manuf/base:ft_personalize_{}".format(sku), + "//sw/device/silicon_creator/manuf/base:sram_ft_individualize_all", + "//third_party/openocd:jtag_cmsis_dap_adapter_cfg", + "//third_party/openocd:jtag_olimex_cfg", + "//third_party/openocd:openocd_bin", + ] + FT_PERSONALIZE_ENDORSEMENT_KEYS, + deps = [ + "//sw/host/opentitanlib", + "//sw/host/provisioning/ft_lib:ft_lib_{}".format(sku), + "//sw/host/provisioning/ujson_lib", + "//sw/host/provisioning/util_lib", + "@crate_index//:anyhow", + "@crate_index//:clap", + "@crate_index//:humantime", + "@crate_index//:log", + ], + ) + for sku in EARLGREY_SKUS.keys() +] diff --git a/sw/host/provisioning/ft_lib/BUILD b/sw/host/provisioning/ft_lib/BUILD index 122901b7df6c2..0bb27ff523f89 100644 --- a/sw/host/provisioning/ft_lib/BUILD +++ b/sw/host/provisioning/ft_lib/BUILD @@ -2,32 +2,36 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 -load("@provisioning_exts//:cfg.bzl", "HOST_FT_EXTS") load("@rules_rust//rust:defs.bzl", "rust_library") +load("//sw/device/silicon_creator/manuf/base:provisioning_inputs.bzl", "EARLGREY_SKUS") package(default_visibility = ["//visibility:public"]) -rust_library( - name = "ft_lib", - srcs = ["src/lib.rs"], - deps = [ - "//sw/host/opentitanlib", - "//sw/host/ot_certs", - "//sw/host/provisioning/cert_lib", - "//sw/host/provisioning/perso_tlv_lib", - "//sw/host/provisioning/perso_tlv_lib:perso_tlv_objects", - "//sw/host/provisioning/ujson_lib", - "//sw/host/provisioning/util_lib", - "@crate_index//:anyhow", - "@crate_index//:arrayvec", - "@crate_index//:clap", - "@crate_index//:elliptic-curve", - "@crate_index//:hex", - "@crate_index//:log", - "@crate_index//:p256", - "@crate_index//:serde", - "@crate_index//:serde_json", - "@crate_index//:sha2", - "@crate_index//:zerocopy", - ] + HOST_FT_EXTS, -) +[ + rust_library( + name = "ft_lib_{}".format(sku), + srcs = ["src/lib.rs"], + crate_name = "ft_lib", + deps = [ + "//sw/host/opentitanlib", + "//sw/host/ot_certs", + "//sw/host/provisioning/cert_lib", + "//sw/host/provisioning/perso_tlv_lib", + "//sw/host/provisioning/perso_tlv_lib:perso_tlv_objects", + "//sw/host/provisioning/ujson_lib", + "//sw/host/provisioning/util_lib", + "@crate_index//:anyhow", + "@crate_index//:arrayvec", + "@crate_index//:clap", + "@crate_index//:elliptic-curve", + "@crate_index//:hex", + "@crate_index//:log", + "@crate_index//:p256", + "@crate_index//:serde", + "@crate_index//:serde_json", + "@crate_index//:sha2", + "@crate_index//:zerocopy", + ] + config["host_ext_libs"], + ) + for sku, config in EARLGREY_SKUS.items() +]