061-0008-SAE-Use-const_time-selection-for-PWE-in-FFC.patch 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. From f8f20717f87eff1f025f48ed585c7684debacf72 Mon Sep 17 00:00:00 2001
  2. From: Jouni Malinen <[email protected]>
  3. Date: Sat, 2 Mar 2019 12:45:33 +0200
  4. Subject: [PATCH 08/14] SAE: Use const_time selection for PWE in FFC
  5. This is an initial step towards making the FFC case use strictly
  6. constant time operations similarly to the ECC case.
  7. sae_test_pwd_seed_ffc() does not yet have constant time behavior,
  8. though.
  9. This is related to CVE-2019-9494.
  10. Signed-off-by: Jouni Malinen <[email protected]>
  11. ---
  12. src/common/sae.c | 53 +++++++++++++++++++++++++++++++++++------------------
  13. 1 file changed, 35 insertions(+), 18 deletions(-)
  14. --- a/src/common/sae.c
  15. +++ b/src/common/sae.c
  16. @@ -589,17 +589,28 @@ static int sae_derive_pwe_ffc(struct sae
  17. const u8 *addr2, const u8 *password,
  18. size_t password_len, const char *identifier)
  19. {
  20. - u8 counter, k;
  21. + u8 counter, k, sel_counter = 0;
  22. u8 addrs[2 * ETH_ALEN];
  23. const u8 *addr[3];
  24. size_t len[3];
  25. size_t num_elem;
  26. - int found = 0;
  27. - struct crypto_bignum *pwe = NULL;
  28. + u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
  29. + * mask */
  30. + u8 mask;
  31. + struct crypto_bignum *pwe;
  32. + size_t prime_len = sae->tmp->prime_len * 8;
  33. + u8 *pwe_buf;
  34. crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
  35. sae->tmp->pwe_ffc = NULL;
  36. + /* Allocate a buffer to maintain selected and candidate PWE for constant
  37. + * time selection. */
  38. + pwe_buf = os_zalloc(prime_len * 2);
  39. + pwe = crypto_bignum_init();
  40. + if (!pwe_buf || !pwe)
  41. + goto fail;
  42. +
  43. wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
  44. password, password_len);
  45. @@ -638,27 +649,33 @@ static int sae_derive_pwe_ffc(struct sae
  46. if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
  47. addr, len, pwd_seed) < 0)
  48. break;
  49. - if (!pwe) {
  50. - pwe = crypto_bignum_init();
  51. - if (!pwe)
  52. - break;
  53. - }
  54. res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
  55. + /* res is -1 for fatal failure, 0 if a valid PWE was not found,
  56. + * or 1 if a valid PWE was found. */
  57. if (res < 0)
  58. break;
  59. - if (res > 0) {
  60. - found = 1;
  61. - if (!sae->tmp->pwe_ffc) {
  62. - wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
  63. - sae->tmp->pwe_ffc = pwe;
  64. - pwe = NULL;
  65. - }
  66. - }
  67. + /* Store the candidate PWE into the second half of pwe_buf and
  68. + * the selected PWE in the beginning of pwe_buf using constant
  69. + * time selection. */
  70. + if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
  71. + prime_len) < 0)
  72. + break;
  73. + const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
  74. + prime_len, pwe_buf);
  75. + sel_counter = const_time_select_u8(found, sel_counter, counter);
  76. + mask = const_time_eq_u8(res, 1);
  77. + found = const_time_select_u8(found, found, mask);
  78. }
  79. - crypto_bignum_deinit(pwe, 1);
  80. + if (!found)
  81. + goto fail;
  82. - return found ? 0 : -1;
  83. + wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
  84. + sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
  85. +fail:
  86. + crypto_bignum_deinit(pwe, 1);
  87. + bin_clear_free(pwe_buf, prime_len * 2);
  88. + return sae->tmp->pwe_ffc ? 0 : -1;
  89. }