Software APIs
ecdsa_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/impl/keyblob.h"
12 #include "sw/device/lib/testing/keymgr_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
15 
16 // Module ID for status codes.
17 #define MODULE_ID MAKE_MODULE_ID('t', 's', 't')
18 
19 enum {
20  /* Number of 32-bit words in a P-256 public key. */
21  kP256PublicKeyWords = 512 / 32,
22  /* Number of 32-bit words in a P-256 signature. */
23  kP256SignatureWords = 512 / 32,
24  /* Number of bytes in a P-256 private key. */
25  kP256PrivateKeyBytes = 256 / 8,
26 };
27 
28 // Message
29 static const char kMessage[] = "test message";
30 
31 static const otcrypto_key_config_t kPrivateKeyConfig = {
32  .version = kOtcryptoLibVersion1,
33  .key_mode = kOtcryptoKeyModeEcdsaP256,
34  .key_length = kP256PrivateKeyBytes,
35  .hw_backed = kHardenedBoolTrue,
36  .security_level = kOtcryptoKeySecurityLevelLow,
37 };
38 
39 static const uint32_t kPrivateKeySalt[7] = {0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
40  0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
41  0xdeadbeef};
42 
43 static const uint32_t kPrivateKeyVersion = 0x0;
44 
45 status_t sign_then_verify_test(void) {
46  // Allocate space for a hardware-backed key.
47  uint32_t keyblob[keyblob_num_words(kPrivateKeyConfig)];
48  otcrypto_blinded_key_t private_key = {
49  .config = kPrivateKeyConfig,
50  .keyblob_length = sizeof(keyblob),
51  .keyblob = keyblob,
52  };
53 
54  // Construct the private key handle.
55  TRY(otcrypto_hw_backed_key(kPrivateKeyVersion, kPrivateKeySalt,
56  &private_key));
57 
58  // Allocate space for a public key.
59  uint32_t pk[kP256PublicKeyWords] = {0};
60  otcrypto_unblinded_key_t public_key = {
61  .key_mode = kOtcryptoKeyModeEcdsaP256,
62  .key_length = sizeof(pk),
63  .key = pk,
64  };
65 
66  // Generate a keypair.
67  LOG_INFO("Generating keypair...");
68  TRY(otcrypto_ecdsa_p256_keygen(&private_key, &public_key));
69 
70  // Hash the message.
71  otcrypto_const_byte_buf_t message = {
72  .len = sizeof(kMessage) - 1,
73  .data = (unsigned char *)&kMessage,
74  };
75  uint32_t message_digest_data[kSha256DigestWords];
76  otcrypto_hash_digest_t message_digest = {
77  .data = message_digest_data,
78  .len = ARRAYSIZE(message_digest_data),
79  .mode = kOtcryptoHashModeSha256,
80  };
81  TRY(otcrypto_hash(message, message_digest));
82 
83  // Allocate space for the signature.
84  uint32_t sig[kP256SignatureWords] = {0};
85 
86  // Generate a signature for the message.
87  LOG_INFO("Signing...");
88  CHECK_STATUS_OK(otcrypto_ecdsa_p256_sign(
89  &private_key, message_digest,
90  (otcrypto_word32_buf_t){.data = sig, .len = ARRAYSIZE(sig)}));
91 
92  // Verify the signature.
93  LOG_INFO("Verifying...");
94  hardened_bool_t verification_result;
95  CHECK_STATUS_OK(otcrypto_ecdsa_p256_verify(
96  &public_key, message_digest,
97  (otcrypto_const_word32_buf_t){.data = sig, .len = ARRAYSIZE(sig)},
98  &verification_result));
99 
100  // The signature should pass verification.
101  TRY_CHECK(verification_result == kHardenedBoolTrue);
102  return OK_STATUS();
103 }
104 
105 static status_t test_setup(void) {
106  // Initialize the key manager and advance to OwnerRootKey state. Note: the
107  // keymgr testutils set this up using software entropy, so there is no need
108  // to initialize the entropy complex first. However, this is of course not
109  // the expected setup in production.
110  dif_keymgr_t keymgr;
111  dif_kmac_t kmac;
112  dif_keymgr_state_t keymgr_state;
113  TRY(keymgr_testutils_try_startup(&keymgr, &kmac, &keymgr_state));
114 
115  if (keymgr_state == kDifKeymgrStateCreatorRootKey) {
116  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
117  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
118  } else if (keymgr_state == kDifKeymgrStateOwnerIntermediateKey) {
119  TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerRootKeyParams));
120  }
121 
122  TRY(keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerRootKey));
123 
124  // Initialize entropy complex for cryptolib, which the key manager uses to
125  // clear sideloaded keys. The `keymgr_testutils_startup` function restarts
126  // the device, so this should happen afterwards.
127  return entropy_complex_init();
128 }
129 
130 OTTF_DEFINE_TEST_CONFIG();
131 
132 bool test_main(void) {
133  status_t result = OK_STATUS();
134 
135  CHECK_STATUS_OK(test_setup());
136  EXECUTE_TEST(result, sign_then_verify_test);
137 
138  return status_ok(result);
139 }