Skip to content

Commit 18b1373

Browse files
siemen11nasahlpa
authored andcommitted
[crypto/ed25519] Verify in Ibex
Change the verification logic of ed25519 to be in line with p256 and p384 where we make the final verification within Ibex and OTBN provides the left and right hand side equations. Signed-off-by: Siemen Dhooghe <sdhooghe@google.com>
1 parent 80924cd commit 18b1373

3 files changed

Lines changed: 75 additions & 139 deletions

File tree

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

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ OTBN_DECLARE_SYMBOL_ADDR(
3434
run_curve25519,
3535
ed25519_hash_h_low); // 32 lowest bytes of the key hash.
3636
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519, ed25519_hash_r); // Message hash r.
37+
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519, ed25519_verify_lhs);
38+
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519, ed25519_verify_rhs);
3739

3840
static const otbn_addr_t kOtbnVarMode = OTBN_ADDR_T_INIT(run_curve25519, mode);
3941
static const otbn_addr_t kOtbnVarVerifyRes =
@@ -50,6 +52,10 @@ static const otbn_addr_t kOtbnVarHashHlow =
5052
OTBN_ADDR_T_INIT(run_curve25519, ed25519_hash_h_low);
5153
static const otbn_addr_t kOtbnVarHashR =
5254
OTBN_ADDR_T_INIT(run_curve25519, ed25519_hash_r);
55+
static const otbn_addr_t kOtbnVarVerifyLhs =
56+
OTBN_ADDR_T_INIT(run_curve25519, ed25519_verify_lhs);
57+
static const otbn_addr_t kOtbnVarVerifyRhs =
58+
OTBN_ADDR_T_INIT(run_curve25519, ed25519_verify_rhs);
5359

5460
// Declare mode constants.
5561
OTBN_DECLARE_SYMBOL_ADDR(run_curve25519, MODE_KEYGEN);
@@ -202,11 +208,23 @@ status_t curve25519_verify_finalize(hardened_bool_t *result) {
202208
// Spin here waiting for OTBN to complete.
203209
HARDENED_TRY_WIPE_DMEM(otbn_busy_wait_for_done());
204210

205-
uint32_t resp;
206-
uint32_t expected_resp = kCurve25519VerifySuccess;
211+
uint32_t ok;
212+
HARDENED_TRY_WIPE_DMEM(otbn_dmem_read(1, kOtbnVarVerifyRes, &ok));
213+
if (launder32(ok) != kHardenedBoolTrue) {
214+
HARDENED_TRY(otbn_dmem_sec_wipe());
215+
return OTCRYPTO_BAD_ARGS;
216+
}
217+
HARDENED_CHECK_EQ(ok, kHardenedBoolTrue);
218+
219+
// Read the computed LHS and RHS out of OTBN dmem.
220+
uint32_t lhs[kCurve25519PointWords];
221+
uint32_t rhs[kCurve25519PointWords];
207222
HARDENED_TRY_WIPE_DMEM(
208-
otbn_dmem_read(kCurve25519ResultWords, kOtbnVarVerifyRes, &resp));
209-
*result = hardened_memeq(&resp, &expected_resp, kCurve25519ResultWords);
223+
otbn_dmem_read(kCurve25519PointWords, kOtbnVarVerifyLhs, lhs));
224+
HARDENED_TRY_WIPE_DMEM(
225+
otbn_dmem_read(kCurve25519PointWords, kOtbnVarVerifyRhs, rhs));
226+
227+
*result = hardened_memeq(lhs, rhs, kCurve25519PointWords);
210228

211229
// Wipe DMEM.
212230
return otbn_dmem_sec_wipe();

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,6 @@ enum {
5656
* Number of words needed to hold a scalar.
5757
*/
5858
kCurve25519ScalarWords = kCurve25519ScalarBytes / 4,
59-
/**
60-
* Magic value for verify success response.
61-
*/
62-
kCurve25519VerifySuccess = 0xf77fe650,
6359
};
6460

6561
/**

sw/otbn/crypto/ed25519.s

Lines changed: 53 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@
7070
magic values, but they cause errors in the assembler from the LI
7171
instructions.
7272

73-
.equ FAILURE, 0xeda2bfaf
74-
.equ SUCCESS, 0xf77fe650
73+
.equ FAILURE, 0x1d4
74+
.equ SUCCESS, 0x739
7575
*/
7676

7777
/**
@@ -283,7 +283,7 @@ ed25519_verify_var:
283283
jal x1, affine_decode_var
284284

285285
/* If R was not a valid point (x20 != SUCCESS), fail. */
286-
li x21, 0xf77fe650
286+
li x21, 0x739
287287
bne x20, x21, verify_fail
288288

