Branch data Line data Source code
1 : : /*
2 : : * Simultaneous authentication of equals
3 : : * Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "includes.h"
10 : :
11 : : #include "common.h"
12 : : #include "crypto/crypto.h"
13 : : #include "crypto/sha256.h"
14 : : #include "crypto/random.h"
15 : : #include "crypto/dh_groups.h"
16 : : #include "ieee802_11_defs.h"
17 : : #include "sae.h"
18 : :
19 : :
20 : 18 : int sae_set_group(struct sae_data *sae, int group)
21 : : {
22 : : struct sae_temporary_data *tmp;
23 : :
24 : 18 : sae_clear_data(sae);
25 : 18 : tmp = sae->tmp = os_zalloc(sizeof(*tmp));
26 [ - + ]: 18 : if (tmp == NULL)
27 : 0 : return -1;
28 : :
29 : : /* First, check if this is an ECC group */
30 : 18 : tmp->ec = crypto_ec_init(group);
31 [ + + ]: 18 : if (tmp->ec) {
32 : 13 : sae->group = group;
33 : 13 : tmp->prime_len = crypto_ec_prime_len(tmp->ec);
34 : 13 : tmp->prime = crypto_ec_get_prime(tmp->ec);
35 : 13 : tmp->order = crypto_ec_get_order(tmp->ec);
36 : 13 : return 0;
37 : : }
38 : :
39 : : /* Not an ECC group, check FFC */
40 : 5 : tmp->dh = dh_groups_get(group);
41 [ + - ]: 5 : if (tmp->dh) {
42 : 5 : sae->group = group;
43 : 5 : tmp->prime_len = tmp->dh->prime_len;
44 [ - + ]: 5 : if (tmp->prime_len > SAE_MAX_PRIME_LEN) {
45 : 0 : sae_clear_data(sae);
46 : 0 : return -1;
47 : : }
48 : :
49 : 5 : tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime,
50 : 5 : tmp->prime_len);
51 [ - + ]: 5 : if (tmp->prime_buf == NULL) {
52 : 0 : sae_clear_data(sae);
53 : 0 : return -1;
54 : : }
55 : 5 : tmp->prime = tmp->prime_buf;
56 : :
57 : 5 : tmp->order_buf = crypto_bignum_init_set(tmp->dh->order,
58 : 5 : tmp->dh->order_len);
59 [ - + ]: 5 : if (tmp->order_buf == NULL) {
60 : 0 : sae_clear_data(sae);
61 : 0 : return -1;
62 : : }
63 : 5 : tmp->order = tmp->order_buf;
64 : :
65 : 5 : return 0;
66 : : }
67 : :
68 : : /* Unsupported group */
69 : 18 : return -1;
70 : : }
71 : :
72 : :
73 : 52 : void sae_clear_temp_data(struct sae_data *sae)
74 : : {
75 : : struct sae_temporary_data *tmp;
76 [ + - ][ + + ]: 52 : if (sae == NULL || sae->tmp == NULL)
77 : 52 : return;
78 : 18 : tmp = sae->tmp;
79 : 18 : crypto_ec_deinit(tmp->ec);
80 : 18 : crypto_bignum_deinit(tmp->prime_buf, 0);
81 : 18 : crypto_bignum_deinit(tmp->order_buf, 0);
82 : 18 : crypto_bignum_deinit(tmp->sae_rand, 1);
83 : 18 : crypto_bignum_deinit(tmp->pwe_ffc, 1);
84 : 18 : crypto_bignum_deinit(tmp->own_commit_scalar, 0);
85 : 18 : crypto_bignum_deinit(tmp->own_commit_element_ffc, 0);
86 : 18 : crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0);
87 : 18 : crypto_ec_point_deinit(tmp->pwe_ecc, 1);
88 : 18 : crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0);
89 : 18 : crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0);
90 : 18 : os_free(sae->tmp);
91 : 18 : sae->tmp = NULL;
92 : : }
93 : :
94 : :
95 : 153 : void sae_clear_data(struct sae_data *sae)
96 : : {
97 [ + + ]: 153 : if (sae == NULL)
98 : 153 : return;
99 : 40 : sae_clear_temp_data(sae);
100 : 40 : crypto_bignum_deinit(sae->peer_commit_scalar, 0);
101 : 40 : os_memset(sae, 0, sizeof(*sae));
102 : : }
103 : :
104 : :
105 : 9 : static void buf_shift_right(u8 *buf, size_t len, size_t bits)
106 : : {
107 : : size_t i;
108 [ + + ]: 970 : for (i = len - 1; i > 0; i--)
109 : 961 : buf[i] = (buf[i - 1] << (8 - bits)) | (buf[i] >> bits);
110 : 9 : buf[0] >>= bits;
111 : 9 : }
112 : :
113 : :
114 : 30 : static struct crypto_bignum * sae_get_rand(struct sae_data *sae)
115 : : {
116 : : u8 val[SAE_MAX_PRIME_LEN];
117 : 30 : int iter = 0;
118 : 30 : struct crypto_bignum *bn = NULL;
119 : 30 : int order_len_bits = crypto_bignum_bits(sae->tmp->order);
120 : 30 : size_t order_len = (order_len_bits + 7) / 8;
121 : :
122 [ - + ]: 30 : if (order_len > sizeof(val))
123 : 0 : return NULL;
124 : :
125 : : for (;;) {
126 [ - + ]: 38 : if (iter++ > 100)
127 : 0 : return NULL;
128 [ - + ]: 38 : if (random_get_bytes(val, order_len) < 0)
129 : 0 : return NULL;
130 [ + + ]: 38 : if (order_len_bits % 8)
131 : 6 : buf_shift_right(val, order_len, 8 - order_len_bits % 8);
132 : 38 : bn = crypto_bignum_init_set(val, order_len);
133 [ - + ]: 38 : if (bn == NULL)
134 : 0 : return NULL;
135 [ + - + - ]: 76 : if (crypto_bignum_is_zero(bn) ||
136 [ + + ]: 76 : crypto_bignum_is_one(bn) ||
137 : 38 : crypto_bignum_cmp(bn, sae->tmp->order) >= 0)
138 : 8 : continue;
139 : 30 : break;
140 : 8 : }
141 : :
142 : 30 : os_memset(val, 0, order_len);
143 : 30 : return bn;
144 : : }
145 : :
146 : :
147 : 15 : static struct crypto_bignum * sae_get_rand_and_mask(struct sae_data *sae)
148 : : {
149 : 15 : crypto_bignum_deinit(sae->tmp->sae_rand, 1);
150 : 15 : sae->tmp->sae_rand = sae_get_rand(sae);
151 [ - + ]: 15 : if (sae->tmp->sae_rand == NULL)
152 : 0 : return NULL;
153 : 15 : return sae_get_rand(sae);
154 : : }
155 : :
156 : :
157 : 15 : static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
158 : : {
159 : 15 : wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR
160 : 180 : " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2));
161 [ - + ]: 15 : if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) {
162 : 0 : os_memcpy(key, addr1, ETH_ALEN);
163 : 0 : os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN);
164 : : } else {
165 : 15 : os_memcpy(key, addr2, ETH_ALEN);
166 : 15 : os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN);
167 : : }
168 : 15 : }
169 : :
170 : :
171 : 30 : static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
172 : : struct crypto_ec_point *pwe)
173 : : {
174 : : u8 pwd_value[SAE_MAX_ECC_PRIME_LEN], prime[SAE_MAX_ECC_PRIME_LEN];
175 : : struct crypto_bignum *x;
176 : : int y_bit;
177 : : size_t bits;
178 : :
179 [ - + ]: 30 : if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
180 : 30 : sae->tmp->prime_len) < 0)
181 : 0 : return -1;
182 : :
183 : 30 : wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
184 : :
185 : : /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
186 : 30 : bits = crypto_ec_prime_len_bits(sae->tmp->ec);
187 : 30 : sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
188 : 30 : prime, sae->tmp->prime_len, pwd_value, bits);
189 [ + + ]: 30 : if (bits % 8)
190 : 3 : buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
191 : 30 : wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value",
192 : 30 : pwd_value, sae->tmp->prime_len);
193 : :
194 [ - + ]: 30 : if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
195 : 0 : return 0;
196 : :
197 : 30 : y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
198 : :
199 : 30 : x = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
200 [ - + ]: 30 : if (x == NULL)
201 : 0 : return -1;
202 [ + + ]: 30 : if (crypto_ec_point_solve_y_coord(sae->tmp->ec, pwe, x, y_bit) < 0) {
203 : 14 : crypto_bignum_deinit(x, 0);
204 : 14 : wpa_printf(MSG_DEBUG, "SAE: No solution found");
205 : 14 : return 0;
206 : : }
207 : 16 : crypto_bignum_deinit(x, 0);
208 : :
209 : 16 : wpa_printf(MSG_DEBUG, "SAE: PWE found");
210 : :
211 : 30 : return 1;
212 : : }
213 : :
214 : :
215 : 5 : static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
216 : : struct crypto_bignum *pwe)
217 : : {
218 : : u8 pwd_value[SAE_MAX_PRIME_LEN];
219 : 5 : size_t bits = sae->tmp->prime_len * 8;
220 : : u8 exp[1];
221 : : struct crypto_bignum *a, *b;
222 : : int res;
223 : :
224 : 5 : wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
225 : :
226 : : /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */
227 : 5 : sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking",
228 : 10 : sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value,
229 : : bits);
230 [ - + ]: 5 : if (bits % 8)
231 : 0 : buf_shift_right(pwd_value, sizeof(pwd_value), 8 - bits % 8);
232 : 5 : wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value,
233 : 5 : sae->tmp->prime_len);
234 : :
235 [ - + ]: 5 : if (os_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len) >= 0)
236 : : {
237 : 0 : wpa_printf(MSG_DEBUG, "SAE: pwd-value >= p");
238 : 0 : return 0;
239 : : }
240 : :
241 : : /* PWE = pwd-value^((p-1)/r) modulo p */
242 : :
243 : 5 : a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
244 : :
245 [ + + ]: 5 : if (sae->tmp->dh->safe_prime) {
246 : : /*
247 : : * r = (p-1)/2 for the group used here, so this becomes:
248 : : * PWE = pwd-value^2 modulo p
249 : : */
250 : 2 : exp[0] = 2;
251 : 2 : b = crypto_bignum_init_set(exp, sizeof(exp));
252 : : } else {
253 : : /* Calculate exponent: (p-1)/r */
254 : 3 : exp[0] = 1;
255 : 3 : b = crypto_bignum_init_set(exp, sizeof(exp));
256 [ + - + - ]: 6 : if (b == NULL ||
257 [ - + ]: 6 : crypto_bignum_sub(sae->tmp->prime, b, b) < 0 ||
258 : 3 : crypto_bignum_div(b, sae->tmp->order, b) < 0) {
259 : 0 : crypto_bignum_deinit(b, 0);
260 : 0 : b = NULL;
261 : : }
262 : : }
263 : :
264 [ + - ][ - + ]: 5 : if (a == NULL || b == NULL)
265 : 0 : res = -1;
266 : : else
267 : 5 : res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe);
268 : :
269 : 5 : crypto_bignum_deinit(a, 0);
270 : 5 : crypto_bignum_deinit(b, 0);
271 : :
272 [ - + ]: 5 : if (res < 0) {
273 : 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to calculate PWE");
274 : 0 : return -1;
275 : : }
276 : :
277 : : /* if (PWE > 1) --> found */
278 [ + - ][ - + ]: 5 : if (crypto_bignum_is_zero(pwe) || crypto_bignum_is_one(pwe)) {
279 : 0 : wpa_printf(MSG_DEBUG, "SAE: PWE <= 1");
280 : 0 : return 0;
281 : : }
282 : :
283 : 5 : wpa_printf(MSG_DEBUG, "SAE: PWE found");
284 : 5 : return 1;
285 : : }
286 : :
287 : :
288 : 10 : static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
289 : : const u8 *addr2, const u8 *password,
290 : : size_t password_len)
291 : : {
292 : 10 : u8 counter, k = 4;
293 : : u8 addrs[2 * ETH_ALEN];
294 : : const u8 *addr[2];
295 : : size_t len[2];
296 : 10 : int found = 0;
297 : : struct crypto_ec_point *pwe_tmp;
298 : :
299 [ + - ]: 10 : if (sae->tmp->pwe_ecc == NULL) {
300 : 10 : sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
301 [ - + ]: 10 : if (sae->tmp->pwe_ecc == NULL)
302 : 0 : return -1;
303 : : }
304 : 10 : pwe_tmp = crypto_ec_point_init(sae->tmp->ec);
305 [ - + ]: 10 : if (pwe_tmp == NULL)
306 : 0 : return -1;
307 : :
308 : 10 : wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
309 : : password, password_len);
310 : :
311 : : /*
312 : : * H(salt, ikm) = HMAC-SHA256(salt, ikm)
313 : : * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
314 : : * password || counter)
315 : : */
316 : 10 : sae_pwd_seed_key(addr1, addr2, addrs);
317 : :
318 : 10 : addr[0] = password;
319 : 10 : len[0] = password_len;
320 : 10 : addr[1] = &counter;
321 : 10 : len[1] = sizeof(counter);
322 : :
323 : : /*
324 : : * Continue for at least k iterations to protect against side-channel
325 : : * attacks that attempt to determine the number of iterations required
326 : : * in the loop.
327 : : */
328 [ + + ][ - + ]: 40 : for (counter = 1; counter < k || !found; counter++) {
329 : : u8 pwd_seed[SHA256_MAC_LEN];
330 : : int res;
331 : :
332 [ - + ]: 30 : if (counter > 200) {
333 : : /* This should not happen in practice */
334 : 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
335 : 0 : break;
336 : : }
337 : :
338 : 30 : wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
339 [ - + ]: 30 : if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
340 : : pwd_seed) < 0)
341 : 0 : break;
342 [ + + ]: 30 : res = sae_test_pwd_seed_ecc(sae, pwd_seed,
343 : : found ? pwe_tmp :
344 : 17 : sae->tmp->pwe_ecc);
345 [ - + ]: 30 : if (res < 0)
346 : 0 : break;
347 [ + + ]: 30 : if (res == 0)
348 : 14 : continue;
349 [ + + ]: 16 : if (found) {
350 : 6 : wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was "
351 : : "already selected)");
352 : : } else {
353 : 10 : wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
354 : 10 : found = 1;
355 : : }
356 : : }
357 : :
358 : 10 : crypto_ec_point_deinit(pwe_tmp, 1);
359 : :
360 [ + - ]: 10 : return found ? 0 : -1;
361 : : }
362 : :
363 : :
364 : 5 : static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1,
365 : : const u8 *addr2, const u8 *password,
366 : : size_t password_len)
367 : : {
368 : : u8 counter;
369 : : u8 addrs[2 * ETH_ALEN];
370 : : const u8 *addr[2];
371 : : size_t len[2];
372 : 5 : int found = 0;
373 : :
374 [ + - ]: 5 : if (sae->tmp->pwe_ffc == NULL) {
375 : 5 : sae->tmp->pwe_ffc = crypto_bignum_init();
376 [ - + ]: 5 : if (sae->tmp->pwe_ffc == NULL)
377 : 0 : return -1;
378 : : }
379 : :
380 : 5 : wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
381 : : password, password_len);
382 : :
383 : : /*
384 : : * H(salt, ikm) = HMAC-SHA256(salt, ikm)
385 : : * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
386 : : * password || counter)
387 : : */
388 : 5 : sae_pwd_seed_key(addr1, addr2, addrs);
389 : :
390 : 5 : addr[0] = password;
391 : 5 : len[0] = password_len;
392 : 5 : addr[1] = &counter;
393 : 5 : len[1] = sizeof(counter);
394 : :
395 [ + + ]: 10 : for (counter = 1; !found; counter++) {
396 : : u8 pwd_seed[SHA256_MAC_LEN];
397 : : int res;
398 : :
399 [ - + ]: 5 : if (counter > 200) {
400 : : /* This should not happen in practice */
401 : 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE");
402 : 0 : break;
403 : : }
404 : :
405 : 5 : wpa_printf(MSG_DEBUG, "SAE: counter = %u", counter);
406 [ - + ]: 5 : if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
407 : : pwd_seed) < 0)
408 : 0 : break;
409 : 5 : res = sae_test_pwd_seed_ffc(sae, pwd_seed, sae->tmp->pwe_ffc);
410 [ - + ]: 5 : if (res < 0)
411 : 0 : break;
412 [ + - ]: 5 : if (res > 0) {
413 : 5 : wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
414 : 5 : found = 1;
415 : : }
416 : : }
417 : :
418 [ + - ]: 5 : return found ? 0 : -1;
419 : : }
420 : :
421 : :
422 : 10 : static int sae_derive_commit_element_ecc(struct sae_data *sae,
423 : : struct crypto_bignum *mask)
424 : : {
425 : : /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
426 [ + - ]: 10 : if (!sae->tmp->own_commit_element_ecc) {
427 : 20 : sae->tmp->own_commit_element_ecc =
428 : 10 : crypto_ec_point_init(sae->tmp->ec);
429 [ - + ]: 10 : if (!sae->tmp->own_commit_element_ecc)
430 : 0 : return -1;
431 : : }
432 : :
433 [ + - ]: 10 : if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask,
434 [ - + ]: 10 : sae->tmp->own_commit_element_ecc) < 0 ||
435 : 10 : crypto_ec_point_invert(sae->tmp->ec,
436 : 10 : sae->tmp->own_commit_element_ecc) < 0) {
437 : 0 : wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
438 : 0 : return -1;
439 : : }
440 : :
441 : 10 : return 0;
442 : : }
443 : :
444 : :
445 : 5 : static int sae_derive_commit_element_ffc(struct sae_data *sae,
446 : : struct crypto_bignum *mask)
447 : : {
448 : : /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
449 [ + - ]: 5 : if (!sae->tmp->own_commit_element_ffc) {
450 : 5 : sae->tmp->own_commit_element_ffc = crypto_bignum_init();
451 [ - + ]: 5 : if (!sae->tmp->own_commit_element_ffc)
452 : 0 : return -1;
453 : : }
454 : :
455 [ + - ]: 5 : if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime,
456 [ - + ]: 5 : sae->tmp->own_commit_element_ffc) < 0 ||
457 : 5 : crypto_bignum_inverse(sae->tmp->own_commit_element_ffc,
458 : 5 : sae->tmp->prime,
459 : 5 : sae->tmp->own_commit_element_ffc) < 0) {
460 : 0 : wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element");
461 : 0 : return -1;
462 : : }
463 : :
464 : 5 : return 0;
465 : : }
466 : :
467 : :
468 : 15 : static int sae_derive_commit(struct sae_data *sae)
469 : : {
470 : : struct crypto_bignum *mask;
471 : 15 : int ret = -1;
472 : :
473 : 15 : mask = sae_get_rand_and_mask(sae);
474 [ - + ]: 15 : if (mask == NULL) {
475 : 0 : wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
476 : 0 : return -1;
477 : : }
478 : :
479 : : /* commit-scalar = (rand + mask) modulo r */
480 [ + - ]: 15 : if (!sae->tmp->own_commit_scalar) {
481 : 15 : sae->tmp->own_commit_scalar = crypto_bignum_init();
482 [ - + ]: 15 : if (!sae->tmp->own_commit_scalar)
483 : 0 : goto fail;
484 : : }
485 : 15 : crypto_bignum_add(sae->tmp->sae_rand, mask,
486 : 15 : sae->tmp->own_commit_scalar);
487 : 15 : crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order,
488 : 15 : sae->tmp->own_commit_scalar);
489 : :
490 [ + + ][ - + ]: 15 : if (sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0)
491 : 0 : goto fail;
492 [ + + ][ - + ]: 15 : if (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0)
493 : 0 : goto fail;
494 : :
495 : 15 : ret = 0;
496 : : fail:
497 : 15 : crypto_bignum_deinit(mask, 1);
498 : 15 : return ret;
499 : : }
500 : :
501 : :
502 : 15 : int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
503 : : const u8 *password, size_t password_len,
504 : : struct sae_data *sae)
505 : : {
506 [ + + ][ - + ]: 15 : if (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
507 : : password_len) < 0)
508 : 0 : return -1;
509 [ + + ][ - + ]: 15 : if (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
510 : : password_len) < 0)
511 : 0 : return -1;
512 [ - + ]: 15 : if (sae_derive_commit(sae) < 0)
513 : 0 : return -1;
514 : 15 : return 0;
515 : : }
516 : :
517 : :
518 : 7 : static int sae_derive_k_ecc(struct sae_data *sae, u8 *k)
519 : : {
520 : : struct crypto_ec_point *K;
521 : 7 : int ret = -1;
522 : :
523 : 7 : K = crypto_ec_point_init(sae->tmp->ec);
524 [ - + ]: 7 : if (K == NULL)
525 : 0 : goto fail;
526 : :
527 : : /*
528 : : * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
529 : : * PEER-COMMIT-ELEMENT)))
530 : : * If K is identity element (point-at-infinity), reject
531 : : * k = F(K) (= x coordinate)
532 : : */
533 : :
534 [ + - ]: 7 : if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc,
535 [ + - ]: 7 : sae->peer_commit_scalar, K) < 0 ||
536 : 7 : crypto_ec_point_add(sae->tmp->ec, K,
537 [ + - ]: 7 : sae->tmp->peer_commit_element_ecc, K) < 0 ||
538 [ + - ]: 14 : crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 ||
539 [ - + ]: 14 : crypto_ec_point_is_at_infinity(sae->tmp->ec, K) ||
540 : 7 : crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) {
541 : 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
542 : 0 : goto fail;
543 : : }
544 : :
545 : 7 : wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
546 : :
547 : 7 : ret = 0;
548 : : fail:
549 : 7 : crypto_ec_point_deinit(K, 1);
550 : 7 : return ret;
551 : : }
552 : :
553 : :
554 : 5 : static int sae_derive_k_ffc(struct sae_data *sae, u8 *k)
555 : : {
556 : : struct crypto_bignum *K;
557 : 5 : int ret = -1;
558 : :
559 : 5 : K = crypto_bignum_init();
560 [ - + ]: 5 : if (K == NULL)
561 : 0 : goto fail;
562 : :
563 : : /*
564 : : * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE),
565 : : * PEER-COMMIT-ELEMENT)))
566 : : * If K is identity element (one), reject.
567 : : * k = F(K) (= x coordinate)
568 : : */
569 : :
570 [ + - ]: 5 : if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar,
571 [ + - ]: 5 : sae->tmp->prime, K) < 0 ||
572 : 5 : crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc,
573 [ + - ]: 5 : sae->tmp->prime, K) < 0 ||
574 : 5 : crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0
575 [ + - ]: 5 : ||
576 [ - + ]: 10 : crypto_bignum_is_one(K) ||
577 : 5 : crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) <
578 : : 0) {
579 : 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k");
580 : 0 : goto fail;
581 : : }
582 : :
583 : 5 : wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len);
584 : :
585 : 5 : ret = 0;
586 : : fail:
587 : 5 : crypto_bignum_deinit(K, 1);
588 : 5 : return ret;
589 : : }
590 : :
591 : :
592 : 12 : static int sae_derive_keys(struct sae_data *sae, const u8 *k)
593 : : {
594 : : u8 null_key[SAE_KEYSEED_KEY_LEN], val[SAE_MAX_PRIME_LEN];
595 : : u8 keyseed[SHA256_MAC_LEN];
596 : : u8 keys[SAE_KCK_LEN + SAE_PMK_LEN];
597 : : struct crypto_bignum *tmp;
598 : 12 : int ret = -1;
599 : :
600 : 12 : tmp = crypto_bignum_init();
601 [ - + ]: 12 : if (tmp == NULL)
602 : 0 : goto fail;
603 : :
604 : : /* keyseed = H(<0>32, k)
605 : : * KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK",
606 : : * (commit-scalar + peer-commit-scalar) modulo r)
607 : : * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128)
608 : : */
609 : :
610 : 12 : os_memset(null_key, 0, sizeof(null_key));
611 : 12 : hmac_sha256(null_key, sizeof(null_key), k, sae->tmp->prime_len,
612 : : keyseed);
613 : 12 : wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, sizeof(keyseed));
614 : :
615 : 12 : crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar,
616 : : tmp);
617 : 12 : crypto_bignum_mod(tmp, sae->tmp->order, tmp);
618 : 12 : crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->prime_len);
619 : 12 : wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN);
620 : 12 : sha256_prf(keyseed, sizeof(keyseed), "SAE KCK and PMK",
621 : 12 : val, sae->tmp->prime_len, keys, sizeof(keys));
622 : 12 : os_memcpy(sae->tmp->kck, keys, SAE_KCK_LEN);
623 : 12 : os_memcpy(sae->pmk, keys + SAE_KCK_LEN, SAE_PMK_LEN);
624 : 12 : wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, SAE_KCK_LEN);
625 : 12 : wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN);
626 : :
627 : 12 : ret = 0;
628 : : fail:
629 : 12 : crypto_bignum_deinit(tmp, 0);
630 : 12 : return ret;
631 : : }
632 : :
633 : :
634 : 12 : int sae_process_commit(struct sae_data *sae)
635 : : {
636 : : u8 k[SAE_MAX_PRIME_LEN];
637 [ + + ][ + - ]: 12 : if ((sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) ||
[ + + ]
638 [ + - - + ]: 17 : (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) ||
639 : 12 : sae_derive_keys(sae, k) < 0)
640 : 0 : return -1;
641 : 12 : return 0;
642 : : }
643 : :
644 : :
645 : 15 : void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
646 : : const struct wpabuf *token)
647 : : {
648 : : u8 *pos;
649 : 15 : wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */
650 [ - + ]: 15 : if (token)
651 : 0 : wpabuf_put_buf(buf, token);
652 : 15 : pos = wpabuf_put(buf, sae->tmp->prime_len);
653 : 15 : crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos,
654 : 30 : sae->tmp->prime_len, sae->tmp->prime_len);
655 : 15 : wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar",
656 : 15 : pos, sae->tmp->prime_len);
657 [ + + ]: 15 : if (sae->tmp->ec) {
658 : 10 : pos = wpabuf_put(buf, 2 * sae->tmp->prime_len);
659 : 10 : crypto_ec_point_to_bin(sae->tmp->ec,
660 : 10 : sae->tmp->own_commit_element_ecc,
661 : 10 : pos, pos + sae->tmp->prime_len);
662 : 10 : wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)",
663 : 10 : pos, sae->tmp->prime_len);
664 : 10 : wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)",
665 : 20 : pos + sae->tmp->prime_len, sae->tmp->prime_len);
666 : : } else {
667 : 5 : pos = wpabuf_put(buf, sae->tmp->prime_len);
668 : 5 : crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos,
669 : 10 : sae->tmp->prime_len, sae->tmp->prime_len);
670 : 5 : wpa_hexdump(MSG_DEBUG, "SAE: own commit-element",
671 : 5 : pos, sae->tmp->prime_len);
672 : : }
673 : 15 : }
674 : :
675 : :
676 : 12 : static u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups,
677 : : u16 group)
678 : : {
679 [ + + ]: 12 : if (allowed_groups) {
680 : : int i;
681 [ + - ]: 14 : for (i = 0; allowed_groups[i] > 0; i++) {
682 [ + + ]: 14 : if (allowed_groups[i] == group)
683 : 11 : break;
684 : : }
685 [ - + ]: 11 : if (allowed_groups[i] != group) {
686 : 0 : wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not "
687 : : "enabled in the current configuration",
688 : : group);
689 : 0 : return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
690 : : }
691 : : }
692 : :
693 [ + - ][ - + ]: 12 : if (sae->state == SAE_COMMITTED && group != sae->group) {
694 : 0 : wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed");
695 : 0 : return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
696 : : }
697 : :
698 [ - + ][ # # ]: 12 : if (group != sae->group && sae_set_group(sae, group) < 0) {
699 : 0 : wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u",
700 : : group);
701 : 0 : return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
702 : : }
703 : :
704 [ + + ][ - + ]: 12 : if (sae->tmp->dh && !allowed_groups) {
705 : 0 : wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without "
706 : : "explicit configuration enabling it", group);
707 : 0 : return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
708 : : }
709 : :
710 : 12 : return WLAN_STATUS_SUCCESS;
711 : : }
712 : :
713 : :
714 : 12 : static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos,
715 : : const u8 *end, const u8 **token,
716 : : size_t *token_len)
717 : : {
718 [ + + ][ - + ]: 12 : if (*pos + (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len < end) {
719 [ # # ]: 0 : size_t tlen = end - (*pos + (sae->tmp->ec ? 3 : 2) *
720 : 0 : sae->tmp->prime_len);
721 : 0 : wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen);
722 [ # # ]: 0 : if (token)
723 : 0 : *token = *pos;
724 [ # # ]: 0 : if (token_len)
725 : 0 : *token_len = tlen;
726 : 0 : *pos += tlen;
727 : : } else {
728 [ - + ]: 12 : if (token)
729 : 0 : *token = NULL;
730 [ - + ]: 12 : if (token_len)
731 : 0 : *token_len = 0;
732 : : }
733 : 12 : }
734 : :
735 : :
736 : 12 : static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
737 : : const u8 *end)
738 : : {
739 : : struct crypto_bignum *peer_scalar;
740 : :
741 [ - + ]: 12 : if (*pos + sae->tmp->prime_len > end) {
742 : 0 : wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar");
743 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
744 : : }
745 : :
746 : 12 : peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len);
747 [ - + ]: 12 : if (peer_scalar == NULL)
748 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
749 : :
750 : : /*
751 : : * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for
752 : : * the peer and it is in Authenticated state, the new Commit Message
753 : : * shall be dropped if the peer-scalar is identical to the one used in
754 : : * the existing protocol instance.
755 : : */
756 [ - + ]: 12 : if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar &&
[ # # # # ]
757 : 0 : crypto_bignum_cmp(sae->peer_commit_scalar, peer_scalar) == 0) {
758 : 0 : wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous "
759 : : "peer-commit-scalar");
760 : 0 : crypto_bignum_deinit(peer_scalar, 0);
761 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
762 : : }
763 : :
764 : : /* 0 < scalar < r */
765 [ + - - + ]: 24 : if (crypto_bignum_is_zero(peer_scalar) ||
766 : 12 : crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
767 : 0 : wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
768 : 0 : crypto_bignum_deinit(peer_scalar, 0);
769 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
770 : : }
771 : :
772 : :
773 : 12 : crypto_bignum_deinit(sae->peer_commit_scalar, 0);
774 : 12 : sae->peer_commit_scalar = peer_scalar;
775 : 12 : wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar",
776 : 12 : *pos, sae->tmp->prime_len);
777 : 12 : *pos += sae->tmp->prime_len;
778 : :
779 : 12 : return WLAN_STATUS_SUCCESS;
780 : : }
781 : :
782 : :
783 : 7 : static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
784 : : const u8 *end)
785 : : {
786 : : u8 prime[SAE_MAX_ECC_PRIME_LEN];
787 : :
788 [ - + ]: 7 : if (pos + 2 * sae->tmp->prime_len > end) {
789 : 0 : wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
790 : : "commit-element");
791 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
792 : : }
793 : :
794 [ - + ]: 7 : if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
795 : 7 : sae->tmp->prime_len) < 0)
796 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
797 : :
798 : : /* element x and y coordinates < p */
799 [ + - ][ - + ]: 7 : if (os_memcmp(pos, prime, sae->tmp->prime_len) >= 0 ||
800 : 7 : os_memcmp(pos + sae->tmp->prime_len + sae->tmp->prime_len, prime,
801 : : sae->tmp->prime_len) >= 0) {
802 : 0 : wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer "
803 : : "element");
804 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
805 : : }
806 : :
807 : 7 : wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)",
808 : 7 : pos, sae->tmp->prime_len);
809 : 7 : wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)",
810 : 14 : pos + sae->tmp->prime_len, sae->tmp->prime_len);
811 : :
812 : 7 : crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0);
813 : 14 : sae->tmp->peer_commit_element_ecc =
814 : 7 : crypto_ec_point_from_bin(sae->tmp->ec, pos);
815 [ - + ]: 7 : if (sae->tmp->peer_commit_element_ecc == NULL)
816 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
817 : :
818 [ - + ]: 7 : if (!crypto_ec_point_is_on_curve(sae->tmp->ec,
819 : 7 : sae->tmp->peer_commit_element_ecc)) {
820 : 0 : wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve");
821 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
822 : : }
823 : :
824 : 7 : return WLAN_STATUS_SUCCESS;
825 : : }
826 : :
827 : :
828 : 5 : static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
829 : : const u8 *end)
830 : : {
831 : : struct crypto_bignum *res;
832 : :
833 [ - + ]: 5 : if (pos + sae->tmp->prime_len > end) {
834 : 0 : wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
835 : : "commit-element");
836 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
837 : : }
838 : 5 : wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", pos,
839 : 5 : sae->tmp->prime_len);
840 : :
841 : 5 : crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0);
842 : 10 : sae->tmp->peer_commit_element_ffc =
843 : 5 : crypto_bignum_init_set(pos, sae->tmp->prime_len);
844 [ - + ]: 5 : if (sae->tmp->peer_commit_element_ffc == NULL)
845 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
846 [ + - + - ]: 10 : if (crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
847 [ - + ]: 10 : crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
848 : 5 : crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc,
849 : 5 : sae->tmp->prime) >= 0) {
850 : 0 : wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
851 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
852 : : }
853 : :
854 : : /* scalar-op(r, ELEMENT) = 1 modulo p */
855 : 5 : res = crypto_bignum_init();
856 [ + - + - ]: 10 : if (res == NULL ||
857 : 5 : crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
858 [ - + ]: 5 : sae->tmp->order, sae->tmp->prime, res) < 0 ||
859 : 5 : !crypto_bignum_is_one(res)) {
860 : 0 : wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
861 : 0 : crypto_bignum_deinit(res, 0);
862 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
863 : : }
864 : 5 : crypto_bignum_deinit(res, 0);
865 : :
866 : 5 : return WLAN_STATUS_SUCCESS;
867 : : }
868 : :
869 : :
870 : 12 : static u16 sae_parse_commit_element(struct sae_data *sae, const u8 *pos,
871 : : const u8 *end)
872 : : {
873 [ + + ]: 12 : if (sae->tmp->dh)
874 : 5 : return sae_parse_commit_element_ffc(sae, pos, end);
875 : 12 : return sae_parse_commit_element_ecc(sae, pos, end);
876 : : }
877 : :
878 : :
879 : 12 : u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
880 : : const u8 **token, size_t *token_len, int *allowed_groups)
881 : : {
882 : 12 : const u8 *pos = data, *end = data + len;
883 : : u16 res;
884 : :
885 : : /* Check Finite Cyclic Group */
886 [ - + ]: 12 : if (pos + 2 > end)
887 : 0 : return WLAN_STATUS_UNSPECIFIED_FAILURE;
888 : 12 : res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos));
889 [ - + ]: 12 : if (res != WLAN_STATUS_SUCCESS)
890 : 0 : return res;
891 : 12 : pos += 2;
892 : :
893 : : /* Optional Anti-Clogging Token */
894 : 12 : sae_parse_commit_token(sae, &pos, end, token, token_len);
895 : :
896 : : /* commit-scalar */
897 : 12 : res = sae_parse_commit_scalar(sae, &pos, end);
898 [ - + ]: 12 : if (res != WLAN_STATUS_SUCCESS)
899 : 0 : return res;
900 : :
901 : : /* commit-element */
902 : 12 : return sae_parse_commit_element(sae, pos, end);
903 : : }
904 : :
905 : :
906 : 24 : static void sae_cn_confirm(struct sae_data *sae, const u8 *sc,
907 : : const struct crypto_bignum *scalar1,
908 : : const u8 *element1, size_t element1_len,
909 : : const struct crypto_bignum *scalar2,
910 : : const u8 *element2, size_t element2_len,
911 : : u8 *confirm)
912 : : {
913 : : const u8 *addr[5];
914 : : size_t len[5];
915 : : u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN];
916 : :
917 : : /* Confirm
918 : : * CN(key, X, Y, Z, ...) =
919 : : * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...)
920 : : * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT,
921 : : * peer-commit-scalar, PEER-COMMIT-ELEMENT)
922 : : * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar,
923 : : * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT)
924 : : */
925 : 24 : addr[0] = sc;
926 : 24 : len[0] = 2;
927 : 24 : crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1),
928 : 24 : sae->tmp->prime_len);
929 : 24 : addr[1] = scalar_b1;
930 : 24 : len[1] = sae->tmp->prime_len;
931 : 24 : addr[2] = element1;
932 : 24 : len[2] = element1_len;
933 : 24 : crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2),
934 : 24 : sae->tmp->prime_len);
935 : 24 : addr[3] = scalar_b2;
936 : 24 : len[3] = sae->tmp->prime_len;
937 : 24 : addr[4] = element2;
938 : 24 : len[4] = element2_len;
939 : 24 : hmac_sha256_vector(sae->tmp->kck, sizeof(sae->tmp->kck), 5, addr, len,
940 : : confirm);
941 : 24 : }
942 : :
943 : :
944 : 14 : static void sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc,
945 : : const struct crypto_bignum *scalar1,
946 : : const struct crypto_ec_point *element1,
947 : : const struct crypto_bignum *scalar2,
948 : : const struct crypto_ec_point *element2,
949 : : u8 *confirm)
950 : : {
951 : : u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN];
952 : : u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN];
953 : :
954 : 14 : crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1,
955 : 14 : element_b1 + sae->tmp->prime_len);
956 : 14 : crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2,
957 : 14 : element_b2 + sae->tmp->prime_len);
958 : :
959 : 14 : sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len,
960 : 14 : scalar2, element_b2, 2 * sae->tmp->prime_len, confirm);
961 : 14 : }
962 : :
963 : :
964 : 10 : static void sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc,
965 : : const struct crypto_bignum *scalar1,
966 : : const struct crypto_bignum *element1,
967 : : const struct crypto_bignum *scalar2,
968 : : const struct crypto_bignum *element2,
969 : : u8 *confirm)
970 : : {
971 : : u8 element_b1[SAE_MAX_PRIME_LEN];
972 : : u8 element_b2[SAE_MAX_PRIME_LEN];
973 : :
974 : 10 : crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1),
975 : 10 : sae->tmp->prime_len);
976 : 10 : crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2),
977 : 10 : sae->tmp->prime_len);
978 : :
979 : 10 : sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len,
980 : 10 : scalar2, element_b2, sae->tmp->prime_len, confirm);
981 : 10 : }
982 : :
983 : :
984 : 12 : void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf)
985 : : {
986 : : const u8 *sc;
987 : :
988 : : /* Send-Confirm */
989 : 12 : sc = wpabuf_put(buf, 0);
990 : 12 : wpabuf_put_le16(buf, sae->send_confirm);
991 : 12 : sae->send_confirm++;
992 : :
993 [ + + ]: 12 : if (sae->tmp->ec)
994 : 7 : sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar,
995 : 7 : sae->tmp->own_commit_element_ecc,
996 : 7 : sae->peer_commit_scalar,
997 : 7 : sae->tmp->peer_commit_element_ecc,
998 : 7 : wpabuf_put(buf, SHA256_MAC_LEN));
999 : : else
1000 : 5 : sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar,
1001 : 5 : sae->tmp->own_commit_element_ffc,
1002 : 5 : sae->peer_commit_scalar,
1003 : 5 : sae->tmp->peer_commit_element_ffc,
1004 : 5 : wpabuf_put(buf, SHA256_MAC_LEN));
1005 : 12 : }
1006 : :
1007 : :
1008 : 12 : int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len)
1009 : : {
1010 : : u8 verifier[SHA256_MAC_LEN];
1011 : :
1012 [ - + ]: 12 : if (len < 2 + SHA256_MAC_LEN) {
1013 : 0 : wpa_printf(MSG_DEBUG, "SAE: Too short confirm message");
1014 : 0 : return -1;
1015 : : }
1016 : :
1017 : 12 : wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data));
1018 : :
1019 [ + + ]: 12 : if (sae->tmp->ec)
1020 : 7 : sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar,
1021 : 7 : sae->tmp->peer_commit_element_ecc,
1022 : 7 : sae->tmp->own_commit_scalar,
1023 : 7 : sae->tmp->own_commit_element_ecc,
1024 : : verifier);
1025 : : else
1026 : 5 : sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar,
1027 : 5 : sae->tmp->peer_commit_element_ffc,
1028 : 5 : sae->tmp->own_commit_scalar,
1029 : 5 : sae->tmp->own_commit_element_ffc,
1030 : : verifier);
1031 : :
1032 [ - + ]: 12 : if (os_memcmp(verifier, data + 2, SHA256_MAC_LEN) != 0) {
1033 : 0 : wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch");
1034 : 0 : wpa_hexdump(MSG_DEBUG, "SAE: Received confirm",
1035 : : data + 2, SHA256_MAC_LEN);
1036 : 0 : wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier",
1037 : : verifier, SHA256_MAC_LEN);
1038 : 0 : return -1;
1039 : : }
1040 : :
1041 : 12 : return 0;
1042 : : }
|