1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * Shared Dragonfly functionality 3e5b75505Sopenharmony_ci * Copyright (c) 2012-2016, Jouni Malinen <j@w1.fi> 4e5b75505Sopenharmony_ci * Copyright (c) 2019, The Linux Foundation 5e5b75505Sopenharmony_ci * 6e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license. 7e5b75505Sopenharmony_ci * See README for more details. 8e5b75505Sopenharmony_ci */ 9e5b75505Sopenharmony_ci 10e5b75505Sopenharmony_ci#include "utils/includes.h" 11e5b75505Sopenharmony_ci 12e5b75505Sopenharmony_ci#include "utils/common.h" 13e5b75505Sopenharmony_ci#include "utils/const_time.h" 14e5b75505Sopenharmony_ci#include "crypto/crypto.h" 15e5b75505Sopenharmony_ci#include "dragonfly.h" 16e5b75505Sopenharmony_ci 17e5b75505Sopenharmony_ci 18e5b75505Sopenharmony_ciint dragonfly_suitable_group(int group, int ecc_only) 19e5b75505Sopenharmony_ci{ 20e5b75505Sopenharmony_ci /* Enforce REVmd rules on which SAE groups are suitable for production 21e5b75505Sopenharmony_ci * purposes: FFC groups whose prime is >= 3072 bits and ECC groups 22e5b75505Sopenharmony_ci * defined over a prime field whose prime is >= 256 bits. Furthermore, 23e5b75505Sopenharmony_ci * ECC groups defined over a characteristic 2 finite field and ECC 24e5b75505Sopenharmony_ci * groups with a co-factor greater than 1 are not suitable. Disable 25e5b75505Sopenharmony_ci * groups that use Brainpool curves as well for now since they leak more 26e5b75505Sopenharmony_ci * timing information due to the prime not being close to a power of 27e5b75505Sopenharmony_ci * two. */ 28e5b75505Sopenharmony_ci return group == 19 || group == 20 || group == 21 || 29e5b75505Sopenharmony_ci (!ecc_only && 30e5b75505Sopenharmony_ci (group == 15 || group == 16 || group == 17 || group == 18)); 31e5b75505Sopenharmony_ci} 32e5b75505Sopenharmony_ci 33e5b75505Sopenharmony_ci 34e5b75505Sopenharmony_ciunsigned int dragonfly_min_pwe_loop_iter(int group) 35e5b75505Sopenharmony_ci{ 36e5b75505Sopenharmony_ci if (group == 22 || group == 23 || group == 24) { 37e5b75505Sopenharmony_ci /* FFC groups for which pwd-value is likely to be >= p 38e5b75505Sopenharmony_ci * frequently */ 39e5b75505Sopenharmony_ci return 40; 40e5b75505Sopenharmony_ci } 41e5b75505Sopenharmony_ci 42e5b75505Sopenharmony_ci if (group == 1 || group == 2 || group == 5 || group == 14 || 43e5b75505Sopenharmony_ci group == 15 || group == 16 || group == 17 || group == 18) { 44e5b75505Sopenharmony_ci /* FFC groups that have prime that is close to a power of two */ 45e5b75505Sopenharmony_ci return 1; 46e5b75505Sopenharmony_ci } 47e5b75505Sopenharmony_ci 48e5b75505Sopenharmony_ci /* Default to 40 (this covers most ECC groups) */ 49e5b75505Sopenharmony_ci return 40; 50e5b75505Sopenharmony_ci} 51e5b75505Sopenharmony_ci 52e5b75505Sopenharmony_ci 53e5b75505Sopenharmony_ciint dragonfly_get_random_qr_qnr(const struct crypto_bignum *prime, 54e5b75505Sopenharmony_ci struct crypto_bignum **qr, 55e5b75505Sopenharmony_ci struct crypto_bignum **qnr) 56e5b75505Sopenharmony_ci{ 57e5b75505Sopenharmony_ci *qr = *qnr = NULL; 58e5b75505Sopenharmony_ci 59e5b75505Sopenharmony_ci while (!(*qr) || !(*qnr)) { 60e5b75505Sopenharmony_ci struct crypto_bignum *tmp; 61e5b75505Sopenharmony_ci int res; 62e5b75505Sopenharmony_ci 63e5b75505Sopenharmony_ci tmp = crypto_bignum_init(); 64e5b75505Sopenharmony_ci if (!tmp || crypto_bignum_rand(tmp, prime) < 0) { 65e5b75505Sopenharmony_ci crypto_bignum_deinit(tmp, 0); 66e5b75505Sopenharmony_ci break; 67e5b75505Sopenharmony_ci } 68e5b75505Sopenharmony_ci 69e5b75505Sopenharmony_ci res = crypto_bignum_legendre(tmp, prime); 70e5b75505Sopenharmony_ci if (res == 1 && !(*qr)) 71e5b75505Sopenharmony_ci *qr = tmp; 72e5b75505Sopenharmony_ci else if (res == -1 && !(*qnr)) 73e5b75505Sopenharmony_ci *qnr = tmp; 74e5b75505Sopenharmony_ci else 75e5b75505Sopenharmony_ci crypto_bignum_deinit(tmp, 0); 76e5b75505Sopenharmony_ci } 77e5b75505Sopenharmony_ci 78e5b75505Sopenharmony_ci if (*qr && *qnr) 79e5b75505Sopenharmony_ci return 0; 80e5b75505Sopenharmony_ci crypto_bignum_deinit(*qr, 0); 81e5b75505Sopenharmony_ci crypto_bignum_deinit(*qnr, 0); 82e5b75505Sopenharmony_ci *qr = *qnr = NULL; 83e5b75505Sopenharmony_ci return -1; 84e5b75505Sopenharmony_ci} 85e5b75505Sopenharmony_ci 86e5b75505Sopenharmony_ci 87e5b75505Sopenharmony_cistatic struct crypto_bignum * 88e5b75505Sopenharmony_cidragonfly_get_rand_1_to_p_1(const struct crypto_bignum *prime) 89e5b75505Sopenharmony_ci{ 90e5b75505Sopenharmony_ci struct crypto_bignum *tmp, *pm1, *one; 91e5b75505Sopenharmony_ci 92e5b75505Sopenharmony_ci tmp = crypto_bignum_init(); 93e5b75505Sopenharmony_ci pm1 = crypto_bignum_init(); 94e5b75505Sopenharmony_ci one = crypto_bignum_init_set((const u8 *) "\x01", 1); 95e5b75505Sopenharmony_ci if (!tmp || !pm1 || !one || 96e5b75505Sopenharmony_ci crypto_bignum_sub(prime, one, pm1) < 0 || 97e5b75505Sopenharmony_ci crypto_bignum_rand(tmp, pm1) < 0 || 98e5b75505Sopenharmony_ci crypto_bignum_add(tmp, one, tmp) < 0) { 99e5b75505Sopenharmony_ci crypto_bignum_deinit(tmp, 0); 100e5b75505Sopenharmony_ci tmp = NULL; 101e5b75505Sopenharmony_ci } 102e5b75505Sopenharmony_ci 103e5b75505Sopenharmony_ci crypto_bignum_deinit(pm1, 0); 104e5b75505Sopenharmony_ci crypto_bignum_deinit(one, 0); 105e5b75505Sopenharmony_ci return tmp; 106e5b75505Sopenharmony_ci} 107e5b75505Sopenharmony_ci 108e5b75505Sopenharmony_ci 109e5b75505Sopenharmony_ciint dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec, 110e5b75505Sopenharmony_ci const u8 *qr, const u8 *qnr, 111e5b75505Sopenharmony_ci const struct crypto_bignum *val) 112e5b75505Sopenharmony_ci{ 113e5b75505Sopenharmony_ci struct crypto_bignum *r, *num, *qr_or_qnr = NULL; 114e5b75505Sopenharmony_ci int check, res = -1; 115e5b75505Sopenharmony_ci u8 qr_or_qnr_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; 116e5b75505Sopenharmony_ci const struct crypto_bignum *prime; 117e5b75505Sopenharmony_ci size_t prime_len; 118e5b75505Sopenharmony_ci unsigned int mask; 119e5b75505Sopenharmony_ci 120e5b75505Sopenharmony_ci prime = crypto_ec_get_prime(ec); 121e5b75505Sopenharmony_ci prime_len = crypto_ec_prime_len(ec); 122e5b75505Sopenharmony_ci 123e5b75505Sopenharmony_ci /* 124e5b75505Sopenharmony_ci * Use a blinding technique to mask val while determining whether it is 125e5b75505Sopenharmony_ci * a quadratic residue modulo p to avoid leaking timing information 126e5b75505Sopenharmony_ci * while determining the Legendre symbol. 127e5b75505Sopenharmony_ci * 128e5b75505Sopenharmony_ci * v = val 129e5b75505Sopenharmony_ci * r = a random number between 1 and p-1, inclusive 130e5b75505Sopenharmony_ci * num = (v * r * r) modulo p 131e5b75505Sopenharmony_ci */ 132e5b75505Sopenharmony_ci r = dragonfly_get_rand_1_to_p_1(prime); 133e5b75505Sopenharmony_ci if (!r) 134e5b75505Sopenharmony_ci return -1; 135e5b75505Sopenharmony_ci 136e5b75505Sopenharmony_ci num = crypto_bignum_init(); 137e5b75505Sopenharmony_ci if (!num || 138e5b75505Sopenharmony_ci crypto_bignum_mulmod(val, r, prime, num) < 0 || 139e5b75505Sopenharmony_ci crypto_bignum_mulmod(num, r, prime, num) < 0) 140e5b75505Sopenharmony_ci goto fail; 141e5b75505Sopenharmony_ci 142e5b75505Sopenharmony_ci /* 143e5b75505Sopenharmony_ci * Need to minimize differences in handling different cases, so try to 144e5b75505Sopenharmony_ci * avoid branches and timing differences. 145e5b75505Sopenharmony_ci * 146e5b75505Sopenharmony_ci * If r is odd: 147e5b75505Sopenharmony_ci * num = (num * qr) module p 148e5b75505Sopenharmony_ci * LGR(num, p) = 1 ==> quadratic residue 149e5b75505Sopenharmony_ci * else: 150e5b75505Sopenharmony_ci * num = (num * qnr) module p 151e5b75505Sopenharmony_ci * LGR(num, p) = -1 ==> quadratic residue 152e5b75505Sopenharmony_ci * 153e5b75505Sopenharmony_ci * mask is set to !odd(r) 154e5b75505Sopenharmony_ci */ 155e5b75505Sopenharmony_ci mask = const_time_is_zero(crypto_bignum_is_odd(r)); 156e5b75505Sopenharmony_ci const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin); 157e5b75505Sopenharmony_ci qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len); 158e5b75505Sopenharmony_ci if (!qr_or_qnr || 159e5b75505Sopenharmony_ci crypto_bignum_mulmod(num, qr_or_qnr, prime, num) < 0) 160e5b75505Sopenharmony_ci goto fail; 161e5b75505Sopenharmony_ci /* branchless version of check = odd(r) ? 1 : -1, */ 162e5b75505Sopenharmony_ci check = const_time_select_int(mask, -1, 1); 163e5b75505Sopenharmony_ci 164e5b75505Sopenharmony_ci /* Determine the Legendre symbol on the masked value */ 165e5b75505Sopenharmony_ci res = crypto_bignum_legendre(num, prime); 166e5b75505Sopenharmony_ci if (res == -2) { 167e5b75505Sopenharmony_ci res = -1; 168e5b75505Sopenharmony_ci goto fail; 169e5b75505Sopenharmony_ci } 170e5b75505Sopenharmony_ci /* branchless version of res = res == check 171e5b75505Sopenharmony_ci * (res is -1, 0, or 1; check is -1 or 1) */ 172e5b75505Sopenharmony_ci mask = const_time_eq(res, check); 173e5b75505Sopenharmony_ci res = const_time_select_int(mask, 1, 0); 174e5b75505Sopenharmony_cifail: 175e5b75505Sopenharmony_ci crypto_bignum_deinit(num, 1); 176e5b75505Sopenharmony_ci crypto_bignum_deinit(r, 1); 177e5b75505Sopenharmony_ci crypto_bignum_deinit(qr_or_qnr, 1); 178e5b75505Sopenharmony_ci return res; 179e5b75505Sopenharmony_ci} 180e5b75505Sopenharmony_ci 181e5b75505Sopenharmony_ci 182e5b75505Sopenharmony_cistatic int dragonfly_get_rand_2_to_r_1(struct crypto_bignum *val, 183e5b75505Sopenharmony_ci const struct crypto_bignum *order) 184e5b75505Sopenharmony_ci{ 185e5b75505Sopenharmony_ci return crypto_bignum_rand(val, order) == 0 && 186e5b75505Sopenharmony_ci !crypto_bignum_is_zero(val) && 187e5b75505Sopenharmony_ci !crypto_bignum_is_one(val); 188e5b75505Sopenharmony_ci} 189e5b75505Sopenharmony_ci 190e5b75505Sopenharmony_ci 191e5b75505Sopenharmony_ciint dragonfly_generate_scalar(const struct crypto_bignum *order, 192e5b75505Sopenharmony_ci struct crypto_bignum *_rand, 193e5b75505Sopenharmony_ci struct crypto_bignum *_mask, 194e5b75505Sopenharmony_ci struct crypto_bignum *scalar) 195e5b75505Sopenharmony_ci{ 196e5b75505Sopenharmony_ci int count; 197e5b75505Sopenharmony_ci 198e5b75505Sopenharmony_ci /* Select two random values rand,mask such that 1 < rand,mask < r and 199e5b75505Sopenharmony_ci * rand + mask mod r > 1. */ 200e5b75505Sopenharmony_ci for (count = 0; count < 100; count++) { 201e5b75505Sopenharmony_ci if (dragonfly_get_rand_2_to_r_1(_rand, order) && 202e5b75505Sopenharmony_ci dragonfly_get_rand_2_to_r_1(_mask, order) && 203e5b75505Sopenharmony_ci crypto_bignum_add(_rand, _mask, scalar) == 0 && 204e5b75505Sopenharmony_ci crypto_bignum_mod(scalar, order, scalar) == 0 && 205e5b75505Sopenharmony_ci !crypto_bignum_is_zero(scalar) && 206e5b75505Sopenharmony_ci !crypto_bignum_is_one(scalar)) 207e5b75505Sopenharmony_ci return 0; 208e5b75505Sopenharmony_ci } 209e5b75505Sopenharmony_ci 210e5b75505Sopenharmony_ci /* This should not be reachable in practice if the random number 211e5b75505Sopenharmony_ci * generation is working. */ 212e5b75505Sopenharmony_ci wpa_printf(MSG_INFO, 213e5b75505Sopenharmony_ci "dragonfly: Unable to get randomness for own scalar"); 214e5b75505Sopenharmony_ci return -1; 215e5b75505Sopenharmony_ci} 216e5b75505Sopenharmony_ci 217e5b75505Sopenharmony_ci 218e5b75505Sopenharmony_ci/* res = sqrt(val) */ 219e5b75505Sopenharmony_ciint dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, 220e5b75505Sopenharmony_ci struct crypto_bignum *res) 221e5b75505Sopenharmony_ci{ 222e5b75505Sopenharmony_ci const struct crypto_bignum *prime; 223e5b75505Sopenharmony_ci struct crypto_bignum *tmp, *one; 224e5b75505Sopenharmony_ci int ret = 0; 225e5b75505Sopenharmony_ci u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; 226e5b75505Sopenharmony_ci size_t prime_len; 227e5b75505Sopenharmony_ci 228e5b75505Sopenharmony_ci /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */ 229e5b75505Sopenharmony_ci 230e5b75505Sopenharmony_ci prime = crypto_ec_get_prime(ec); 231e5b75505Sopenharmony_ci prime_len = crypto_ec_prime_len(ec); 232e5b75505Sopenharmony_ci tmp = crypto_bignum_init(); 233e5b75505Sopenharmony_ci one = crypto_bignum_init_uint(1); 234e5b75505Sopenharmony_ci 235e5b75505Sopenharmony_ci if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), 236e5b75505Sopenharmony_ci prime_len) < 0 || 237e5b75505Sopenharmony_ci (prime_bin[prime_len - 1] & 0x03) != 3 || 238e5b75505Sopenharmony_ci !tmp || !one || 239e5b75505Sopenharmony_ci /* tmp = (p+1)/4 */ 240e5b75505Sopenharmony_ci crypto_bignum_add(prime, one, tmp) < 0 || 241e5b75505Sopenharmony_ci crypto_bignum_rshift(tmp, 2, tmp) < 0 || 242e5b75505Sopenharmony_ci /* res = sqrt(val) */ 243e5b75505Sopenharmony_ci crypto_bignum_exptmod(val, tmp, prime, res) < 0) 244e5b75505Sopenharmony_ci ret = -1; 245e5b75505Sopenharmony_ci 246e5b75505Sopenharmony_ci crypto_bignum_deinit(tmp, 0); 247e5b75505Sopenharmony_ci crypto_bignum_deinit(one, 0); 248e5b75505Sopenharmony_ci return ret; 249e5b75505Sopenharmony_ci} 250