Skip to content

Commit ccebaec

Browse files
h-filalinasahlpa
authored andcommitted
[cryptolib,sw] Add instruction count checks to ECC functions
This commit adds instruction count checks to ECC functions that run in constant time. This helps protect against fault injection. Signed-off-by: Hakim Filali <[email protected]> (cherry picked from commit efb425a)
1 parent 4187383 commit ccebaec

File tree

2 files changed

+32
-14
lines changed

2 files changed

+32
-14
lines changed

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

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ status_t p256_sideload_keygen_start(void) {
176176
status_t p256_keygen_finalize(p256_masked_scalar_t *private_key,
177177
p256_point_t *public_key) {
178178
// Spin here waiting for OTBN to complete.
179-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
179+
HARDENED_TRY(otbn_busy_wait_for_done());
180+
HARDENED_CHECK_EQ(otbn_instruction_count_get(), kModeKeygenInsCnt);
180181

181182
// Read the masked private key from OTBN dmem.
182183
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP256MaskedScalarShareWords, kOtbnVarD0,
@@ -199,7 +200,8 @@ status_t p256_keygen_finalize(p256_masked_scalar_t *private_key,
199200

200201
status_t p256_sideload_keygen_finalize(p256_point_t *public_key) {
201202
// Spin here waiting for OTBN to complete.
202-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
203+
HARDENED_TRY(otbn_busy_wait_for_done());
204+
HARDENED_CHECK_EQ(otbn_instruction_count_get(), kModeKeygenSideloadInsCnt);
203205

204206
// Read the public key from OTBN dmem.
205207
HARDENED_TRY_WIPE_DMEM(
@@ -273,8 +275,15 @@ status_t p256_ecdsa_sideload_sign_start(
273275
}
274276

275277
status_t p256_ecdsa_sign_finalize(p256_ecdsa_signature_t *result) {
278+
uint32_t ins_cnt;
276279
// Spin here waiting for OTBN to complete.
277-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
280+
HARDENED_TRY(otbn_busy_wait_for_done());
281+
ins_cnt = otbn_instruction_count_get();
282+
if (launder32(ins_cnt) == kModeEcdsaSignSideloadInsCnt) {
283+
HARDENED_CHECK_EQ(ins_cnt, kModeEcdsaSignSideloadInsCnt);
284+
} else {
285+
HARDENED_CHECK_EQ(ins_cnt, kModeEcdsaSignInsCnt);
286+
}
278287

279288
// Read signature R out of OTBN dmem.
280289
HARDENED_TRY_WIPE_DMEM(
@@ -370,7 +379,7 @@ status_t p256_ecdh_start(p256_masked_scalar_t *private_key,
370379

371380
status_t p256_ecdh_finalize(p256_ecdh_shared_key_t *shared_key) {
372381
// Spin here waiting for OTBN to complete.
373-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
382+
HARDENED_TRY(otbn_busy_wait_for_done());
374383

375384
// Read the code indicating if the public key is valid.
376385
uint32_t ok;

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,12 @@ enum {
9292
/*
9393
* The expected instruction counts for constant time functions.
9494
*/
95-
kModeKeygenInsCnt = 1899012,
96-
kModeKeygenSideloadInsCnt = 1898905,
97-
kModeEcdhInsCnt = 1910611,
98-
kModeEcdhSideloadInsCnt = 1910759,
99-
kModeEcdsaSignInsCnt = 1546541,
100-
kModeEcdsaSignSideloadInsCnt = 1546689,
95+
kModeKeygenInsCnt = 1935430,
96+
kModeKeygenSideloadInsCnt = 1935323,
97+
kModeEcdhInsCnt = 1947029,
98+
kModeEcdhSideloadInsCnt = 1947177,
99+
kModeEcdsaSignInsCnt = 1574769,
100+
kModeEcdsaSignSideloadInsCnt = 1574917,
101101
};
102102

103103
static status_t p384_masked_scalar_write(p384_masked_scalar_t *src,
@@ -217,7 +217,8 @@ status_t p384_keygen_start(void) {
217217
status_t p384_keygen_finalize(p384_masked_scalar_t *private_key,
218218
p384_point_t *public_key) {
219219
// Spin here waiting for OTBN to complete.
220-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
220+
HARDENED_TRY(otbn_busy_wait_for_done());
221+
HARDENED_CHECK_EQ(otbn_instruction_count_get(), kModeKeygenInsCnt);
221222

222223
// Read the masked private key from OTBN dmem.
223224
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP384MaskedScalarShareWords, kOtbnVarD0,
@@ -252,7 +253,8 @@ status_t p384_sideload_keygen_start(void) {
252253

253254
status_t p384_sideload_keygen_finalize(p384_point_t *public_key) {
254255
// Spin here waiting for OTBN to complete.
255-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
256+
HARDENED_TRY(otbn_busy_wait_for_done());
257+
HARDENED_CHECK_EQ(otbn_instruction_count_get(), kModeKeygenSideloadInsCnt);
256258

257259
// Read the public key from OTBN dmem.
258260
HARDENED_TRY_WIPE_DMEM(
@@ -302,8 +304,15 @@ status_t p384_ecdsa_sideload_sign_start(
302304
}
303305

304306
status_t p384_ecdsa_sign_finalize(p384_ecdsa_signature_t *result) {
307+
uint32_t ins_cnt;
305308
// Spin here waiting for OTBN to complete.
306-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
309+
HARDENED_TRY(otbn_busy_wait_for_done());
310+
ins_cnt = otbn_instruction_count_get();
311+
if (launder32(ins_cnt) == kModeEcdsaSignSideloadInsCnt) {
312+
HARDENED_CHECK_EQ(ins_cnt, kModeEcdsaSignSideloadInsCnt);
313+
} else {
314+
HARDENED_CHECK_EQ(ins_cnt, kModeEcdsaSignInsCnt);
315+
}
307316

308317
// Read signature R out of OTBN dmem.
309318
HARDENED_TRY_WIPE_DMEM(
@@ -393,7 +402,7 @@ status_t p384_ecdh_start(p384_masked_scalar_t *private_key,
393402

394403
status_t p384_ecdh_finalize(p384_ecdh_shared_key_t *shared_key) {
395404
// Spin here waiting for OTBN to complete.
396-
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
405+
HARDENED_TRY(otbn_busy_wait_for_done());
397406

398407
// Read the status code out of DMEM (false if basic checks on the validity of
399408
// the signature and public key failed).

0 commit comments

Comments
 (0)