Skip to content

Commit 7bcdd38

Browse files
committed
[crypto] Wipe DMEM also in error cases
When an error occurs, HARDENED_TRY() immediately returns. As we also want to wipe the OTBN DMEM when an error happens, this commit adds HARDENED_TRY_WIPE_DMEM() which wipes DMEM on an error before returning. Signed-off-by: Pascal Nasahl <nasahlpa@lowrisc.org>
1 parent aa54b60 commit 7bcdd38

File tree

8 files changed

+86
-42
lines changed

8 files changed

+86
-42
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,27 @@
1515
extern "C" {
1616
#endif
1717

18+
/**
19+
* Hardened version of the `TRY` macro that wipes DMEM() on an error.
20+
*
21+
* Returns an error if either expr_ represents an error, or if the OK code does
22+
* not match the expected hardened value.
23+
*
24+
* @param expr_ An expression that evaluates to a `status_t`.
25+
* @return The enclosed OK value.
26+
*/
27+
#define HARDENED_TRY_WIPE_DMEM(expr_) \
28+
do { \
29+
status_t status_ = expr_; \
30+
if (launder32(OT_UNSIGNED(status_.value)) != kHardenedBoolTrue) { \
31+
otbn_dmem_sec_wipe(); \
32+
return (status_t){ \
33+
.value = (int32_t)(OT_UNSIGNED(status_.value) | 0x80000000)}; \
34+
} \
35+
HARDENED_CHECK_EQ(status_.value, kHardenedBoolTrue); \
36+
status_.value; \
37+
} while (false)
38+
1839
/**
1940
* Constants related to OTBN wide words
2041
*/

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

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,16 @@ status_t p256_keygen_finalize(p256_masked_scalar_t *private_key,
126126
HARDENED_TRY(otbn_busy_wait_for_done());
127127

128128
// Read the masked private key from OTBN dmem.
129-
HARDENED_TRY(otbn_dmem_read(kP256MaskedScalarShareWords, kOtbnVarD0,
130-
private_key->share0));
131-
HARDENED_TRY(otbn_dmem_read(kP256MaskedScalarShareWords, kOtbnVarD1,
132-
private_key->share1));
129+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP256MaskedScalarShareWords, kOtbnVarD0,
130+
private_key->share0));
131+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP256MaskedScalarShareWords, kOtbnVarD1,
132+
private_key->share1));
133133

134134
// Read the public key from OTBN dmem.
135-
HARDENED_TRY(otbn_dmem_read(kP256CoordWords, kOtbnVarX, public_key->x));
136-
HARDENED_TRY(otbn_dmem_read(kP256CoordWords, kOtbnVarY, public_key->y));
135+
HARDENED_TRY_WIPE_DMEM(
136+
otbn_dmem_read(kP256CoordWords, kOtbnVarX, public_key->x));
137+
HARDENED_TRY_WIPE_DMEM(
138+
otbn_dmem_read(kP256CoordWords, kOtbnVarY, public_key->y));
137139

138140
// Wipe DMEM.
139141
return otbn_dmem_sec_wipe();
@@ -144,8 +146,10 @@ status_t p256_sideload_keygen_finalize(p256_point_t *public_key) {
144146
HARDENED_TRY(otbn_busy_wait_for_done());
145147

146148
// Read the public key from OTBN dmem.
147-
HARDENED_TRY(otbn_dmem_read(kP256CoordWords, kOtbnVarX, public_key->x));
148-
HARDENED_TRY(otbn_dmem_read(kP256CoordWords, kOtbnVarY, public_key->y));
149+
HARDENED_TRY_WIPE_DMEM(
150+
otbn_dmem_read(kP256CoordWords, kOtbnVarX, public_key->x));
151+
HARDENED_TRY_WIPE_DMEM(
152+
otbn_dmem_read(kP256CoordWords, kOtbnVarY, public_key->y));
149153

150154
// Wipe DMEM.
151155
return otbn_dmem_sec_wipe();
@@ -215,10 +219,12 @@ status_t p256_ecdsa_sign_finalize(p256_ecdsa_signature_t *result) {
215219
HARDENED_TRY(otbn_busy_wait_for_done());
216220

217221
// Read signature R out of OTBN dmem.
218-
HARDENED_TRY(otbn_dmem_read(kP256ScalarWords, kOtbnVarR, result->r));
222+
HARDENED_TRY_WIPE_DMEM(
223+
otbn_dmem_read(kP256ScalarWords, kOtbnVarR, result->r));
219224

220225
// Read signature S out of OTBN dmem.
221-
HARDENED_TRY(otbn_dmem_read(kP256ScalarWords, kOtbnVarS, result->s));
226+
HARDENED_TRY_WIPE_DMEM(
227+
otbn_dmem_read(kP256ScalarWords, kOtbnVarS, result->s));
222228

223229
// Wipe DMEM.
224230
return otbn_dmem_sec_wipe();
@@ -261,15 +267,16 @@ status_t p256_ecdsa_verify_finalize(const p256_ecdsa_signature_t *signature,
261267
// Read the status code out of DMEM (false if basic checks on the validity of
262268
// the signature and public key failed).
263269
uint32_t ok;
264-
HARDENED_TRY(otbn_dmem_read(1, kOtbnVarOk, &ok));
270+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(1, kOtbnVarOk, &ok));
265271
if (launder32(ok) != kHardenedBoolTrue) {
272+
HARDENED_TRY(otbn_dmem_sec_wipe());
266273
return OTCRYPTO_BAD_ARGS;
267274
}
268275
HARDENED_CHECK_EQ(ok, kHardenedBoolTrue);
269276

270277
// Read x_r (recovered R) out of OTBN dmem.
271278
uint32_t x_r[kP256ScalarWords];
272-
HARDENED_TRY(otbn_dmem_read(kP256ScalarWords, kOtbnVarXr, x_r));
279+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP256ScalarWords, kOtbnVarXr, x_r));
273280

