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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. From f8f20717f87eff1f025f48ed585c7684debacf72 Mon Sep 17 00:00:00 2001
  2. From: Jouni Malinen <jouni@codeaurora.org>
  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 <jouni@codeaurora.org>
  11. ---
  12. src/common/sae.c | 53 +++++++++++++++++++++++++++++++++++------------------
  13. 1 file changed, 35 insertions(+), 18 deletions(-)
  14. diff --git a/src/common/sae.c b/src/common/sae.c
  15. index 75b1b4a..fa9a145 100644
  16. --- a/src/common/sae.c
  17. +++ b/src/common/sae.c
  18. @@ -612,17 +612,28 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
  19. const u8 *addr2, const u8 *password,
  20. size_t password_len, const char *identifier)
  21. {
  22. - u8 counter, k;
  23. + u8 counter, k, sel_counter = 0;
  24. u8 addrs[2 * ETH_ALEN];
  25. const u8 *addr[3];
  26. size_t len[3];
  27. size_t num_elem;
  28. - int found = 0;
  29. - struct crypto_bignum *pwe = NULL;
  30. + u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_*
  31. + * mask */
  32. + u8 mask;
  33. + struct crypto_bignum *pwe;
  34. + size_t prime_len = sae->tmp->prime_len * 8;
  35. + u8 *pwe_buf;
  36. crypto_bignum_deinit(sae->tmp->pwe_ffc, 1);
  37. sae->tmp->pwe_ffc = NULL;
  38. + /* Allocate a buffer to maintain selected and candidate PWE for constant
  39. + * time selection. */
  40. + pwe_buf = os_zalloc(prime_len * 2);
  41. + pwe = crypto_bignum_init();
  42. + if (!pwe_buf || !pwe)
  43. + goto fail;
  44. +
  45. wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
  46. password, password_len);
  47. @@ -661,27 +672,33 @@ static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
  48. if (hmac_sha256_vector(addrs, sizeof(addrs), num_elem,
  49. addr, len, pwd_seed) < 0)
  50. break;
  51. - if (!pwe) {
  52. - pwe = crypto_bignum_init();
  53. - if (!pwe)
  54. - break;
  55. - }
  56. res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe);
  57. + /* res is -1 for fatal failure, 0 if a valid PWE was not found,
  58. + * or 1 if a valid PWE was found. */
  59. if (res < 0)
  60. break;
  61. - if (res > 0) {
  62. - found = 1;
  63. - if (!sae->tmp->pwe_ffc) {
  64. - wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
  65. - sae->tmp->pwe_ffc = pwe;
  66. - pwe = NULL;
  67. - }
  68. - }
  69. + /* Store the candidate PWE into the second half of pwe_buf and
  70. + * the selected PWE in the beginning of pwe_buf using constant
  71. + * time selection. */
  72. + if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len,
  73. + prime_len) < 0)
  74. + break;
  75. + const_time_select_bin(found, pwe_buf, pwe_buf + prime_len,
  76. + prime_len, pwe_buf);
  77. + sel_counter = const_time_select_u8(found, sel_counter, counter);
  78. + mask = const_time_eq_u8(res, 1);
  79. + found = const_time_select_u8(found, found, mask);
  80. }
  81. - crypto_bignum_deinit(pwe, 1);
  82. + if (!found)
  83. + goto fail;
  84. - return found ? 0 : -1;
  85. + wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter);
  86. + sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len);
  87. +fail:
  88. + crypto_bignum_deinit(pwe, 1);
  89. + bin_clear_free(pwe_buf, prime_len * 2);
  90. + return sae->tmp->pwe_ffc ? 0 : -1;
  91. }
  92. --
  93. 2.7.4