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() +]