Skip to content

Commit cbedccd

Browse files
committed
Constant-time X25519 order reduction
1 parent 7a4845a commit cbedccd

1 file changed

Lines changed: 23 additions & 12 deletions

File tree

src/wp_ecx_exch.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -248,21 +248,32 @@ static int wp_x25519_derive(wp_EcxCtx* ctx, unsigned char* secret,
248248
ok = 0;
249249
}
250250
if (ok) {
251+
/* Constant-time: always subtract, then select based on
252+
* whether secret >= order. */
253+
unsigned char reduced[CURVE25519_KEYSIZE];
254+
int16_t carry = 0;
255+
byte gt = 0;
256+
byte eq = 0xFF;
257+
258+
for (i = CURVE25519_KEYSIZE - 1; i >= 0; i--) {
259+
carry += secret[i];
260+
carry -= wp_curve25519_order[i];
261+
reduced[i] = (unsigned char)carry;
262+
carry >>= 8;
263+
}
264+
/* Determine if secret >= order in constant time. */
251265
for (i = 0; i < CURVE25519_KEYSIZE; i++) {
252-
if (secret[i] != wp_curve25519_order[i]) {
253-
break;
254-
}
266+
gt |= eq & wp_ct_int_mask_gte(secret[i],
267+
wp_curve25519_order[i] + 1);
268+
eq &= wp_ct_byte_mask_eq(secret[i],
269+
wp_curve25519_order[i]);
255270
}
256-
if ((i < CURVE25519_KEYSIZE) &&
257-
(secret[i] > wp_curve25519_order[i])) {
258-
int16_t carry = 0;
259-
for (i = CURVE25519_KEYSIZE - 1; i >= 0; i--) {
260-
carry += secret[i];
261-
carry -= wp_curve25519_order[i];
262-
secret[i] = (unsigned char)carry;
263-
carry >>= 8;
264-
}
271+
/* Select reduced if secret >= order. */
272+
for (i = 0; i < CURVE25519_KEYSIZE; i++) {
273+
secret[i] = wp_ct_byte_mask_sel(gt | eq, reduced[i],
274+
secret[i]);
265275
}
276+
OPENSSL_cleanse(reduced, sizeof(reduced));
266277
}
267278
if (ok) {
268279
*secLen = len;

0 commit comments

Comments
 (0)