Skip to content

Commit b64522c

Browse files
siemen11nasahlpa
authored andcommitted
[crypto/25519] Propagate the masking in x25519
Propagate the masking of the keys in x25519 to the OTBN and use the masked scalar multiplication from ed25519. Change the sc_blind subroutine to blind with a clamped blinding factor (adding 3 bits to the size). Use the s2b and b2a from p256. Note that due to the sharing change (additive versus substraction) we switch the masking by adding a new mask B. Signed-off-by: Siemen Dhooghe <sdhooghe@google.com>
1 parent df8a84a commit b64522c

8 files changed

Lines changed: 209 additions & 79 deletions

File tree

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ OTBN_DECLARE_SYMBOL_ADDR(run_curve25519,
3939
ed25519_r0); // 640-bit first share of r.
4040
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519,
4141
ed25519_r1); // 640-bit second share of r.
42-
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519,
43-
x25519_private_key); // X25519 private key.
4442
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519,
4543
x25519_public_key); // X25519 public key.
4644
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519,
@@ -62,8 +60,8 @@ enum {
6260
/*
6361
* The expected instruction counts for constant time functions.
6462
*/
65-
kModeKeygenInsCnt = 339495,
66-
kModeSignStage1InsCnt = 679051,
63+
kModeKeygenInsCnt = 342109,
64+
kModeSignStage1InsCnt = 684279,
6765
kModeSignStage2InsCnt = 655,
6866
};
6967

@@ -299,7 +297,8 @@ status_t curve25519_verify_finalize(hardened_bool_t *result) {
299297
}
300298

