Software APIs
dice.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/silicon_creator/lib/cert/dice.h"
6 
7 #include <stdint.h>
8 
10 #include "sw/device/lib/testing/test_framework/check.h"
11 #include "sw/device/silicon_creator/lib/base/util.h"
12 #include "sw/device/silicon_creator/lib/cert/cdi_0.h" // Generated.
13 #include "sw/device/silicon_creator/lib/cert/cdi_1.h" // Generated.
14 #include "sw/device/silicon_creator/lib/cert/cert.h"
15 #include "sw/device/silicon_creator/lib/cert/dice_keys.h"
16 #include "sw/device/silicon_creator/lib/cert/template.h"
17 #include "sw/device/silicon_creator/lib/cert/uds.h" // Generated.
18 #include "sw/device/silicon_creator/lib/drivers/hmac.h"
19 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
20 #include "sw/device/silicon_creator/lib/error.h"
21 #include "sw/device/silicon_creator/lib/otbn_boot_services.h"
22 #include "sw/device/silicon_creator/lib/ownership/datatypes.h"
23 #include "sw/device/silicon_creator/lib/sigverify/ecdsa_p256_key.h"
24 #include "sw/device/silicon_creator/manuf/base/perso_tlv_data.h"
25 #include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
26 
27 static ecdsa_p256_signature_t curr_tbs_signature = {.r = {0}, .s = {0}};
28 
29 static uint8_t cdi_0_tbs_buffer[kCdi0MaxTbsSizeBytes];
30 static uint8_t cdi_1_tbs_buffer[kCdi1MaxTbsSizeBytes];
31 
32 const dice_cert_format_t kDiceCertFormat = kDiceCertFormatX509TcbInfo;
33 
34 static_assert(kDiceMeasurementSizeInBytes == 32,
35  "The DICE attestation measurement size should equal the size of "
36  "the keymgr binding registers.");
37 
38 /**
39  * Returns true if debug (JTAG) access is exposed in the current LC state.
40  */
41 static bool is_debug_exposed(void) {
42  lifecycle_state_t lc_state = lifecycle_state_get();
43  if (lc_state == kLcStateProd || lc_state == kLcStateProdEnd) {
44  return false;
45  }
46  return true;
47 }
48 
49 /**
50  * Returns true if the OwnerSw is booting outside of prod ladder.
51  */
52 static bool get_debug_mode_cdi1(owner_app_domain_t key_domain) {
53  if (launder32(key_domain) != kOwnerAppDomainProd) {
54  return true;
55  }
56  HARDENED_CHECK_EQ(key_domain, kOwnerAppDomainProd);
57  return false;
58 }
59 
60 rom_error_t dice_uds_tbs_cert_build(
61  hmac_digest_t *otp_creator_sw_cfg_measurement,
62  hmac_digest_t *otp_owner_sw_cfg_measurement,
63  hmac_digest_t *otp_rot_creator_auth_codesign_measurement,
64  hmac_digest_t *otp_rot_creator_auth_state_measurement,
65  cert_key_id_pair_t *key_ids, ecdsa_p256_public_key_t *uds_pubkey,
66  uint8_t *tbs_cert, size_t *tbs_cert_size) {
67  // Generate the TBS certificate.
68  uds_tbs_values_t uds_tbs_params = {0};
69 
70  TEMPLATE_SET(uds_tbs_params, Uds, OtpCreatorSwCfgHash,
71  otp_creator_sw_cfg_measurement->digest);
72  TEMPLATE_SET(uds_tbs_params, Uds, OtpOwnerSwCfgHash,
73  otp_owner_sw_cfg_measurement->digest);
74  TEMPLATE_SET(uds_tbs_params, Uds, OtpRotCreatorAuthCodesignHash,
75  otp_rot_creator_auth_codesign_measurement->digest);
76  TEMPLATE_SET(uds_tbs_params, Uds, OtpRotCreatorAuthStateHash,
77  otp_rot_creator_auth_state_measurement->digest);
78  TEMPLATE_SET(uds_tbs_params, Uds, DebugFlag, is_debug_exposed());
79  TEMPLATE_SET(uds_tbs_params, Uds, CreatorPubKeyEcX, uds_pubkey->x);
80  TEMPLATE_SET(uds_tbs_params, Uds, CreatorPubKeyEcY, uds_pubkey->y);
81 
82  TEMPLATE_SET_TRUNCATED(uds_tbs_params, Uds, CreatorPubKeyId,
83  key_ids->cert->digest, kCertKeyIdSizeInBytes);
84  TEMPLATE_SET_TRUNCATED(uds_tbs_params, Uds, AuthKeyKeyId,
85  key_ids->endorsement->digest, kCertKeyIdSizeInBytes);
86 
87  HARDENED_RETURN_IF_ERROR(
88  uds_build_tbs(&uds_tbs_params, tbs_cert, tbs_cert_size));
89 
90  return kErrorOk;
91 }
92 
93 rom_error_t dice_cdi_0_cert_build(hmac_digest_t *rom_ext_measurement,
94  uint32_t rom_ext_security_version,
95  cert_key_id_pair_t *key_ids,
96  ecdsa_p256_public_key_t *cdi_0_pubkey,
97  uint8_t *cert, size_t *cert_size) {
98  uint32_t rom_ext_security_version_be =
99  __builtin_bswap32(rom_ext_security_version);
100  hmac_digest_t rom_ext_hash = *rom_ext_measurement;
101  util_reverse_bytes(&rom_ext_hash, sizeof(rom_ext_hash));
102 
103  // Generate the TBS certificate.
104  cdi_0_tbs_values_t cdi_0_tbs_params = {0};
105 
106  TEMPLATE_SET(cdi_0_tbs_params, Cdi0, RomExtHash, rom_ext_hash.digest);
107  TEMPLATE_SET(cdi_0_tbs_params, Cdi0, RomExtSecurityVersion,
108  &rom_ext_security_version_be);
109  TEMPLATE_SET(cdi_0_tbs_params, Cdi0, OwnerIntermediatePubKeyEcX,
110  cdi_0_pubkey->x);
111  TEMPLATE_SET(cdi_0_tbs_params, Cdi0, OwnerIntermediatePubKeyEcY,
112  cdi_0_pubkey->y);
113 
114  TEMPLATE_SET_TRUNCATED(cdi_0_tbs_params, Cdi0, OwnerIntermediatePubKeyId,
115  key_ids->cert->digest, kCertKeyIdSizeInBytes);
116  TEMPLATE_SET_TRUNCATED(cdi_0_tbs_params, Cdi0, CreatorPubKeyId,
117  key_ids->endorsement->digest, kCertKeyIdSizeInBytes);
118 
119  size_t tbs_size = kCdi0MaxTbsSizeBytes;
120  HARDENED_RETURN_IF_ERROR(
121  cdi_0_build_tbs(&cdi_0_tbs_params, cdi_0_tbs_buffer, &tbs_size));
122 
123  // Sign the TBS and generate the certificate.
124  hmac_digest_t tbs_digest;
125  hmac_sha256(cdi_0_tbs_buffer, tbs_size, &tbs_digest);
126  HARDENED_RETURN_IF_ERROR(
127  otbn_boot_attestation_endorse(&tbs_digest, &curr_tbs_signature));
128  util_p256_signature_le_to_be_convert(curr_tbs_signature.r,
129  curr_tbs_signature.s);
130 
131  cdi_0_sig_values_t cdi_0_params = {0};
132  TEMPLATE_SET(cdi_0_params, Cdi0, Tbs, cdi_0_tbs_buffer);
133  // Asserts that tbs is fixed-length, so we don't need to set tbs_size.
134  TEMPLATE_ASSERT_FIXED_LENGTH(Cdi0, Tbs);
135  TEMPLATE_SET(cdi_0_params, Cdi0, CertSignatureR, curr_tbs_signature.r);
136  TEMPLATE_SET(cdi_0_params, Cdi0, CertSignatureS, curr_tbs_signature.s);
137 
138  HARDENED_RETURN_IF_ERROR(cdi_0_build_cert(&cdi_0_params, cert, cert_size));
139 
140  // Save the CDI_0 private key to OTBN DMEM so it can endorse the next stage.
141  HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_key_save(
142  kDiceKeyCdi0.keygen_seed_idx, kDiceKeyCdi0.type,
143  *kDiceKeyCdi0.keymgr_diversifier));
144 
145  return kErrorOk;
146 }
147 
148 rom_error_t dice_cdi_1_cert_build(hmac_digest_t *owner_measurement,
149  hmac_digest_t *owner_manifest_measurement,
150  uint32_t owner_security_version,
151  owner_app_domain_t key_domain,
152  cert_key_id_pair_t *key_ids,
153  ecdsa_p256_public_key_t *cdi_1_pubkey,
154  uint8_t *cert, size_t *cert_size) {
155  uint32_t owner_security_version_be =
156  __builtin_bswap32(owner_security_version);
157  hmac_digest_t owner_hash = *owner_measurement;
158  hmac_digest_t owner_manifest_hash = *owner_manifest_measurement;
159  util_reverse_bytes(&owner_hash, sizeof(owner_hash));
160  util_reverse_bytes(&owner_manifest_hash, sizeof(owner_manifest_hash));
161 
162  // Generate the TBS certificate.
163  cdi_1_tbs_values_t cdi_1_tbs_params = {0};
164 
165  TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerHash, owner_hash.digest);
166  TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerManifestHash,
167  owner_manifest_hash.digest);
168  TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerSecurityVersion,
169  &owner_security_version_be);
170  TEMPLATE_SET(cdi_1_tbs_params, Cdi1, DebugFlag,
171  get_debug_mode_cdi1(key_domain));
172  TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerPubKeyEcX, cdi_1_pubkey->x);
173  TEMPLATE_SET(cdi_1_tbs_params, Cdi1, OwnerPubKeyEcY, cdi_1_pubkey->y);
174 
175  TEMPLATE_SET_TRUNCATED(cdi_1_tbs_params, Cdi1, OwnerPubKeyId,
176  key_ids->cert->digest, kCertKeyIdSizeInBytes);
177  TEMPLATE_SET_TRUNCATED(cdi_1_tbs_params, Cdi1, OwnerIntermediatePubKeyId,
178  key_ids->endorsement->digest, kCertKeyIdSizeInBytes);
179 
180  size_t tbs_size = kCdi1MaxTbsSizeBytes;
181  HARDENED_RETURN_IF_ERROR(
182  cdi_1_build_tbs(&cdi_1_tbs_params, cdi_1_tbs_buffer, &tbs_size));
183 
184  // Sign the TBS and generate the certificate.
185  hmac_digest_t tbs_digest;
186  hmac_sha256(cdi_1_tbs_buffer, tbs_size, &tbs_digest);
187  HARDENED_RETURN_IF_ERROR(
188  otbn_boot_attestation_endorse(&tbs_digest, &curr_tbs_signature));
189  util_p256_signature_le_to_be_convert(curr_tbs_signature.r,
190  curr_tbs_signature.s);
191 
192  cdi_1_sig_values_t cdi_1_params = {0};
193  TEMPLATE_SET(cdi_1_params, Cdi1, Tbs, cdi_1_tbs_buffer);
194  // Asserts that tbs is fixed-length, so we don't need to set tbs_size.
195  TEMPLATE_ASSERT_FIXED_LENGTH(Cdi1, Tbs);
196  TEMPLATE_SET(cdi_1_params, Cdi1, CertSignatureR, curr_tbs_signature.r);
197  TEMPLATE_SET(cdi_1_params, Cdi1, CertSignatureS, curr_tbs_signature.s);
198 
199  HARDENED_RETURN_IF_ERROR(cdi_1_build_cert(&cdi_1_params, cert, cert_size));
200 
201  // Save the CDI_1 private key to OTBN DMEM so it can endorse the next stage.
202  HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_key_save(
203  kDiceKeyCdi1.keygen_seed_idx, kDiceKeyCdi1.type,
204  *kDiceKeyCdi1.keymgr_diversifier));
205 
206  return kErrorOk;
207 }
208 
209 rom_error_t dice_cert_check_valid(const perso_tlv_cert_obj_t *cert_obj,
210  const hmac_digest_t *pubkey_id,
211  const ecdsa_p256_public_key_t *pubkey,
212  hardened_bool_t *cert_valid_output) {
213  // The function prototype is shared across X.509 and CWT cert formats.
214  // For X.509, we only check the serial_number but not public key contents.
215  OT_DISCARD(pubkey);
216 
217  // Assert the digest is not shorter then the key id before truncation.
218  static_assert(sizeof(pubkey_id->digest) >= sizeof(cert_key_id_t),
219  "Pubkey Id is too short.");
220 
221  return cert_x509_asn1_check_serial_number(
222  cert_obj->cert_body_p, cert_obj->cert_body_size,
223  (cert_key_id_t *)pubkey_id->digest, cert_valid_output);
224 }