xref: /freebsd/contrib/wpa/src/eap_common/eap_teap_common.c (revision 19fae0f66023a97a9b464b3beeeabb2081f575b3)
1 /*
2  * EAP-TEAP common helper functions (RFC 7170)
3  * Copyright (c) 2008-2019, 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/sha1.h"
13 #include "crypto/sha256.h"
14 #include "crypto/sha384.h"
15 #include "crypto/tls.h"
16 #include "eap_defs.h"
17 #include "eap_teap_common.h"
18 
19 
20 static int tls_cipher_suite_mac_sha384(u16 cs);
21 
22 
23 void eap_teap_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
24 {
25 	struct teap_tlv_hdr hdr;
26 
27 	hdr.tlv_type = host_to_be16(type);
28 	hdr.length = host_to_be16(len);
29 	wpabuf_put_data(buf, &hdr, sizeof(hdr));
30 }
31 
32 
33 void eap_teap_put_tlv(struct wpabuf *buf, u16 type, const void *data, u16 len)
34 {
35 	eap_teap_put_tlv_hdr(buf, type, len);
36 	wpabuf_put_data(buf, data, len);
37 }
38 
39 
40 void eap_teap_put_tlv_buf(struct wpabuf *buf, u16 type,
41 			  const struct wpabuf *data)
42 {
43 	eap_teap_put_tlv_hdr(buf, type, wpabuf_len(data));
44 	wpabuf_put_buf(buf, data);
45 }
46 
47 
48 struct wpabuf * eap_teap_tlv_eap_payload(struct wpabuf *buf)
49 {
50 	struct wpabuf *e;
51 
52 	if (!buf)
53 		return NULL;
54 
55 	/* Encapsulate EAP packet in EAP-Payload TLV */
56 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Add EAP-Payload TLV");
57 	e = wpabuf_alloc(sizeof(struct teap_tlv_hdr) + wpabuf_len(buf));
58 	if (!e) {
59 		wpa_printf(MSG_ERROR,
60 			   "EAP-TEAP: Failed to allocate memory for TLV encapsulation");
61 		wpabuf_free(buf);
62 		return NULL;
63 	}
64 	eap_teap_put_tlv_buf(e, TEAP_TLV_MANDATORY | TEAP_TLV_EAP_PAYLOAD, buf);
65 	wpabuf_free(buf);
66 
67 	/* TODO: followed by optional TLVs associated with the EAP packet */
68 
69 	return e;
70 }
71 
72 
73 static int eap_teap_tls_prf(u16 tls_cs, const u8 *secret, size_t secret_len,
74 			    const char *label, const u8 *seed, size_t seed_len,
75 			    u8 *out, size_t outlen)
76 {
77 	/* TODO: TLS-PRF for TLSv1.3 */
78 	if (tls_cipher_suite_mac_sha384(tls_cs))
79 		return tls_prf_sha384(secret, secret_len, label, seed, seed_len,
80 				      out, outlen);
81 	return tls_prf_sha256(secret, secret_len, label, seed, seed_len,
82 			      out, outlen);
83 }
84 
85 
86 int eap_teap_derive_eap_msk(u16 tls_cs, const u8 *simck, u8 *msk)
87 {
88 	/*
89 	 * RFC 7170, Section 5.4: EAP Master Session Key Generation
90 	 * MSK = TLS-PRF(S-IMCK[j], "Session Key Generating Function", 64)
91 	 */
92 
93 	if (eap_teap_tls_prf(tls_cs, simck, EAP_TEAP_SIMCK_LEN,
94 			     "Session Key Generating Function", (u8 *) "", 0,
95 			     msk, EAP_TEAP_KEY_LEN) < 0)
96 		return -1;
97 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (MSK)",
98 			msk, EAP_TEAP_KEY_LEN);
99 	return 0;
100 }
101 
102 
103 int eap_teap_derive_eap_emsk(u16 tls_cs, const u8 *simck, u8 *emsk)
104 {
105 	/*
106 	 * RFC 7170, Section 5.4: EAP Master Session Key Generation
107 	 * EMSK = TLS-PRF(S-IMCK[j],
108 	 *        "Extended Session Key Generating Function", 64)
109 	 */
110 
111 	if (eap_teap_tls_prf(tls_cs, simck, EAP_TEAP_SIMCK_LEN,
112 			     "Extended Session Key Generating Function",
113 			     (u8 *) "", 0, emsk, EAP_EMSK_LEN) < 0)
114 		return -1;
115 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Derived key (EMSK)",
116 			emsk, EAP_EMSK_LEN);
117 	return 0;
118 }
119 
120 
121 int eap_teap_derive_cmk_basic_pw_auth(u16 tls_cs, const u8 *s_imck_msk, u8 *cmk)
122 {
123 	u8 imsk[32], imck[EAP_TEAP_IMCK_LEN];
124 	int res;
125 
126 	/* FIX: The Basic-Password-Auth (i.e., no inner EAP) case is
127 	 * not fully defined in RFC 7170, so this CMK derivation may
128 	 * need to be changed if a fixed definition is eventually
129 	 * published. For now, derive CMK[0] based on S-IMCK[0] and
130 	 * IMSK of 32 octets of zeros. */
131 	os_memset(imsk, 0, 32);
132 	res = eap_teap_tls_prf(tls_cs, s_imck_msk, EAP_TEAP_SIMCK_LEN,
133 			       "Inner Methods Compound Keys",
134 			       imsk, 32, imck, sizeof(imck));
135 	if (res < 0)
136 		return -1;
137 	os_memcpy(cmk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN);
138 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: CMK[no-inner-EAP]",
139 			cmk, EAP_TEAP_CMK_LEN);
140 	forced_memzero(imck, sizeof(imck));
141 	return 0;
142 }
143 
144 
145 int eap_teap_derive_imck(u16 tls_cs,
146 			 const u8 *prev_s_imck_msk, const u8 *prev_s_imck_emsk,
147 			 const u8 *msk, size_t msk_len,
148 			 const u8 *emsk, size_t emsk_len,
149 			 u8 *s_imck_msk, u8 *cmk_msk,
150 			 u8 *s_imck_emsk, u8 *cmk_emsk)
151 {
152 	u8 imsk[64], imck[EAP_TEAP_IMCK_LEN];
153 	int res;
154 
155 	/*
156 	 * RFC 7170, Section 5.2:
157 	 * IMSK = First 32 octets of TLS-PRF(EMSK, "TEAPbindkey@ietf.org" |
158 	 *                                   "\0" | 64)
159 	 * (if EMSK is not available, MSK is used instead; if neither is
160 	 * available, IMSK is 32 octets of zeros; MSK is truncated to 32 octets
161 	 * or padded to 32 octets, if needed)
162 	 * (64 is encoded as a 2-octet field in network byte order)
163 	 *
164 	 * S-IMCK[0] = session_key_seed
165 	 * IMCK[j] = TLS-PRF(S-IMCK[j-1], "Inner Methods Compound Keys",
166 	 *                   IMSK[j], 60)
167 	 * S-IMCK[j] = first 40 octets of IMCK[j]
168 	 * CMK[j] = last 20 octets of IMCK[j]
169 	 */
170 
171 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK[j]", msk, msk_len);
172 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK[j]", emsk, emsk_len);
173 
174 	if (emsk && emsk_len > 0) {
175 		u8 context[3];
176 
177 		context[0] = 0;
178 		context[1] = 0;
179 		context[2] = 64;
180 		if (eap_teap_tls_prf(tls_cs, emsk, emsk_len,
181 				     "TEAPbindkey@ietf.org",
182 				     context, sizeof(context), imsk, 64) < 0)
183 			return -1;
184 
185 		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from EMSK",
186 				imsk, 32);
187 
188 		res = eap_teap_tls_prf(tls_cs,
189 				       prev_s_imck_emsk, EAP_TEAP_SIMCK_LEN,
190 				       "Inner Methods Compound Keys",
191 				       imsk, 32, imck, EAP_TEAP_IMCK_LEN);
192 		forced_memzero(imsk, sizeof(imsk));
193 		if (res < 0)
194 			return -1;
195 
196 		os_memcpy(s_imck_emsk, imck, EAP_TEAP_SIMCK_LEN);
197 		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK S-IMCK[j]",
198 				s_imck_emsk, EAP_TEAP_SIMCK_LEN);
199 		os_memcpy(cmk_emsk, &imck[EAP_TEAP_SIMCK_LEN],
200 			  EAP_TEAP_CMK_LEN);
201 		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK CMK[j]",
202 				cmk_emsk, EAP_TEAP_CMK_LEN);
203 		forced_memzero(imck, EAP_TEAP_IMCK_LEN);
204 	}
205 
206 	if (msk && msk_len > 0) {
207 		size_t copy_len = msk_len;
208 
209 		os_memset(imsk, 0, 32); /* zero pad, if needed */
210 		if (copy_len > 32)
211 			copy_len = 32;
212 		os_memcpy(imsk, msk, copy_len);
213 		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from MSK", imsk, 32);
214 	} else {
215 		os_memset(imsk, 0, 32);
216 		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Zero IMSK", imsk, 32);
217 	}
218 
219 	res = eap_teap_tls_prf(tls_cs, prev_s_imck_msk, EAP_TEAP_SIMCK_LEN,
220 			       "Inner Methods Compound Keys",
221 			       imsk, 32, imck, EAP_TEAP_IMCK_LEN);
222 	forced_memzero(imsk, sizeof(imsk));
223 	if (res < 0)
224 		return -1;
225 
226 	os_memcpy(s_imck_msk, imck, EAP_TEAP_SIMCK_LEN);
227 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK S-IMCK[j]",
228 			s_imck_msk, EAP_TEAP_SIMCK_LEN);
229 	os_memcpy(cmk_msk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN);
230 	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK CMK[j]",
231 			cmk_msk, EAP_TEAP_CMK_LEN);
232 	forced_memzero(imck, EAP_TEAP_IMCK_LEN);
233 
234 	return 0;
235 }
236 
237 
238 static int tls_cipher_suite_match(const u16 *list, size_t count, u16 cs)
239 {
240 	size_t i;
241 
242 	for (i = 0; i < count; i++) {
243 		if (list[i] == cs)
244 			return 1;
245 	}
246 
247 	return 0;
248 }
249 
250 
251 static int tls_cipher_suite_mac_sha1(u16 cs)
252 {
253 	static const u16 sha1_cs[] = {
254 		0x0005, 0x0007, 0x000a, 0x000d, 0x0010, 0x0013, 0x0016, 0x001b,
255 		0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036,
256 		0x0037, 0x0038, 0x0039, 0x003a, 0x0041, 0x0042, 0x0043, 0x0044,
257 		0x0045, 0x0046, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
258 		0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091,
259 		0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099,
260 		0x009a, 0x009b,
261 		0xc002, 0xc003, 0xc004, 0xc005, 0xc007, 0xc008, 0xc009, 0xc009,
262 		0xc00a, 0xc00c, 0xc00d, 0xc00e, 0xc00f, 0xc011, 0xc012, 0xc013,
263 		0xc014, 0xc016, 0xc017, 0xc018, 0xc019, 0xc01a, 0xc01b, 0xc01c,
264 		0xc014, 0xc01e, 0xc01f, 0xc020, 0xc021, 0xc022, 0xc033, 0xc034,
265 		0xc035, 0xc036
266 	};
267 
268 	return tls_cipher_suite_match(sha1_cs, ARRAY_SIZE(sha1_cs), cs);
269 }
270 
271 
272 static int tls_cipher_suite_mac_sha256(u16 cs)
273 {
274 	static const u16 sha256_cs[] = {
275 		0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0067, 0x0068, 0x0069,
276 		0x006a, 0x006b, 0x006c, 0x006d, 0x009c, 0x009e, 0x00a0, 0x00a2,
277 		0x00a4, 0x00a6, 0x00a8, 0x00aa, 0x00ac, 0x00ae, 0x00b2, 0x00b6,
278 		0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bd, 0x00be, 0x00be,
279 		0x00bf, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
280 		0x1301, 0x1303, 0x1304, 0x1305,
281 		0xc023, 0xc025, 0xc027, 0xc029, 0xc02b, 0xc02d, 0xc02f, 0xc031,
282 		0xc037, 0xc03c, 0xc03e, 0xc040, 0xc040, 0xc042, 0xc044, 0xc046,
283 		0xc048, 0xc04a, 0xc04c, 0xc04e, 0xc050, 0xc052, 0xc054, 0xc056,
284 		0xc058, 0xc05a, 0xc05c, 0xc05e, 0xc060, 0xc062, 0xc064, 0xc066,
285 		0xc068, 0xc06a, 0xc06c, 0xc06e, 0xc070, 0xc072, 0xc074, 0xc076,
286 		0xc078, 0xc07a, 0xc07c, 0xc07e, 0xc080, 0xc082, 0xc084, 0xc086,
287 		0xc088, 0xc08a, 0xc08c, 0xc08e, 0xc090, 0xc092, 0xc094, 0xc096,
288 		0xc098, 0xc09a, 0xc0b0, 0xc0b2, 0xc0b4,
289 		0xcca8, 0xcca9, 0xccaa, 0xccab, 0xccac, 0xccad, 0xccae,
290 		0xd001, 0xd003, 0xd005
291 	};
292 
293 	return tls_cipher_suite_match(sha256_cs, ARRAY_SIZE(sha256_cs), cs);
294 }
295 
296 
297 static int tls_cipher_suite_mac_sha384(u16 cs)
298 {
299 	static const u16 sha384_cs[] = {
300 		0x009d, 0x009f, 0x00a1, 0x00a3, 0x00a5, 0x00a7, 0x00a9, 0x00ab,
301 		0x00ad, 0x00af, 0x00b3, 0x00b7, 0x1302,
302 		0xc024, 0xc026, 0xc028, 0xc02a, 0xc02c, 0xc02e, 0xc030, 0xc032,
303 		0xc038, 0xc03d, 0xc03f, 0xc041, 0xc043, 0xc045, 0xc047, 0xc049,
304 		0xc04b, 0xc04d, 0xc04f, 0xc051, 0xc053, 0xc055, 0xc057, 0xc059,
305 		0xc05b, 0xc05d, 0xc05f, 0xc061, 0xc063, 0xc065, 0xc067, 0xc069,
306 		0xc06b, 0xc06d, 0xc06f, 0xc071, 0xc073, 0xc075, 0xc077, 0xc079,
307 		0xc07b, 0xc07d, 0xc07f, 0xc081, 0xc083, 0xc085, 0xc087, 0xc089,
308 		0xc08b, 0xc08d, 0xc08f, 0xc091, 0xc093, 0xc095, 0xc097, 0xc099,
309 		0xc09b, 0xc0b1, 0xc0b3, 0xc0b5,
310 		0xd002
311 	};
312 
313 	return tls_cipher_suite_match(sha384_cs, ARRAY_SIZE(sha384_cs), cs);
314 }
315 
316 
317 static int eap_teap_tls_mac(u16 tls_cs, const u8 *cmk, size_t cmk_len,
318 			    const u8 *buffer, size_t buffer_len,
319 			    u8 *mac, size_t mac_len)
320 {
321 	int res;
322 	u8 tmp[48];
323 
324 	os_memset(tmp, 0, sizeof(tmp));
325 	os_memset(mac, 0, mac_len);
326 
327 	if (tls_cipher_suite_mac_sha1(tls_cs)) {
328 		wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA1");
329 		res = hmac_sha1(cmk, cmk_len, buffer, buffer_len, tmp);
330 	} else if (tls_cipher_suite_mac_sha256(tls_cs)) {
331 		wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA256");
332 		res = hmac_sha256(cmk, cmk_len, buffer, buffer_len, tmp);
333 	} else if (tls_cipher_suite_mac_sha384(tls_cs)) {
334 		wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA384");
335 		res = hmac_sha384(cmk, cmk_len, buffer, buffer_len, tmp);
336 	} else {
337 		wpa_printf(MSG_INFO,
338 			   "EAP-TEAP: Unsupported TLS cipher suite 0x%04x",
339 			   tls_cs);
340 		res = -1;
341 	}
342 	if (res < 0)
343 		return res;
344 
345 	/* FIX: RFC 7170 does not describe how to handle truncation of the
346 	 * Compound MAC or if the fields are supposed to be of variable length
347 	 * based on the negotiated TLS cipher suite (they are defined as having
348 	 * fixed size of 20 octets in the TLV description) */
349 	if (mac_len > sizeof(tmp))
350 		mac_len = sizeof(tmp);
351 	os_memcpy(mac, tmp, mac_len);
352 	return 0;
353 }
354 
355 
356 int eap_teap_compound_mac(u16 tls_cs, const struct teap_tlv_crypto_binding *cb,
357 			  const struct wpabuf *server_outer_tlvs,
358 			  const struct wpabuf *peer_outer_tlvs,
359 			  const u8 *cmk, u8 *compound_mac)
360 {
361 	u8 *pos, *buffer;
362 	size_t bind_len, buffer_len;
363 	struct teap_tlv_crypto_binding *tmp_cb;
364 	int res;
365 
366 	/* RFC 7170, Section 5.3 */
367 	bind_len = sizeof(struct teap_tlv_hdr) + be_to_host16(cb->length);
368 	buffer_len = bind_len + 1;
369 	if (server_outer_tlvs)
370 		buffer_len += wpabuf_len(server_outer_tlvs);
371 	if (peer_outer_tlvs)
372 		buffer_len += wpabuf_len(peer_outer_tlvs);
373 	buffer = os_malloc(buffer_len);
374 	if (!buffer)
375 		return -1;
376 
377 	pos = buffer;
378 	/* 1. The entire Crypto-Binding TLV attribute with both the EMSK and MSK
379 	 * Compound MAC fields zeroed out. */
380 	os_memcpy(pos, cb, bind_len);
381 	pos += bind_len;
382 	tmp_cb = (struct teap_tlv_crypto_binding *) buffer;
383 	os_memset(tmp_cb->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
384 	os_memset(tmp_cb->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
385 
386 	/* 2. The EAP Type sent by the other party in the first TEAP message. */
387 	/* This is supposed to be the EAP Type sent by the other party in the
388 	 * first TEAP message, but since we cannot get here without having
389 	 * successfully negotiated use of TEAP, this can only be the fixed EAP
390 	 * Type of TEAP. */
391 	*pos++ = EAP_TYPE_TEAP;
392 
393 	/* 3. All the Outer TLVs from the first TEAP message sent by EAP server
394 	 * to peer. */
395 	if (server_outer_tlvs) {
396 		os_memcpy(pos, wpabuf_head(server_outer_tlvs),
397 			  wpabuf_len(server_outer_tlvs));
398 		pos += wpabuf_len(server_outer_tlvs);
399 	}
400 
401 	/* 4. All the Outer TLVs from the first TEAP message sent by the peer to
402 	 * the EAP server. */
403 	if (peer_outer_tlvs) {
404 		os_memcpy(pos, wpabuf_head(peer_outer_tlvs),
405 			  wpabuf_len(peer_outer_tlvs));
406 		pos += wpabuf_len(peer_outer_tlvs);
407 	}
408 
409 	buffer_len = pos - buffer;
410 
411 	wpa_hexdump_key(MSG_MSGDUMP,
412 			"EAP-TEAP: CMK for Compound MAC calculation",
413 			cmk, EAP_TEAP_CMK_LEN);
414 	wpa_hexdump(MSG_MSGDUMP,
415 		    "EAP-TEAP: BUFFER for Compound MAC calculation",
416 		    buffer, buffer_len);
417 	res = eap_teap_tls_mac(tls_cs, cmk, EAP_TEAP_CMK_LEN,
418 			       buffer, buffer_len,
419 			       compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
420 	os_free(buffer);
421 
422 	return res;
423 }
424 
425 
426 int eap_teap_parse_tlv(struct eap_teap_tlv_parse *tlv,
427 		       int tlv_type, u8 *pos, size_t len)
428 {
429 	switch (tlv_type) {
430 	case TEAP_TLV_IDENTITY_TYPE:
431 		if (len < 2) {
432 			wpa_printf(MSG_INFO,
433 				   "EAP-TEAP: Too short Identity-Type TLV");
434 			tlv->result = TEAP_STATUS_FAILURE;
435 			break;
436 		}
437 		tlv->identity_type = WPA_GET_BE16(pos);
438 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Identity-Type: %u",
439 			   tlv->identity_type);
440 		break;
441 	case TEAP_TLV_RESULT:
442 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Result TLV", pos, len);
443 		if (tlv->result) {
444 			wpa_printf(MSG_INFO,
445 				   "EAP-TEAP: More than one Result TLV in the message");
446 			tlv->result = TEAP_STATUS_FAILURE;
447 			return -2;
448 		}
449 		if (len < 2) {
450 			wpa_printf(MSG_INFO, "EAP-TEAP: Too short Result TLV");
451 			tlv->result = TEAP_STATUS_FAILURE;
452 			break;
453 		}
454 		tlv->result = WPA_GET_BE16(pos);
455 		if (tlv->result != TEAP_STATUS_SUCCESS &&
456 		    tlv->result != TEAP_STATUS_FAILURE) {
457 			wpa_printf(MSG_INFO, "EAP-TEAP: Unknown Result %d",
458 				   tlv->result);
459 			tlv->result = TEAP_STATUS_FAILURE;
460 		}
461 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Result: %s",
462 			   tlv->result == TEAP_STATUS_SUCCESS ?
463 			   "Success" : "Failure");
464 		break;
465 	case TEAP_TLV_NAK:
466 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: NAK TLV", pos, len);
467 		if (len < 6) {
468 			wpa_printf(MSG_INFO, "EAP-TEAP: Too short NAK TLV");
469 			tlv->result = TEAP_STATUS_FAILURE;
470 			break;
471 		}
472 		tlv->nak = pos;
473 		tlv->nak_len = len;
474 		break;
475 	case TEAP_TLV_ERROR:
476 		if (len < 4) {
477 			wpa_printf(MSG_INFO, "EAP-TEAP: Too short Error TLV");
478 			tlv->result = TEAP_STATUS_FAILURE;
479 			break;
480 		}
481 		tlv->error_code = WPA_GET_BE32(pos);
482 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Error: %u", tlv->error_code);
483 		break;
484 	case TEAP_TLV_REQUEST_ACTION:
485 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Request-Action TLV",
486 			    pos, len);
487 		if (tlv->request_action) {
488 			wpa_printf(MSG_INFO,
489 				   "EAP-TEAP: More than one Request-Action TLV in the message");
490 			tlv->iresult = TEAP_STATUS_FAILURE;
491 			return -2;
492 		}
493 		if (len < 2) {
494 			wpa_printf(MSG_INFO,
495 				   "EAP-TEAP: Too short Request-Action TLV");
496 			tlv->iresult = TEAP_STATUS_FAILURE;
497 			break;
498 		}
499 		tlv->request_action_status = pos[0];
500 		tlv->request_action = pos[1];
501 		wpa_printf(MSG_DEBUG,
502 			   "EAP-TEAP: Request-Action: Status=%u Action=%u",
503 			   tlv->request_action_status, tlv->request_action);
504 		break;
505 	case TEAP_TLV_EAP_PAYLOAD:
506 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: EAP-Payload TLV",
507 			    pos, len);
508 		if (tlv->eap_payload_tlv) {
509 			wpa_printf(MSG_INFO,
510 				   "EAP-TEAP: More than one EAP-Payload TLV in the message");
511 			tlv->iresult = TEAP_STATUS_FAILURE;
512 			return -2;
513 		}
514 		tlv->eap_payload_tlv = pos;
515 		tlv->eap_payload_tlv_len = len;
516 		break;
517 	case TEAP_TLV_INTERMEDIATE_RESULT:
518 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Intermediate-Result TLV",
519 			    pos, len);
520 		if (len < 2) {
521 			wpa_printf(MSG_INFO,
522 				   "EAP-TEAP: Too short Intermediate-Result TLV");
523 			tlv->iresult = TEAP_STATUS_FAILURE;
524 			break;
525 		}
526 		if (tlv->iresult) {
527 			wpa_printf(MSG_INFO,
528 				   "EAP-TEAP: More than one Intermediate-Result TLV in the message");
529 			tlv->iresult = TEAP_STATUS_FAILURE;
530 			return -2;
531 		}
532 		tlv->iresult = WPA_GET_BE16(pos);
533 		if (tlv->iresult != TEAP_STATUS_SUCCESS &&
534 		    tlv->iresult != TEAP_STATUS_FAILURE) {
535 			wpa_printf(MSG_INFO,
536 				   "EAP-TEAP: Unknown Intermediate Result %d",
537 				   tlv->iresult);
538 			tlv->iresult = TEAP_STATUS_FAILURE;
539 		}
540 		wpa_printf(MSG_DEBUG, "EAP-TEAP: Intermediate Result: %s",
541 			   tlv->iresult == TEAP_STATUS_SUCCESS ?
542 			   "Success" : "Failure");
543 		break;
544 	case TEAP_TLV_PAC:
545 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: PAC TLV", pos, len);
546 		if (tlv->pac) {
547 			wpa_printf(MSG_INFO,
548 				   "EAP-TEAP: More than one PAC TLV in the message");
549 			tlv->iresult = TEAP_STATUS_FAILURE;
550 			return -2;
551 		}
552 		tlv->pac = pos;
553 		tlv->pac_len = len;
554 		break;
555 	case TEAP_TLV_CRYPTO_BINDING:
556 		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Crypto-Binding TLV",
557 			    pos, len);
558 		if (tlv->crypto_binding) {
559 			wpa_printf(MSG_INFO,
560 				   "EAP-TEAP: More than one Crypto-Binding TLV in the message");
561 			tlv->iresult = TEAP_STATUS_FAILURE;
562 			return -2;
563 		}
564 		tlv->crypto_binding_len = sizeof(struct teap_tlv_hdr) + len;
565 		if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
566 			wpa_printf(MSG_INFO,
567 				   "EAP-TEAP: Too short Crypto-Binding TLV");
568 			tlv->iresult = TEAP_STATUS_FAILURE;
569 			return -2;
570 		}
571 		tlv->crypto_binding = (struct teap_tlv_crypto_binding *)
572 			(pos - sizeof(struct teap_tlv_hdr));
573 		break;
574 	case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ:
575 		wpa_hexdump_ascii(MSG_MSGDUMP,
576 				  "EAP-TEAP: Basic-Password-Auth-Req TLV",
577 				  pos, len);
578 		if (tlv->basic_auth_req) {
579 			wpa_printf(MSG_INFO,
580 				   "EAP-TEAP: More than one Basic-Password-Auth-Req TLV in the message");
581 			tlv->iresult = TEAP_STATUS_FAILURE;
582 			return -2;
583 		}
584 		tlv->basic_auth_req = pos;
585 		tlv->basic_auth_req_len = len;
586 		break;
587 	case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP:
588 		wpa_hexdump_ascii(MSG_MSGDUMP,
589 				  "EAP-TEAP: Basic-Password-Auth-Resp TLV",
590 				  pos, len);
591 		if (tlv->basic_auth_resp) {
592 			wpa_printf(MSG_INFO,
593 				   "EAP-TEAP: More than one Basic-Password-Auth-Resp TLV in the message");
594 			tlv->iresult = TEAP_STATUS_FAILURE;
595 			return -2;
596 		}
597 		tlv->basic_auth_resp = pos;
598 		tlv->basic_auth_resp_len = len;
599 		break;
600 	default:
601 		/* Unknown TLV */
602 		return -1;
603 	}
604 
605 	return 0;
606 }
607 
608 
609 const char * eap_teap_tlv_type_str(enum teap_tlv_types type)
610 {
611 	switch (type) {
612 	case TEAP_TLV_AUTHORITY_ID:
613 		return "Authority-ID";
614 	case TEAP_TLV_IDENTITY_TYPE:
615 		return "Identity-Type";
616 	case TEAP_TLV_RESULT:
617 		return "Result";
618 	case TEAP_TLV_NAK:
619 		return "NAK";
620 	case TEAP_TLV_ERROR:
621 		return "Error";
622 	case TEAP_TLV_CHANNEL_BINDING:
623 		return "Channel-Binding";
624 	case TEAP_TLV_VENDOR_SPECIFIC:
625 		return "Vendor-Specific";
626 	case TEAP_TLV_REQUEST_ACTION:
627 		return "Request-Action";
628 	case TEAP_TLV_EAP_PAYLOAD:
629 		return "EAP-Payload";
630 	case TEAP_TLV_INTERMEDIATE_RESULT:
631 		return "Intermediate-Result";
632 	case TEAP_TLV_PAC:
633 		return "PAC";
634 	case TEAP_TLV_CRYPTO_BINDING:
635 		return "Crypto-Binding";
636 	case TEAP_TLV_BASIC_PASSWORD_AUTH_REQ:
637 		return "Basic-Password-Auth-Req";
638 	case TEAP_TLV_BASIC_PASSWORD_AUTH_RESP:
639 		return "Basic-Password-Auth-Resp";
640 	case TEAP_TLV_PKCS7:
641 		return "PKCS#7";
642 	case TEAP_TLV_PKCS10:
643 		return "PKCS#10";
644 	case TEAP_TLV_TRUSTED_SERVER_ROOT:
645 		return "Trusted-Server-Root";
646 	}
647 
648 	return "?";
649 }
650 
651 
652 struct wpabuf * eap_teap_tlv_result(int status, int intermediate)
653 {
654 	struct wpabuf *buf;
655 	struct teap_tlv_result *result;
656 
657 	if (status != TEAP_STATUS_FAILURE && status != TEAP_STATUS_SUCCESS)
658 		return NULL;
659 
660 	buf = wpabuf_alloc(sizeof(*result));
661 	if (!buf)
662 		return NULL;
663 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Add %sResult TLV(status=%s)",
664 		   intermediate ? "Intermediate-" : "",
665 		   status == TEAP_STATUS_SUCCESS ? "Success" : "Failure");
666 	result = wpabuf_put(buf, sizeof(*result));
667 	result->tlv_type = host_to_be16(TEAP_TLV_MANDATORY |
668 					(intermediate ?
669 					 TEAP_TLV_INTERMEDIATE_RESULT :
670 					 TEAP_TLV_RESULT));
671 	result->length = host_to_be16(2);
672 	result->status = host_to_be16(status);
673 	return buf;
674 }
675 
676 
677 struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error)
678 {
679 	struct wpabuf *buf;
680 
681 	buf = wpabuf_alloc(4 + 4);
682 	if (!buf)
683 		return NULL;
684 	wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Error TLV(Error Code=%d)",
685 		   error);
686 	wpabuf_put_be16(buf, TEAP_TLV_MANDATORY | TEAP_TLV_ERROR);
687 	wpabuf_put_be16(buf, 4);
688 	wpabuf_put_be32(buf, error);
689 	return buf;
690 }
691 
692 
693 struct wpabuf * eap_teap_tlv_identity_type(enum teap_identity_types id)
694 {
695 	struct wpabuf *buf;
696 
697 	buf = wpabuf_alloc(4 + 2);
698 	if (!buf)
699 		return NULL;
700 	wpa_printf(MSG_DEBUG,
701 		   "EAP-TEAP: Add Identity-Type TLV(Identity-Type=%d)", id);
702 	wpabuf_put_be16(buf, TEAP_TLV_IDENTITY_TYPE);
703 	wpabuf_put_be16(buf, 2);
704 	wpabuf_put_be16(buf, id);
705 	return buf;
706 }
707 
708 
709 int eap_teap_allowed_anon_prov_phase2_method(int vendor, enum eap_type type)
710 {
711 	/* RFC 7170, Section 3.8.3: MUST provide mutual authentication,
712 	 * provide key generation, and be resistant to dictionary attack.
713 	 * Section 3.8 also mentions requirement for using EMSK Compound MAC. */
714 	return vendor == EAP_VENDOR_IETF &&
715 		(type == EAP_TYPE_PWD || type == EAP_TYPE_EKE);
716 }
717 
718 
719 int eap_teap_allowed_anon_prov_cipher_suite(u16 cs)
720 {
721 	/* RFC 7170, Section 3.8.3: anonymous ciphersuites MAY be supported as
722 	 * long as the TLS pre-master secret is generated form contribution from
723 	 * both peers. Accept the recommended TLS_DH_anon_WITH_AES_128_CBC_SHA
724 	 * cipher suite and other ciphersuites that use DH in some form, have
725 	 * SHA-1 or stronger MAC function, and use reasonable strong cipher. */
726 	static const u16 ok_cs[] = {
727 		/* DH-anon */
728 		0x0034, 0x003a, 0x006c, 0x006d, 0x00a6, 0x00a7,
729 		/* DHE-RSA */
730 		0x0033, 0x0039, 0x0067, 0x006b, 0x009e, 0x009f,
731 		/* ECDH-anon */
732 		0xc018, 0xc019,
733 		/* ECDH-RSA */
734 		0xc003, 0xc00f, 0xc029, 0xc02a, 0xc031, 0xc032,
735 		/* ECDH-ECDSA */
736 		0xc004, 0xc005, 0xc025, 0xc026, 0xc02d, 0xc02e,
737 		/* ECDHE-RSA */
738 		0xc013, 0xc014, 0xc027, 0xc028, 0xc02f, 0xc030,
739 		/* ECDHE-ECDSA */
740 		0xc009, 0xc00a, 0xc023, 0xc024, 0xc02b, 0xc02c,
741 	};
742 
743 	return tls_cipher_suite_match(ok_cs, ARRAY_SIZE(ok_cs), cs);
744 }
745