blob: 1467196aab43b3c2e476bc02391bfd6d67dda534 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include <array>
#include <cstring>
#include <limits>
#include <numeric>
#include <unordered_set>
#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/mock_mod_exp_otbn.h"
#include "sw/device/silicon_creator/lib/sigverify/sigverify.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<uint32_t> 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[2]{
// message: "test"
{
.key = &kSigverifyRsaKeys[0].key,
// echo -n "test" | openssl dgst -sha256 -keyform DER -sign \
// rom_ext_test_key_0_rsa_3072_exp_f4.der -hex
.sig =
{
0x0a43b030, 0xa82d7c33, 0xb9b1228a, 0x5a0f8892, 0xaa58c077,
0x365e2b25, 0xc5f013f8, 0xbf32bc11, 0x15350128, 0x07522924,
0x8f7e0889, 0x82084b48, 0xb92b0077, 0x82d3514e, 0xbecda671,
0x571009d2, 0xd4606ba7, 0x66bd5fc3, 0xddae3c76, 0xc388a4c3,
0x808d5e2a, 0x2dc32965, 0x4e008e5b, 0x4abfc93d, 0xdb6eb16d,
0x6cb028f0, 0x4aeffb6b, 0xe7574f3e, 0xff73b548, 0x08649d80,
0xb2009425, 0xe2bbd368, 0xa28e3b8a, 0xdd2875cb, 0xc54fdf24,
0x1a9a59ac, 0x54ee1013, 0x6da6244d, 0x5cfd3eaa, 0xc7cb551f,
0x68626f79, 0xf1cd06c6, 0x5fe8eadd, 0x220c9362, 0x8cc33f50,
0xc3918984, 0xe1967286, 0xfd0376ac, 0x41e0f3ee, 0x5f221d07,
0x90803f71, 0x6c7cef85, 0x835975e7, 0xa6b9fee5, 0x87155038,
0x0fb5407e, 0x050f0cd0, 0x85225aec, 0x0a407a9f, 0x5a175126,
0xe2e67818, 0x21deaa56, 0x9df45426, 0x361f14ab, 0xd93d22e7,
0xb9cc475e, 0xe8b28289, 0xc56fbc95, 0x18b2d1ab, 0x14e18896,
0x07ff5105, 0xce8f5e9f, 0xdee539a9, 0x2cf56ccd, 0xabe93abf,
0xc51bee68, 0xd29df209, 0xebba0ab8, 0x9985a37b, 0xf30ec0fb,
0xeba0bf7b, 0xa508045c, 0x02f09bb2, 0x9f674fe3, 0xb9c07238,
0xc9c88282, 0xada38689, 0x6d7c3294, 0x479e27dd, 0x01bd6436,
0x412c377f, 0x51a56959, 0x530432e8, 0x53e4f546, 0x163d3282,
0xc25256a9,
},
},
{
.key = &kSigverifyRsaKeys[1].key,
// echo -n "test" | openssl dgst -sha256 -keyform DER -sign \
// rom_ext_dev_key_0_rsa_3072_exp_f4.der -hex
.sig =
{
0x6e317a1c, 0x9068313e, 0x3f9610c1, 0x261cb66b, 0x0d6f49c6,
0x6e062654, 0x87a0febe, 0xae824f16, 0xeca90143, 0x56ea924c,
0x34dc1f64, 0xa9b756f9, 0xa6965f0d, 0x366c89cc, 0x921520ca,
0xab0c17ec, 0x199a0b02, 0x6551663a, 0x9ff7ab3e, 0x4aea7455,
0x3a3d6b2f, 0x0e8fe77e, 0x1b18ed7c, 0x643168d0, 0x91de7e47,
0x86190fc2, 0x7b9b7a64, 0x5784b535, 0xb358354a, 0xad42ed4c,
0x539823a8, 0xe7cf98ec, 0x68c4a7ae, 0xad35612e, 0xc43c18c6,
0x5da4fa0b, 0x918a15b2, 0xbde51df7, 0x5d63a9d2, 0x96af2137,
0x02c1cf63, 0x0a285e1a, 0x4d228a24, 0x45aa181e, 0xdefe4371,
0x5a6c986e, 0x1d5455a5, 0xf342a7f2, 0x9e6d116f, 0x0cde267b,
0x360997c0, 0x5da55860, 0xfe2ccf61, 0xc9517096, 0xb5e3891b,
0xa7a0194b, 0xa1b094bd, 0x1dd61621, 0x79061426, 0x5eba1c71,
0x5e3981c4, 0xcd38b155, 0xe47d6d5a, 0x985ef71c, 0xe69e4ba9,
0xbfec165d, 0x1f5beff6, 0x15f18950, 0x18173348, 0xdfb7d0b2,
0x8379cf38, 0x16636f15, 0x8b741f64, 0xd7bbd6e6, 0x0915d0fa,
0x16f60d28, 0x54966caf, 0x5d415bc1, 0x2f033158, 0x140efe45,
0xe0ed8089, 0xa79d27fa, 0xb256bf12, 0x4597dc61, 0x75d62c3e,
0x18cb1285, 0xdedc32a3, 0x7238f240, 0xe9c7e35b, 0xecab323e,
0xf39e74b9, 0x04cba244, 0x36ff5c6a, 0x5ed63996, 0xe5510a91,
0x536875ef,
},
},
};
TEST(RsaVerifyTestCases, AllKeys) {
std::unordered_set<uint32_t> 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<RsaVerifyTestCase> {
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;
EXPECT_EQ(sigverify_rsa_verify(&GetParam().sig, GetParam().key, &kDigest,
kLcStateProd, &flash_exec),
kErrorOk);
EXPECT_EQ(flash_exec, kSigverifyFlashExec);
}
INSTANTIATE_TEST_SUITE_P(AllCases, SigverifyRsaVerify,
testing::ValuesIn(kRsaVerifyTestCases));
} // namespace
} // namespace sigverify_keys_unittest