Skip to content

Commit 8c33145

Browse files
siemen11cfrantz
authored andcommitted
[crypto/dice] Add dice attestation sign and keygen
The cryptolib needs a feature to recreate the CDI key from ROM_EXT without allowing Ibex direct read access to it. The cryptolib should get a keygen function to return the public attestation key and a sign function to sign with the attestation key. Currently, the ecc_p256_dice_functest simply generates the public key and performs a sign-then-verify operation. This was rerun several times to check the same public key is generated. However, in the future, this test needs to improve such that it checks the public key against the x509 cert from the ROM_EXT. Co-authored-by: Chris Frantz <cfrantz@google.com> Signed-off-by: Siemen Dhooghe <sdhooghe@google.com>
1 parent 6abbec1 commit 8c33145

15 files changed

Lines changed: 606 additions & 22 deletions

File tree

sw/device/lib/crypto/drivers/keymgr.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,19 +125,17 @@ static status_t keymgr_wait_until_done(void) {
125125
/**
126126
* Set the control register of the key manager.
127127
*
128-
* The CDI select bit is always set to false for this driver (i.e. Sealing
129-
* CDI). The driver does not support attestation CDI.
130-
*
131128
* @param dest (NONE, AES, OTBN, or KMAC)
132129
* @param operation (GENERATE_SW or GENERATE_HW)
130+
* @param attestation (true, false)
133131
*/
134-
#define WRITE_CTRL(dest, operation) \
132+
#define WRITE_CTRL(dest, operation, attestation) \
135133
do { \
136134
uint32_t ctrl = \
137135
bitfield_field32_write(0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD, \
138136
KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_##dest); \
139137
ctrl = bitfield_bit32_write(ctrl, KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT, \
140-
false); \
138+
attestation); \
141139
ctrl = bitfield_field32_write( \
142140
ctrl, KEYMGR_CONTROL_SHADOWED_OPERATION_FIELD, \
143141
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_##operation##_OUTPUT); \
@@ -150,14 +148,15 @@ static status_t keymgr_wait_until_done(void) {
150148
*
151149
* @param dest (NONE, AES, OTBN, or KMAC)
152150
* @param operation (GENERATE_SW or GENERATE_HW)
151+
* @param attestation (true, false)
153152
*/
154-
#define VERIFY_CTRL(dest, operation) \
153+
#define VERIFY_CTRL(dest, operation, attestation) \
155154
do { \
156155
uint32_t ctrl = \
157156
bitfield_field32_write(0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD, \
158157
KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_##dest); \
159158
ctrl = bitfield_bit32_write(ctrl, KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT, \
160-
false); \
159+
attestation); \
161160
ctrl = bitfield_field32_write( \
162161
ctrl, KEYMGR_CONTROL_SHADOWED_OPERATION_FIELD, \
163162
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_##operation##_OUTPUT); \
@@ -173,14 +172,14 @@ status_t keymgr_generate_key_sw(keymgr_diversification_t diversification,
173172
HARDENED_TRY(keymgr_is_idle());
174173

175174
// Set the control register to generate a software-visible key.
176-
WRITE_CTRL(NONE, GENERATE_SW);
175+
WRITE_CTRL(NONE, GENERATE_SW, false);
177176

178177
// Start the operation and wait for it to complete.
179178
HARDENED_TRY(keymgr_start(diversification));
180179
HARDENED_TRY(keymgr_wait_until_done());
181180

182181
// Check the control register.
183-
VERIFY_CTRL(NONE, GENERATE_SW);
182+
VERIFY_CTRL(NONE, GENERATE_SW, false);
184183

185184
// Collect the output. To avoid side-channel lekage, first randomize the
186185
// destination buffers using memshred. Then copy the key using a hardened
@@ -203,13 +202,13 @@ status_t keymgr_generate_key_aes(keymgr_diversification_t diversification) {
203202
HARDENED_TRY(keymgr_is_idle());
204203

205204
// Set the control register to generate an AES key.
206-
WRITE_CTRL(AES, GENERATE_HW);
205+
WRITE_CTRL(AES, GENERATE_HW, false);
207206

208207
// Start the operation and wait for it to complete.
209208
HARDENED_TRY(keymgr_start(diversification));
210209
HARDENED_TRY(keymgr_wait_until_done());
211210
// Check the control register.
212-
VERIFY_CTRL(AES, GENERATE_HW);
211+
VERIFY_CTRL(AES, GENERATE_HW, false);
213212

214213
return OTCRYPTO_OK;
215214
}
@@ -220,29 +219,50 @@ status_t keymgr_generate_key_kmac(keymgr_diversification_t diversification) {
220219
HARDENED_TRY(keymgr_is_idle());
221220

222221
// Set the control register to generate a KMAC key.
223-
WRITE_CTRL(KMAC, GENERATE_HW);
222+
WRITE_CTRL(KMAC, GENERATE_HW, false);
224223

225224
// Start the operation and wait for it to complete.
226225
HARDENED_TRY(keymgr_start(diversification));
227226
HARDENED_TRY(keymgr_wait_until_done());
228227
// Check the control register.
229-
VERIFY_CTRL(KMAC, GENERATE_HW);
228+
VERIFY_CTRL(KMAC, GENERATE_HW, false);
230229
return OTCRYPTO_OK;
231230
}
232231

233-
status_t keymgr_generate_key_otbn(keymgr_diversification_t diversification) {
232+
status_t keymgr_generate_key_otbn(keymgr_diversification_t diversification,
233+
hardened_bool_t attestation) {
234234
// Ensure that the entropy complex has been initialized and keymgr is idle.
235235
HARDENED_TRY(entropy_complex_check());
236236
HARDENED_TRY(keymgr_is_idle());
237237

238238
// Set the control register to generate an OTBN key.
239-
WRITE_CTRL(OTBN, GENERATE_HW);
239+
switch (attestation) {
240+
case kHardenedBoolFalse:
241+
WRITE_CTRL(OTBN, GENERATE_HW, false);
242+
break;
243+
case kHardenedBoolTrue:
244+
WRITE_CTRL(OTBN, GENERATE_HW, true);
245+
break;
246+
default:
247+
HARDENED_TRAP();
248+
return OTCRYPTO_FATAL_ERR;
249+
}
240250

241251
// Start the operation and wait for it to complete.
242252
HARDENED_TRY(keymgr_start(diversification));
243253
HARDENED_TRY(keymgr_wait_until_done());
244254
// Check the control register.
245-
VERIFY_CTRL(OTBN, GENERATE_HW);
255+
switch (attestation) {
256+
case kHardenedBoolFalse:
257+
VERIFY_CTRL(OTBN, GENERATE_HW, false);
258+
break;
259+
case kHardenedBoolTrue:
260+
VERIFY_CTRL(OTBN, GENERATE_HW, true);
261+
break;
262+
default:
263+
HARDENED_TRAP();
264+
return OTCRYPTO_FATAL_ERR;
265+
}
246266
return OTCRYPTO_OK;
247267
}
248268

sw/device/lib/crypto/drivers/keymgr.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,13 @@ status_t keymgr_generate_key_kmac(
9595
* waits until the operation is complete before returning.
9696
*
9797
* @param diversification Diversification input for the key derivation.
98+
* @param attestation Whether to use the DICE key.
9899
* @return OK or error.
99100
*/
100101
OT_WARN_UNUSED_RESULT
101102
status_t keymgr_generate_key_otbn(
102-
const keymgr_diversification_t diversification);
103+
const keymgr_diversification_t diversification,
104+
hardened_bool_t attestation);
103105

104106
/**
105107
* Clear the sideloaded AES key.

sw/device/lib/crypto/drivers/keymgr_test.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,14 @@ status_t kmac_basic_test(void) {
7878
* Test generating a single sideloaded OTBN key.
7979
*/
8080
status_t otbn_basic_test(void) {
81-
return keymgr_generate_key_otbn(kTestDiversification);
81+
return keymgr_generate_key_otbn(kTestDiversification, kHardenedBoolFalse);
82+
}
83+
84+
/**
85+
* Test generating a single sideloaded OTBN CDI key.
86+
*/
87+
status_t otbn_basic_cdi_test(void) {
88+
return keymgr_generate_key_otbn(kTestDiversification, kHardenedBoolTrue);
8289
}
8390

8491
/**
@@ -212,6 +219,7 @@ bool test_main(void) {
212219
EXECUTE_TEST(result, aes_basic_test);
213220
EXECUTE_TEST(result, kmac_basic_test);
214221
EXECUTE_TEST(result, otbn_basic_test);
222+
EXECUTE_TEST(result, otbn_basic_cdi_test);
215223
EXECUTE_TEST(result, run_negative_test);
216224

217225
return status_ok(result);

sw/device/lib/crypto/impl/ecc/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ cc_library(
3333
"//sw/device/lib/base:hardened_memory",
3434
"//sw/device/lib/crypto/drivers:otbn",
3535
"//sw/device/lib/crypto/drivers:rv_core_ibex",
36+
"//sw/device/lib/crypto/impl:integrity",
3637
"//sw/device/lib/crypto/impl:status",
3738
"//sw/otbn/crypto:run_p256",
3839
],

sw/device/lib/crypto/impl/ecc/p256.c

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "sw/device/lib/base/hardened.h"
99
#include "sw/device/lib/base/hardened_memory.h"
1010
#include "sw/device/lib/crypto/drivers/otbn.h"
11+
#include "sw/device/lib/crypto/include/integrity.h"
1112

1213
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
1314

@@ -31,6 +32,9 @@ OTBN_DECLARE_SYMBOL_ADDR(run_p256, k0_io); // Secret scalar k (share 0).
3132
OTBN_DECLARE_SYMBOL_ADDR(run_p256, k1_io); // Secret scalar k (share 1).
3233
OTBN_DECLARE_SYMBOL_ADDR(run_p256, x_r); // ECDSA verification result.
3334
OTBN_DECLARE_SYMBOL_ADDR(run_p256, ok); // Status code.
35+
OTBN_DECLARE_SYMBOL_ADDR(
36+
run_p256,
37+
attestation_additional_seed); // Additional seed for attestation keygen.
3438

3539
static const otbn_addr_t kOtbnVarMode = OTBN_ADDR_T_INIT(run_p256, mode);
3640
static const otbn_addr_t kOtbnVarMsg = OTBN_ADDR_T_INIT(run_p256, msg);
@@ -44,6 +48,8 @@ static const otbn_addr_t kOtbnVarK0 = OTBN_ADDR_T_INIT(run_p256, k0_io);
4448
static const otbn_addr_t kOtbnVarK1 = OTBN_ADDR_T_INIT(run_p256, k1_io);
4549
static const otbn_addr_t kOtbnVarXr = OTBN_ADDR_T_INIT(run_p256, x_r);
4650
static const otbn_addr_t kOtbnVarOk = OTBN_ADDR_T_INIT(run_p256, ok);
51+
static const otbn_addr_t kOtbnVarBootAttestationAdditionalSeed =
52+
OTBN_ADDR_T_INIT(run_p256, attestation_additional_seed);
4753

4854
// Declare mode constants.
4955
OTBN_DECLARE_SYMBOL_ADDR(run_p256, MODE_KEYGEN);
@@ -99,12 +105,12 @@ enum {
99105
* The expected instruction counts for constant time functions.
100106
*/
101107
kModeKeygenInsCnt = 573915,
102-
kModeKeygenSideloadInsCnt = 573800,
108+
kModeKeygenSideloadInsCnt = 573807,
103109
kModeEcdhInsCnt = 581600,
104-
kModeEcdhSideloadInsCnt = 581658,
110+
kModeEcdhSideloadInsCnt = 581665,
105111
kModeEcdsaSignConfigKInsCnt = 606939,
106112
kModeEcdsaSignInsCnt = 607089,
107-
kModeEcdsaSignSideloadInsCnt = 607147,
113+
kModeEcdsaSignSideloadInsCnt = 607154,
108114
kModePointOnCurveCheckInsCnt = 224,
109115
kModeBasePointMultInsCnt = 573749,
110116
kModeShareSecretKeyInsCnt = 147,
@@ -188,6 +194,36 @@ status_t p256_sideload_keygen_start(void) {
188194
// Set mode so start() will jump into sideload-keygen.
189195
uint32_t mode = kOtbnP256ModeSideloadKeygen;
190196
HARDENED_TRY(otbn_dmem_write(kOtbnP256ModeWords, &mode, kOtbnVarMode));
197+
// No attestation seed is used.
198+
HARDENED_TRY(otbn_dmem_set(kDiceAttestationMaxSeedLength, 0,
199+
kOtbnVarBootAttestationAdditionalSeed));
200+
201+
// Start the OTBN routine.
202+
return otbn_execute();
203+
}
204+
205+
status_t p256_sideload_attestation_keygen_start(
206+
otcrypto_const_word32_buf_t *attestation_seed) {
207+
if (launder32(attestation_seed->len) > kDiceAttestationMaxSeedLength) {
208+
return OTCRYPTO_BAD_ARGS;
209+
}
210+
211+
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(attestation_seed));
212+
213+
// Load the P-256 app. Fails if OTBN is non-idle.
214+
HARDENED_TRY(otbn_load_app(kOtbnAppP256));
215+
216+
// Set mode so start() will jump into sideload-keygen.
217+
uint32_t mode = kOtbnP256ModeSideloadKeygen;
218+
HARDENED_TRY(otbn_dmem_write(kOtbnP256ModeWords, &mode, kOtbnVarMode));
219+
220+
HARDENED_TRY(otbn_dmem_write(attestation_seed->len, attestation_seed->data,
221+
kOtbnVarBootAttestationAdditionalSeed));
222+
// Pad the remainder by zeros.
223+
HARDENED_TRY(
224+
otbn_dmem_set(kDiceAttestationMaxSeedLength - attestation_seed->len, 0,
225+
kOtbnVarBootAttestationAdditionalSeed +
226+
attestation_seed->len * sizeof(uint32_t)));
191227

192228
// Start the OTBN routine.
193229
return otbn_execute();
@@ -309,6 +345,9 @@ status_t p256_ecdsa_sideload_sign_start(
309345
// Set mode so start() will jump into sideloaded signing.
310346
uint32_t mode = kOtbnP256ModeSideloadSign;
311347
HARDENED_TRY(otbn_dmem_write(kOtbnP256ModeWords, &mode, kOtbnVarMode));
348+
// No attestation seed is used.
349+
HARDENED_TRY(otbn_dmem_set(kDiceAttestationMaxSeedLength, 0,
350+
kOtbnVarBootAttestationAdditionalSeed));
312351

313352
// Set the message digest.
314353
HARDENED_TRY(set_message_digest(digest));
@@ -317,6 +356,37 @@ status_t p256_ecdsa_sideload_sign_start(
317356
return otbn_execute();
318357
}
319358

359+
status_t p256_sideload_attestation_sign_start(
360+
const uint32_t digest[kP256ScalarWords],
361+
otcrypto_const_word32_buf_t *attestation_seed) {
362+
if (launder32(attestation_seed->len) > kDiceAttestationMaxSeedLength) {
363+
return OTCRYPTO_BAD_ARGS;
364+
}
365+
HARDENED_CHECK_EQ(kHardenedBoolTrue, OTCRYPTO_CHECK_BUF(attestation_seed));
366+
367+
// Load the P-256 app. Fails if OTBN is non-idle.
368+
HARDENED_TRY(otbn_load_app(kOtbnAppP256));
369+
370+
// Set mode so start() will jump into sideloaded signing.
371+
uint32_t mode = kOtbnP256ModeSideloadSign;
372+
HARDENED_TRY(otbn_dmem_write(kOtbnP256ModeWords, &mode, kOtbnVarMode));
373+
374+
// Set the message digest.
375+
HARDENED_TRY(set_message_digest(digest));
376+
377+
// Write the attestation seed to the extra variables area.
378+
HARDENED_TRY(otbn_dmem_write(attestation_seed->len, attestation_seed->data,
379+
kOtbnVarBootAttestationAdditionalSeed));
380+
// Pad the remainder by zeros.
381+
HARDENED_TRY(
382+
otbn_dmem_set(kDiceAttestationMaxSeedLength - attestation_seed->len, 0,
383+
kOtbnVarBootAttestationAdditionalSeed +
384+
attestation_seed->len * sizeof(uint32_t)));
385+
386+
// Start the OTBN routine.
387+
return otbn_execute();
388+
}
389+
320390
status_t p256_ecdsa_sign_finalize(p256_ecdsa_signature_t *result) {
321391
uint32_t ins_cnt;
322392
// Spin here waiting for OTBN to complete.
@@ -472,6 +542,10 @@ status_t p256_sideload_ecdh_start(const p256_point_t *public_key) {
472542
// Set the public key y coordinate.
473543
HARDENED_TRY(otbn_dmem_write(kP256CoordWords, public_key->y, kOtbnVarY));
474544

545+
// No attestation seed is used.
546+
HARDENED_TRY(otbn_dmem_set(kDiceAttestationMaxSeedLength, 0,
547+
kOtbnVarBootAttestationAdditionalSeed));
548+
475549
// Start the OTBN routine.
476550
return otbn_execute();
477551
}

sw/device/lib/crypto/impl/ecc/p256.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ enum {
7373
*/
7474
kP256MaskedScalarTotalShareWords =
7575
kP256MaskedScalarNumShares * kP256MaskedScalarShareWords,
76+
/**
77+
* Maximum length of the attestation seed for the CDI key.
78+
*/
79+
kDiceAttestationMaxSeedLength = 512 / 32,
7680
};
7781

7882
/**
@@ -218,6 +222,20 @@ status_t p256_keygen_finalize(p256_masked_scalar_t *private_key,
218222
OT_WARN_UNUSED_RESULT
219223
status_t p256_sideload_keygen_start(void);
220224

225+
/**
226+
* Start an async P-256 sideloaded keypair generation operation with the CDI
227+
* secret on OTBN.
228+
*
229+
* Expects a sideloaded key from keymgr to be already loaded on OTBN. Returns
230+
* an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
231+
*
232+
* @param attestation_seed The additional per-chip fixed entropy.
233+
* @return Result of the operation (OK or error).
234+
*/
235+
OT_WARN_UNUSED_RESULT
236+
status_t p256_sideload_attestation_keygen_start(
237+
otcrypto_const_word32_buf_t *attestation_seed);
238+
221239
/**
222240
* Finish an async P-256 sideloaded keypair generation operation on OTBN.
223241
*
@@ -282,6 +300,22 @@ OT_WARN_UNUSED_RESULT
282300
status_t p256_ecdsa_sideload_sign_start(
283301
const uint32_t digest[kP256ScalarWords]);
284302

303+
/**
304+
* Start an async ECDSA/P-256 signature generation operation on OTBN with the
305+
* CDI key.
306+
*
307+
* Expects a sideloaded key from keymgr to be already loaded on OTBN. Returns
308+
* an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
309+
*
310+
* @param digest Digest of the message to sign.
311+
* @param attestation_seed The additional per-chip fixed entropy.
312+
* @return Result of the operation (OK or error).
313+
*/
314+
OT_WARN_UNUSED_RESULT
315+
status_t p256_sideload_attestation_sign_start(
316+
const uint32_t digest[kP256ScalarWords],
317+
otcrypto_const_word32_buf_t *attestation_seed);
318+
285319
/**
286320
* Finish an async ECDSA/P-256 signature generation operation on OTBN.
287321
*

0 commit comments

Comments
 (0)