Software APIs
ecdh_p256_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 
5 #include "sw/device/lib/crypto/drivers/entropy.h"
6 #include "sw/device/lib/crypto/drivers/otbn.h"
7 #include "sw/device/lib/crypto/impl/integrity.h"
8 #include "sw/device/lib/crypto/impl/keyblob.h"
12 #include "sw/device/lib/testing/entropy_testutils.h"
13 #include "sw/device/lib/testing/keymgr_testutils.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
16 
17 // Module ID for status codes.
18 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
19 
20 enum {
21  /* Number of 32-bit words in a P-256 public key. */
22  kP256PublicKeyWords = 512 / 32,
23  /* Number of 32-bit words in a P-256 signature. */
24  kP256SignatureWords = 512 / 32,
25  /* Number of bytes in a P-256 private key. */
26  kP256PrivateKeyBytes = 256 / 8,
27  /* Number of bytes in an ECDH/P-256 shared key. */
28  kP256SharedKeyBytes = 256 / 8,
29  /* Number of 32-bit words in an ECDH/P-256 shared key. */
30  kP256SharedKeyWords = kP256SharedKeyBytes / sizeof(uint32_t),
31 };
32 
33 // Versions for private keys A and B.
34 static const uint32_t kPrivateKeyAVersion = 0;
35 static const uint32_t kPrivateKeyBVersion = 0;
36 
37 // Salt for private keys A and B.
38 static const uint32_t kPrivateKeyASalt[7] = {0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
39  0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
40  0xdeadbeef};
41 static const uint32_t kPrivateKeyBSalt[7] = {0xa0a1a2a3, 0xa4a5a6a7, 0xa8a9aaab,
42  0xacadaeaf, 0xb0b1b2b3, 0xb4b5b6b7,
43  0xb8b9babb};
44 
45 // Configuration for the private key.
46 static const otcrypto_key_config_t kEcdhPrivateKeyConfig = {
47  .version = kOtcryptoLibVersion1,
48  .key_mode = kOtcryptoKeyModeEcdhP256,
49  .key_length = kP256PrivateKeyBytes,
50  .hw_backed = kHardenedBoolTrue,
51  .security_level = kOtcryptoKeySecurityLevelLow,
52 };
53 
54 // Configuration for the ECDH shared (symmetric) key. This configuration
55 // specifies an AES key, but any symmetric mode that supports 256-bit keys is
56 // OK here.
57 static const otcrypto_key_config_t kEcdhSharedKeyConfig = {
58  .version = kOtcryptoLibVersion1,
59  .key_mode = kOtcryptoKeyModeAesCtr,
60  .key_length = kP256SharedKeyBytes,
61  .hw_backed = kHardenedBoolFalse,
62  .security_level = kOtcryptoKeySecurityLevelLow,
63 };
64 
65 status_t key_exchange_test(void) {
66  // Allocate space for two sideloaded private keys.
67  uint32_t keyblobA[keyblob_num_words(kEcdhPrivateKeyConfig)];
68  otcrypto_blinded_key_t private_keyA = {
69  .config = kEcdhPrivateKeyConfig,
70  .keyblob_length = sizeof(keyblobA),
71  .keyblob = keyblobA,
72  };
73  TRY(otcrypto_hw_backed_key(kPrivateKeyAVersion, kPrivateKeyASalt,
74  &private_keyA));
75  uint32_t keyblobB[keyblob_num_words(kEcdhPrivateKeyConfig)];
76  otcrypto_blinded_key_t private_keyB = {
77  .config = kEcdhPrivateKeyConfig,
78  .keyblob_length = sizeof(keyblobB),
79  .keyblob = keyblobB,
80  };
81  TRY(otcrypto_hw_backed_key(kPrivateKeyBVersion, kPrivateKeyBSalt,
82  &private_keyB));
83 
84  // Allocate space for two public keys.
85  uint32_t pkA[kP256PublicKeyWords] = {0};
86  uint32_t pkB[kP256PublicKeyWords] = {0};
87  otcrypto_unblinded_key_t public_keyA = {
88  .key_mode = kOtcryptoKeyModeEcdhP256,
89  .key_length = sizeof(pkA),
90  .key = pkA,
91  };
92  otcrypto_unblinded_key_t public_keyB = {
93  .key_mode = kOtcryptoKeyModeEcdhP256,
94  .key_length = sizeof(pkB),
95  .key = pkB,
96  };
97 
98  // Generate a keypair.
99  LOG_INFO("Generating keypair A...");
100  TRY(otcrypto_ecdh_p256_keygen(&private_keyA, &public_keyA));
101 
102  // Generate a second keypair.
103  LOG_INFO("Generating keypair B...");
104  TRY(otcrypto_ecdh_p256_keygen(&private_keyB, &public_keyB));
105 
106  // Sanity check; public keys should be different from each other.
107  CHECK_ARRAYS_NE(pkA, pkB, ARRAYSIZE(pkA));
108 
109  // Allocate space for two shared keys.
110  uint32_t shared_keyblobA[keyblob_num_words(kEcdhSharedKeyConfig)];
111  otcrypto_blinded_key_t shared_keyA = {
112  .config = kEcdhSharedKeyConfig,
113  .keyblob_length = sizeof(shared_keyblobA),
114  .keyblob = shared_keyblobA,
115  .checksum = 0,
116  };
117  uint32_t shared_keyblobB[keyblob_num_words(kEcdhSharedKeyConfig)];
118  otcrypto_blinded_key_t shared_keyB = {
119  .config = kEcdhSharedKeyConfig,
120  .keyblob_length = sizeof(shared_keyblobB),
121  .keyblob = shared_keyblobB,
122  .checksum = 0,
123  };
124 
125  // Compute the shared secret from A's side of the computation (using A's
126  // private key and B's public key).
127  LOG_INFO("Generating shared secret (A)...");
128  TRY(otcrypto_ecdh_p256(&private_keyA, &public_keyB, &shared_keyA));
129 
130  // Compute the shared secret from B's side of the computation (using B's
131  // private key and A's public key).
132  LOG_INFO("Generating shared secret (B)...");
133  TRY(otcrypto_ecdh_p256(&private_keyB, &public_keyA, &shared_keyB));
134 
135  // Get pointers to individual shares of both shared keys.
136  uint32_t *keyA0;
137  uint32_t *keyA1;
138  TRY(keyblob_to_shares(&shared_keyA, &keyA0, &keyA1));
139  uint32_t *keyB0;
140  uint32_t *keyB1;
141  TRY(keyblob_to_shares(&shared_keyB, &keyB0, &keyB1));
142 
143  // Unmask the keys and check that they match.
144  uint32_t keyA[kP256SharedKeyWords];
145  uint32_t keyB[kP256SharedKeyWords];
146  for (size_t i = 0; i < ARRAYSIZE(keyA); i++) {
147  keyA[i] = keyA0[i] ^ keyA1[i];
148  keyB[i] = keyB0[i] ^ keyB1[i];
149  }
150  CHECK_ARRAYS_EQ(keyA, keyB, ARRAYSIZE(keyA));
151 
152  return OTCRYPTO_OK;
153 }
154 
155 static status_t test_setup(void) {
156  // Initialize the key manager and advance to OwnerRootKey state. Note: the
157  // keymgr testutils set this up using software entropy, so there is no need
158  // to initialize the entropy complex first. However, this is of course not
159  // the expected setup in production.
160  dif_keymgr_t keymgr;
161  dif_kmac_t kmac;
162  dif_keymgr_state_t keymgr_state;
163  TRY(keymgr_testutils_try_startup(&keymgr, &kmac, &keymgr_state));
164 
165  if (keymgr_state == kDifKeymgrStateCreatorRootKey) {
166  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
167  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
168  } else if (keymgr_state == kDifKeymgrStateOwnerIntermediateKey) {
169  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
170  }
171 
172  TRY(keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerRootKey));
173 
174  // Initialize entropy complex for cryptolib, which the key manager uses to
175  // clear sideloaded keys. The `keymgr_testutils_startup` function restarts
176  // the device, so this should happen afterwards.
177  return entropy_complex_init();
178 }
179 
180 OTTF_DEFINE_TEST_CONFIG();
181 
182 bool test_main(void) {
183  status_t result = OK_STATUS();
184 
185  CHECK_STATUS_OK(test_setup());
186  EXECUTE_TEST(result, key_exchange_test);
187 
188  return status_ok(result);
189 }