Software APIs
keymgr_test.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/keymgr.h"
6 
8 #include "sw/device/lib/crypto/drivers/entropy.h"
9 #include "sw/device/lib/crypto/impl/status.h"
11 #include "sw/device/lib/testing/keymgr_testutils.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 
15 // Module ID for status codes.
16 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
17 
18 // Key diversification data for testing
19 static const keymgr_diversification_t kTestDiversification = {
20  .salt =
21  {
22  0x00112233,
23  0x44556677,
24  0x8899aabb,
25  0xccddeeff,
26  0x00010203,
27  0x04050607,
28  0x08090a0b,
29  0x0c0d0e0f,
30  },
31  .version = 0x9,
32 };
33 
34 /**
35  * Setup keymgr and entropy complex.
36  *
37  * Run this test before any others.
38  */
39 status_t test_setup(void) {
40  // Initialize the key manager and advance to OwnerRootKey state.
41  dif_keymgr_t keymgr;
42  dif_kmac_t kmac;
43  TRY(keymgr_testutils_startup(&keymgr, &kmac));
44  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
45  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
46  TRY(keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerRootKey));
47 
48  // Initialize entropy complex, which the key manager uses to clear sideloaded
49  // keys. The `keymgr_testutils_startup` function restarts the device, so this
50  // should happen afterwards.
51  return entropy_complex_init();
52 }
53 
54 /**
55  * Test generating a single software-visible key.
56  *
57  * This test just checks that the key generation process finished without
58  * errors, without performing any validation on the key.
59  */
60 status_t sw_single_key_test(void) {
61  keymgr_output_t key;
62  return keymgr_generate_key_sw(kTestDiversification, &key);
63 }
64 
65 /**
66  * Test generating a single sideloaded AES key.
67  *
68  * This test just checks that the key generation process finished without
69  * errors, without actually attempting to use the key.
70  */
71 status_t aes_basic_test(void) {
72  return keymgr_generate_key_aes(kTestDiversification);
73 }
74 
75 /**
76  * Test generating a single sideloaded KMAC key.
77  *
78  * This test just checks that the key generation process finished without
79  * errors, without actually attempting to use the key.
80  */
81 status_t kmac_basic_test(void) {
82  return keymgr_generate_key_kmac(kTestDiversification);
83 }
84 
85 /**
86  * Test generating a single sideloaded OTBN key.
87  *
88  * This test just checks that the key generation process finished without
89  * errors, without actually attempting to use the key.
90  */
91 status_t otbn_basic_test(void) {
92  return keymgr_generate_key_otbn(kTestDiversification);
93 }
94 
95 /**
96  * Check whether two key manager output values are equivalent.
97  *
98  * Unmasks both keys and compares their unmasked values; masking should not
99  * affect this comparison.
100  *
101  * @param key1 First key manager output.
102  * @param key2 Second key manager output.
103  * @return true if the keys are equivalent, false otherwise.
104  */
105 static bool output_equiv(keymgr_output_t key1, keymgr_output_t key2) {
106  for (size_t i = 0; i < kKeymgrOutputShareNumWords; i++) {
107  uint32_t word1 = key1.share0[i] ^ key1.share1[i];
108  uint32_t word2 = key2.share0[i] ^ key2.share1[i];
109  if (word1 != word2) {
110  return false;
111  }
112  }
113  return true;
114 }
115 
116 /**
117  * Test generating software-visible keys with different salts.
118  *
119  * Different salts should produce different keys; the same salt should produce
120  * the same key but with different masking.
121  */
122 status_t sw_keys_change_salt_test(void) {
123  // Copy the test data into a mutable structure.
125  memcpy(div.salt, kTestDiversification.salt, sizeof(div.salt));
126  div.version = kTestDiversification.version;
127 
128  // Generate a key.
129  keymgr_output_t key1;
130  TRY(keymgr_generate_key_sw(div, &key1));
131 
132  // Change the salt and generate the key again.
133  div.salt[0]++;
134  keymgr_output_t key2;
135  TRY(keymgr_generate_key_sw(div, &key2));
136 
137  // Check that the keys are distinct.
138  TRY_CHECK(!output_equiv(key1, key2));
139 
140  // Change the salt back to its original value and generate a third time.
141  div.salt[0]--;
142  keymgr_output_t key3;
143  TRY(keymgr_generate_key_sw(div, &key3));
144 
145  // Check that the key is the equivalent to the first key when unmasked.
146  TRY_CHECK(output_equiv(key1, key3));
147 
148  // Check that the masking on the equivalent keys is different.
149  TRY_CHECK_ARRAYS_NE(key1.share0, key2.share0, sizeof(key1.share0));
150 
151  return OK_STATUS();
152 }
153 
154 /**
155  * Test generating software-visible keys with different versions.
156  *
157  * Different versions should produce different keys; the same version should
158  * produce the same key but with different masking.
159  */
160 status_t sw_keys_change_version_test(void) {
161  // Copy the test data into a mutable structure.
163  memcpy(div.salt, kTestDiversification.salt, sizeof(div.salt));
164  div.version = kTestDiversification.version;
165 
166  // Generate a key.
167  keymgr_output_t key1;
168  TRY(keymgr_generate_key_sw(div, &key1));
169 
170  // Change the version and generate the key again.
171  div.version++;
172  keymgr_output_t key2;
173  TRY(keymgr_generate_key_sw(div, &key2));
174 
175  // Check that the keys are distinct.
176  TRY_CHECK(!output_equiv(key1, key2));
177 
178  // Change the version back to its original value and generate a third time.
179  div.version--;
180  keymgr_output_t key3;
181  TRY(keymgr_generate_key_sw(div, &key3));
182 
183  // Check that the key is the equivalent to the first key when unmasked.
184  TRY_CHECK(output_equiv(key1, key3));
185 
186  // Check that the masking on the equivalent keys is different.
187  TRY_CHECK_ARRAYS_NE(key1.share0, key2.share0, sizeof(key1.share0));
188 
189  return OK_STATUS();
190 }
191 
192 OTTF_DEFINE_TEST_CONFIG();
193 
194 bool test_main(void) {
195  static status_t result;
196 
197  EXECUTE_TEST(result, test_setup);
198  EXECUTE_TEST(result, sw_single_key_test);
199  EXECUTE_TEST(result, sw_keys_change_salt_test);
200  EXECUTE_TEST(result, sw_keys_change_version_test);
201  EXECUTE_TEST(result, aes_basic_test);
202  EXECUTE_TEST(result, kmac_basic_test);
203  EXECUTE_TEST(result, otbn_basic_test);
204 
205  return status_ok(result);
206 }