Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ecc - regularize scalar for scalar multiplication

ecc_point_mult is supposed to be used with a regularized scalar,
otherwise, it's possible to deduce the position of the top bit of the
scalar with timing attack. This is important when the scalar is a
private key.

ecc_point_mult is already using a regular algorithm (i.e. having an
operation flow independent of the input scalar) but regularization step
is not implemented.

Arrange scalar to always have fixed top bit by adding a multiple of the
curve order (n).

References:
The constant time regularization step is based on micro-ecc by Kenneth
MacKay and also referenced in the literature (Bernstein, D. J., & Lange,
T. (2017). Montgomery curves and the Montgomery ladder. (Cryptology
ePrint Archive; Vol. 2017/293). s.l.: IACR. Chapter 4.6.2.)

Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Cc: kernel-hardening@lists.openwall.com
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Vitaly Chikunov and committed by
Herbert Xu
3da2c1df 8a5a79d5

+12 -4
+12 -4
crypto/ecc.c
··· 842 842 843 843 static void ecc_point_mult(struct ecc_point *result, 844 844 const struct ecc_point *point, const u64 *scalar, 845 - u64 *initial_z, u64 *curve_prime, 845 + u64 *initial_z, const struct ecc_curve *curve, 846 846 unsigned int ndigits) 847 847 { 848 848 /* R0 and R1 */ 849 849 u64 rx[2][ECC_MAX_DIGITS]; 850 850 u64 ry[2][ECC_MAX_DIGITS]; 851 851 u64 z[ECC_MAX_DIGITS]; 852 + u64 sk[2][ECC_MAX_DIGITS]; 853 + u64 *curve_prime = curve->p; 852 854 int i, nb; 853 - int num_bits = vli_num_bits(scalar, ndigits); 855 + int num_bits; 856 + int carry; 857 + 858 + carry = vli_add(sk[0], scalar, curve->n, ndigits); 859 + vli_add(sk[1], sk[0], curve->n, ndigits); 860 + scalar = sk[!carry]; 861 + num_bits = sizeof(u64) * ndigits * 8 + 1; 854 862 855 863 vli_set(rx[1], point->x, ndigits); 856 864 vli_set(ry[1], point->y, ndigits); ··· 1022 1014 goto out; 1023 1015 } 1024 1016 1025 - ecc_point_mult(pk, &curve->g, priv, NULL, curve->p, ndigits); 1017 + ecc_point_mult(pk, &curve->g, priv, NULL, curve, ndigits); 1026 1018 if (ecc_point_is_zero(pk)) { 1027 1019 ret = -EAGAIN; 1028 1020 goto err_free_point; ··· 1108 1100 goto err_alloc_product; 1109 1101 } 1110 1102 1111 - ecc_point_mult(product, pk, priv, rand_z, curve->p, ndigits); 1103 + ecc_point_mult(product, pk, priv, rand_z, curve, ndigits); 1112 1104 1113 1105 ecc_swap_digits(product->x, secret, ndigits); 1114 1106