274281
*result = hardened_memeq(x_r, signature->r, kP256ScalarWords);
275282

@@ -305,15 +312,18 @@ status_t p256_ecdh_finalize(p256_ecdh_shared_key_t *shared_key) {
305312

306313
// Read the code indicating if the public key is valid.
307314
uint32_t ok;
308-
HARDENED_TRY(otbn_dmem_read(1, kOtbnVarOk, &ok));
315+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(1, kOtbnVarOk, &ok));
309316
if (launder32(ok) != kHardenedBoolTrue) {
317+
HARDENED_TRY(otbn_dmem_sec_wipe());
310318
return OTCRYPTO_BAD_ARGS;
311319
}
312320
HARDENED_CHECK_EQ(ok, kHardenedBoolTrue);
313321

314322
// Read the shares of the key from OTBN dmem (at vars x and y).
315-
HARDENED_TRY(otbn_dmem_read(kP256CoordWords, kOtbnVarX, shared_key->share0));
316-
HARDENED_TRY(otbn_dmem_read(kP256CoordWords, kOtbnVarY, shared_key->share1));
323+
HARDENED_TRY_WIPE_DMEM(
324+
otbn_dmem_read(kP256CoordWords, kOtbnVarX, shared_key->share0));
325+
HARDENED_TRY_WIPE_DMEM(
326+
otbn_dmem_read(kP256CoordWords, kOtbnVarY, shared_key->share1));
317327

318328
// Wipe DMEM.
319329
return otbn_dmem_sec_wipe();

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

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,16 @@ status_t p384_keygen_finalize(p384_masked_scalar_t *private_key,
167167
HARDENED_TRY(otbn_busy_wait_for_done());
168168

169169
// Read the masked private key from OTBN dmem.
170-
HARDENED_TRY(otbn_dmem_read(kP384MaskedScalarShareWords, kOtbnVarD0,
171-
private_key->share0));
172-
HARDENED_TRY(otbn_dmem_read(kP384MaskedScalarShareWords, kOtbnVarD1,
173-
private_key->share1));
170+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP384MaskedScalarShareWords, kOtbnVarD0,
171+
private_key->share0));
172+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP384MaskedScalarShareWords, kOtbnVarD1,
173+
private_key->share1));
174174

175175
// Read the public key from OTBN dmem.
176-
HARDENED_TRY(otbn_dmem_read(kP384CoordWords, kOtbnVarX, public_key->x));
177-
HARDENED_TRY(otbn_dmem_read(kP384CoordWords, kOtbnVarY, public_key->y));
176+
HARDENED_TRY_WIPE_DMEM(
177+
otbn_dmem_read(kP384CoordWords, kOtbnVarX, public_key->x));
178+
HARDENED_TRY_WIPE_DMEM(
179+
otbn_dmem_read(kP384CoordWords, kOtbnVarY, public_key->y));
178180

