Software APIs
aes_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/aes.h"
7 #include "sw/device/lib/crypto/drivers/entropy.h"
8 #include "sw/device/lib/crypto/drivers/keymgr.h"
9 #include "sw/device/lib/crypto/impl/integrity.h"
10 #include "sw/device/lib/crypto/impl/status.h"
14 #include "sw/device/lib/testing/keymgr_testutils.h"
15 #include "sw/device/lib/testing/test_framework/check.h"
17 
18 // Module ID for status codes.
19 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
20 
21 // Key version data for testing.
22 static const uint32_t kKeyVersion = 0x0;
23 
24 // Two distinct key salts for testing.
25 static const uint32_t kKeySalt1[7] = {
26  0x00112233, 0x44556677, 0x8899aabb, 0xccddeeff,
27  0x00010203, 0x04050607, 0x08090a0b,
28 };
29 static const uint32_t kKeySalt2[7] = {
30  0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f,
31  0x00112233, 0x44556677, 0x8899aabb,
32 };
33 
34 // Indicates a sideloaded 256-bit AES-CTR key.
35 static const otcrypto_key_config_t kAesKeyConfig = {
36  .version = kOtcryptoLibVersion1,
37  .key_mode = kOtcryptoKeyModeAesCtr,
38  .key_length = 256 / 8,
39  .hw_backed = kHardenedBoolTrue,
40  .security_level = kOtcryptoKeySecurityLevelLow,
41 };
42 
43 // AES IV testing data.
44 static const uint32_t kAesIv[4] = {
45  0xdeadbeef,
46  0xdeadbeef,
47  0xdeadbeef,
48  0xdeadbeef,
49 };
50 
51 // AES plaintext testing data.
52 static const uint32_t kAesPlaintextBlock[4] = {0};
53 
54 /**
55  * Convenience function to run AES with the test data.
56  *
57  * The salt should be exactly `kSaltNumWords` words long; the input and output
58  * buffers should both match the size of `kAesPlaintextBlock` and be a multiple
59  * of the block size (so no padding is needed).
60  *
61  * @param salt Key salt to use.
62  * @param input Cipher input block(s).
63  * @param[out] output Resulting output block(s).
64  * @return OK or error.
65  */
66 static status_t run_aes(otcrypto_aes_operation_t operation,
67  const uint32_t salt[7], const uint32_t *input,
68  uint32_t *output) {
69  // Construct the key.
70  uint32_t keyblob[8];
72  .config = kAesKeyConfig,
73  .keyblob_length = sizeof(keyblob),
74  .keyblob = keyblob,
75  };
76  TRY(otcrypto_hw_backed_key(kKeyVersion, salt, &key));
77 
78  // Construct the IV.
79  uint32_t iv_data[ARRAYSIZE(kAesIv)];
80  memcpy(iv_data, kAesIv, sizeof(kAesIv));
82  .data = iv_data,
83  .len = ARRAYSIZE(iv_data),
84  };
85 
86  // Construct the input buffer.
87  otcrypto_const_byte_buf_t input_buf = {
88  .data = (const unsigned char *)input,
89  .len = sizeof(kAesPlaintextBlock),
90  };
91 
92  // Construct the output buffer.
93  otcrypto_byte_buf_t output_buf = {
94  .data = (unsigned char *)output,
95  .len = sizeof(kAesPlaintextBlock),
96  };
97 
98  return otcrypto_aes(&key, iv, kOtcryptoAesModeCtr, operation, input_buf,
99  kOtcryptoAesPaddingNull, output_buf);
100 }
101 
102 /**
103  * Convenience function to encrypt the test plaintext.
104  *
105  * The salt should be exactly `kSaltNumWords` words long; the output buffer
106  * should match the size of `kAesPlaintextBlock`.
107  *
108  * @param salt Key salt to use.
109  * @param[out] ciphertext Resulting encrypted output.
110  * @return OK or error.
111  */
112 static status_t encrypt(const uint32_t *salt, uint32_t *ciphertext) {
113  return run_aes(kOtcryptoAesOperationEncrypt, salt, kAesPlaintextBlock,
114  ciphertext);
115 }
116 
117 /**
118  * Convenience function to decrypt ciphertext.
119  *
120  * The salt should be exactly `kSaltNumWords` words long; the plaintext and
121  * ciphertext buffers should both match the size of `kAesPlaintextBlock`.
122  *
123  * @param salt Key salt to use.
124  * @param ciphertext Encrypted message.
125  * @param[out] plaintext Resulting decrypted output.
126  * @return OK or error.
127  */
128 static status_t decrypt(const uint32_t *salt, const uint32_t *ciphertext,
129  uint32_t *plaintext) {
130  return run_aes(kOtcryptoAesOperationDecrypt, salt, ciphertext, plaintext);
131 }
132 
133 /**
134  * Setup keymgr and entropy complex.
135  *
136  * Run this test before any others.
137  */
138 status_t test_setup(void) {
139  // Initialize the key manager and advance to OwnerRootKey state. Note: the
140  // keymgr testutils set this up using software entropy, so there is no need
141  // to initialize the entropy complex first. However, this is of course not
142  // the expected setup in production.
143  dif_keymgr_t keymgr;
144  dif_kmac_t kmac;
145  dif_keymgr_state_t keymgr_state;
146  TRY(keymgr_testutils_try_startup(&keymgr, &kmac, &keymgr_state));
147 
148  if (keymgr_state == kDifKeymgrStateCreatorRootKey) {
149  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
150  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
151  } else if (keymgr_state == kDifKeymgrStateOwnerIntermediateKey) {
152  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
153  }
154 
155  TRY(keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerRootKey));
156 
157  // Initialize entropy complex for cryptolib, which the key manager uses to
158  // clear sideloaded keys. The `keymgr_testutils_startup` function restarts
159  // the device, so this should happen afterwards.
160  return entropy_complex_init();
161 }
162 
163 /**
164  * Test that a sideloaded AES key can be used.
165  *
166  * Loads a sideloaded key, then runs encryption and decryption using the key.
167  */
168 status_t basic_encrypt_decrypt_test(void) {
169  // Encrypt the test plaintext.
170  uint32_t ciphertext1[ARRAYSIZE(kAesPlaintextBlock)];
171  TRY(encrypt(kKeySalt1, ciphertext1));
172 
173  // Decrypt the ciphertext.
174  uint32_t recovered_plaintext[ARRAYSIZE(kAesPlaintextBlock)];
175  TRY(decrypt(kKeySalt1, ciphertext1, recovered_plaintext));
176 
177  // Check that the recovered plaintext matches the original plaintext.
178  TRY_CHECK_ARRAYS_EQ(recovered_plaintext, kAesPlaintextBlock,
179  ARRAYSIZE(kAesPlaintextBlock));
180 
181  return OK_STATUS();
182 }
183 
184 /**
185  * Test that sideloaded AES keys are updated as expected.
186  *
187  * Different keys should produce different ciphertexts, and the same key
188  * should produce the same ciphertext.
189  */
190 status_t sideload_update_test(void) {
191  // Sideload the first key and encrypt the plaintext.
192  uint32_t ciphertext1[ARRAYSIZE(kAesPlaintextBlock)];
193  TRY(encrypt(kKeySalt1, ciphertext1));
194 
195  // Sideload the second key and encrypt the plaintext.
196  uint32_t ciphertext2[ARRAYSIZE(kAesPlaintextBlock)];
197  TRY(encrypt(kKeySalt2, ciphertext2));
198 
199  // Check that the ciphertexts are different.
200  TRY_CHECK_ARRAYS_NE(ciphertext1, ciphertext2, ARRAYSIZE(ciphertext1));
201 
202  // Sideload the first key again and encrypt the plaintext.
203  uint32_t ciphertext3[ARRAYSIZE(kAesPlaintextBlock)];
204  TRY(encrypt(kKeySalt1, ciphertext3));
205 
206  // Check that the ciphertexts are the same.
207  TRY_CHECK_ARRAYS_EQ(ciphertext1, ciphertext3, ARRAYSIZE(ciphertext1));
208 
209  return OK_STATUS();
210 }
211 
212 /**
213  * Test that sideloaded AES keys are properly cleared.
214  *
215  * Clearing a key should result in an invalid key error.
216  */
217 status_t sideload_clear_test(void) {
218  // Sideload the first key and encrypt the plaintext.
219  uint32_t ciphertext1[ARRAYSIZE(kAesPlaintextBlock)];
220  TRY(encrypt(kKeySalt1, ciphertext1));
221 
222  // Construct a mock key for the AES driver.
223  uint32_t share0[256 / 32] = {0};
224  uint32_t share1[256 / 32] = {0};
225  aes_key_t key = {
226  .mode = kAesCipherModeCtr,
227  .sideload = kHardenedBoolTrue,
228  .key_len = kAesKeyConfig.key_length,
229  .key_shares = {share0, share1},
230  };
231 
232  // Construct the IV.
233  aes_block_t iv;
234  memcpy(iv.data, kAesIv, sizeof(kAesIv));
235 
236  // Try to start another encryption operation using the AES driver directly,
237  // and expect an error because the sideloaded key is not present.
238  TRY_CHECK(!status_ok(aes_encrypt_begin(key, &iv)));
239 
240  return OK_STATUS();
241 }
242 
243 OTTF_DEFINE_TEST_CONFIG();
244 
245 bool test_main(void) {
246  static status_t result;
247 
248  CHECK_STATUS_OK(test_setup());
249  EXECUTE_TEST(result, basic_encrypt_decrypt_test);
250  EXECUTE_TEST(result, sideload_update_test);
251  EXECUTE_TEST(result, sideload_clear_test);
252 
253  return status_ok(result);
254 }