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  
eap_teap_put_tlv_hdr(struct wpabuf * buf,u16 type,u16 len)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  
eap_teap_put_tlv(struct wpabuf * buf,u16 type,const void * data,u16 len)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  
eap_teap_put_tlv_buf(struct wpabuf * buf,u16 type,const struct wpabuf * data)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  
eap_teap_tlv_eap_payload(struct wpabuf * buf)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  
eap_teap_tls_prf(u16 tls_cs,const u8 * secret,size_t secret_len,const char * label,const u8 * seed,size_t seed_len,u8 * out,size_t outlen)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  
eap_teap_derive_eap_msk(u16 tls_cs,const u8 * simck,u8 * msk)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  
eap_teap_derive_eap_emsk(u16 tls_cs,const u8 * simck,u8 * emsk)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  
eap_teap_derive_imck(u16 tls_cs,const u8 * prev_s_imck,const u8 * msk,size_t msk_len,const u8 * emsk,size_t emsk_len,u8 * s_imck_msk,u8 * cmk_msk,u8 * s_imck_emsk,u8 * cmk_emsk)121  int eap_teap_derive_imck(u16 tls_cs, const u8 *prev_s_imck,
122  			 const u8 *msk, size_t msk_len,
123  			 const u8 *emsk, size_t emsk_len,
124  			 u8 *s_imck_msk, u8 *cmk_msk,
125  			 u8 *s_imck_emsk, u8 *cmk_emsk)
126  {
127  	u8 imsk[64], imck[EAP_TEAP_IMCK_LEN];
128  	int res;
129  
130  	/*
131  	 * RFC 7170, Section 5.2:
132  	 * IMSK = First 32 octets of TLS-PRF(EMSK, "TEAPbindkey@ietf.org" |
133  	 *                                   "\0" | 64)
134  	 * (if EMSK is not available, MSK is used instead; if neither is
135  	 * available, IMSK is 32 octets of zeros; MSK is truncated to 32 octets
136  	 * or padded to 32 octets, if needed)
137  	 * (64 is encoded as a 2-octet field in network byte order)
138  	 *
139  	 * S-IMCK[0] = session_key_seed
140  	 * IMCK[j] = TLS-PRF(S-IMCK[j-1], "Inner Methods Compound Keys",
141  	 *                   IMSK[j], 60)
142  	 * S-IMCK[j] = first 40 octets of IMCK[j]
143  	 * CMK[j] = last 20 octets of IMCK[j]
144  	 */
145  
146  	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK[j]", msk, msk_len);
147  	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK[j]", emsk, emsk_len);
148  
149  	if (emsk && emsk_len > 0) {
150  		u8 context[3];
151  
152  		context[0] = 0;
153  		context[1] = 0;
154  		context[2] = 64;
155  		if (eap_teap_tls_prf(tls_cs, emsk, emsk_len,
156  				     "TEAPbindkey@ietf.org",
157  				     context, sizeof(context), imsk, 64) < 0)
158  			return -1;
159  
160  		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from EMSK",
161  				imsk, 32);
162  
163  		res = eap_teap_tls_prf(tls_cs,
164  				       prev_s_imck, EAP_TEAP_SIMCK_LEN,
165  				       "Inner Methods Compound Keys",
166  				       imsk, 32, imck, EAP_TEAP_IMCK_LEN);
167  		forced_memzero(imsk, sizeof(imsk));
168  		if (res < 0)
169  			return -1;
170  
171  		os_memcpy(s_imck_emsk, imck, EAP_TEAP_SIMCK_LEN);
172  		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK S-IMCK[j]",
173  				s_imck_emsk, EAP_TEAP_SIMCK_LEN);
174  		os_memcpy(cmk_emsk, &imck[EAP_TEAP_SIMCK_LEN],
175  			  EAP_TEAP_CMK_LEN);
176  		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: EMSK CMK[j]",
177  				cmk_emsk, EAP_TEAP_CMK_LEN);
178  		forced_memzero(imck, EAP_TEAP_IMCK_LEN);
179  	}
180  
181  	if (msk && msk_len > 0) {
182  		size_t copy_len = msk_len;
183  
184  		os_memset(imsk, 0, 32); /* zero pad, if needed */
185  		if (copy_len > 32)
186  			copy_len = 32;
187  		os_memcpy(imsk, msk, copy_len);
188  		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: IMSK from MSK", imsk, 32);
189  	} else {
190  		os_memset(imsk, 0, 32);
191  		wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: Zero IMSK", imsk, 32);
192  	}
193  
194  	res = eap_teap_tls_prf(tls_cs, prev_s_imck, EAP_TEAP_SIMCK_LEN,
195  			       "Inner Methods Compound Keys",
196  			       imsk, 32, imck, EAP_TEAP_IMCK_LEN);
197  	forced_memzero(imsk, sizeof(imsk));
198  	if (res < 0)
199  		return -1;
200  
201  	os_memcpy(s_imck_msk, imck, EAP_TEAP_SIMCK_LEN);
202  	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK S-IMCK[j]",
203  			s_imck_msk, EAP_TEAP_SIMCK_LEN);
204  	os_memcpy(cmk_msk, &imck[EAP_TEAP_SIMCK_LEN], EAP_TEAP_CMK_LEN);
205  	wpa_hexdump_key(MSG_DEBUG, "EAP-TEAP: MSK CMK[j]",
206  			cmk_msk, EAP_TEAP_CMK_LEN);
207  	forced_memzero(imck, EAP_TEAP_IMCK_LEN);
208  
209  	return 0;
210  }
211  
212  
tls_cipher_suite_match(const u16 * list,size_t count,u16 cs)213  static int tls_cipher_suite_match(const u16 *list, size_t count, u16 cs)
214  {
215  	size_t i;
216  
217  	for (i = 0; i < count; i++) {
218  		if (list[i] == cs)
219  			return 1;
220  	}
221  
222  	return 0;
223  }
224  
225  
tls_cipher_suite_mac_sha1(u16 cs)226  static int tls_cipher_suite_mac_sha1(u16 cs)
227  {
228  	static const u16 sha1_cs[] = {
229  		0x0005, 0x0007, 0x000a, 0x000d, 0x0010, 0x0013, 0x0016, 0x001b,
230  		0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036,
231  		0x0037, 0x0038, 0x0039, 0x003a, 0x0041, 0x0042, 0x0043, 0x0044,
232  		0x0045, 0x0046, 0x0084, 0x0085, 0x0086, 0x0087, 0x0088, 0x0089,
233  		0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, 0x0090, 0x0091,
234  		0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, 0x0098, 0x0099,
235  		0x009a, 0x009b,
236  		0xc002, 0xc003, 0xc004, 0xc005, 0xc007, 0xc008, 0xc009, 0xc009,
237  		0xc00a, 0xc00c, 0xc00d, 0xc00e, 0xc00f, 0xc011, 0xc012, 0xc013,
238  		0xc014, 0xc016, 0xc017, 0xc018, 0xc019, 0xc01a, 0xc01b, 0xc01c,
239  		0xc014, 0xc01e, 0xc01f, 0xc020, 0xc021, 0xc022, 0xc033, 0xc034,
240  		0xc035, 0xc036
241  	};
242  
243  	return tls_cipher_suite_match(sha1_cs, ARRAY_SIZE(sha1_cs), cs);
244  }
245  
246  
tls_cipher_suite_mac_sha256(u16 cs)247  static int tls_cipher_suite_mac_sha256(u16 cs)
248  {
249  	static const u16 sha256_cs[] = {
250  		0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0067, 0x0068, 0x0069,
251  		0x006a, 0x006b, 0x006c, 0x006d, 0x009c, 0x009e, 0x00a0, 0x00a2,
252  		0x00a4, 0x00a6, 0x00a8, 0x00aa, 0x00ac, 0x00ae, 0x00b2, 0x00b6,
253  		0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bd, 0x00be, 0x00be,
254  		0x00bf, 0x00bf, 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5,
255  		0x1301, 0x1303, 0x1304, 0x1305,
256  		0xc023, 0xc025, 0xc027, 0xc029, 0xc02b, 0xc02d, 0xc02f, 0xc031,
257  		0xc037, 0xc03c, 0xc03e, 0xc040, 0xc040, 0xc042, 0xc044, 0xc046,
258  		0xc048, 0xc04a, 0xc04c, 0xc04e, 0xc050, 0xc052, 0xc054, 0xc056,
259  		0xc058, 0xc05a, 0xc05c, 0xc05e, 0xc060, 0xc062, 0xc064, 0xc066,
260  		0xc068, 0xc06a, 0xc06c, 0xc06e, 0xc070, 0xc072, 0xc074, 0xc076,
261  		0xc078, 0xc07a, 0xc07c, 0xc07e, 0xc080, 0xc082, 0xc084, 0xc086,
262  		0xc088, 0xc08a, 0xc08c, 0xc08e, 0xc090, 0xc092, 0xc094, 0xc096,
263  		0xc098, 0xc09a, 0xc0b0, 0xc0b2, 0xc0b4,
264  		0xcca8, 0xcca9, 0xccaa, 0xccab, 0xccac, 0xccad, 0xccae,
265  		0xd001, 0xd003, 0xd005
266  	};
267  
268  	return tls_cipher_suite_match(sha256_cs, ARRAY_SIZE(sha256_cs), cs);
269  }
270  
271  
tls_cipher_suite_mac_sha384(u16 cs)272  static int tls_cipher_suite_mac_sha384(u16 cs)
273  {
274  	static const u16 sha384_cs[] = {
275  		0x009d, 0x009f, 0x00a1, 0x00a3, 0x00a5, 0x00a7, 0x00a9, 0x00ab,
276  		0x00ad, 0x00af, 0x00b3, 0x00b7, 0x1302,
277  		0xc024, 0xc026, 0xc028, 0xc02a, 0xc02c, 0xc02e, 0xc030, 0xc032,
278  		0xc038, 0xc03d, 0xc03f, 0xc041, 0xc043, 0xc045, 0xc047, 0xc049,
279  		0xc04b, 0xc04d, 0xc04f, 0xc051, 0xc053, 0xc055, 0xc057, 0xc059,
280  		0xc05b, 0xc05d, 0xc05f, 0xc061, 0xc063, 0xc065, 0xc067, 0xc069,
281  		0xc06b, 0xc06d, 0xc06f, 0xc071, 0xc073, 0xc075, 0xc077, 0xc079,
282  		0xc07b, 0xc07d, 0xc07f, 0xc081, 0xc083, 0xc085, 0xc087, 0xc089,
283  		0xc08b, 0xc08d, 0xc08f, 0xc091, 0xc093, 0xc095, 0xc097, 0xc099,
284  		0xc09b, 0xc0b1, 0xc0b3, 0xc0b5,
285  		0xd002
286  	};
287  
288  	return tls_cipher_suite_match(sha384_cs, ARRAY_SIZE(sha384_cs), cs);
289  }
290  
291  
eap_teap_tls_mac(u16 tls_cs,const u8 * cmk,size_t cmk_len,const u8 * buffer,size_t buffer_len,u8 * mac,size_t mac_len)292  static int eap_teap_tls_mac(u16 tls_cs, const u8 *cmk, size_t cmk_len,
293  			    const u8 *buffer, size_t buffer_len,
294  			    u8 *mac, size_t mac_len)
295  {
296  	int res;
297  	u8 tmp[48];
298  
299  	os_memset(tmp, 0, sizeof(tmp));
300  	os_memset(mac, 0, mac_len);
301  
302  	if (tls_cipher_suite_mac_sha1(tls_cs)) {
303  		wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA1");
304  		res = hmac_sha1(cmk, cmk_len, buffer, buffer_len, tmp);
305  	} else if (tls_cipher_suite_mac_sha256(tls_cs)) {
306  		wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA256");
307  		res = hmac_sha256(cmk, cmk_len, buffer, buffer_len, tmp);
308  	} else if (tls_cipher_suite_mac_sha384(tls_cs)) {
309  		wpa_printf(MSG_DEBUG, "EAP-TEAP: MAC algorithm: HMAC-SHA384");
310  		res = hmac_sha384(cmk, cmk_len, buffer, buffer_len, tmp);
311  	} else {
312  		wpa_printf(MSG_INFO,
313  			   "EAP-TEAP: Unsupported TLS cipher suite 0x%04x",
314  			   tls_cs);
315  		res = -1;
316  	}
317  	if (res < 0)
318  		return res;
319  
320  	if (mac_len > sizeof(tmp))
321  		mac_len = sizeof(tmp);
322  	os_memcpy(mac, tmp, mac_len);
323  	return 0;
324  }
325  
326  
eap_teap_compound_mac(u16 tls_cs,const struct teap_tlv_crypto_binding * cb,const struct wpabuf * server_outer_tlvs,const struct wpabuf * peer_outer_tlvs,const u8 * cmk,u8 * compound_mac)327  int eap_teap_compound_mac(u16 tls_cs, const struct teap_tlv_crypto_binding *cb,
328  			  const struct wpabuf *server_outer_tlvs,
329  			  const struct wpabuf *peer_outer_tlvs,
330  			  const u8 *cmk, u8 *compound_mac)
331  {
332  	u8 *pos, *buffer;
333  	size_t bind_len, buffer_len;
334  	struct teap_tlv_crypto_binding *tmp_cb;
335  	int res;
336  
337  	/* RFC 7170, Section 5.3 */
338  	bind_len = sizeof(struct teap_tlv_hdr) + be_to_host16(cb->length);
339  	buffer_len = bind_len + 1;
340  	if (server_outer_tlvs)
341  		buffer_len += wpabuf_len(server_outer_tlvs);
342  	if (peer_outer_tlvs)
343  		buffer_len += wpabuf_len(peer_outer_tlvs);
344  	buffer = os_malloc(buffer_len);
345  	if (!buffer)
346  		return -1;
347  
348  	pos = buffer;
349  	/* 1. The entire Crypto-Binding TLV attribute with both the EMSK and MSK
350  	 * Compound MAC fields zeroed out. */
351  	os_memcpy(pos, cb, bind_len);
352  	pos += bind_len;
353  	tmp_cb = (struct teap_tlv_crypto_binding *) buffer;
354  	os_memset(tmp_cb->emsk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
355  	os_memset(tmp_cb->msk_compound_mac, 0, EAP_TEAP_COMPOUND_MAC_LEN);
356  
357  	/* 2. The EAP Type sent by the other party in the first TEAP message. */
358  	/* This is supposed to be the EAP Type sent by the other party in the
359  	 * first TEAP message, but since we cannot get here without having
360  	 * successfully negotiated use of TEAP, this can only be the fixed EAP
361  	 * Type of TEAP. */
362  	*pos++ = EAP_TYPE_TEAP;
363  
364  	/* 3. All the Outer TLVs from the first TEAP message sent by EAP server
365  	 * to peer. */
366  	if (server_outer_tlvs) {
367  		os_memcpy(pos, wpabuf_head(server_outer_tlvs),
368  			  wpabuf_len(server_outer_tlvs));
369  		pos += wpabuf_len(server_outer_tlvs);
370  	}
371  
372  	/* 4. All the Outer TLVs from the first TEAP message sent by the peer to
373  	 * the EAP server. */
374  	if (peer_outer_tlvs) {
375  		os_memcpy(pos, wpabuf_head(peer_outer_tlvs),
376  			  wpabuf_len(peer_outer_tlvs));
377  		pos += wpabuf_len(peer_outer_tlvs);
378  	}
379  
380  	buffer_len = pos - buffer;
381  
382  	wpa_hexdump_key(MSG_MSGDUMP,
383  			"EAP-TEAP: CMK for Compound MAC calculation",
384  			cmk, EAP_TEAP_CMK_LEN);
385  	wpa_hexdump(MSG_MSGDUMP,
386  		    "EAP-TEAP: BUFFER for Compound MAC calculation",
387  		    buffer, buffer_len);
388  	res = eap_teap_tls_mac(tls_cs, cmk, EAP_TEAP_CMK_LEN,
389  			       buffer, buffer_len,
390  			       compound_mac, EAP_TEAP_COMPOUND_MAC_LEN);
391  	os_free(buffer);
392  
393  	return res;
394  }
395  
396  
eap_teap_parse_tlv(struct eap_teap_tlv_parse * tlv,int tlv_type,u8 * pos,size_t len)397  int eap_teap_parse_tlv(struct eap_teap_tlv_parse *tlv,
398  		       int tlv_type, u8 *pos, size_t len)
399  {
400  	switch (tlv_type) {
401  	case TEAP_TLV_IDENTITY_TYPE:
402  		if (len < 2) {
403  			wpa_printf(MSG_INFO,
404  				   "EAP-TEAP: Too short Identity-Type TLV");
405  			tlv->result = TEAP_STATUS_FAILURE;
406  			break;
407  		}
408  		tlv->identity_type = WPA_GET_BE16(pos);
409  		wpa_printf(MSG_DEBUG, "EAP-TEAP: Identity-Type: %u",
410  			   tlv->identity_type);
411  		break;
412  	case TEAP_TLV_RESULT:
413  		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: Result TLV", pos, len);
414  		if (tlv->result) {
415  			wpa_printf(MSG_INFO,
416  				   "EAP-TEAP: More than one Result TLV in the message");
417  			tlv->result = TEAP_STATUS_FAILURE;
418  			return -2;
419  		}
420  		if (len < 2) {
421  			wpa_printf(MSG_INFO, "EAP-TEAP: Too short Result TLV");
422  			tlv->result = TEAP_STATUS_FAILURE;
423  			break;
424  		}
425  		tlv->result = WPA_GET_BE16(pos);
426  		if (tlv->result != TEAP_STATUS_SUCCESS &&
427  		    tlv->result != TEAP_STATUS_FAILURE) {
428  			wpa_printf(MSG_INFO, "EAP-TEAP: Unknown Result %d",
429  				   tlv->result);
430  			tlv->result = TEAP_STATUS_FAILURE;
431  		}
432  		wpa_printf(MSG_DEBUG, "EAP-TEAP: Result: %s",
433  			   tlv->result == TEAP_STATUS_SUCCESS ?
434  			   "Success" : "Failure");
435  		break;
436  	case TEAP_TLV_NAK:
437  		wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: NAK TLV", pos, len);
438  		if (len < 6) {
439  			wpa_printf(MSG_INFO, "EAP-TEAP: Too short NAK TLV");
440  			tlv->result = TEAP_STATUS_FAILURE;
441  			break;
442  		}
443  		tlv->nak = pos;
444  		tlv->nak_len = len;
445  		break;
446  	case TEAP_TLV_ERROR:
447  		if (len < 4) {
448  			wpa_printf(MSG_INFO, "EAP-TEAP: Too short Error TLV");
449  			tlv->result = TEAP_STATUS_FAILURE;
450  			break;
451  		}
452  		tlv->error_code = WPA_GET_BE32(pos);
453  		wpa_printf(MSG_DEBUG, "EAP-TEAP: Error: %u", tlv->error_code);
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  
eap_teap_tlv_type_str(enum teap_tlv_types type)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  
eap_teap_tlv_result(int status,int intermediate)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  
eap_teap_tlv_error(enum teap_error_codes error)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  
eap_teap_tlv_identity_type(enum teap_identity_types id)664  struct wpabuf * eap_teap_tlv_identity_type(enum teap_identity_types id)
665  {
666  	struct wpabuf *buf;
667  
668  	buf = wpabuf_alloc(4 + 2);
669  	if (!buf)
670  		return NULL;
671  	wpa_printf(MSG_DEBUG,
672  		   "EAP-TEAP: Add Identity-Type TLV(Identity-Type=%d)", id);
673  	wpabuf_put_be16(buf, TEAP_TLV_IDENTITY_TYPE);
674  	wpabuf_put_be16(buf, 2);
675  	wpabuf_put_be16(buf, id);
676  	return buf;
677  }
678