289289
/* Save R (in affine coordinates) for later.
@@ -386,19 +386,44 @@ ed25519_verify_var:
386386
[w13:w10] <= w28 * [w9:w6] = [8][S]B */
387387
jal x1, ext_scmul
388388

389-
/* Compare both sides of the equation for equality.
390-
dmem[ed25519_verify_result] <= SUCCESS if [w5:w2] == [w13:w10],
391-
otherwise FAILURE */
392-
jal x1, ext_equal_var
389+
/* Convert LHS [8][S]B to affine and encode. */
390+
jal x1, ext_to_affine
391+
jal x1, affine_encode
392+
393+
/* Write encoded LHS to dmem[ed25519_verify_lhs] */
394+
li x2, 11
395+
la x3, ed25519_verify_lhs
396+
bn.sid x2, 0(x3)
397+
398+
/* Prepare RHS [8]R + [8][k]A for encoding.
399+
[w5:w2] holds the RHS from earlier. Move it to [w13:w10] */
400+
bn.mov w10, w2
401+
bn.mov w11, w3
402+
bn.mov w12, w4
403+
bn.mov w13, w5
404+
405+
/* Convert RHS to affine and encode. */
406+
jal x1, ext_to_affine
407+
jal x1, affine_encode
408+
409+
/* Write encoded RHS to dmem[ed25519_verify_rhs] */
410+
li x2, 11
411+
la x3, ed25519_verify_rhs
412+
bn.sid x2, 0(x3)
413+
414+
/* Exit with SUCCESS. */
415+
li x23, 0x739
416+
la x4, ed25519_verify_result
417+
sw x23, 0(x4)
393418

394419
ret
395420

396421
verify_fail:
397-
/* Write the FAILURE magic value.
398-
dmem[ed25519_verify_result] <= x23 = FAILURE */
399-
li x22, 0xeda2bfaf
400-
la x2, ed25519_verify_result
401-
sw x22, 0(x2)
422+
/* Write FAILURE.
423+
dmem[ed25519_verify_result] <= x22 = FAILURE */
424+
li x22, 0x1d4
425+
la x4, ed25519_verify_result
426+
sw x22, 0(x4)
402427
ret
403428

404429
/**
@@ -982,7 +1007,7 @@ affine_decode_var:
9821007

9831008
/* If we get here, then r^2 was not equal to either (u/v) or - (u/v), so we
9841009
are in case 3, (u/v) is nonsquare mod p, and point decoding fails. */
985-
li x20, 0xeda2bfaf
1010+
li x22, 0x1d4
9861011
bn.mov w10, w31
9871012
bn.mov w11, w31
9881013
ret
@@ -1034,7 +1059,7 @@ affine_decode_var:
10341059
against glitching? */
10351060

10361061
/* Exit point decoding with SUCCESS. */
1037-
li x20, 0xf77fe650
1062+
li x20, 0x739
10381063

10391064
ret
10401065

@@ -1342,121 +1367,6 @@ ext_add:
13421367

13431368
ret
13441369

