Software APIs
ecdh_p384_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/otbn.h"
6 #include "sw/device/lib/crypto/impl/keyblob.h"
9 #include "sw/device/lib/testing/entropy_testutils.h"
10 #include "sw/device/lib/testing/test_framework/check.h"
12 
13 enum {
14  /* Number of 32-bit words in a P-384 public key. */
15  kP384PublicKeyWords = 768 / 32,
16  /* Number of 32-bit words in a P-384 signature. */
17  kP384SignatureWords = 768 / 32,
18  /* Number of bytes in a P-384 private key. */
19  kP384PrivateKeyBytes = 384 / 8,
20  /* Number of bytes in an ECDH/P-384 shared key. */
21  kP384SharedKeyBytes = 384 / 8,
22  /* Number of 32-bit words in an ECDH/P-384 shared key. */
23  kP384SharedKeyWords = kP384SharedKeyBytes / sizeof(uint32_t),
24 };
25 
26 // Configuration for the private key.
27 static const otcrypto_key_config_t kEcdhPrivateKeyConfig = {
28  .version = kOtcryptoLibVersion1,
29  .key_mode = kOtcryptoKeyModeEcdhP384,
30  .key_length = kP384PrivateKeyBytes,
31  .hw_backed = kHardenedBoolFalse,
32  .security_level = kOtcryptoKeySecurityLevelLow,
33 };
34 
35 // Configuration for the ECDH shared (symmetric) key. This configuration
36 // specifies an AES key, but any symmetric mode that supports 384-bit keys is
37 // OK here.
38 static const otcrypto_key_config_t kEcdhSharedKeyConfig = {
39  .version = kOtcryptoLibVersion1,
40  .key_mode = kOtcryptoKeyModeAesCtr,
41  .key_length = kP384SharedKeyBytes,
42  .hw_backed = kHardenedBoolFalse,
43  .security_level = kOtcryptoKeySecurityLevelLow,
44 };
45 
46 status_t key_exchange_test(void) {
47  // Allocate space for two private keys.
48  uint32_t keyblobA[keyblob_num_words(kEcdhPrivateKeyConfig)];
49  otcrypto_blinded_key_t private_keyA = {
50  .config = kEcdhPrivateKeyConfig,
51  .keyblob_length = sizeof(keyblobA),
52  .keyblob = keyblobA,
53  .checksum = 0,
54  };
55  uint32_t keyblobB[keyblob_num_words(kEcdhPrivateKeyConfig)];
56  otcrypto_blinded_key_t private_keyB = {
57  .config = kEcdhPrivateKeyConfig,
58  .keyblob_length = sizeof(keyblobB),
59  .keyblob = keyblobB,
60  .checksum = 0,
61  };
62 
63  // Allocate space for two public keys.
64  uint32_t pkA[kP384PublicKeyWords] = {0};
65  uint32_t pkB[kP384PublicKeyWords] = {0};
66  otcrypto_unblinded_key_t public_keyA = {
67  .key_mode = kOtcryptoKeyModeEcdhP384,
68  .key_length = sizeof(pkA),
69  .key = pkA,
70  };
71  otcrypto_unblinded_key_t public_keyB = {
72  .key_mode = kOtcryptoKeyModeEcdhP384,
73  .key_length = sizeof(pkB),
74  .key = pkB,
75  };
76 
77  // Generate a keypair.
78  LOG_INFO("Generating keypair A...");
79  TRY(otcrypto_ecdh_p384_keygen(&private_keyA, &public_keyA));
80 
81  // Generate a second keypair.
82  LOG_INFO("Generating keypair B...");
83  TRY(otcrypto_ecdh_p384_keygen(&private_keyB, &public_keyB));
84 
85  // Sanity check; public keys should be different from each other.
86  CHECK_ARRAYS_NE(pkA, pkB, ARRAYSIZE(pkA));
87  // Sanity check; private keys should be different from each other.
88  CHECK_ARRAYS_NE(keyblobA, keyblobB, ARRAYSIZE(keyblobA));
89 
90  // Allocate space for two shared keys.
91  uint32_t shared_keyblobA[keyblob_num_words(kEcdhSharedKeyConfig)];
92  otcrypto_blinded_key_t shared_keyA = {
93  .config = kEcdhSharedKeyConfig,
94  .keyblob_length = sizeof(shared_keyblobA),
95  .keyblob = shared_keyblobA,
96  .checksum = 0,
97  };
98  uint32_t shared_keyblobB[keyblob_num_words(kEcdhSharedKeyConfig)];
99  otcrypto_blinded_key_t shared_keyB = {
100  .config = kEcdhSharedKeyConfig,
101  .keyblob_length = sizeof(shared_keyblobB),
102  .keyblob = shared_keyblobB,
103  .checksum = 0,
104  };
105 
106  // Compute the shared secret from A's side of the computation (using A's
107  // private key and B's public key).
108  LOG_INFO("Generating shared secret (A)...");
109  TRY(otcrypto_ecdh_p384(&private_keyA, &public_keyB, &shared_keyA));
110 
111  // Compute the shared secret from B's side of the computation (using B's
112  // private key and A's public key).
113  LOG_INFO("Generating shared secret (B)...");
114  TRY(otcrypto_ecdh_p384(&private_keyB, &public_keyA, &shared_keyB));
115 
116  // Get pointers to individual shares of both shared keys.
117  uint32_t *keyA0;
118  uint32_t *keyA1;
119  TRY(keyblob_to_shares(&shared_keyA, &keyA0, &keyA1));
120  uint32_t *keyB0;
121  uint32_t *keyB1;
122  TRY(keyblob_to_shares(&shared_keyB, &keyB0, &keyB1));
123 
124  // Unmask the keys and check that they match.
125  uint32_t keyA[kP384SharedKeyWords];
126  uint32_t keyB[kP384SharedKeyWords];
127  for (size_t i = 0; i < ARRAYSIZE(keyA); i++) {
128  keyA[i] = keyA0[i] ^ keyA1[i];
129  keyB[i] = keyB0[i] ^ keyB1[i];
130  }
131  CHECK_ARRAYS_EQ(keyA, keyB, ARRAYSIZE(keyA));
132 
133  return OTCRYPTO_OK;
134 }
135 
136 OTTF_DEFINE_TEST_CONFIG();
137 
138 bool test_main(void) {
139  CHECK_STATUS_OK(entropy_testutils_auto_mode_init());
140 
141  status_t err = key_exchange_test();
142  if (!status_ok(err)) {
143  // If there was an error, print the OTBN error bits and instruction count.
144  LOG_INFO("OTBN error bits: 0x%08x", otbn_err_bits_get());
145  LOG_INFO("OTBN instruction count: 0x%08x", otbn_instruction_count_get());
146  // Print the error.
147  CHECK_STATUS_OK(err);
148  return false;
149  }
150 
151  return true;
152 }