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