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