Software APIs
otbn_boot_services_functest.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/lib/crypto/drivers/entropy.h"
8 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
9 #include "sw/device/lib/testing/keymgr_testutils.h"
10 #include "sw/device/lib/testing/test_framework/check.h"
12 #include "sw/device/silicon_creator/lib/drivers/hmac.h"
13 #include "sw/device/silicon_creator/lib/otbn_boot_services.h"
14 #include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
15 
16 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
17 
18 OTTF_DEFINE_TEST_CONFIG();
19 
20 // Keymgr handle for this test.
21 static dif_keymgr_t keymgr;
22 
23 // Global variable holding the number of times we advanced keymgr after startup.
24 size_t num_keymgr_advances = 0;
25 
26 // Message value for signature generation/verification tests.
27 const char kTestMessage[] = "Test message.";
28 const size_t kTestMessageLen = sizeof(kTestMessage) - 1;
29 
30 // Valid ECDSA-P256 public key.
31 static const ecdsa_p256_public_key_t kEcdsaKey = {
32  .x = {0x1ceb402b, 0x9dc600d1, 0x182ec21b, 0x5ede3640, 0x3566bdac,
33  0x1debf94b, 0x1a286a75, 0x8904d749},
34  .y = {0x63eab6dc, 0x0c53bf99, 0x086d3ee7, 0x1076efa6, 0x8dd8ece2,
35  0xbfececf0, 0x9b94e34d, 0x59b12f3c},
36 };
37 
38 // Valid ECDSA-P256 signature for `kTestMessage`.
39 static const ecdsa_p256_signature_t kEcdsaSignature = {
40  .r = {0x4811545a, 0x088d927b, 0x5d8624b5, 0x2ef1f329, 0x184ba14a,
41  0xf655eede, 0xaaed0d54, 0xa20e1ac7},
42  .s = {0x729b945d, 0x181dc116, 0x1025dba4, 0xb99828a0, 0xe7225df3,
43  0x0e200e9b, 0x785690b4, 0xf47efe98}};
44 
45 // Sample key manager diversification data for testing.
46 static const sc_keymgr_diversification_t kDiversification = {
47  .salt = {0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0xf0f1f2f3,
48  0xf4f5f6f7, 0xf8f9fafb, 0xfcfdfeff},
49  .version = 0,
50 };
51 
52 // Test values for attestation key seeds.
53 static const uint32_t kSeedValues[3][kAttestationSeedWords] = {
54  {0x70717273, 0x74757677, 0x78797a7b, 0x7c7d7e7f, 0x80818283, 0x84858687,
55  0x88898a8b, 0x8c8d8e8f, 0x90b1b2b3, 0x94959697},
56  {0xa0a1a2a3, 0xa4a5a6a7, 0xa8a9aaab, 0xacadaeaf, 0xb0b1b2b3, 0xb4b5b6b7,
57  0xb8b9babb, 0xbcbdbebf, 0xc0b1b2b3, 0xc4c5c6c7},
58  {0xd0d1d2d3, 0xd4d5d6d7, 0xd8d9dadb, 0xdcdddedf, 0xe0e1e2e3, 0xe4e5e6e7,
59  0xe8e9eaeb, 0xecedeeef, 0xf0b1b2b3, 0xf4f5f6f7},
60 };
61 
62 rom_error_t sigverify_test(void) {
63  // Hash the test message.
64  hmac_digest_t digest;
65  hmac_sha256(kTestMessage, kTestMessageLen, &digest);
66 
67  // The recovered `r` value from sigverify should be equal to the signature
68  // `r` value.
69  uint32_t recovered_r[kEcdsaP256SignatureComponentWords];
70  RETURN_IF_ERROR(
71  otbn_boot_sigverify(&kEcdsaKey, &kEcdsaSignature, &digest, recovered_r));
72  CHECK_ARRAYS_EQ(recovered_r, kEcdsaSignature.r, ARRAYSIZE(kEcdsaSignature.r));
73  return kErrorOk;
74 }
75 
76 rom_error_t attestation_keygen_test(void) {
77  // Check that key generations with different seeds result in different keys.
79  RETURN_IF_ERROR(otbn_boot_attestation_keygen(kFlashInfoFieldUdsKeySeedIdx,
80  kScKeymgrKeyTypeAttestation,
81  kDiversification, &pk_uds));
83  RETURN_IF_ERROR(otbn_boot_attestation_keygen(kFlashInfoFieldCdi0KeySeedIdx,
84  kScKeymgrKeyTypeAttestation,
85  kDiversification, &pk_cdi0));
87  RETURN_IF_ERROR(otbn_boot_attestation_keygen(kFlashInfoFieldCdi1KeySeedIdx,
88  kScKeymgrKeyTypeAttestation,
89  kDiversification, &pk_cdi1));
90  ecdsa_p256_public_key_t pk_tpm_ek;
91  RETURN_IF_ERROR(otbn_boot_attestation_keygen(kFlashInfoFieldTpmEkKeySeedIdx,
92  kScKeymgrKeyTypeSealing,
93  kDiversification, &pk_tpm_ek));
94  CHECK_ARRAYS_NE((unsigned char *)&pk_uds, (unsigned char *)&pk_cdi0,
95  sizeof(pk_uds));
96  CHECK_ARRAYS_NE((unsigned char *)&pk_uds, (unsigned char *)&pk_cdi1,
97  sizeof(pk_uds));
98  CHECK_ARRAYS_NE((unsigned char *)&pk_cdi0, (unsigned char *)&pk_cdi1,
99  sizeof(pk_uds));
100  CHECK_ARRAYS_NE((unsigned char *)&pk_tpm_ek, (unsigned char *)&pk_cdi1,
101  sizeof(pk_uds));
102 
103  // Check that running the same key generation twice results in the same key.
104  ecdsa_p256_public_key_t pk_uds_again;
105  RETURN_IF_ERROR(otbn_boot_attestation_keygen(
106  kFlashInfoFieldUdsKeySeedIdx, kScKeymgrKeyTypeAttestation,
107  kDiversification, &pk_uds_again));
108  CHECK_ARRAYS_EQ((unsigned char *)&pk_uds_again, (unsigned char *)&pk_uds,
109  sizeof(pk_uds));
110 
111  // Check that key generations with different diversification result in
112  // different keys.
113  sc_keymgr_diversification_t diversification_modified;
114  memcpy(&diversification_modified, &kDiversification,
115  sizeof(diversification_modified));
116  diversification_modified.salt[0] ^= 1;
117  ecdsa_p256_public_key_t pk_uds_div;
118  RETURN_IF_ERROR(otbn_boot_attestation_keygen(
119  kFlashInfoFieldUdsKeySeedIdx, kScKeymgrKeyTypeAttestation,
120  diversification_modified, &pk_uds_div));
121  CHECK_ARRAYS_NE((unsigned char *)&pk_uds_div, (unsigned char *)&pk_uds,
122  sizeof(pk_uds));
123  return kErrorOk;
124 }
125 
126 rom_error_t attestation_advance_and_endorse_test(void) {
127  // Generate and save the a keypair.
129  RETURN_IF_ERROR(otbn_boot_attestation_keygen(kFlashInfoFieldUdsKeySeedIdx,
130  kScKeymgrKeyTypeAttestation,
131  kDiversification, &pk));
132  RETURN_IF_ERROR(otbn_boot_attestation_key_save(kFlashInfoFieldUdsKeySeedIdx,
133  kScKeymgrKeyTypeAttestation,
134  kDiversification));
135 
136  // Advance keymgr to the next stage.
137  if (num_keymgr_advances == 0) {
138  CHECK_STATUS_OK(
139  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateCreatorRootKey));
140  CHECK_STATUS_OK(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
141  num_keymgr_advances++;
142  } else {
143  CHECK(num_keymgr_advances == 1);
144  CHECK_STATUS_OK(keymgr_testutils_check_state(
146  CHECK_STATUS_OK(
147  keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
148  num_keymgr_advances++;
149  }
150 
151  // Run endorsement (should overwrite the key with randomness when done).
152  hmac_digest_t digest;
153  hmac_sha256(kTestMessage, kTestMessageLen, &digest);
155  RETURN_IF_ERROR(otbn_boot_attestation_endorse(&digest, &sig));
156 
157  // Check that the signature is valid (recovered r == r).
158  uint32_t recovered_r[kEcdsaP256SignatureComponentWords];
159  RETURN_IF_ERROR(otbn_boot_sigverify(&pk, &sig, &digest, recovered_r));
160  CHECK_ARRAYS_EQ(recovered_r, sig.r, ARRAYSIZE(sig.r));
161 
162  // Run endorsement again (should not return an error, but should produce an
163  // invalid signature).
164  RETURN_IF_ERROR(otbn_boot_attestation_endorse(&digest, &sig));
165 
166  // Check that the signature is invalid (recovered r != r).
167  RETURN_IF_ERROR(otbn_boot_sigverify(&pk, &sig, &digest, recovered_r));
168  CHECK_ARRAYS_NE(recovered_r, sig.r, ARRAYSIZE(sig.r));
169 
170  // Check that generating a new key with the same diversification as before
171  // now gets a different public key because keymgr has advanced.
173  RETURN_IF_ERROR(otbn_boot_attestation_keygen(kFlashInfoFieldUdsKeySeedIdx,
174  kScKeymgrKeyTypeAttestation,
175  kDiversification, &pk_adv));
176  CHECK_ARRAYS_NE((unsigned char *)&pk, (unsigned char *)&pk_adv, sizeof(pk));
177 
178  return kErrorOk;
179 }
180 
181 // N.B. This test will lock OTBN, so it needs to be the last test that runs.
182 rom_error_t attestation_save_clear_key_test(void) {
183  // Save and then clear a private key.
184  RETURN_IF_ERROR(otbn_boot_attestation_key_save(kFlashInfoFieldUdsKeySeedIdx,
185  kScKeymgrKeyTypeAttestation,
186  kDiversification));
187  RETURN_IF_ERROR(otbn_boot_attestation_key_clear());
188 
189  // Save the private key again and check that endorsing succeeds.
190  RETURN_IF_ERROR(otbn_boot_attestation_key_save(kFlashInfoFieldUdsKeySeedIdx,
191  kScKeymgrKeyTypeAttestation,
192  kDiversification));
193  hmac_digest_t digest;
194  hmac_sha256(kTestMessage, kTestMessageLen, &digest);
196  RETURN_IF_ERROR(otbn_boot_attestation_endorse(&digest, &sig));
197 
198  // Clear the key and check that endorsing now fails (it should even lock
199  // OTBN).
200  RETURN_IF_ERROR(otbn_boot_attestation_key_clear());
201  hmac_sha256(kTestMessage, kTestMessageLen, &digest);
202  CHECK(otbn_boot_attestation_endorse(&digest, &sig) ==
203  kErrorOtbnExecutionFailed);
204  return kErrorOk;
205 }
206 
207 bool test_main(void) {
208  status_t result = OK_STATUS();
209 
210  // Initialize the entropy complex, KMAC, and the key manager.
211  CHECK_STATUS_OK(entropy_complex_init());
212  dif_kmac_t kmac;
213  CHECK_STATUS_OK(keymgr_testutils_startup(&keymgr, &kmac));
214  CHECK_STATUS_OK(
215  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateCreatorRootKey));
216 
217  // Initialize flash.
218  dif_flash_ctrl_state_t flash_ctrl;
219  CHECK_DIF_OK(dif_flash_ctrl_init_state(
220  &flash_ctrl,
222  CHECK_STATUS_OK(flash_ctrl_testutils_wait_for_init(&flash_ctrl));
223 
224  // Program the attestation key seeds in flash. The setup step only needs to
225  // be done once, since the seeds are on the same page.
226  flash_info_field_t seed_fields[] = {
227  kFlashInfoFieldUdsAttestationKeySeed,
228  kFlashInfoFieldCdi0AttestationKeySeed,
229  kFlashInfoFieldCdi1AttestationKeySeed,
230  };
231  uint32_t page_address = 0;
232  CHECK_STATUS_OK(flash_ctrl_testutils_info_region_scrambled_setup(
233  &flash_ctrl, seed_fields[0].page, seed_fields[0].bank,
234  seed_fields[0].partition, &page_address));
235  CHECK_STATUS_OK(flash_ctrl_testutils_erase_and_write_page(
236  &flash_ctrl, page_address, seed_fields[0].partition, kSeedValues[0],
237  kDifFlashCtrlPartitionTypeInfo, kAttestationSeedWords));
238  CHECK(ARRAYSIZE(seed_fields) == ARRAYSIZE(kSeedValues));
239  for (size_t i = 1; i < ARRAYSIZE(seed_fields); i++) {
240  CHECK(seed_fields[i].page == seed_fields[i - 1].page);
241  CHECK(seed_fields[i].bank == seed_fields[i - 1].bank);
242  CHECK(seed_fields[i].partition == seed_fields[i - 1].partition);
243  CHECK_STATUS_OK(flash_ctrl_testutils_write(
244  &flash_ctrl, page_address + seed_fields[i].byte_offset,
245  seed_fields[i].partition, kSeedValues[i],
246  kDifFlashCtrlPartitionTypeInfo, kAttestationSeedWords));
247  }
248 
249  // Load the boot services OTBN app.
250  CHECK(otbn_boot_app_load() == kErrorOk);
251 
252  EXECUTE_TEST(result, sigverify_test);
253  EXECUTE_TEST(result, attestation_keygen_test);
254  EXECUTE_TEST(result, attestation_advance_and_endorse_test);
255  EXECUTE_TEST(result, attestation_keygen_test);
256  EXECUTE_TEST(result, attestation_advance_and_endorse_test);
257  EXECUTE_TEST(result, attestation_save_clear_key_test);
258 
259  return status_ok(result);
260 }