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