diff --git a/sw/device/silicon_creator/rom_ext/prodc/BUILD b/sw/device/silicon_creator/rom_ext/prodc/BUILD new file mode 100644 index 0000000000000..836d92ad7893a --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/prodc/BUILD @@ -0,0 +1,137 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +load("//rules:const.bzl", "CONST", "hex") +load("//rules:manifest.bzl", "manifest") +load("//rules/opentitan:defs.bzl", "opentitan_binary") +load("//rules:signing.bzl", "offline_presigning_artifacts", "offline_signature_attach") +load("@rules_pkg//pkg:tar.bzl", "pkg_tar") + +package(default_visibility = ["//visibility:public"]) + +# In order to prevent the linker from prematurely discarding symbols, we +# need to give the CRT library last. +LINK_ORDER = [ + "$(location //sw/device/silicon_creator/rom_ext)", + "$(location //sw/device/lib/crt)", +] + +manifest(d = { + "name": "manifest_prodc", + "address_translation": hex(CONST.HARDENED_FALSE), + "identifier": hex(CONST.ROM_EXT), + "manuf_state_creator": hex(CONST.MANUF_STATE.PRODC), + "visibility": ["//visibility:public"], +}) + +# To test that the fake-signed ProdC ROM_EXT can boot, you need a bitstream +# with the OTP word CREATOR_SW_CCFG_MANUF_STATE set to `PRODC` (as above +# in the manifest definition). You can manually create such a bitstream with: +# +# bazel build //hw/bitstream/universal:splice --//hw/bitstream/universal:env=//hw/top_earlgrey:fpga_cw310_sival +opentitan_binary( + name = "rom_ext_fake_prod_signed_slot_a", + exec_env = [ + "//hw/top_earlgrey:silicon_creator", + "//hw/top_earlgrey:fpga_cw310", + "//hw/top_earlgrey:sim_dv_base", + "//hw/top_earlgrey:sim_verilator_base", + ], + linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_a", + linkopts = LINK_ORDER, + manifest = ":manifest_prodc", + rsa_key = {"//sw/device/silicon_creator/rom/keys/fake/rsa:prod_private_key_2": "prod_key_2"}, + deps = [ + "//sw/device/lib/crt", + "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/rom_ext", + "//sw/device/silicon_creator/rom_ext/keys/fake", + ], +) + +opentitan_binary( + name = "rom_ext_fake_prod_signed_slot_b", + exec_env = [ + "//hw/top_earlgrey:silicon_creator", + "//hw/top_earlgrey:fpga_cw310", + "//hw/top_earlgrey:sim_dv_base", + "//hw/top_earlgrey:sim_verilator_base", + ], + linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_b", + linkopts = LINK_ORDER, + manifest = ":manifest_prodc", + rsa_key = {"//sw/device/silicon_creator/rom/keys/fake/rsa:prod_private_key_2": "prod_key_2"}, + deps = [ + "//sw/device/lib/crt", + "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/rom_ext", + "//sw/device/silicon_creator/rom_ext/keys/fake", + ], +) + +opentitan_binary( + name = "rom_ext_real_prod_signed_slot_a", + exec_env = [ + "//hw/top_earlgrey:silicon_creator", + "//hw/top_earlgrey:fpga_cw310", + ], + linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_a", + linkopts = LINK_ORDER, + deps = [ + "//sw/device/lib/crt", + "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/rom_ext", + "//sw/device/silicon_creator/rom_ext/prodc/keys", + ], +) + +opentitan_binary( + name = "rom_ext_real_prod_signed_slot_b", + exec_env = [ + "//hw/top_earlgrey:silicon_creator", + "//hw/top_earlgrey:fpga_cw310", + ], + linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_b", + linkopts = LINK_ORDER, + deps = [ + "//sw/device/lib/crt", + "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/rom_ext", + "//sw/device/silicon_creator/rom_ext/prodc/keys", + ], +) + +offline_presigning_artifacts( + name = "presigning", + testonly = True, + srcs = [ + ":rom_ext_real_prod_signed_slot_a", + ":rom_ext_real_prod_signed_slot_b", + ], + manifest = ":manifest_prodc", + rsa_key = { + "//sw/device/silicon_creator/rom/keys/real/rsa:keyset": "earlgrey_a0_prod_2", + }, + tags = ["manual"], +) + +pkg_tar( + name = "digests", + testonly = True, + srcs = [":presigning"], + mode = "0644", + tags = ["manual"], +) + +offline_signature_attach( + name = "signed", + testonly = True, + srcs = [ + ":presigning", + ], + rsa_signatures = [ + "//sw/device/silicon_creator/rom_ext/prodc/signatures:rsa_signatures", + ], + tags = ["manual"], +) diff --git a/sw/device/silicon_creator/rom_ext/prodc/keys/BUILD b/sw/device/silicon_creator/rom_ext/prodc/keys/BUILD new file mode 100644 index 0000000000000..ef00810bcc5f4 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/prodc/keys/BUILD @@ -0,0 +1,56 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +load("//rules:signing.bzl", "keyset") + +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "keys", + srcs = [ + "sigverify_rsa_keys_prodc.c", + "//sw/device/silicon_creator/rom_ext:sigverify_keys.h", + ], + hdrs = [ + "earlgrey_z1_prodc_1.h", + ], + deps = [ + "//hw/ip/otp_ctrl/data:otp_ctrl_regs", + "//sw/device/lib/base:macros", + "//sw/device/silicon_creator/lib/sigverify", + ], +) + +cc_test( + name = "keys_unittest", + srcs = [ + "sigverify_rsa_keys_prodc_unittest.cc", + "//sw/device/silicon_creator/lib/sigverify:rsa_verify.c", + "//sw/device/silicon_creator/lib/sigverify:rsa_verify.h", + ], + deps = [ + ":keys", + "//sw/device/lib/base:hardened", + "//sw/device/silicon_creator/lib/drivers:hmac", + "//sw/device/silicon_creator/lib/drivers:lifecycle", + "//sw/device/silicon_creator/lib/drivers:otp", + "//sw/device/silicon_creator/lib/sigverify:mod_exp_ibex_device_library", + "//sw/device/silicon_creator/lib/sigverify:mod_exp_otbn", + "//sw/device/silicon_creator/lib/sigverify:rsa_key", + "//sw/device/silicon_creator/lib/sigverify:rsa_verify", + "//sw/device/silicon_creator/rom_ext:sigverify_keys", + "//sw/device/silicon_creator/testing:rom_test", + "@googletest//:gtest_main", + ], +) + +keyset( + name = "keyset", + build_setting_default = "", + keys = { + "earlgrey_z1_prodc_1.der": "earlgrey_z1_prodc_1", + }, + profile = "earlgrey_z1_prodc", + tool = "//signing:token", +) diff --git a/sw/device/silicon_creator/rom_ext/prodc/keys/earlgrey_z1_prodc_1.der b/sw/device/silicon_creator/rom_ext/prodc/keys/earlgrey_z1_prodc_1.der new file mode 100644 index 0000000000000..43bbf79d33d67 Binary files /dev/null and b/sw/device/silicon_creator/rom_ext/prodc/keys/earlgrey_z1_prodc_1.der differ diff --git a/sw/device/silicon_creator/rom_ext/prodc/keys/earlgrey_z1_prodc_1.h b/sw/device/silicon_creator/rom_ext/prodc/keys/earlgrey_z1_prodc_1.h new file mode 100644 index 0000000000000..aaab8aa2ec7c7 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/prodc/keys/earlgrey_z1_prodc_1.h @@ -0,0 +1,39 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_PRODC_KEYS_EARLGREY_Z1_PRODC_1_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_PRODC_KEYS_EARLGREY_Z1_PRODC_1_H_ + +#define EARLGREY_Z1_PRODC_1 \ + { \ + .n = \ + {{ \ + 0xd7af0dd5, 0x0a2296ff, 0x03627e28, 0x858e557a, 0xf31e2246, \ + 0x1972ff61, 0xfa972b63, 0x2f755cb8, 0xcbb7f242, 0x8b14a139, \ + 0xaf2ef152, 0x4f2991a6, 0x2b647171, 0xd9778edb, 0x434acb79, \ + 0x4fde9aa1, 0xa7be6fa0, 0xfd1e2d4f, 0xc06d497c, 0x6385b2ec, \ + 0x6b1799af, 0x3eedaf0f, 0x58a80508, 0xf9f991f3, 0xf8abee4c, \ + 0x3517ba93, 0x0f625565, 0x2c02427a, 0x3dce3809, 0x072194cd, \ + 0xe455076c, 0xab1189f1, 0x29afca62, 0xe487061c, 0xeef2255d, \ + 0x91c96072, 0xad54cb22, 0xe63ea5ff, 0xc6cf64ef, 0x66d27d1d, \ + 0x396dd4e3, 0x5bbdb7ed, 0xf7c805cf, 0xa70a282f, 0x19a8b307, \ + 0x6dd3008b, 0x686e3788, 0x0ccfdb19, 0xc47a821a, 0x83c157f5, \ + 0x52fea68b, 0xd645f4d2, 0x206ed7cb, 0x899c7b1b, 0x9a777335, \ + 0x0bc65c6b, 0x8fcea773, 0xd1799e75, 0xbc23d660, 0x0e8c18a8, \ + 0x6527b5d4, 0x3eb7e278, 0x93546a7e, 0x67deba97, 0x9433cb40, \ + 0x6b330bdf, 0xcfe52600, 0xa02f8cc2, 0xea50b2da, 0x549891cb, \ + 0x87735ceb, 0xf257b804, 0xd96c7566, 0x4dcf77da, 0xe38b464f, \ + 0xb6c9afca, 0xeab879b2, 0x3fb1ed41, 0xe1f20209, 0x2819397f, \ + 0x3c6ef023, 0x0c754ffe, 0x61512fb7, 0x448b297e, 0xba5af191, \ + 0x88dd9d71, 0xd6e05fa9, 0x5266d4a8, 0x005aa42e, 0x58cbf6c4, \ + 0x65df874e, 0x0afcf690, 0x2b24b10b, 0xf3f422ab, 0x55933e0c, \ + 0xba900bcb, \ + }}, \ + .n0_inv = { \ + 0x52763c83, 0x4c89d945, 0x7dc117bd, 0x923a4240, \ + 0x88605510, 0x7f38dd72, 0xa3963a0e, 0x865793d2, \ + }, \ + } + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_PRODC_KEYS_EARLGREY_Z1_PRODC_1_H_ diff --git a/sw/device/silicon_creator/rom_ext/prodc/keys/sigverify_rsa_keys_prodc.c b/sw/device/silicon_creator/rom_ext/prodc/keys/sigverify_rsa_keys_prodc.c new file mode 100644 index 0000000000000..edbc2e73f10b4 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/prodc/keys/sigverify_rsa_keys_prodc.c @@ -0,0 +1,36 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/lib/base/macros.h" +#include "sw/device/silicon_creator/rom_ext/prodc/keys/earlgrey_z1_prodc_1.h" +#include "sw/device/silicon_creator/rom_ext/sigverify_keys.h" + +/** + * Number of RSA public keys. + */ +enum { + kSigverifyRsaKeysCnt_ = 1, +}; +const size_t kSigverifyRsaKeysCnt = kSigverifyRsaKeysCnt_; + +/** + * Step size to use when checking RSA public keys. + * + * This must be coprime with and less than `kSigverifyNumRsaKeys`. + * Note: Step size is not applicable when `kSigverifyNumRsaKeys` is 1. + */ +const size_t kSigverifyRsaKeysStep = 1; + +/** + * Fake public keys for signature verification in tests. + * + * Please see sw/device/silicon_creator/rom/keys/README.md for more + * details. + */ +const sigverify_rom_ext_key_t kSigverifyRsaKeys[kSigverifyRsaKeysCnt_] = { + { + .key = EARLGREY_Z1_PRODC_1, + .key_type = kSigverifyKeyTypeFirmwareProd, + }, +}; diff --git a/sw/device/silicon_creator/rom_ext/prodc/keys/sigverify_rsa_keys_prodc_unittest.cc b/sw/device/silicon_creator/rom_ext/prodc/keys/sigverify_rsa_keys_prodc_unittest.cc new file mode 100644 index 0000000000000..1cbcb9dc5c4aa --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/prodc/keys/sigverify_rsa_keys_prodc_unittest.cc @@ -0,0 +1,171 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include + +#include "gtest/gtest.h" +#include "sw/device/lib/base/hardened.h" +#include "sw/device/silicon_creator/lib/drivers/mock_lifecycle.h" +#include "sw/device/silicon_creator/lib/drivers/mock_otp.h" +#include "sw/device/silicon_creator/lib/drivers/mock_rnd.h" +#include "sw/device/silicon_creator/lib/error.h" +#include "sw/device/silicon_creator/lib/sigverify/rsa_verify.h" +#include "sw/device/silicon_creator/rom_ext/sigverify_keys.h" +#include "sw/device/silicon_creator/testing/rom_test.h" + +#include "otp_ctrl_regs.h" + +namespace sigverify_keys_unittest { +namespace { +using ::testing::Return; + +TEST(Keys, UniqueIds) { + std::unordered_set ids; + for (size_t i = 0; i < kSigverifyRsaKeysCnt; ++i) { + ids.insert(sigverify_rsa_key_id_get(&kSigverifyRsaKeys[i].key.n)); + } + + EXPECT_EQ(ids.size(), kSigverifyRsaKeysCnt); +} + +/** + * An implementation of the Euclidean algorithm since we can't use c++17's + * `std::gcd()` yet. + */ +uint32_t Gcd(uint32_t a, uint32_t b) { + while (b != 0) { + std::tie(a, b) = std::make_tuple(b, a % b); + } + return a; +} + +TEST(KeysStep, IsCorrect) { + if (kSigverifyRsaKeysCnt > 1) { + EXPECT_LT(kSigverifyRsaKeysStep, kSigverifyRsaKeysCnt); + EXPECT_EQ(Gcd(kSigverifyRsaKeysStep, kSigverifyRsaKeysCnt), 1); + } +} + +// Note: The test cases below test sigverify using ROM keys. They have some +// overlap with sigverify_mod_exp_ibex unit tests but this way we don't have to +// worry about keeping the keys used in those tests in sync with ROM keys. + +/** + * Message and digest used in tests. + * + * The digest can be obtained using: + * ``` + * echo -n "test" | openssl dgst -sha256 -binary | \ + * xxd -p -c 4 | tac | sed 's|.*|0x&,|' + * ``` + */ +constexpr hmac_digest_t kDigest = { + .digest = + { + 0xb0f00a08, + 0xd15d6c15, + 0x2b0b822c, + 0xa3bf4f1b, + 0xc55ad015, + 0x9a2feaa0, + 0x884c7d65, + 0x9f86d081, + }, +}; + +/** + * Keys and signatures used in tests. + * + * These can be generated using the `openssl dgst` command as discussed in + * sw/device/silicon_creator/keys/README.md. + */ +struct RsaVerifyTestCase { + /** + * Signer's RSA public key. + */ + const sigverify_rsa_key_t *key; + /** + * Signature to be verified. + */ + sigverify_rsa_buffer_t sig; +}; + +const RsaVerifyTestCase kRsaVerifyTestCases[1]{ + // message: "test" + { + .key = &kSigverifyRsaKeys[0].key, + /* + * echo -n "test" > test.txt + * + * hsmtool -t ot-earlgrey-z0-sival -u user rsa sign -f plain-text \ + * -l earlgrey_z0_sival_1 -o test.sig test.txt + * + * cat test.sig | xxd -p -c 4 | tac | sed 's|.*|0x&,|' + */ + .sig = + { + 0x8f377053, 0x84f3b28b, 0x679a0612, 0x0c6113ce, 0x866d2e26, + 0xc77cf46f, 0x6b4fbc29, 0x6ee46599, 0x5f4fb71e, 0x2545331c, + 0xf348d902, 0xcb99fd20, 0x0d847abc, 0x9beead72, 0x1c2120bf, + 0xfdd126f7, 0x360857af, 0xccaeb60e, 0x071bc97b, 0xa1153749, + 0x13a70f63, 0x78f7656a, 0x87335c35, 0x17cf900c, 0x178f4da0, + 0x92bdd3cf, 0x2e2b07ff, 0x2c9966d6, 0x62f3f6fd, 0x0d798700, + 0xfe7f6dfd, 0x4fff2fcd, 0xd3659016, 0xd6b2294f, 0x9a9b435b, + 0x88bf97ea, 0x15216b1d, 0x0a5c8a57, 0xae01e283, 0xf3a5f516, + 0x08d85472, 0x0fc112db, 0x9f8b9176, 0xf5b934ed, 0x2477c59d, + 0xb08e660b, 0x0cac1047, 0x9dcb7e15, 0x95172f46, 0x54534029, + 0x521e1305, 0x1287fa18, 0xc612a532, 0x0c9c6adf, 0x13af326e, + 0x0c821490, 0x34f1df90, 0x6e06b13a, 0xecd46938, 0xf8677789, + 0xfeb279e9, 0x10e7af0e, 0xdf822495, 0x3643f357, 0xf663ed24, + 0xb3d178a5, 0x668c2172, 0x3c6348cb, 0xec3f2790, 0xd5daf3c9, + 0xab9fa6ee, 0x8c43b22e, 0x9dd8d59b, 0x02d762ec, 0xbd671bba, + 0xa75549f0, 0xd755aa72, 0xfb7e9908, 0x6844ade8, 0xa8b1b689, + 0x898aa733, 0x4a1db29d, 0x7684c27e, 0x74f0dc83, 0x7300e86f, + 0x0a47ce7a, 0x07f7b635, 0xb42e9894, 0x4414c04a, 0x1079982a, + 0x75a18fe6, 0x9217217b, 0xd2e6b201, 0xaa31b81a, 0x9f34c1d7, + 0x5de12a1e, + + }, + }, +}; + +TEST(RsaVerifyTestCases, AllKeys) { + std::unordered_set ids; + for (auto const &test_case : kRsaVerifyTestCases) { + ids.insert(sigverify_rsa_key_id_get(&test_case.key->n)); + } + + EXPECT_EQ(ids.size(), kSigverifyRsaKeysCnt); +} + +class SigverifyRsaVerify + : public rom_test::RomTest, + public testing::WithParamInterface { + protected: + rom_test::MockOtp otp_; +}; + +TEST_P(SigverifyRsaVerify, Ibex) { + EXPECT_CALL( + otp_, + read32( + OTP_CTRL_PARAM_CREATOR_SW_CFG_SIGVERIFY_RSA_MOD_EXP_IBEX_EN_OFFSET)) + .WillOnce(Return(kHardenedBoolTrue)); + + uint32_t flash_exec = 0; + EXPECT_EQ(sigverify_rsa_verify(&GetParam().sig, GetParam().key, &kDigest, + kLcStateProd, &flash_exec), + kErrorOk); + EXPECT_EQ(flash_exec, kSigverifyRsaSuccess); +} + +INSTANTIATE_TEST_SUITE_P(AllCases, SigverifyRsaVerify, + testing::ValuesIn(kRsaVerifyTestCases)); + +} // namespace +} // namespace sigverify_keys_unittest diff --git a/sw/device/silicon_creator/rom_ext/prodc/signatures/BUILD b/sw/device/silicon_creator/rom_ext/prodc/signatures/BUILD new file mode 100644 index 0000000000000..7d4bb7ec86080 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/prodc/signatures/BUILD @@ -0,0 +1,15 @@ +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "rsa_signatures", + srcs = glob(["*.rsa_sig"]), +) + +filegroup( + name = "spx_signatures", + srcs = glob(["*.spx_sig"]), +)