]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Run through prf result processing even if it >= prime
authorJouni Malinen <j@w1.fi>
Mon, 24 Jun 2019 20:01:06 +0000 (23:01 +0300)
committerJouni Malinen <j@w1.fi>
Tue, 2 Jul 2019 19:19:27 +0000 (22:19 +0300)
This reduces differences in timing and memory access within the
hunting-and-pecking loop for ECC groups that have a prime that is not
close to a power of two (e.g., Brainpool curves).

Signed-off-by: Jouni Malinen <j@w1.fi>
src/common/sae.c

index c1c80710cc1844ca05fcfff763806cd4f11d3549..0da7145e2d183ccaf3aa4e47b3fcc15ce1506eb5 100644 (file)
@@ -142,6 +142,8 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
        struct crypto_bignum *y_sqr, *x_cand;
        int res;
        size_t bits;
+       int cmp_prime;
+       unsigned int in_range;
 
        wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
 
@@ -155,8 +157,13 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
        wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
                        pwd_value, sae->tmp->prime_len);
 
-       if (const_time_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
-               return 0;
+       cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len);
+       /* Create a const_time mask for selection based on prf result
+        * being smaller than prime. */
+       in_range = const_time_fill_msb((unsigned int) cmp_prime);
+       /* The algorithm description would skip the next steps if
+        * cmp_prime >= 0 (reutnr 0 here), but go through them regardless to
+        * minimize externally observable differences in behavior. */
 
        x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
        if (!x_cand)
@@ -169,7 +176,9 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
        res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr,
                                                   y_sqr);
        crypto_bignum_deinit(y_sqr, 1);
-       return res;
+       if (res < 0)
+               return res;
+       return const_time_select_int(in_range, res, 0);
 }