eap_teap_common.c revision 351611
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
20void 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
30void 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
37void 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
45struct 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
70static 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
80int 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
97int 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
115int 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
139int 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
229static 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
242static 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
263static 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
288static 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
308static 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
347int 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
417int 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
580const 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
623struct 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
648struct 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
664int 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
673int 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