1206b73d0SCy Schubert /* 2206b73d0SCy Schubert * Shared Dragonfly functionality 3206b73d0SCy Schubert * Copyright (c) 2012-2016, Jouni Malinen <j@w1.fi> 4206b73d0SCy Schubert * Copyright (c) 2019, The Linux Foundation 5206b73d0SCy Schubert * 6206b73d0SCy Schubert * This software may be distributed under the terms of the BSD license. 7206b73d0SCy Schubert * See README for more details. 8206b73d0SCy Schubert */ 9206b73d0SCy Schubert 10206b73d0SCy Schubert #include "utils/includes.h" 11206b73d0SCy Schubert 12206b73d0SCy Schubert #include "utils/common.h" 13206b73d0SCy Schubert #include "utils/const_time.h" 14206b73d0SCy Schubert #include "crypto/crypto.h" 15206b73d0SCy Schubert #include "dragonfly.h" 16206b73d0SCy Schubert 17206b73d0SCy Schubert 18206b73d0SCy Schubert int dragonfly_suitable_group(int group, int ecc_only) 19206b73d0SCy Schubert { 20206b73d0SCy Schubert /* Enforce REVmd rules on which SAE groups are suitable for production 21206b73d0SCy Schubert * purposes: FFC groups whose prime is >= 3072 bits and ECC groups 22206b73d0SCy Schubert * defined over a prime field whose prime is >= 256 bits. Furthermore, 23206b73d0SCy Schubert * ECC groups defined over a characteristic 2 finite field and ECC 24206b73d0SCy Schubert * groups with a co-factor greater than 1 are not suitable. Disable 25206b73d0SCy Schubert * groups that use Brainpool curves as well for now since they leak more 26206b73d0SCy Schubert * timing information due to the prime not being close to a power of 27206b73d0SCy Schubert * two. */ 28206b73d0SCy Schubert return group == 19 || group == 20 || group == 21 || 29206b73d0SCy Schubert (!ecc_only && 30206b73d0SCy Schubert (group == 15 || group == 16 || group == 17 || group == 18)); 31206b73d0SCy Schubert } 32206b73d0SCy Schubert 33206b73d0SCy Schubert 34206b73d0SCy Schubert unsigned int dragonfly_min_pwe_loop_iter(int group) 35206b73d0SCy Schubert { 36206b73d0SCy Schubert if (group == 22 || group == 23 || group == 24) { 37206b73d0SCy Schubert /* FFC groups for which pwd-value is likely to be >= p 38206b73d0SCy Schubert * frequently */ 39206b73d0SCy Schubert return 40; 40206b73d0SCy Schubert } 41206b73d0SCy Schubert 42206b73d0SCy Schubert if (group == 1 || group == 2 || group == 5 || group == 14 || 43206b73d0SCy Schubert group == 15 || group == 16 || group == 17 || group == 18) { 44206b73d0SCy Schubert /* FFC groups that have prime that is close to a power of two */ 45206b73d0SCy Schubert return 1; 46206b73d0SCy Schubert } 47206b73d0SCy Schubert 48206b73d0SCy Schubert /* Default to 40 (this covers most ECC groups) */ 49206b73d0SCy Schubert return 40; 50206b73d0SCy Schubert } 51206b73d0SCy Schubert 52206b73d0SCy Schubert 53206b73d0SCy Schubert int dragonfly_get_random_qr_qnr(const struct crypto_bignum *prime, 54206b73d0SCy Schubert struct crypto_bignum **qr, 55206b73d0SCy Schubert struct crypto_bignum **qnr) 56206b73d0SCy Schubert { 57206b73d0SCy Schubert *qr = *qnr = NULL; 58206b73d0SCy Schubert 59206b73d0SCy Schubert while (!(*qr) || !(*qnr)) { 60206b73d0SCy Schubert struct crypto_bignum *tmp; 61206b73d0SCy Schubert int res; 62206b73d0SCy Schubert 63206b73d0SCy Schubert tmp = crypto_bignum_init(); 64206b73d0SCy Schubert if (!tmp || crypto_bignum_rand(tmp, prime) < 0) { 65206b73d0SCy Schubert crypto_bignum_deinit(tmp, 0); 66206b73d0SCy Schubert break; 67206b73d0SCy Schubert } 68206b73d0SCy Schubert 69206b73d0SCy Schubert res = crypto_bignum_legendre(tmp, prime); 70*a90b9d01SCy Schubert if (res == 1 && !(*qr)) { 71206b73d0SCy Schubert *qr = tmp; 72*a90b9d01SCy Schubert } else if (res == -1 && !(*qnr)) { 73206b73d0SCy Schubert *qnr = tmp; 74*a90b9d01SCy Schubert } else { 75206b73d0SCy Schubert crypto_bignum_deinit(tmp, 0); 76*a90b9d01SCy Schubert if (res == -2) 77*a90b9d01SCy Schubert break; 78*a90b9d01SCy Schubert } 79206b73d0SCy Schubert } 80206b73d0SCy Schubert 81206b73d0SCy Schubert if (*qr && *qnr) 82206b73d0SCy Schubert return 0; 83206b73d0SCy Schubert crypto_bignum_deinit(*qr, 0); 84206b73d0SCy Schubert crypto_bignum_deinit(*qnr, 0); 85206b73d0SCy Schubert *qr = *qnr = NULL; 86206b73d0SCy Schubert return -1; 87206b73d0SCy Schubert } 88206b73d0SCy Schubert 89206b73d0SCy Schubert 90206b73d0SCy Schubert static struct crypto_bignum * 91206b73d0SCy Schubert dragonfly_get_rand_1_to_p_1(const struct crypto_bignum *prime) 92206b73d0SCy Schubert { 93206b73d0SCy Schubert struct crypto_bignum *tmp, *pm1, *one; 94206b73d0SCy Schubert 95206b73d0SCy Schubert tmp = crypto_bignum_init(); 96206b73d0SCy Schubert pm1 = crypto_bignum_init(); 97206b73d0SCy Schubert one = crypto_bignum_init_set((const u8 *) "\x01", 1); 98206b73d0SCy Schubert if (!tmp || !pm1 || !one || 99206b73d0SCy Schubert crypto_bignum_sub(prime, one, pm1) < 0 || 100206b73d0SCy Schubert crypto_bignum_rand(tmp, pm1) < 0 || 101206b73d0SCy Schubert crypto_bignum_add(tmp, one, tmp) < 0) { 102206b73d0SCy Schubert crypto_bignum_deinit(tmp, 0); 103206b73d0SCy Schubert tmp = NULL; 104206b73d0SCy Schubert } 105206b73d0SCy Schubert 106206b73d0SCy Schubert crypto_bignum_deinit(pm1, 0); 107206b73d0SCy Schubert crypto_bignum_deinit(one, 0); 108206b73d0SCy Schubert return tmp; 109206b73d0SCy Schubert } 110206b73d0SCy Schubert 111206b73d0SCy Schubert 112206b73d0SCy Schubert int dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec, 113206b73d0SCy Schubert const u8 *qr, const u8 *qnr, 114206b73d0SCy Schubert const struct crypto_bignum *val) 115206b73d0SCy Schubert { 116206b73d0SCy Schubert struct crypto_bignum *r, *num, *qr_or_qnr = NULL; 117206b73d0SCy Schubert int check, res = -1; 118206b73d0SCy Schubert u8 qr_or_qnr_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; 119206b73d0SCy Schubert const struct crypto_bignum *prime; 120206b73d0SCy Schubert size_t prime_len; 121206b73d0SCy Schubert unsigned int mask; 122206b73d0SCy Schubert 123206b73d0SCy Schubert prime = crypto_ec_get_prime(ec); 124206b73d0SCy Schubert prime_len = crypto_ec_prime_len(ec); 125206b73d0SCy Schubert 126206b73d0SCy Schubert /* 127206b73d0SCy Schubert * Use a blinding technique to mask val while determining whether it is 128206b73d0SCy Schubert * a quadratic residue modulo p to avoid leaking timing information 129206b73d0SCy Schubert * while determining the Legendre symbol. 130206b73d0SCy Schubert * 131206b73d0SCy Schubert * v = val 132206b73d0SCy Schubert * r = a random number between 1 and p-1, inclusive 133206b73d0SCy Schubert * num = (v * r * r) modulo p 134206b73d0SCy Schubert */ 135206b73d0SCy Schubert r = dragonfly_get_rand_1_to_p_1(prime); 136206b73d0SCy Schubert if (!r) 137206b73d0SCy Schubert return -1; 138206b73d0SCy Schubert 139206b73d0SCy Schubert num = crypto_bignum_init(); 140206b73d0SCy Schubert if (!num || 141206b73d0SCy Schubert crypto_bignum_mulmod(val, r, prime, num) < 0 || 142206b73d0SCy Schubert crypto_bignum_mulmod(num, r, prime, num) < 0) 143206b73d0SCy Schubert goto fail; 144206b73d0SCy Schubert 145206b73d0SCy Schubert /* 146206b73d0SCy Schubert * Need to minimize differences in handling different cases, so try to 147206b73d0SCy Schubert * avoid branches and timing differences. 148206b73d0SCy Schubert * 149206b73d0SCy Schubert * If r is odd: 150206b73d0SCy Schubert * num = (num * qr) module p 151206b73d0SCy Schubert * LGR(num, p) = 1 ==> quadratic residue 152206b73d0SCy Schubert * else: 153206b73d0SCy Schubert * num = (num * qnr) module p 154206b73d0SCy Schubert * LGR(num, p) = -1 ==> quadratic residue 155206b73d0SCy Schubert * 156206b73d0SCy Schubert * mask is set to !odd(r) 157206b73d0SCy Schubert */ 158206b73d0SCy Schubert mask = const_time_is_zero(crypto_bignum_is_odd(r)); 159206b73d0SCy Schubert const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin); 160206b73d0SCy Schubert qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len); 161206b73d0SCy Schubert if (!qr_or_qnr || 162206b73d0SCy Schubert crypto_bignum_mulmod(num, qr_or_qnr, prime, num) < 0) 163206b73d0SCy Schubert goto fail; 164206b73d0SCy Schubert /* branchless version of check = odd(r) ? 1 : -1, */ 165206b73d0SCy Schubert check = const_time_select_int(mask, -1, 1); 166206b73d0SCy Schubert 167206b73d0SCy Schubert /* Determine the Legendre symbol on the masked value */ 168206b73d0SCy Schubert res = crypto_bignum_legendre(num, prime); 169206b73d0SCy Schubert if (res == -2) { 170206b73d0SCy Schubert res = -1; 171206b73d0SCy Schubert goto fail; 172206b73d0SCy Schubert } 173206b73d0SCy Schubert /* branchless version of res = res == check 174206b73d0SCy Schubert * (res is -1, 0, or 1; check is -1 or 1) */ 175206b73d0SCy Schubert mask = const_time_eq(res, check); 176206b73d0SCy Schubert res = const_time_select_int(mask, 1, 0); 177206b73d0SCy Schubert fail: 178206b73d0SCy Schubert crypto_bignum_deinit(num, 1); 179206b73d0SCy Schubert crypto_bignum_deinit(r, 1); 180206b73d0SCy Schubert crypto_bignum_deinit(qr_or_qnr, 1); 181206b73d0SCy Schubert return res; 182206b73d0SCy Schubert } 183206b73d0SCy Schubert 184206b73d0SCy Schubert 185206b73d0SCy Schubert static int dragonfly_get_rand_2_to_r_1(struct crypto_bignum *val, 186206b73d0SCy Schubert const struct crypto_bignum *order) 187206b73d0SCy Schubert { 188206b73d0SCy Schubert return crypto_bignum_rand(val, order) == 0 && 189206b73d0SCy Schubert !crypto_bignum_is_zero(val) && 190206b73d0SCy Schubert !crypto_bignum_is_one(val); 191206b73d0SCy Schubert } 192206b73d0SCy Schubert 193206b73d0SCy Schubert 194206b73d0SCy Schubert int dragonfly_generate_scalar(const struct crypto_bignum *order, 195206b73d0SCy Schubert struct crypto_bignum *_rand, 196206b73d0SCy Schubert struct crypto_bignum *_mask, 197206b73d0SCy Schubert struct crypto_bignum *scalar) 198206b73d0SCy Schubert { 199206b73d0SCy Schubert int count; 200206b73d0SCy Schubert 201206b73d0SCy Schubert /* Select two random values rand,mask such that 1 < rand,mask < r and 202206b73d0SCy Schubert * rand + mask mod r > 1. */ 203206b73d0SCy Schubert for (count = 0; count < 100; count++) { 204206b73d0SCy Schubert if (dragonfly_get_rand_2_to_r_1(_rand, order) && 205206b73d0SCy Schubert dragonfly_get_rand_2_to_r_1(_mask, order) && 206206b73d0SCy Schubert crypto_bignum_add(_rand, _mask, scalar) == 0 && 207206b73d0SCy Schubert crypto_bignum_mod(scalar, order, scalar) == 0 && 208206b73d0SCy Schubert !crypto_bignum_is_zero(scalar) && 209206b73d0SCy Schubert !crypto_bignum_is_one(scalar)) 210206b73d0SCy Schubert return 0; 211206b73d0SCy Schubert } 212206b73d0SCy Schubert 213206b73d0SCy Schubert /* This should not be reachable in practice if the random number 214206b73d0SCy Schubert * generation is working. */ 215206b73d0SCy Schubert wpa_printf(MSG_INFO, 216206b73d0SCy Schubert "dragonfly: Unable to get randomness for own scalar"); 217206b73d0SCy Schubert return -1; 218206b73d0SCy Schubert } 219ec080394SCy Schubert 220ec080394SCy Schubert 221ec080394SCy Schubert /* res = sqrt(val) */ 222ec080394SCy Schubert int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, 223ec080394SCy Schubert struct crypto_bignum *res) 224ec080394SCy Schubert { 225ec080394SCy Schubert const struct crypto_bignum *prime; 226ec080394SCy Schubert struct crypto_bignum *tmp, *one; 227ec080394SCy Schubert int ret = 0; 228ec080394SCy Schubert u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; 229ec080394SCy Schubert size_t prime_len; 230ec080394SCy Schubert 231ec080394SCy Schubert /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */ 232ec080394SCy Schubert 233ec080394SCy Schubert prime = crypto_ec_get_prime(ec); 234ec080394SCy Schubert prime_len = crypto_ec_prime_len(ec); 235ec080394SCy Schubert tmp = crypto_bignum_init(); 236ec080394SCy Schubert one = crypto_bignum_init_uint(1); 237ec080394SCy Schubert 238ec080394SCy Schubert if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), 239ec080394SCy Schubert prime_len) < 0 || 240ec080394SCy Schubert (prime_bin[prime_len - 1] & 0x03) != 3 || 241ec080394SCy Schubert !tmp || !one || 242ec080394SCy Schubert /* tmp = (p+1)/4 */ 243ec080394SCy Schubert crypto_bignum_add(prime, one, tmp) < 0 || 244ec080394SCy Schubert crypto_bignum_rshift(tmp, 2, tmp) < 0 || 245ec080394SCy Schubert /* res = sqrt(val) */ 246ec080394SCy Schubert crypto_bignum_exptmod(val, tmp, prime, res) < 0) 247ec080394SCy Schubert ret = -1; 248ec080394SCy Schubert 249ec080394SCy Schubert crypto_bignum_deinit(tmp, 0); 250ec080394SCy Schubert crypto_bignum_deinit(one, 0); 251ec080394SCy Schubert return ret; 252ec080394SCy Schubert } 253