179181
// Wipe DMEM.
180182
return otbn_dmem_sec_wipe();
@@ -197,8 +199,10 @@ status_t p384_sideload_keygen_finalize(p384_point_t *public_key) {
197199
HARDENED_TRY(otbn_busy_wait_for_done());
198200

199201
// Read the public key from OTBN dmem.
200-
HARDENED_TRY(otbn_dmem_read(kP384CoordWords, kOtbnVarX, public_key->x));
201-
HARDENED_TRY(otbn_dmem_read(kP384CoordWords, kOtbnVarY, public_key->y));
202+
HARDENED_TRY_WIPE_DMEM(
203+
otbn_dmem_read(kP384CoordWords, kOtbnVarX, public_key->x));
204+
HARDENED_TRY_WIPE_DMEM(
205+
otbn_dmem_read(kP384CoordWords, kOtbnVarY, public_key->y));
202206

203207
// Wipe DMEM.
204208
return otbn_dmem_sec_wipe();
@@ -244,10 +248,12 @@ status_t p384_ecdsa_sign_finalize(p384_ecdsa_signature_t *result) {
244248
HARDENED_TRY(otbn_busy_wait_for_done());
245249

246250
// Read signature R out of OTBN dmem.
247-
HARDENED_TRY(otbn_dmem_read(kP384ScalarWords, kOtbnVarR, result->r));
251+
HARDENED_TRY_WIPE_DMEM(
252+
otbn_dmem_read(kP384ScalarWords, kOtbnVarR, result->r));
248253

249254
// Read signature S out of OTBN dmem.
250-
HARDENED_TRY(otbn_dmem_read(kP384ScalarWords, kOtbnVarS, result->s));
255+
HARDENED_TRY_WIPE_DMEM(
256+
otbn_dmem_read(kP384ScalarWords, kOtbnVarS, result->s));
251257

252258
// Wipe DMEM.
253259
return otbn_dmem_sec_wipe();
@@ -287,15 +293,16 @@ status_t p384_ecdsa_verify_finalize(const p384_ecdsa_signature_t *signature,
287293
// Read the status code out of DMEM (false if basic checks on the validity of
288294
// the signature and public key failed).
289295
uint32_t ok;
290-
HARDENED_TRY(otbn_dmem_read(1, kOtbnVarOk, &ok));
296+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(1, kOtbnVarOk, &ok));
291297
if (launder32(ok) != kHardenedBoolTrue) {
298+
HARDENED_TRY(otbn_dmem_sec_wipe());
292299
return OTCRYPTO_BAD_ARGS;
293300
}
294301
HARDENED_CHECK_EQ(ok, kHardenedBoolTrue);
295302

296303
// Read x_r (recovered R) out of OTBN dmem.
297304
uint32_t x_r[kP384ScalarWords];
298-
HARDENED_TRY(otbn_dmem_read(kP384ScalarWords, kOtbnVarXr, x_r));
305+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(kP384ScalarWords, kOtbnVarXr, x_r));
299306

300307
*result = hardened_memeq(x_r, signature->r, kP384ScalarWords);
301308

@@ -329,15 +336,18 @@ status_t p384_ecdh_finalize(p384_ecdh_shared_key_t *shared_key) {
329336
// Read the status code out of DMEM (false if basic checks on the validity of
330337
// the signature and public key failed).
331338
uint32_t ok;
332-
HARDENED_TRY(otbn_dmem_read(1, kOtbnVarOk, &ok));
339+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(1, kOtbnVarOk, &ok));
333340
if (launder32(ok) != kHardenedBoolTrue) {
341+
HARDENED_TRY(otbn_dmem_sec_wipe());
334342
return OTCRYPTO_BAD_ARGS;
335343
}
336344
HARDENED_CHECK_EQ(ok, kHardenedBoolTrue);
337345

338346
// Read the shares of the key from OTBN dmem (at vars x and y).
339-
HARDENED_TRY(otbn_dmem_read(kP384CoordWords, kOtbnVarX, shared_key->share0));
340-
HARDENED_TRY(otbn_dmem_read(kP384CoordWords, kOtbnVarY, shared_key->share1));
347+
HARDENED_TRY_WIPE_DMEM(
348+
otbn_dmem_read(kP384CoordWords, kOtbnVarX, shared_key->share0));
349+
HARDENED_TRY_WIPE_DMEM(
350+
otbn_dmem_read(kP384CoordWords, kOtbnVarY, shared_key->share1));
341351

342352
// Wipe DMEM.
343353
return otbn_dmem_sec_wipe();

sw/device/lib/crypto/impl/rsa/rsa_3072_verify.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,11 @@ status_t rsa_3072_compute_constants(const rsa_3072_public_key_t *public_key,
140140
HARDENED_TRY(otbn_busy_wait_for_done());
141141

142142
// Read constant rr out of DMEM.
143-
HARDENED_TRY(read_rsa_3072_int_from_otbn(kOtbnVarRsaRR, &result->rr));
143+
HARDENED_TRY_WIPE_DMEM(
144+
read_rsa_3072_int_from_otbn(kOtbnVarRsaRR, &result->rr));
144145

145146
// Read constant m0_inv out of DMEM.
146-
HARDENED_TRY(
147+
HARDENED_TRY_WIPE_DMEM(
147148
otbn_dmem_read(kOtbnWideWordNumWords, kOtbnVarRsaM0Inv, result->m0_inv));
148149

149150
// Wipe DMEM.
@@ -201,7 +202,7 @@ status_t rsa_3072_verify_finalize(const rsa_3072_int_t *message,
201202

202203
// Read recovered message out of OTBN dmem.
203204
rsa_3072_int_t recoveredMessage;
204-
HARDENED_TRY(
205+
HARDENED_TRY_WIPE_DMEM(
205206
read_rsa_3072_int_from_otbn(kOtbnVarRsaOutBuf, &recoveredMessage));
206207

207208
// TODO: harden this memory comparison

sw/device/lib/crypto/impl/rsa/rsa_keygen.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,17 @@ static status_t keygen_finalize(uint32_t exp_mode, size_t num_words,
8787

8888
// Read the mode from OTBN dmem and panic if it's not as expected.
8989
uint32_t act_mode = 0;
90-
HARDENED_TRY(otbn_dmem_read(1, kOtbnVarRsaMode, &act_mode));
90+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(1, kOtbnVarRsaMode, &act_mode));
9191
if (act_mode != exp_mode) {
92+
HARDENED_TRY(otbn_dmem_sec_wipe());
9293
return OTCRYPTO_FATAL_ERR;
9394
}
9495

9596
// Read the public modulus (n) from OTBN dmem.
96-
HARDENED_TRY(otbn_dmem_read(num_words, kOtbnVarRsaN, n));
97+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(num_words, kOtbnVarRsaN, n));
9798

9899
// Read the private exponent (d) from OTBN dmem.
99-
HARDENED_TRY(otbn_dmem_read(num_words, kOtbnVarRsaD, d));
100+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(num_words, kOtbnVarRsaD, d));
100101

101102
// Wipe DMEM.
102103
return otbn_dmem_sec_wipe();

sw/device/lib/crypto/impl/rsa/rsa_modexp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ status_t rsa_modexp_wait(size_t *num_words) {
6262

6363
// Read the application mode.
6464
uint32_t mode;
65-
HARDENED_TRY(otbn_dmem_read(1, kOtbnVarRsaMode, &mode));
65+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(1, kOtbnVarRsaMode, &mode));
6666

6767
*num_words = 0;
6868
if (mode == kMode2048Modexp || mode == kMode2048ModexpF4) {
@@ -94,7 +94,7 @@ status_t rsa_modexp_wait(size_t *num_words) {
9494
static status_t rsa_modexp_finalize(const size_t num_words, uint32_t *result) {
9595
// Wait for OTBN to complete and get the result size.
9696
size_t num_words_inferred;
97-
HARDENED_TRY(rsa_modexp_wait(&num_words_inferred));
97+
HARDENED_TRY_WIPE_DMEM(rsa_modexp_wait(&num_words_inferred));
9898

9999
// Check that the inferred result size matches expectations.
100100
if (num_words != num_words_inferred) {
@@ -104,7 +104,7 @@ static status_t rsa_modexp_finalize(const size_t num_words, uint32_t *result) {
104104
}
105105

106106
// Read the result.
107-
HARDENED_TRY(otbn_dmem_read(num_words, kOtbnVarRsaInOut, result));
107+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(num_words, kOtbnVarRsaInOut, result));
108108

109109
// Wipe DMEM.
110110
return otbn_dmem_sec_wipe();

sw/device/lib/crypto/impl/sha2/sha256.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ static status_t process_message(sha256_state_t *state, const uint8_t *msg,
245245
}
246246

247247
// Read the final state from OTBN dmem.
248-
HARDENED_TRY(
248+
HARDENED_TRY_WIPE_DMEM(
249249
otbn_dmem_read(kSha256StateWords, kOtbnVarSha256State, new_state.H));
250250

251251
// Clear OTBN's memory.

sw/device/lib/crypto/impl/sha2/sha512.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,9 @@ static status_t process_message(sha512_state_t *state, const uint8_t *msg,
307307
// boundaries.
308308
otbn_addr_t state_read_addr = kOtbnVarSha512State;
309309
for (size_t i = 0; i + 1 < kSha512StateWords; i += 2) {
310-
HARDENED_TRY(otbn_dmem_read(1, state_read_addr, &new_state.H[i + 1]));
311-
HARDENED_TRY(
310+
HARDENED_TRY_WIPE_DMEM(
311+
otbn_dmem_read(1, state_read_addr, &new_state.H[i + 1]));
312+
HARDENED_TRY_WIPE_DMEM(
312313
otbn_dmem_read(1, state_read_addr + sizeof(uint32_t), &new_state.H[i]));
313314
state_read_addr += kOtbnWideWordNumBytes;
314315
}

0 commit comments

Comments
 (0)