Software APIs
ecdsa_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/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-384 public key. */
21  kP384PublicKeyWords = 768 / 32,
22  /* Number of 32-bit words in a P-384 signature. */
23  kP384SignatureWords = 768 / 32,
24  /* Number of bytes in a P-384 private key. */
25  kP384PrivateKeyBytes = 384 / 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 = kOtcryptoKeyModeEcdsaP384,
34  .key_length = kP384PrivateKeyBytes,
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[kP384PublicKeyWords] = {0};
60  otcrypto_unblinded_key_t public_key = {
61  .key_mode = kOtcryptoKeyModeEcdsaP384,
62  .key_length = sizeof(pk),
63  .key = pk,
64  };
65 
66  // Generate a keypair.
67  LOG_INFO("Generating keypair...");
68  CHECK_STATUS_OK(otcrypto_ecdsa_p384_keygen(&private_key, &public_key));
69 
70  // Hash the message.
72  .len = sizeof(kMessage) - 1,
73  .data = (unsigned char *)&kMessage,
74  };
75  uint32_t msg_digest_data[kSha384DigestWords];
76  otcrypto_hash_digest_t msg_digest = {
77  .data = msg_digest_data,
78  .len = ARRAYSIZE(msg_digest_data),
79  .mode = kOtcryptoHashModeSha384,
80  };
81  TRY(otcrypto_hash(msg, msg_digest));
82 
83  // Allocate space for the signature.
84  uint32_t sig[kP384SignatureWords] = {0};
85 
86  // Generate a signature for the message.
87  LOG_INFO("Signing...");
88  CHECK_STATUS_OK(otcrypto_ecdsa_p384_sign(
89  &private_key, msg_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_p384_verify(
96  &public_key, msg_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 OTCRYPTO_OK;
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 
140  return true;
141 }