301299
status_t curve25519_x25519_start(
302-
const uint32_t private_key[kCurve25519ScalarWords],
300+
const uint32_t s0[kCurve25519ScalarWords],
301+
const uint32_t s1[kCurve25519ScalarWords],
303302
const uint32_t public_key[kCurve25519PointWords]) {
304303
// Load the Curve25519 app. Fails if OTBN is non-idle.
305304
const otbn_app_t kOtbnAppCurve25519 = OTBN_APP_T_INIT(run_curve25519);
@@ -310,11 +309,11 @@ status_t curve25519_x25519_start(
310309
const otbn_addr_t kOtbnVarMode = OTBN_ADDR_T_INIT(run_curve25519, mode);
311310
HARDENED_TRY(otbn_dmem_write(kCurve25519ModeWords, &mode, kOtbnVarMode));
312311

313-
// Write the private key to DMEM.
314-
const otbn_addr_t kOtbnVarX25519PrivateKey =
315-
OTBN_ADDR_T_INIT(run_curve25519, x25519_private_key);
316-
HARDENED_TRY(otbn_dmem_write(kCurve25519ScalarWords, private_key,
317-
kOtbnVarX25519PrivateKey));
312+
// Write the private key arithmetic shares to DMEM.
313+
const otbn_addr_t kOtbnVarS0 = OTBN_ADDR_T_INIT(run_curve25519, ed25519_s0);
314+
const otbn_addr_t kOtbnVarS1 = OTBN_ADDR_T_INIT(run_curve25519, ed25519_s1);
315+
HARDENED_TRY(otbn_dmem_write(kCurve25519ScalarWords, s0, kOtbnVarS0));
316+
HARDENED_TRY(otbn_dmem_write(kCurve25519ScalarWords, s1, kOtbnVarS1));
318317

319318
// Write the public key to DMEM.
320319
const otbn_addr_t kOtbnVarX25519PublicKey =
@@ -386,7 +385,8 @@ status_t curve25519_x25519_finalize(
386385
}
387386

388387
status_t curve25519_x25519_keygen_start(
389-
const uint32_t private_key[kCurve25519ScalarWords]) {
388+
const uint32_t s0[kCurve25519ScalarWords],
389+
const uint32_t s1[kCurve25519ScalarWords]) {
390390
// Load the Curve25519 app. Fails if OTBN is non-idle.
391391
const otbn_app_t kOtbnAppCurve25519 = OTBN_APP_T_INIT(run_curve25519);
392392
HARDENED_TRY(otbn_load_app(kOtbnAppCurve25519));
@@ -396,11 +396,11 @@ status_t curve25519_x25519_keygen_start(
396396
const otbn_addr_t kOtbnVarMode = OTBN_ADDR_T_INIT(run_curve25519, mode);
397397
HARDENED_TRY(otbn_dmem_write(kCurve25519ModeWords, &mode, kOtbnVarMode));
398398

399-
// Write the private key to DMEM.
400-
const otbn_addr_t kOtbnVarX25519PrivateKey =
401-
OTBN_ADDR_T_INIT(run_curve25519, x25519_private_key);
402-
HARDENED_TRY(otbn_dmem_write(kCurve25519ScalarWords, private_key,
403-
kOtbnVarX25519PrivateKey));
399+
// Write the private key arithmetic shares to DMEM.
400+
const otbn_addr_t kOtbnVarS0 = OTBN_ADDR_T_INIT(run_curve25519, ed25519_s0);
401+
const otbn_addr_t kOtbnVarS1 = OTBN_ADDR_T_INIT(run_curve25519, ed25519_s1);
402+
HARDENED_TRY(otbn_dmem_write(kCurve25519ScalarWords, s0, kOtbnVarS0));
403+
HARDENED_TRY(otbn_dmem_write(kCurve25519ScalarWords, s1, kOtbnVarS1));
404404

405405
// Start the OTBN routine.
406406
return otbn_execute();

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,15 @@ status_t curve25519_verify_finalize(hardened_bool_t *result);
277277
*
278278
* Returns an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
279279
*
280-
* @param private_key The unmasked private key.
280+
* @param s0 The first arithmetic share of the masked private key.
281+
* @param s1 The second arithmetic share of the masked private key.
281282
* @param public_key The public key from the other party.
282283
* @return Result of the operation (OK or error).
283284
*/
284285
OT_WARN_UNUSED_RESULT
285286
status_t curve25519_x25519_start(
286-
const uint32_t private_key[kCurve25519ScalarWords],
287+
const uint32_t s0[kCurve25519ScalarWords],
288+
const uint32_t s1[kCurve25519ScalarWords],
287289
const uint32_t public_key[kCurve25519PointWords]);
288290

289291
/**
@@ -324,12 +326,14 @@ status_t curve25519_x25519_finalize(
324326
*
325327
* Returns an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
326328
*
327-
* @param private_key The unmasked private key.
329+
* @param s0 The first arithmetic share of the masked private key.
330+
* @param s1 The second arithmetic share of the masked private key.
328331
* @return Result of the operation (OK or error).
329332
*/
330333
OT_WARN_UNUSED_RESULT
331334
status_t curve25519_x25519_keygen_start(
332-
const uint32_t private_key[kCurve25519ScalarWords]);
335+
const uint32_t s0[kCurve25519ScalarWords],
336+
const uint32_t s1[kCurve25519ScalarWords]);
333337

334338
/**
335339
* Finish an async X25519 keygen operation on OTBN.

sw/device/lib/crypto/impl/ecc_curve25519.c

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -729,22 +729,13 @@ otcrypto_status_t otcrypto_x25519_keygen_async_start(
729729

730730
return otcrypto_eval_exit(curve25519_x25519_keygen_sideload_start());
731731
} else if (private_key->config.hw_backed == kHardenedBoolFalse) {
732-
uint32_t private_key_unmasked[kCurve25519ScalarWords];
733732
uint32_t *share0 = private_key->keyblob;
734733
uint32_t *share1 =
735734
private_key->keyblob + keyblob_share_num_words(private_key->config);
736735

737-
HARDENED_TRY(hardened_add(share0, share1, kCurve25519ScalarWords,
738-
private_key_unmasked));
736+
HARDENED_TRY(curve25519_x25519_keygen_start(share0, share1));
739737

740-
HARDENED_TRY(ed25519_clamp(private_key_unmasked));
741-
742-
// Start the OTBN key exchange app.
743-
HARDENED_TRY(curve25519_x25519_keygen_start(private_key_unmasked));
744-
745-
// Wipe the unmasked private key.
746-
return otcrypto_eval_exit(
747-
hardened_memshred(private_key_unmasked, kCurve25519ScalarWords));
738+
return otcrypto_eval_exit(OTCRYPTO_OK);
748739
}
749740

750741
return OTCRYPTO_BAD_ARGS;
@@ -777,23 +768,13 @@ otcrypto_status_t otcrypto_x25519_async_start(
777768
curve25519_x25519_sideload_start(public_key->key));
778769

779770
} else if (private_key->config.hw_backed == kHardenedBoolFalse) {
780-
uint32_t private_key_unmasked[kCurve25519ScalarWords];
781-
782-
// Unmask the private key
783771
uint32_t *share0 = private_key->keyblob;
784772
uint32_t *share1 =
785773
private_key->keyblob + keyblob_share_num_words(private_key->config);
786-
HARDENED_TRY(hardened_add(share0, share1, kCurve25519ScalarWords,
787-
private_key_unmasked));
788-
HARDENED_TRY(ed25519_clamp(private_key_unmasked));
789774

790-
// Start the standard OTBN key exchange app
791-
HARDENED_TRY(
792-
curve25519_x25519_start(private_key_unmasked, public_key->key));
775+
HARDENED_TRY(curve25519_x25519_start(share0, share1, public_key->key));
793776

794-
// Wipe the unmasked private key from CPU memory and return
795-
return otcrypto_eval_exit(
796-
hardened_memshred(private_key_unmasked, kCurve25519ScalarWords));
777+
return otcrypto_eval_exit(OTCRYPTO_OK);
797778
}
798779

799780
return OTCRYPTO_BAD_ARGS;

sw/otbn/crypto/25519.s

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,18 +1320,20 @@ ext_scmul_sca:
13201320
bn.mov w4, w16
13211321
bn.mov w5, w17
13221322

1323-
/* Move the blinded 382-bit share s0 to the MSB position. */
1324-
bn.rshi w3, w3, w2 >> 126
1325-
bn.rshi w2, w2, w31 >> 126
1323+
/* Move the newly expanded 385-bit share s0 to the MSB position.
1324+
Left-shift by 127 bits = rshi by 129. */
1325+
bn.rshi w3, w3, w2 >> 129
1326+
bn.rshi w2, w2, w31 >> 129
13261327

13271328
bn.xor w31, w31, w31 /* dummy */
13281329

1329-
/* Move the blinded 382-bit share s1 to the MSB position. */
1330-
bn.rshi w5, w5, w4 >> 126
1331-
bn.rshi w4, w4, w31 >> 126
1330+
/* Move the newly expanded 385-bit share s1 to the MSB position. */
1331+
bn.rshi w5, w5, w4 >> 129
1332+
bn.rshi w4, w4, w31 >> 129
1333+
13321334

13331335
/* Iterate over all scalar bits starting at the MSB. */
1334-
loopi 382, 56
1336+
loopi 385, 56
13351337
/* Compute Q = 2 * Q.
13361338
[w13:w10] <= [w13:w10] + [w13:w10] = 2 * Q */
13371339
jal x1, ext_double
@@ -2033,9 +2035,6 @@ x25519_ed_y_to_mont_u:
20332035
* clobbered flag groups: FG0
20342036
*/
20352037
X25519:
2036-
/* Move the private key scalar */
2037-
bn.mov w2, w8
2038-
20392038
/* Initialize field arithmetic (MOD <= p, w19 <= 19) */
20402039
jal x1, fe_init
20412040
bn.xor w31, w31, w31
@@ -2076,11 +2075,8 @@ X25519:
20762075
/* Double w29 so it equals (2*d) mod p */
20772076
bn.addm w29, w29, w29
20782077

2079-
/* Move scalar from w2 to w28 for ext_scmul */
2080-
bn.mov w28, w2
2081-
2082-
/* Perform scalar multiplication: [w13:w10] = w28 * [w9:w6] */
2083-
jal x1, ext_scmul
2078+
/* Perform masked scalar multiplication: [w13:w10] = (w2 - w4) * [w9:w6] */
2079+
jal x1, ext_scmul_sca
20842080

20852081
/* Convert result back to affine (x, y) */
20862082
jal x1, ext_to_affine

sw/otbn/crypto/25519_scalar.s

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,10 @@ sc_mul:
331331
* Blind a scalar with a multiple of the curve order L.
332332
*
333333
* Given a scalar s < L, this routine adds a random multiple of the group order
334-
* k * L to the scalar such that s + k * L. In accordance, with Schindler's and
335-
* Wiemers' recommendation [1] the blinding factor k is 128 bits. Since the
334+
* 8 * k * L to the scalar such that s + 8 * k * L. We left shift k * L (multiply by 8) in order to clamp the blinding factor.
335+
* In accordance, with Schindler's and Wiemers' recommendation [1] the blinding factor k is 128 bits. Since the
336336
* curve order L is 253 bits, by choosing a 128-bit factor k we can guarantee
337-
* that the blinded scalar s + k * L is at most 382 bits.
337+
* that the blinded scalar s + 8 * k * L is at most 385 bits.
338338
*
339339
* [1] https://csrc.nist.gov/csrc/media/events/workshop-on-elliptic-curve-cryptography-standards/documents/papers/session6-schindler-werner.pdf
340340
*
@@ -358,7 +358,7 @@ sc_blind:
358358

359359
/* Calculate k * L, i.e., 128-bit x 253-bit multiplication resulting in a
360360
381-bit value.
361-
[w17:w16] <= [w23:w22] * w21 = k * L. */
361+
[w17:w16] <= w22 * w21 = k * L. */
362362
bn.mulqacc.z w21.0, w22.0, 0
363363
bn.mulqacc w21.0, w22.1, 64
364364
bn.mulqacc.so w16.L, w21.1, w22.0, 64
@@ -368,6 +368,12 @@ sc_blind:
368368
bn.mulqacc.so w16.U, w21.3, w22.0, 64
369369
bn.mulqacc.wo w17, w21.3, w22.1, 0
370370

371+
/* w17 = (w17 << 3) | (w16 >> 253) */
372+
bn.rshi w17, w17, w16 >> 253
373+
374+
/* w16 = (w16 << 3) | (0 >> 253) */
375+
bn.rshi w16, w16, w31 >> 253
376+
371377
/* Add the 381-bit blinding value to the 253-bit scalar resulting in a
372378
382-bit blinded scalar avoiding any overflow.
373379
[w17:w16] <= [w17:w16] + w20 = k * L + s. */
@@ -403,6 +409,9 @@ x25519_clamp_shares:
403409
/* Shift right 2: inserts the 1 at bit 254, original bit 253 moves back to 253 */
404410
bn.rshi w8, w2, w8 >> 2
405411

412+
/* Clear flags */
413+
bn.xor w31, w31, w31
414+
406415
/* --- Clamp Share 1 (w7) --- */
407416
/* Clear bottom 3 bits */
408417
bn.rshi w7, w31, w7 >> 3
@@ -411,6 +420,9 @@ x25519_clamp_shares:
411420
/* Prepare bit 254 = 0 (use w31 instead of w2) */
412421
bn.rshi w7, w31, w7 >> 2
413422

423+
/* Clear flags before exit */
424+
bn.sub w31, w31, w31, FG0
425+
414426
ret
415427

416428
.data

sw/otbn/crypto/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ otbn_binary(
6363
":25519",
6464
":25519_scalar",
6565
":field25519",
66+
":p256_a2b",
67+
":p256_b2a",
6668
],
6769
)
6870

0 commit comments

Comments
 (0)