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