1  /*
2   * SAE-PK
3   * Copyright (c) 2020, The Linux Foundation
4   *
5   * This software may be distributed under the terms of the BSD license.
6   * See README for more details.
7   */
8  
9  #include "utils/includes.h"
10  #include <stdint.h>
11  
12  #include "utils/common.h"
13  #include "utils/base64.h"
14  #include "common/ieee802_11_defs.h"
15  #include "common/ieee802_11_common.h"
16  #include "crypto/crypto.h"
17  #include "crypto/aes.h"
18  #include "crypto/aes_siv.h"
19  #include "sae.h"
20  
21  
22  /* RFC 4648 base 32 alphabet with lowercase characters */
23  static const char *sae_pk_base32_table = "abcdefghijklmnopqrstuvwxyz234567";
24  
25  
26  static const u8 d_mult_table[] = {
27  	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
28  	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
29  	 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,
30  	17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16,
31  	 2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,
32  	18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17,
33  	 3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,
34  	19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18,
35  	 4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,
36  	20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19,
37  	 5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,
38  	21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20,
39  	 6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,
40  	22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21,
41  	 7,  8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,
42  	23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22,
43  	 8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,
44  	24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23,
45  	 9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,
46  	25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24,
47  	10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
48  	26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
49  	11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
50  	27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
51  	12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,
52  	28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
53  	13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,
54  	29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
55  	14, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
56  	30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
57  	15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
58  	31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
59  	16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
60  	 0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,
61  	17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18,
62  	 1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,
63  	18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,
64  	 2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,
65  	19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20,
66  	 3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,
67  	20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
68  	 4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,
69  	21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
70  	 5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,
71  	22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23,
72  	 6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,  7,
73  	23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24,
74  	 7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,
75  	24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25,
76  	 8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,
77  	25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26,
78  	 9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,
79  	26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27,
80  	10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11,
81  	27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28,
82  	11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12,
83  	28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29,
84  	12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13,
85  	29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30,
86  	13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15, 14,
87  	30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31,
88  	14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 15,
89  	31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
90  	15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0
91  };
92  
93  static const u8 d_perm_table[] = {
94  	 7,  2,  1, 30, 16, 20, 27, 11, 31,  6,  8, 13, 29,  5, 10, 21,
95  	22,  3, 24,  0, 23, 25, 12,  9, 28, 14,  4, 15, 17, 18, 19, 26
96  };
97  
98  
d_permute(u8 val,unsigned int iter)99  static u8 d_permute(u8 val, unsigned int iter)
100  {
101  	if (iter == 0)
102  		return val;
103  	return d_permute(d_perm_table[val], iter - 1);
104  }
105  
106  
d_invert(u8 val)107  static u8 d_invert(u8 val)
108  {
109  	if (val > 0 && val < 16)
110  		return 16 - val;
111  	return val;
112  }
113  
114  
d_check_char(const char * str,size_t len)115  static char d_check_char(const char *str, size_t len)
116  {
117  	size_t i;
118  	u8 val = 0;
119  	u8 dtable[256];
120  	unsigned int iter = 1;
121  	int j;
122  
123  	os_memset(dtable, 0x80, 256);
124  	for (i = 0; sae_pk_base32_table[i]; i++)
125  		dtable[(u8) sae_pk_base32_table[i]] = i;
126  
127  	for (j = len - 1; j >= 0; j--) {
128  		u8 c, p;
129  
130  		c = dtable[(u8) str[j]];
131  		if (c == 0x80)
132  			continue;
133  		p = d_permute(c, iter);
134  		iter++;
135  		val = d_mult_table[val * 32 + p];
136  	}
137  
138  	return sae_pk_base32_table[d_invert(val)];
139  }
140  
141  
sae_pk_valid_password(const char * pw)142  bool sae_pk_valid_password(const char *pw)
143  {
144  	int pos;
145  	size_t i, pw_len = os_strlen(pw);
146  	u8 sec_1b;
147  	u8 dtable[256];
148  
149  	os_memset(dtable, 0x80, 256);
150  	for (i = 0; sae_pk_base32_table[i]; i++)
151  		dtable[(u8) sae_pk_base32_table[i]] = i;
152  
153  	/* SAE-PK password has at least three four character components
154  	 * separated by hyphens. */
155  	if (pw_len < 14 || pw_len % 5 != 4) {
156  		wpa_printf(MSG_DEBUG, "SAE-PK: Not a valid password (length)");
157  		return false;
158  	}
159  
160  	for (pos = 0; pw[pos]; pos++) {
161  		if (pos && pos % 5 == 4) {
162  			if (pw[pos] != '-') {
163  				wpa_printf(MSG_DEBUG,
164  					   "SAE-PK: Not a valid password (separator)");
165  				return false;
166  			}
167  			continue;
168  		}
169  		if (dtable[(u8) pw[pos]] == 0x80) {
170  			wpa_printf(MSG_DEBUG,
171  				   "SAE-PK: Not a valid password (character)");
172  			return false;
173  		}
174  	}
175  
176  	/* Verify that the checksum character is valid */
177  	if (pw[pw_len - 1] != d_check_char(pw, pw_len - 1)) {
178  		wpa_printf(MSG_DEBUG,
179  			   "SAE-PK: Not a valid password (checksum)");
180  		return false;
181  	}
182  
183  	/* Verify that Sec_1b bits match */
184  	sec_1b = dtable[(u8) pw[0]] & BIT(4);
185  	for (i = 5; i < pw_len; i += 5) {
186  		if (sec_1b != (dtable[(u8) pw[i]] & BIT(4))) {
187  			wpa_printf(MSG_DEBUG,
188  				   "SAE-PK: Not a valid password (Sec_1b)");
189  			return false;
190  		}
191  	}
192  	return true;
193  }
194  
195  
add_char(const char * start,char * pos,u8 idx,size_t * bits)196  static char * add_char(const char *start, char *pos, u8 idx, size_t *bits)
197  {
198  	if (*bits == 0)
199  		return pos;
200  	if (*bits > 5)
201  		*bits -= 5;
202  	else
203  		*bits = 0;
204  
205  	if ((pos - start) % 5 == 4)
206  		*pos++ = '-';
207  	*pos++ = sae_pk_base32_table[idx];
208  	return pos;
209  }
210  
211  
212  /* Base32 encode a password and add hyper separators and checksum */
sae_pk_base32_encode(const u8 * src,size_t len_bits)213  char * sae_pk_base32_encode(const u8 *src, size_t len_bits)
214  {
215  	char *out, *pos;
216  	size_t olen, extra_pad, i;
217  	u64 block = 0;
218  	u8 val;
219  	size_t len = (len_bits + 7) / 8;
220  	size_t left = len_bits;
221  	int j;
222  
223  	if (len == 0 || len >= SIZE_MAX / 8)
224  		return NULL;
225  	olen = len * 8 / 5 + 1;
226  	olen += olen / 4; /* hyphen separators */
227  	pos = out = os_zalloc(olen + 2); /* include room for ChkSum and nul */
228  	if (!out)
229  		return NULL;
230  
231  	extra_pad = (5 - len % 5) % 5;
232  	for (i = 0; i < len + extra_pad; i++) {
233  		val = i < len ? src[i] : 0;
234  		block <<= 8;
235  		block |= val;
236  		if (i % 5 == 4) {
237  			for (j = 7; j >= 0; j--)
238  				pos = add_char(out, pos,
239  					       (block >> j * 5) & 0x1f, &left);
240  			block = 0;
241  		}
242  	}
243  
244  	*pos = d_check_char(out, os_strlen(out));
245  
246  	return out;
247  }
248  
249  
sae_pk_base32_decode(const char * src,size_t len,size_t * out_len)250  u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len)
251  {
252  	u8 dtable[256], *out, *pos, tmp;
253  	u64 block = 0;
254  	size_t i, count, olen;
255  	int pad = 0;
256  	size_t extra_pad;
257  
258  	os_memset(dtable, 0x80, 256);
259  	for (i = 0; sae_pk_base32_table[i]; i++)
260  		dtable[(u8) sae_pk_base32_table[i]] = i;
261  	dtable['='] = 0;
262  
263  	count = 0;
264  	for (i = 0; i < len; i++) {
265  		if (dtable[(u8) src[i]] != 0x80)
266  			count++;
267  	}
268  
269  	if (count == 0)
270  		return NULL;
271  	extra_pad = (8 - count % 8) % 8;
272  
273  	olen = (count + extra_pad) / 8 * 5;
274  	pos = out = os_malloc(olen);
275  	if (!out)
276  		return NULL;
277  
278  	count = 0;
279  	for (i = 0; i < len + extra_pad; i++) {
280  		u8 val;
281  
282  		if (i >= len)
283  			val = '=';
284  		else
285  			val = src[i];
286  		tmp = dtable[val];
287  		if (tmp == 0x80)
288  			continue;
289  
290  		if (val == '=')
291  			pad++;
292  		block <<= 5;
293  		block |= tmp;
294  		count++;
295  		if (count == 8) {
296  			*pos++ = (block >> 32) & 0xff;
297  			*pos++ = (block >> 24) & 0xff;
298  			*pos++ = (block >> 16) & 0xff;
299  			*pos++ = (block >> 8) & 0xff;
300  			*pos++ = block & 0xff;
301  			count = 0;
302  			block = 0;
303  			if (pad) {
304  				/* Leave in all the available bits with zero
305  				 * padding to full octets from right. */
306  				pos -= pad * 5 / 8;
307  				break;
308  			}
309  		}
310  	}
311  
312  	*out_len = pos - out;
313  	return out;
314  }
315  
316  
sae_pk_get_be19(const u8 * buf)317  u32 sae_pk_get_be19(const u8 *buf)
318  {
319  	return (buf[0] << 11) | (buf[1] << 3) | (buf[2] >> 5);
320  }
321  
322  
323  /* shift left by two octets and three bits; fill in zeros from right;
324   * len must be at least three */
sae_pk_buf_shift_left_19(u8 * buf,size_t len)325  void sae_pk_buf_shift_left_19(u8 *buf, size_t len)
326  {
327  	u8 *dst, *src, *end;
328  
329  	dst = buf;
330  	src = buf + 2;
331  	end = buf + len;
332  
333  	while (src + 1 < end) {
334  		*dst++ = (src[0] << 3) | (src[1] >> 5);
335  		src++;
336  	}
337  	*dst++ = *src << 3;
338  	*dst++ = 0;
339  	*dst++ = 0;
340  }
341  
342  
sae_pk_buf_shift_left_1(u8 * buf,size_t len)343  static void sae_pk_buf_shift_left_1(u8 *buf, size_t len)
344  {
345  	u8 *dst, *src, *end;
346  
347  	dst = buf;
348  	src = buf;
349  	end = buf + len;
350  
351  	while (src + 1 < end) {
352  		*dst++ = (src[0] << 1) | (src[1] >> 7);
353  		src++;
354  	}
355  	*dst++ = *src << 1;
356  }
357  
358  
sae_pk_set_password(struct sae_data * sae,const char * password)359  int sae_pk_set_password(struct sae_data *sae, const char *password)
360  {
361  	struct sae_temporary_data *tmp = sae->tmp;
362  	size_t len, pw_len;
363  	u8 *pw, *pos;
364  	int bits;
365  	u32 val = 0, val19;
366  	unsigned int val_bits = 0;
367  
368  	if (!tmp)
369  		return -1;
370  
371  	os_memset(tmp->fingerprint, 0, sizeof(tmp->fingerprint));
372  	tmp->fingerprint_bytes = tmp->fingerprint_bits = 0;
373  
374  	len = os_strlen(password);
375  	if (len < 1 || !sae_pk_valid_password(password))
376  		return -1;
377  
378  	pw = sae_pk_base32_decode(password, len, &pw_len);
379  	if (!pw)
380  		return -1;
381  
382  	tmp->sec = (pw[0] & BIT(7)) ? 3 : 5;
383  	tmp->lambda = len - len / 5;
384  	tmp->fingerprint_bits = 8 * tmp->sec + 19 * tmp->lambda / 4 - 5;
385  	wpa_printf(MSG_DEBUG, "SAE-PK: Sec=%u Lambda=%zu fingerprint_bits=%zu",
386  		   tmp->sec, tmp->lambda, tmp->fingerprint_bits);
387  
388  	/* Construct Fingerprint from PasswordBase by prefixing with Sec zero
389  	 * octets and skipping the Sec_1b bits */
390  	pos = &tmp->fingerprint[tmp->sec];
391  	bits = tmp->fingerprint_bits - 8 * tmp->sec;
392  	wpa_hexdump_key(MSG_DEBUG, "SAE-PK: PasswordBase", pw, pw_len);
393  	while (bits > 0) {
394  		if (val_bits < 8) {
395  			sae_pk_buf_shift_left_1(pw, pw_len); /* Sec_1b */
396  			val19 = sae_pk_get_be19(pw);
397  			sae_pk_buf_shift_left_19(pw, pw_len);
398  			val = (val << 19) | val19;
399  			val_bits += 19;
400  		}
401  		if (val_bits >= 8) {
402  			if (bits < 8)
403  				break;
404  			*pos++ = (val >> (val_bits - 8)) & 0xff;
405  			val_bits -= 8;
406  			bits -= 8;
407  		}
408  	}
409  	if (bits > 0) {
410  		val >>= val_bits - bits;
411  		*pos++ = val << (8 - bits);
412  	}
413  	tmp->fingerprint_bytes = pos - tmp->fingerprint;
414  	wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Fingerprint",
415  			tmp->fingerprint, tmp->fingerprint_bytes);
416  	bin_clear_free(pw, pw_len);
417  	return 0;
418  }
419  
420  
sae_group_2_hash_len(int group)421  static size_t sae_group_2_hash_len(int group)
422  {
423  	switch (group) {
424  	case 19:
425  		return 32;
426  	case 20:
427  		return 48;
428  	case 21:
429  		return 64;
430  	}
431  
432  	return 0;
433  }
434  
435  
sae_deinit_pk(struct sae_pk * pk)436  void sae_deinit_pk(struct sae_pk *pk)
437  {
438  	if (pk) {
439  		wpabuf_free(pk->m);
440  		crypto_ec_key_deinit(pk->key);
441  #ifdef CONFIG_TESTING_OPTIONS
442  		crypto_ec_key_deinit(pk->sign_key_override);
443  #endif /* CONFIG_TESTING_OPTIONS */
444  		wpabuf_free(pk->pubkey);
445  		os_free(pk);
446  	}
447  }
448  
449  
sae_parse_pk(const char * val)450  struct sae_pk * sae_parse_pk(const char *val)
451  {
452  	struct sae_pk *pk;
453  	const char *pos;
454  #ifdef CONFIG_TESTING_OPTIONS
455  	const char *pos2;
456  #endif /* CONFIG_TESTING_OPTIONS */
457  	size_t len;
458  	unsigned char *der;
459  	size_t der_len, b_len;
460  
461  	/* <m-as-hexdump>:<base64-encoded-DER-encoded-key> */
462  
463  	pos = os_strchr(val, ':');
464  	if (!pos || (pos - val) & 0x01)
465  		return NULL;
466  	len = (pos - val) / 2;
467  	if (len != SAE_PK_M_LEN) {
468  		wpa_printf(MSG_INFO, "SAE: Unexpected Modifier M length %zu",
469  			   len);
470  		return NULL;
471  	}
472  
473  	pk = os_zalloc(sizeof(*pk));
474  	if (!pk)
475  		return NULL;
476  	pk->m = wpabuf_alloc(len);
477  	if (!pk->m || hexstr2bin(val, wpabuf_put(pk->m, len), len)) {
478  		wpa_printf(MSG_INFO, "SAE: Failed to parse m");
479  		goto fail;
480  	}
481  
482  	pos++;
483  	b_len = os_strlen(pos);
484  #ifdef CONFIG_TESTING_OPTIONS
485  	pos2 = os_strchr(pos, ':');
486  	if (pos2) {
487  		b_len = pos2 - pos;
488  		pos2++;
489  	}
490  #endif /* CONFIG_TESTING_OPTIONS */
491  	der = base64_decode(pos, b_len, &der_len);
492  	if (!der) {
493  		wpa_printf(MSG_INFO, "SAE: Failed to base64 decode PK key");
494  		goto fail;
495  	}
496  
497  	pk->key = crypto_ec_key_parse_priv(der, der_len);
498  	bin_clear_free(der, der_len);
499  	if (!pk->key)
500  		goto fail;
501  	pk->group = crypto_ec_key_group(pk->key);
502  	pk->pubkey = crypto_ec_key_get_subject_public_key(pk->key);
503  	if (!pk->pubkey)
504  		goto fail;
505  
506  #ifdef CONFIG_TESTING_OPTIONS
507  	if (pos2) {
508  		der = base64_decode(pos2, os_strlen(pos2), &der_len);
509  		if (!der) {
510  			wpa_printf(MSG_INFO,
511  				   "SAE: Failed to base64 decode PK key");
512  			goto fail;
513  		}
514  
515  		pk->sign_key_override = crypto_ec_key_parse_priv(der, der_len);
516  		bin_clear_free(der, der_len);
517  		if (!pk->sign_key_override)
518  			goto fail;
519  	}
520  #endif /* CONFIG_TESTING_OPTIONS */
521  
522  	return pk;
523  fail:
524  	sae_deinit_pk(pk);
525  	return NULL;
526  }
527  
528  
sae_hash(size_t hash_len,const u8 * data,size_t len,u8 * hash)529  int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash)
530  {
531  	if (hash_len == 32)
532  		return sha256_vector(1, &data, &len, hash);
533  #ifdef CONFIG_SHA384
534  	if (hash_len == 48)
535  		return sha384_vector(1, &data, &len, hash);
536  #endif /* CONFIG_SHA384 */
537  #ifdef CONFIG_SHA512
538  	if (hash_len == 64)
539  		return sha512_vector(1, &data, &len, hash);
540  #endif /* CONFIG_SHA512 */
541  	return -1;
542  }
543  
544  
sae_pk_hash_sig_data(struct sae_data * sae,size_t hash_len,bool ap,const u8 * m,size_t m_len,const u8 * pubkey,size_t pubkey_len,u8 * hash)545  static int sae_pk_hash_sig_data(struct sae_data *sae, size_t hash_len,
546  				bool ap, const u8 *m, size_t m_len,
547  				const u8 *pubkey, size_t pubkey_len, u8 *hash)
548  {
549  	struct sae_temporary_data *tmp = sae->tmp;
550  	struct wpabuf *sig_data;
551  	u8 *pos;
552  	int ret = -1;
553  
554  	/* Signed data for KeyAuth: eleAP || eleSTA || scaAP || scaSTA ||
555  	 * M || K_AP || AP-BSSID || STA-MAC */
556  	sig_data = wpabuf_alloc(tmp->prime_len * 6 + m_len + pubkey_len +
557  				2 * ETH_ALEN);
558  	if (!sig_data)
559  		goto fail;
560  	pos = wpabuf_put(sig_data, 2 * tmp->prime_len);
561  	if (crypto_ec_point_to_bin(tmp->ec, ap ? tmp->own_commit_element_ecc :
562  				   tmp->peer_commit_element_ecc,
563  				   pos, pos + tmp->prime_len) < 0)
564  		goto fail;
565  	pos = wpabuf_put(sig_data, 2 * tmp->prime_len);
566  	if (crypto_ec_point_to_bin(tmp->ec, ap ? tmp->peer_commit_element_ecc :
567  				   tmp->own_commit_element_ecc,
568  				   pos, pos + tmp->prime_len) < 0)
569  		goto fail;
570  	if (crypto_bignum_to_bin(ap ? tmp->own_commit_scalar :
571  				 sae->peer_commit_scalar,
572  				 wpabuf_put(sig_data, tmp->prime_len),
573  				 tmp->prime_len, tmp->prime_len) < 0 ||
574  	    crypto_bignum_to_bin(ap ? sae->peer_commit_scalar :
575  				 tmp->own_commit_scalar,
576  				 wpabuf_put(sig_data, tmp->prime_len),
577  				 tmp->prime_len, tmp->prime_len) < 0)
578  		goto fail;
579  	wpabuf_put_data(sig_data, m, m_len);
580  	wpabuf_put_data(sig_data, pubkey, pubkey_len);
581  	wpabuf_put_data(sig_data, ap ? tmp->own_addr : tmp->peer_addr,
582  			ETH_ALEN);
583  	wpabuf_put_data(sig_data, ap ? tmp->peer_addr : tmp->own_addr,
584  			ETH_ALEN);
585  	wpa_hexdump_buf_key(MSG_DEBUG, "SAE-PK: Data to be signed for KeyAuth",
586  			    sig_data);
587  	if (sae_hash(hash_len, wpabuf_head(sig_data), wpabuf_len(sig_data),
588  		     hash) < 0)
589  		goto fail;
590  	wpa_hexdump(MSG_DEBUG, "SAE-PK: hash(data to be signed)",
591  		    hash, hash_len);
592  	ret = 0;
593  fail:
594  	wpabuf_free(sig_data);
595  	return ret;
596  }
597  
598  
sae_write_confirm_pk(struct sae_data * sae,struct wpabuf * buf)599  int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf)
600  {
601  	struct sae_temporary_data *tmp = sae->tmp;
602  	struct wpabuf *sig = NULL;
603  	size_t need;
604  	int ret = -1;
605  	u8 *encr_mod;
606  	size_t encr_mod_len;
607  	const struct sae_pk *pk;
608  	u8 hash[SAE_MAX_HASH_LEN];
609  	size_t hash_len;
610  	struct crypto_ec_key *key;
611  
612  	if (!tmp)
613  		return -1;
614  
615  	pk = tmp->ap_pk;
616  	if (!sae->pk || !pk)
617  		return 0;
618  
619  	key = pk->key;
620  #ifdef CONFIG_TESTING_OPTIONS
621  	if (tmp->omit_pk_elem)
622  		return 0;
623  	if (pk->sign_key_override) {
624  		wpa_printf(MSG_INFO, "TESTING: Override SAE-PK signing key");
625  		key = pk->sign_key_override;
626  	}
627  #endif /* CONFIG_TESTING_OPTIONS */
628  
629  	if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) {
630  		wpa_printf(MSG_INFO,
631  			   "SAE-PK: No KEK available for writing confirm");
632  		return -1;
633  	}
634  
635  	if (!tmp->ec) {
636  		/* Only ECC groups are supported for SAE-PK in the current
637  		 * implementation. */
638  		wpa_printf(MSG_INFO,
639  			   "SAE-PK: SAE commit did not use an ECC group");
640  		return -1;
641  	}
642  
643  	hash_len = sae_group_2_hash_len(pk->group);
644  	if (sae_pk_hash_sig_data(sae, hash_len, true, wpabuf_head(pk->m),
645  				 wpabuf_len(pk->m), wpabuf_head(pk->pubkey),
646  				 wpabuf_len(pk->pubkey), hash) < 0)
647  		goto fail;
648  	sig = crypto_ec_key_sign(key, hash, hash_len);
649  	if (!sig)
650  		goto fail;
651  	wpa_hexdump_buf(MSG_DEBUG, "SAE-PK: KeyAuth = Sig_AP()", sig);
652  
653  	/* TODO: fragmentation if any of the elements needs it for a group
654  	 * using sufficiently large primes (none of the currently supported
655  	 * ones do) */
656  
657  	encr_mod_len = wpabuf_len(pk->m) + AES_BLOCK_SIZE;
658  	need = 4 + wpabuf_len(pk->pubkey) + 3 + wpabuf_len(sig) +
659  		6 + encr_mod_len;
660  	if (wpabuf_tailroom(buf) < need) {
661  		wpa_printf(MSG_INFO,
662  			   "SAE-PK: No room in message buffer for SAE-PK elements (%zu < %zu)",
663  			   wpabuf_tailroom(buf), need);
664  		goto fail;
665  	}
666  
667  	/* FILS Public Key element */
668  	wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
669  	wpabuf_put_u8(buf, 2 + wpabuf_len(pk->pubkey));
670  	wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_PUBLIC_KEY);
671  	wpabuf_put_u8(buf, 2); /* Key Type: ECDSA public key */
672  	wpabuf_put_buf(buf, pk->pubkey);
673  
674  	/* FILS Key Confirmation element (KeyAuth) */
675  	wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
676  	wpabuf_put_u8(buf, 1 + wpabuf_len(sig));
677  	wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
678  	/* KeyAuth = Sig_AP(eleAP || eleSTA || scaAP || scaSTA || M || K_AP ||
679  	 *                  AP-BSSID || STA-MAC) */
680  	wpabuf_put_buf(buf, sig);
681  
682  	/* SAE-PK element */
683  	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
684  	wpabuf_put_u8(buf, 4 + encr_mod_len);
685  	wpabuf_put_be32(buf, SAE_PK_IE_VENDOR_TYPE);
686  	/* EncryptedModifier = AES-SIV-Q(M); no AAD */
687  	encr_mod = wpabuf_put(buf, encr_mod_len);
688  	if (aes_siv_encrypt(tmp->kek, tmp->kek_len,
689  			    wpabuf_head(pk->m), wpabuf_len(pk->m),
690  			    0, NULL, NULL, encr_mod) < 0)
691  		goto fail;
692  	wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier",
693  		    encr_mod, encr_mod_len);
694  
695  	ret = 0;
696  fail:
697  	wpabuf_free(sig);
698  	return ret;
699  
700  }
701  
702  
sae_pk_valid_fingerprint(struct sae_data * sae,const u8 * m,size_t m_len,const u8 * k_ap,size_t k_ap_len,int group)703  static bool sae_pk_valid_fingerprint(struct sae_data *sae,
704  				     const u8 *m, size_t m_len,
705  				     const u8 *k_ap, size_t k_ap_len, int group)
706  {
707  	struct sae_temporary_data *tmp = sae->tmp;
708  	u8 *hash_data, *pos;
709  	size_t hash_len, hash_data_len;
710  	u8 hash[SAE_MAX_HASH_LEN];
711  	int res;
712  
713  	if (!tmp->fingerprint_bytes) {
714  		wpa_printf(MSG_DEBUG,
715  			   "SAE-PK: No PW available for K_AP fingerprint check");
716  		return false;
717  	}
718  
719  	/* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 19*Lambda/4 - 5)
720  	 */
721  
722  	hash_len = sae_group_2_hash_len(group);
723  	hash_data_len = tmp->ssid_len + m_len + k_ap_len;
724  	hash_data = os_malloc(hash_data_len);
725  	if (!hash_data)
726  		return false;
727  	pos = hash_data;
728  	os_memcpy(pos, tmp->ssid, tmp->ssid_len);
729  	pos += tmp->ssid_len;
730  	os_memcpy(pos, m, m_len);
731  	pos += m_len;
732  	os_memcpy(pos, k_ap, k_ap_len);
733  
734  	wpa_hexdump_key(MSG_DEBUG, "SAE-PK: SSID || M || K_AP",
735  			hash_data, hash_data_len);
736  	res = sae_hash(hash_len, hash_data, hash_data_len, hash);
737  	bin_clear_free(hash_data, hash_data_len);
738  	if (res < 0)
739  		return false;
740  	wpa_hexdump(MSG_DEBUG, "SAE-PK: Hash(SSID || M || K_AP)",
741  		    hash, hash_len);
742  
743  	if (tmp->fingerprint_bits > hash_len * 8) {
744  		wpa_printf(MSG_INFO,
745  			   "SAE-PK: Not enough hash output bits for the fingerprint");
746  		return false;
747  	}
748  	if (tmp->fingerprint_bits % 8) {
749  		size_t extra;
750  
751  		/* Zero out the extra bits in the last octet */
752  		extra = 8 - tmp->fingerprint_bits % 8;
753  		pos = &hash[tmp->fingerprint_bits / 8];
754  		*pos = (*pos >> extra) << extra;
755  	}
756  	wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint", hash,
757  		    tmp->fingerprint_bytes);
758  	res = os_memcmp_const(hash, tmp->fingerprint, tmp->fingerprint_bytes);
759  	if (res) {
760  		wpa_printf(MSG_DEBUG, "SAE-PK: K_AP fingerprint mismatch");
761  	wpa_hexdump(MSG_DEBUG, "SAE-PK: Expected fingerprint",
762  		    tmp->fingerprint, tmp->fingerprint_bytes);
763  		return false;
764  	}
765  
766  	wpa_printf(MSG_DEBUG, "SAE-PK: Valid K_AP fingerprint");
767  	return true;
768  }
769  
770  
sae_check_confirm_pk(struct sae_data * sae,const u8 * ies,size_t ies_len)771  int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len)
772  {
773  	struct sae_temporary_data *tmp = sae->tmp;
774  	const u8 *k_ap;
775  	u8 m[SAE_PK_M_LEN];
776  	size_t k_ap_len;
777  	struct crypto_ec_key *key;
778  	int res;
779  	u8 hash[SAE_MAX_HASH_LEN];
780  	size_t hash_len;
781  	int group;
782  	struct ieee802_11_elems elems;
783  
784  	if (!tmp)
785  		return -1;
786  	if (!sae->pk || tmp->ap_pk)
787  		return 0;
788  
789  	if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) {
790  		wpa_printf(MSG_INFO,
791  			   "SAE-PK: No KEK available for checking confirm");
792  		return -1;
793  	}
794  
795  	if (!tmp->ec) {
796  		/* Only ECC groups are supported for SAE-PK in the current
797  		 * implementation. */
798  		wpa_printf(MSG_INFO,
799  			   "SAE-PK: SAE commit did not use an ECC group");
800  		return -1;
801  	}
802  
803  	wpa_hexdump(MSG_DEBUG, "SAE-PK: Received confirm IEs", ies, ies_len);
804  	if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
805  		wpa_printf(MSG_INFO, "SAE-PK: Failed to parse confirm IEs");
806  		return -1;
807  	}
808  	if (!elems.fils_pk || !elems.fils_key_confirm || !elems.sae_pk) {
809  		wpa_printf(MSG_INFO,
810  			   "SAE-PK: Not all mandatory IEs included in confirm");
811  		return -1;
812  	}
813  
814  	/* TODO: Fragment reassembly */
815  
816  	if (elems.sae_pk_len < SAE_PK_M_LEN + AES_BLOCK_SIZE) {
817  		wpa_printf(MSG_INFO,
818  			   "SAE-PK: No room for EncryptedModifier in SAE-PK element");
819  		return -1;
820  	}
821  
822  	wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier",
823  		    elems.sae_pk, SAE_PK_M_LEN + AES_BLOCK_SIZE);
824  
825  	if (aes_siv_decrypt(tmp->kek, tmp->kek_len,
826  			    elems.sae_pk, SAE_PK_M_LEN + AES_BLOCK_SIZE,
827  			    0, NULL, NULL, m) < 0) {
828  		wpa_printf(MSG_INFO,
829  			   "SAE-PK: Failed to decrypt EncryptedModifier");
830  		return -1;
831  	}
832  	wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Modifier M", m, SAE_PK_M_LEN);
833  
834  	if (elems.fils_pk[0] != 2) {
835  		wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u",
836  			   elems.fils_pk[0]);
837  		return -1;
838  	}
839  	k_ap_len = elems.fils_pk_len - 1;
840  	k_ap = elems.fils_pk + 1;
841  	wpa_hexdump(MSG_DEBUG, "SAE-PK: Received K_AP", k_ap, k_ap_len);
842  	/* TODO: Check against the public key, if one is stored in the network
843  	 * profile */
844  
845  	key = crypto_ec_key_parse_pub(k_ap, k_ap_len);
846  	if (!key) {
847  		wpa_printf(MSG_INFO, "SAE-PK: Failed to parse K_AP");
848  		return -1;
849  	}
850  
851  	group = crypto_ec_key_group(key);
852  	if (!sae_pk_valid_fingerprint(sae, m, SAE_PK_M_LEN, k_ap, k_ap_len,
853  				      group)) {
854  		crypto_ec_key_deinit(key);
855  		return -1;
856  	}
857  
858  	wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth",
859  		    elems.fils_key_confirm, elems.fils_key_confirm_len);
860  
861  	hash_len = sae_group_2_hash_len(group);
862  	if (sae_pk_hash_sig_data(sae, hash_len, false, m, SAE_PK_M_LEN,
863  				 k_ap, k_ap_len, hash) < 0) {
864  		crypto_ec_key_deinit(key);
865  		return -1;
866  	}
867  
868  	res = crypto_ec_key_verify_signature(key, hash, hash_len,
869  					     elems.fils_key_confirm,
870  					     elems.fils_key_confirm_len);
871  	crypto_ec_key_deinit(key);
872  
873  	if (res != 1) {
874  		wpa_printf(MSG_INFO,
875  			   "SAE-PK: Invalid or incorrect signature in KeyAuth");
876  		return -1;
877  	}
878  
879  	wpa_printf(MSG_DEBUG, "SAE-PK: Valid KeyAuth signature received");
880  
881  	/* TODO: Store validated public key into network profile */
882  
883  	return 0;
884  }
885