Software APIs
aes_kwp_sideload_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 
6 #include "sw/device/lib/crypto/drivers/entropy.h"
9 #include "sw/device/lib/testing/keymgr_testutils.h"
10 #include "sw/device/lib/testing/test_framework/check.h"
12 
13 // Module ID for status codes.
14 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
15 
16 // Key version data for testing.
17 static const uint32_t kKeyVersion = 0x0;
18 
19 // Key salt for testing.
20 static const uint32_t kKeySalt[7] = {
21  0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff,
22  0x00010203, 0x04050607, 0x08090a0b,
23 };
24 
25 // Key configuration for wrapping key (AES-256).
26 static const otcrypto_key_config_t kWrappingKeyConfig = {
27  .version = kOtcryptoLibVersion1,
28  .key_mode = kOtcryptoKeyModeAesKwp,
29  .key_length = 256 / 8,
30  .hw_backed = kHardenedBoolTrue,
31  .security_level = kOtcryptoKeySecurityLevelLow,
32 };
33 
34 /**
35  * Check that wrapping and unwrapping returns the original key.
36  *
37  * @param key_to_wrap Blinded key to wrap/unwrap.
38  * @param kek_kek AES-KWP key to wrap with.
39  */
40 static status_t run_wrap_unwrap(const otcrypto_blinded_key_t *key_to_wrap,
41  const otcrypto_blinded_key_t *key_kek) {
42  size_t wrapped_num_words;
43  TRY(otcrypto_wrapped_key_len(key_to_wrap->config, &wrapped_num_words));
44 
45  // Wrap the key.
46  uint32_t wrapped_key_data[wrapped_num_words];
47  otcrypto_word32_buf_t wrapped_key = {
48  .data = wrapped_key_data,
49  .len = ARRAYSIZE(wrapped_key_data),
50  };
51  TRY(otcrypto_key_wrap(key_to_wrap, key_kek, wrapped_key));
52 
53  // Unwrap the key.
54  hardened_bool_t success;
55  TRY_CHECK(key_to_wrap->keyblob_length % sizeof(uint32_t) == 0);
56  size_t keyblob_words = key_to_wrap->keyblob_length / sizeof(uint32_t);
57  uint32_t unwrapped_key_keyblob[keyblob_words];
58  otcrypto_blinded_key_t unwrapped_key = {
59  .keyblob_length = keyblob_words * sizeof(uint32_t),
60  .keyblob = unwrapped_key_keyblob,
61  };
64  .data = wrapped_key_data,
65  .len = ARRAYSIZE(wrapped_key_data),
66  },
67  key_kek, &success, &unwrapped_key));
68 
69  // Check the result.
70  TRY_CHECK(success == kHardenedBoolTrue);
71  TRY_CHECK_ARRAYS_EQ(unwrapped_key.keyblob, key_to_wrap->keyblob,
72  keyblob_words);
73  TRY_CHECK(memcmp(&unwrapped_key.config, &key_to_wrap->config,
74  sizeof(otcrypto_key_config_t)) == 0);
75  TRY_CHECK(unwrapped_key.keyblob_length == key_to_wrap->keyblob_length);
76  TRY_CHECK(unwrapped_key.checksum == key_to_wrap->checksum);
77 
78  return OK_STATUS();
79 }
80 
81 /**
82  * Test wrapping/unwrapping a random key.
83  */
84 static status_t wrap_unwrap_random_test(void) {
85  const otcrypto_key_config_t kKmacKeyConfig = {
86  .version = kOtcryptoLibVersion1,
87  .key_mode = kOtcryptoKeyModeKmac128,
88  .key_length = 128 / 8,
89  .hw_backed = kHardenedBoolFalse,
90  .security_level = kOtcryptoKeySecurityLevelLow,
91  };
92 
93  // Generate a random KMAC key.
94  uint32_t keyblob[(kKmacKeyConfig.key_length * 2) / sizeof(uint32_t)];
95  otcrypto_blinded_key_t kmac_key = {
96  .config = kKmacKeyConfig,
97  .keyblob_length = sizeof(keyblob),
98  .keyblob = keyblob,
99  };
100  otcrypto_const_byte_buf_t personalization = {.data = NULL, .len = 0};
101  TRY(otcrypto_symmetric_keygen(personalization, &kmac_key));
102 
103  // Construct the sideloaded wrapping key.
104  uint32_t keyblob_kek[8];
105  otcrypto_blinded_key_t kek = {
106  .config = kWrappingKeyConfig,
107  .keyblob_length = sizeof(keyblob_kek),
108  .keyblob = keyblob_kek,
109  };
110  TRY(otcrypto_hw_backed_key(kKeyVersion, kKeySalt, &kek));
111 
112  return run_wrap_unwrap(&kmac_key, &kek);
113 }
114 
115 /**
116  * Setup keymgr and entropy complex.
117  *
118  * Run this before any tests.
119  */
120 status_t test_setup(void) {
121  // Initialize the key manager and advance to OwnerRootKey state. Note: the
122  // keymgr testutils set this up using software entropy, so there is no need
123  // to initialize the entropy complex first. However, this is of course not
124  // the expected setup in production.
125  dif_keymgr_t keymgr;
126  dif_kmac_t kmac;
127  dif_keymgr_state_t keymgr_state;
128  TRY(keymgr_testutils_try_startup(&keymgr, &kmac, &keymgr_state));
129 
130  if (keymgr_state == kDifKeymgrStateCreatorRootKey) {
131  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
132  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
133  } else if (keymgr_state == kDifKeymgrStateOwnerIntermediateKey) {
134  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
135  }
136 
137  TRY(keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerRootKey));
138 
139  // Initialize entropy complex for cryptolib, which the key manager uses to
140  // clear sideloaded keys. The `keymgr_testutils_startup` function restarts
141  // the device, so this should happen afterwards.
142  return entropy_complex_init();
143 }
144 
145 OTTF_DEFINE_TEST_CONFIG();
146 
147 bool test_main(void) {
148  status_t result = OK_STATUS();
149 
150  CHECK_STATUS_OK(test_setup());
151  EXECUTE_TEST(result, wrap_unwrap_random_test);
152 
153  return status_ok(result);
154 }