1345-
/**
1346-
* Check if two points in extended coordinates are equal.
1347-
*
1348-
* If the input points (X1, Y1, Z1, T1) and (X2, Y2, Z2, T2) are not equal,
1349-
* this procedure writes FAILURE to dmem[ed25519_verify_result]. If the points
1350-
* are equal, it appends the third and final byte of the SUCCESS magic value to
1351-
* dmem[ed25519_verify_result] by shifting the current value left by 8 and then
1352-
* ORing with the final byte.
1353-
*
1354-
* As per RFC 8032, returns 1 iff:
1355-
* (X1 * Z2 - X2 * Z1) mod p = 0, and
1356-
* (Y1 * Z2 - Y2 * Z2) mod p = 0.
1357-
*
1358-
* This routine runs in variable time.
1359-
*
1360-
* @param[in] w2: input X1 (X1 < p)
1361-
* @param[in] w3: input Y1 (Y1 < p)
1362-
* @param[in] w4: input Z1 (Z1 < p)
1363-
* @param[in] w5: input T1 (T1 < p)
1364-
* @param[in] w10: input X2 (X2 < p)
1365-
* @param[in] w11: input Y2 (Y2 < p)
1366-
* @param[in] w12: input Z2 (Z2 < p)
1367-
* @param[in] w13: input T2 (T2 < p)
1368-
* @param[in] w19: constant, w19 = 19
1369-
* @param[in] w31: all-zero
1370-
* @param[in] MOD: p, modulus = 2^255 - 19
1371-
* @param[out] dmem[ed25519_verify_result]: result, SUCCESS or FAILURE
1372-
*
1373-
* clobbered registers: w14 to w17
1374-
* clobbered flag groups: FG0
1375-
*/
1376-
ext_equal_var:
1377-
/* x22 <= FAILURE */
1378-
li x22, 0xeda2bfaf
1379-
/* x23 <= SUCCESS */
1380-
li x23, 0xf77fe650
1381-
1382-
/* Compute (X1 * Z2). */
1383-
1384-
/* w22 <= w2 = X1 */
1385-
bn.mov w22, w2
1386-
/* w23 <= w12 = Z2 */
1387-
bn.mov w23, w12
1388-
/* w22 <= w22 * w23 = X1 * Z2 */
1389-
jal x1, fe_mul
1390-
/* w16 <= w22 <= X1 * Z2 */
1391-
bn.mov w16, w22
1392-
1393-
/* Compute (X2 * Z1). */
1394-
1395-
/* w22 <= w10 = X2 */
1396-
bn.mov w22, w10
1397-
/* w23 <= w4 = Z1 */
1398-
bn.mov w23, w4
1399-
/* w22 <= w22 * w23 = X2 * Z1 */
1400-
jal x1, fe_mul
1401-
1402-
/* First check. */
1403-
1404-
/* w16 <= w16 - w22 <= (X1 * Z2) - (X2 * Z1) */
1405-
bn.sub w16, w16, w22
1406-
/* x2 <= FG0[3] = FG0.Z << 3 = result of check 1 */
1407-
csrrs x2, FG0, x0
1408-
andi x2, x2, 8
1409-
1410-
/* Fail if the FG0.Z flag was unset. */
1411-
li x3, 8
1412-
bne x2, x3, ext_equal_var_fail
1413-
1414-
/* Compute (Y1 * Z2). */
1415-
1416-
/* w22 <= w3 = Y1 */
1417-
bn.mov w22, w3
1418-
/* w23 <= w12 = Z2 */
1419-
bn.mov w23, w12
1420-
/* w22 <= w22 * w23 = Y1 * Z2 */
1421-
jal x1, fe_mul
1422-
/* w6 <= w22 <= Y1 * Z2 */
1423-
bn.mov w16, w22
1424-
1425-
/* Compute (Y2 * Z1). */
1426-
1427-
/* w22 <= w11 = Y2 */
1428-
bn.mov w22, w11
1429-
/* w23 <= w4 = Z1 */
1430-
bn.mov w23, w4
1431-
/* w22 <= w22 * w23 = Y2 * Z1 */
1432-
jal x1, fe_mul
1433-
1434-
/* Second check. */
1435-
1436-
/* w16 <= w16 - w22 <= (Y1 * Z2) - (Y2 * Z1) */
1437-
bn.sub w16, w16, w22
1438-
/* x2 <= FG0[3] = FG0.Z << 3 = result of check 2 */
1439-
csrrs x2, FG0, x0
1440-
andi x2, x2, 8
1441-
1442-
/* Fail if the FG0.Z flag was unset. */
1443-
li x3, 8
1444-
bne x2, x3, ext_equal_var_fail
1445-
1446-
/* If we got here, both checks passed; write the SUCCESS value to DMEM.
1447-
1448-
TODO: this should be hardened against glitching attacks that simply jump
1449-
to this point in the code, perhaps by separating the SUCCESS code into
1450-
multiple shares that get XORed into the final value at multiple points in
1451-
the successful code path. */
1452-
1453-
/* Write the SUCCESS magic value.
1454-
dmem[ed25519_verify_result] <= x23 = SUCCESS */
1455-
la x4, ed25519_verify_result
1456-
sw x23, 0(x4)
1457-
1458-
ret
1459-
14601370
ext_equal_var_fail:
14611371
/* Write the FAILURE magic value.
14621372
dmem[ed25519_verify_result] <= x22 = FAILURE */
@@ -1604,8 +1514,8 @@ fe_pow_2252m3:
16041514
.bss
16051515

16061516
/* Verification result code (32 bits). Output for verify.
1607-
If verification is successful, this will be SUCCESS = 0xf77fe650.
1608-
Otherwise, this will be FAILURE = 0xeda2bfaf. */
1517+
If verification is successful, this will be SUCCESS = 0x739.
1518+
Otherwise, this will be FAILURE = 0x1d4. */
16091519
.balign 32
16101520
.weak ed25519_verify_result
16111521
ed25519_verify_result:
@@ -1649,6 +1559,18 @@ ed25519_hash_h_low:
16491559
ed25519_hash_r:
16501560
.zero 64
16511561

1562+
/* Encoded LHS for verification (256 bits). */
1563+
.balign 32
1564+
.globl ed25519_verify_lhs
1565+
ed25519_verify_lhs:
1566+
.zero 32
1567+
1568+
/* Encoded RHS for verification (256 bits). */
1569+
.balign 32
1570+
.globl ed25519_verify_rhs
1571+
ed25519_verify_rhs:
1572+
.zero 32
1573+
16521574
.data
16531575

16541576
/* Affine x coordinate of base point B (see RFC 8032, section 5.1). */

0 commit comments

Comments
 (0)