1 /*
2 * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
3 * Copyright (c) 2004-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/tls.h"
14 #include "crypto/random.h"
15 #include "eap_i.h"
16 #include "eap_tls_common.h"
17 #include "eap_common/eap_tlv_common.h"
18 #include "eap_common/eap_peap_common.h"
19 #include "tncs.h"
20
21
22 /* Maximum supported PEAP version
23 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
24 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
25 */
26 #define EAP_PEAP_VERSION 1
27
28
29 static void eap_peap_reset(struct eap_sm *sm, void *priv);
30
31
32 struct eap_peap_data {
33 struct eap_ssl_data ssl;
34 enum {
35 START, PHASE1, PHASE1_ID2, PHASE2_START, PHASE2_ID,
36 PHASE2_METHOD, PHASE2_SOH,
37 PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE
38 } state;
39
40 int peap_version;
41 int recv_version;
42 const struct eap_method *phase2_method;
43 void *phase2_priv;
44 int force_version;
45 struct wpabuf *pending_phase2_resp;
46 enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request;
47 int crypto_binding_sent;
48 int crypto_binding_used;
49 enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
50 u8 binding_nonce[32];
51 u8 ipmk[40];
52 u8 cmk[20];
53 u8 *phase2_key;
54 size_t phase2_key_len;
55 struct wpabuf *soh_response;
56 };
57
58
59 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
60 int vendor, enum eap_type eap_type);
61
62
eap_peap_state_txt(int state)63 static const char * eap_peap_state_txt(int state)
64 {
65 switch (state) {
66 case START:
67 return "START";
68 case PHASE1:
69 return "PHASE1";
70 case PHASE1_ID2:
71 return "PHASE1_ID2";
72 case PHASE2_START:
73 return "PHASE2_START";
74 case PHASE2_ID:
75 return "PHASE2_ID";
76 case PHASE2_METHOD:
77 return "PHASE2_METHOD";
78 case PHASE2_SOH:
79 return "PHASE2_SOH";
80 case PHASE2_TLV:
81 return "PHASE2_TLV";
82 case SUCCESS_REQ:
83 return "SUCCESS_REQ";
84 case FAILURE_REQ:
85 return "FAILURE_REQ";
86 case SUCCESS:
87 return "SUCCESS";
88 case FAILURE:
89 return "FAILURE";
90 default:
91 return "Unknown?!";
92 }
93 }
94
95
eap_peap_state(struct eap_peap_data * data,int state)96 static void eap_peap_state(struct eap_peap_data *data, int state)
97 {
98 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s -> %s",
99 eap_peap_state_txt(data->state),
100 eap_peap_state_txt(state));
101 data->state = state;
102 if (state == FAILURE || state == FAILURE_REQ)
103 tls_connection_remove_session(data->ssl.conn);
104 }
105
106
eap_peap_valid_session(struct eap_sm * sm,struct eap_peap_data * data)107 static void eap_peap_valid_session(struct eap_sm *sm,
108 struct eap_peap_data *data)
109 {
110 struct wpabuf *buf;
111
112 if (!sm->cfg->tls_session_lifetime ||
113 tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
114 return;
115
116 buf = wpabuf_alloc(1 + 1 + sm->identity_len);
117 if (!buf)
118 return;
119 wpabuf_put_u8(buf, EAP_TYPE_PEAP);
120 if (sm->identity) {
121 u8 id_len;
122
123 if (sm->identity_len <= 255)
124 id_len = sm->identity_len;
125 else
126 id_len = 255;
127 wpabuf_put_u8(buf, id_len);
128 wpabuf_put_data(buf, sm->identity, id_len);
129 } else {
130 wpabuf_put_u8(buf, 0);
131 }
132 tls_connection_set_success_data(data->ssl.conn, buf);
133 }
134
135
eap_peap_req_success(struct eap_sm * sm,struct eap_peap_data * data)136 static void eap_peap_req_success(struct eap_sm *sm,
137 struct eap_peap_data *data)
138 {
139 if (data->state == FAILURE || data->state == FAILURE_REQ) {
140 eap_peap_state(data, FAILURE);
141 return;
142 }
143
144 if (data->peap_version == 0) {
145 data->tlv_request = TLV_REQ_SUCCESS;
146 eap_peap_state(data, PHASE2_TLV);
147 } else {
148 eap_peap_state(data, SUCCESS_REQ);
149 }
150 }
151
152
eap_peap_req_failure(struct eap_sm * sm,struct eap_peap_data * data)153 static void eap_peap_req_failure(struct eap_sm *sm,
154 struct eap_peap_data *data)
155 {
156 if (data->state == FAILURE || data->state == FAILURE_REQ ||
157 data->state == SUCCESS_REQ || data->tlv_request != TLV_REQ_NONE) {
158 eap_peap_state(data, FAILURE);
159 return;
160 }
161
162 if (data->peap_version == 0) {
163 data->tlv_request = TLV_REQ_FAILURE;
164 eap_peap_state(data, PHASE2_TLV);
165 } else {
166 eap_peap_state(data, FAILURE_REQ);
167 }
168 }
169
170
eap_peap_init(struct eap_sm * sm)171 static void * eap_peap_init(struct eap_sm *sm)
172 {
173 struct eap_peap_data *data;
174
175 data = os_zalloc(sizeof(*data));
176 if (data == NULL)
177 return NULL;
178 data->peap_version = EAP_PEAP_VERSION;
179 data->force_version = -1;
180 if (sm->user && sm->user->force_version >= 0) {
181 data->force_version = sm->user->force_version;
182 wpa_printf(MSG_DEBUG, "EAP-PEAP: forcing version %d",
183 data->force_version);
184 data->peap_version = data->force_version;
185 }
186 data->state = START;
187 data->crypto_binding = OPTIONAL_BINDING;
188
189 if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_PEAP)) {
190 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
191 eap_peap_reset(sm, data);
192 return NULL;
193 }
194
195 return data;
196 }
197
198
eap_peap_reset(struct eap_sm * sm,void * priv)199 static void eap_peap_reset(struct eap_sm *sm, void *priv)
200 {
201 struct eap_peap_data *data = priv;
202 if (data == NULL)
203 return;
204 if (data->phase2_priv && data->phase2_method)
205 data->phase2_method->reset(sm, data->phase2_priv);
206 eap_server_tls_ssl_deinit(sm, &data->ssl);
207 wpabuf_free(data->pending_phase2_resp);
208 os_free(data->phase2_key);
209 wpabuf_free(data->soh_response);
210 bin_clear_free(data, sizeof(*data));
211 }
212
213
eap_peap_build_start(struct eap_sm * sm,struct eap_peap_data * data,u8 id)214 static struct wpabuf * eap_peap_build_start(struct eap_sm *sm,
215 struct eap_peap_data *data, u8 id)
216 {
217 struct wpabuf *req;
218
219 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, 1,
220 EAP_CODE_REQUEST, id);
221 if (req == NULL) {
222 wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for"
223 " request");
224 eap_peap_state(data, FAILURE);
225 return NULL;
226 }
227
228 wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->peap_version);
229
230 eap_peap_state(data, PHASE1);
231
232 return req;
233 }
234
235
eap_peap_build_phase2_req(struct eap_sm * sm,struct eap_peap_data * data,u8 id)236 static struct wpabuf * eap_peap_build_phase2_req(struct eap_sm *sm,
237 struct eap_peap_data *data,
238 u8 id)
239 {
240 struct wpabuf *buf, *encr_req, msgbuf;
241 const u8 *req;
242 size_t req_len;
243
244 if (data->phase2_method == NULL || data->phase2_priv == NULL) {
245 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 method not ready");
246 return NULL;
247 }
248 buf = data->phase2_method->buildReq(sm, data->phase2_priv, id);
249 if (buf == NULL)
250 return NULL;
251
252 req = wpabuf_head(buf);
253 req_len = wpabuf_len(buf);
254 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
255 req, req_len);
256
257 if (data->peap_version == 0 &&
258 data->phase2_method->method != EAP_TYPE_TLV) {
259 req += sizeof(struct eap_hdr);
260 req_len -= sizeof(struct eap_hdr);
261 }
262
263 wpabuf_set(&msgbuf, req, req_len);
264 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
265 wpabuf_free(buf);
266
267 return encr_req;
268 }
269
270
271 #ifdef EAP_SERVER_TNC
eap_peap_build_phase2_soh(struct eap_sm * sm,struct eap_peap_data * data,u8 id)272 static struct wpabuf * eap_peap_build_phase2_soh(struct eap_sm *sm,
273 struct eap_peap_data *data,
274 u8 id)
275 {
276 struct wpabuf *buf1, *buf, *encr_req, msgbuf;
277 const u8 *req;
278 size_t req_len;
279
280 buf1 = tncs_build_soh_request();
281 if (buf1 == NULL)
282 return NULL;
283
284 buf = eap_msg_alloc(EAP_VENDOR_MICROSOFT, 0x21, wpabuf_len(buf1),
285 EAP_CODE_REQUEST, id);
286 if (buf == NULL) {
287 wpabuf_free(buf1);
288 return NULL;
289 }
290 wpabuf_put_buf(buf, buf1);
291 wpabuf_free(buf1);
292
293 req = wpabuf_head(buf);
294 req_len = wpabuf_len(buf);
295
296 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 SOH data",
297 req, req_len);
298
299 req += sizeof(struct eap_hdr);
300 req_len -= sizeof(struct eap_hdr);
301 wpabuf_set(&msgbuf, req, req_len);
302
303 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
304 wpabuf_free(buf);
305
306 return encr_req;
307 }
308 #endif /* EAP_SERVER_TNC */
309
310
eap_peap_get_isk(struct eap_peap_data * data,u8 * isk,size_t isk_len)311 static void eap_peap_get_isk(struct eap_peap_data *data,
312 u8 *isk, size_t isk_len)
313 {
314 size_t key_len;
315
316 os_memset(isk, 0, isk_len);
317 if (data->phase2_key == NULL)
318 return;
319
320 key_len = data->phase2_key_len;
321 if (key_len > isk_len)
322 key_len = isk_len;
323 os_memcpy(isk, data->phase2_key, key_len);
324 }
325
326
eap_peap_derive_cmk(struct eap_sm * sm,struct eap_peap_data * data)327 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
328 {
329 u8 *tk;
330 u8 isk[32], imck[60];
331 int res;
332 const char *label;
333 const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
334 const u8 *context = NULL;
335 size_t context_len = 0;
336
337 if (data->ssl.tls_v13) {
338 label = "EXPORTER_EAP_TLS_Key_Material";
339 context = eap_tls13_context;
340 context_len = sizeof(eap_tls13_context);
341 } else {
342 /* TODO: PEAPv1 - different label in some cases */
343 label = "client EAP encryption";
344 }
345
346 /*
347 * Tunnel key (TK) is the first 60 octets of the key generated by
348 * phase 1 of PEAP (based on TLS).
349 */
350 tk = eap_server_tls_derive_key(sm, &data->ssl, label,
351 context, context_len,
352 EAP_TLS_KEY_LEN);
353 if (tk == NULL)
354 return -1;
355 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
356
357 if (tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn)) {
358 /* Fast-connect: IPMK|CMK = TK */
359 os_memcpy(data->ipmk, tk, 40);
360 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
361 data->ipmk, 40);
362 os_memcpy(data->cmk, tk + 40, 20);
363 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK",
364 data->cmk, 20);
365 os_free(tk);
366 return 0;
367 }
368
369 eap_peap_get_isk(data, isk, sizeof(isk));
370 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
371
372 /*
373 * IPMK Seed = "Inner Methods Compound Keys" | ISK
374 * TempKey = First 40 octets of TK
375 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
376 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
377 * in the end of the label just before ISK; is that just a typo?)
378 */
379 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
380 res = peap_prfplus(data->peap_version, tk, 40,
381 "Inner Methods Compound Keys",
382 isk, sizeof(isk), imck, sizeof(imck));
383 forced_memzero(isk, sizeof(isk));
384 if (res < 0) {
385 os_free(tk);
386 return -1;
387 }
388 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
389 imck, sizeof(imck));
390
391 os_free(tk);
392
393 os_memcpy(data->ipmk, imck, 40);
394 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
395 os_memcpy(data->cmk, imck + 40, 20);
396 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
397 forced_memzero(imck, sizeof(imck));
398
399 return 0;
400 }
401
402
eap_peap_build_phase2_tlv(struct eap_sm * sm,struct eap_peap_data * data,u8 id)403 static struct wpabuf * eap_peap_build_phase2_tlv(struct eap_sm *sm,
404 struct eap_peap_data *data,
405 u8 id)
406 {
407 struct wpabuf *buf, *encr_req;
408 size_t mlen;
409
410 mlen = 6; /* Result TLV */
411 if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
412 data->crypto_binding != NO_BINDING) {
413 mlen += 60; /* Cryptobinding TLV */
414 #ifdef EAP_SERVER_TNC
415 if (data->soh_response)
416 mlen += wpabuf_len(data->soh_response);
417 #endif /* EAP_SERVER_TNC */
418 }
419
420 buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, mlen,
421 EAP_CODE_REQUEST, id);
422 if (buf == NULL)
423 return NULL;
424
425 wpabuf_put_u8(buf, 0x80); /* Mandatory */
426 wpabuf_put_u8(buf, EAP_TLV_RESULT_TLV);
427 /* Length */
428 wpabuf_put_be16(buf, 2);
429 /* Status */
430 wpabuf_put_be16(buf, data->tlv_request == TLV_REQ_SUCCESS ?
431 EAP_TLV_RESULT_SUCCESS : EAP_TLV_RESULT_FAILURE);
432
433 if (data->peap_version == 0 && data->tlv_request == TLV_REQ_SUCCESS &&
434 data->crypto_binding != NO_BINDING) {
435 u8 *mac;
436 u8 eap_type = EAP_TYPE_PEAP;
437 const u8 *addr[2];
438 size_t len[2];
439 u16 tlv_type;
440
441 #ifdef EAP_SERVER_TNC
442 if (data->soh_response) {
443 wpa_printf(MSG_DEBUG, "EAP-PEAP: Adding MS-SOH "
444 "Response TLV");
445 wpabuf_put_buf(buf, data->soh_response);
446 wpabuf_free(data->soh_response);
447 data->soh_response = NULL;
448 }
449 #endif /* EAP_SERVER_TNC */
450
451 if (eap_peap_derive_cmk(sm, data) < 0 ||
452 random_get_bytes(data->binding_nonce, 32)) {
453 wpabuf_free(buf);
454 return NULL;
455 }
456
457 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
458 addr[0] = wpabuf_put(buf, 0);
459 len[0] = 60;
460 addr[1] = &eap_type;
461 len[1] = 1;
462
463 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
464 wpabuf_put_be16(buf, tlv_type);
465 wpabuf_put_be16(buf, 56);
466
467 wpabuf_put_u8(buf, 0); /* Reserved */
468 wpabuf_put_u8(buf, data->peap_version); /* Version */
469 wpabuf_put_u8(buf, data->recv_version); /* RecvVersion */
470 wpabuf_put_u8(buf, 0); /* SubType: 0 = Request, 1 = Response */
471 wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
472 mac = wpabuf_put(buf, 20); /* Compound_MAC */
473 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK",
474 data->cmk, 20);
475 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
476 addr[0], len[0]);
477 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
478 addr[1], len[1]);
479 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
480 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC",
481 mac, SHA1_MAC_LEN);
482 data->crypto_binding_sent = 1;
483 }
484
485 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 TLV data",
486 buf);
487
488 encr_req = eap_server_tls_encrypt(sm, &data->ssl, buf);
489 wpabuf_free(buf);
490
491 return encr_req;
492 }
493
494
eap_peap_build_phase2_term(struct eap_sm * sm,struct eap_peap_data * data,u8 id,int success)495 static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm,
496 struct eap_peap_data *data,
497 u8 id, int success)
498 {
499 struct wpabuf *encr_req, msgbuf;
500 size_t req_len;
501 struct eap_hdr *hdr;
502
503 req_len = sizeof(*hdr);
504 hdr = os_zalloc(req_len);
505 if (hdr == NULL)
506 return NULL;
507
508 hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE;
509 hdr->identifier = id;
510 hdr->length = host_to_be16(req_len);
511
512 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data",
513 (u8 *) hdr, req_len);
514
515 wpabuf_set(&msgbuf, hdr, req_len);
516 encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf);
517 os_free(hdr);
518
519 if (!data->ssl.tls_v13 ||
520 !tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn)) {
521 wpabuf_free(data->ssl.tls_out);
522 data->ssl.tls_out_pos = 0;
523 return encr_req;
524 }
525
526 if (wpabuf_resize(&data->ssl.tls_out, wpabuf_len(encr_req)) < 0) {
527 wpa_printf(MSG_INFO,
528 "EAP-PEAP: Failed to resize output buffer");
529 wpabuf_free(encr_req);
530 return NULL;
531 }
532 wpabuf_put_buf(data->ssl.tls_out, encr_req);
533 wpa_hexdump_buf(MSG_DEBUG,
534 "EAP-PEAP: Data appended to the message", encr_req);
535 os_free(encr_req);
536
537 return data->ssl.tls_out;
538 }
539
540
eap_peap_buildReq(struct eap_sm * sm,void * priv,u8 id)541 static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id)
542 {
543 struct eap_peap_data *data = priv;
544
545 if (data->ssl.state == FRAG_ACK) {
546 return eap_server_tls_build_ack(id, EAP_TYPE_PEAP,
547 data->peap_version);
548 }
549
550 if (data->ssl.state == WAIT_FRAG_ACK) {
551 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
552 data->peap_version, id);
553 }
554
555 switch (data->state) {
556 case START:
557 return eap_peap_build_start(sm, data, id);
558 case PHASE1:
559 case PHASE1_ID2:
560 if (tls_connection_established(sm->cfg->ssl_ctx,
561 data->ssl.conn)) {
562 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase1 done, "
563 "starting Phase2");
564 eap_peap_state(data, PHASE2_START);
565 if (data->ssl.tls_v13 && data->ssl.tls_out &&
566 wpabuf_len(data->ssl.tls_out) == 0) {
567 /* This can happen with TLS 1.3 when a new
568 * session ticket is not generated and the
569 * Finished message from the peer terminates
570 * Phase 1. */
571 wpa_printf(MSG_DEBUG,
572 "EAP-PEAP: No pending data to send - move directly to Phase 2 ID query");
573 eap_peap_state(data, PHASE2_ID);
574 eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
575 EAP_TYPE_IDENTITY);
576 goto phase2_id;
577 }
578 }
579 break;
580 case PHASE2_ID:
581 case PHASE2_METHOD:
582 phase2_id:
583 wpabuf_free(data->ssl.tls_out);
584 data->ssl.tls_out_pos = 0;
585 data->ssl.tls_out = eap_peap_build_phase2_req(sm, data, id);
586 break;
587 #ifdef EAP_SERVER_TNC
588 case PHASE2_SOH:
589 wpabuf_free(data->ssl.tls_out);
590 data->ssl.tls_out_pos = 0;
591 data->ssl.tls_out = eap_peap_build_phase2_soh(sm, data, id);
592 break;
593 #endif /* EAP_SERVER_TNC */
594 case PHASE2_TLV:
595 wpabuf_free(data->ssl.tls_out);
596 data->ssl.tls_out_pos = 0;
597 data->ssl.tls_out = eap_peap_build_phase2_tlv(sm, data, id);
598 break;
599 case SUCCESS_REQ:
600 data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
601 1);
602 break;
603 case FAILURE_REQ:
604 wpabuf_free(data->ssl.tls_out);
605 data->ssl.tls_out_pos = 0;
606 data->ssl.tls_out = eap_peap_build_phase2_term(sm, data, id,
607 0);
608 break;
609 default:
610 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
611 __func__, data->state);
612 return NULL;
613 }
614
615 return eap_server_tls_build_msg(&data->ssl, EAP_TYPE_PEAP,
616 data->peap_version, id);
617 }
618
619
eap_peap_check(struct eap_sm * sm,void * priv,struct wpabuf * respData)620 static bool eap_peap_check(struct eap_sm *sm, void *priv,
621 struct wpabuf *respData)
622 {
623 const u8 *pos;
624 size_t len;
625
626 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len);
627 if (pos == NULL || len < 1) {
628 wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame");
629 return true;
630 }
631
632 return false;
633 }
634
635
eap_peap_phase2_init(struct eap_sm * sm,struct eap_peap_data * data,int vendor,enum eap_type eap_type)636 static int eap_peap_phase2_init(struct eap_sm *sm, struct eap_peap_data *data,
637 int vendor, enum eap_type eap_type)
638 {
639 if (data->phase2_priv && data->phase2_method) {
640 data->phase2_method->reset(sm, data->phase2_priv);
641 data->phase2_method = NULL;
642 data->phase2_priv = NULL;
643 }
644 data->phase2_method = eap_server_get_eap_method(vendor, eap_type);
645 if (!data->phase2_method)
646 return -1;
647
648 sm->init_phase2 = 1;
649 data->phase2_priv = data->phase2_method->init(sm);
650 sm->init_phase2 = 0;
651 return 0;
652 }
653
654
eap_tlv_validate_cryptobinding(struct eap_sm * sm,struct eap_peap_data * data,const u8 * crypto_tlv,size_t crypto_tlv_len)655 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
656 struct eap_peap_data *data,
657 const u8 *crypto_tlv,
658 size_t crypto_tlv_len)
659 {
660 u8 buf[61], mac[SHA1_MAC_LEN];
661 const u8 *pos;
662
663 if (crypto_tlv_len != 4 + 56) {
664 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
665 "length %d", (int) crypto_tlv_len);
666 return -1;
667 }
668
669 pos = crypto_tlv;
670 pos += 4; /* TLV header */
671 if (pos[1] != data->peap_version) {
672 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
673 "mismatch (was %d; expected %d)",
674 pos[1], data->peap_version);
675 return -1;
676 }
677
678 if (pos[3] != 1) {
679 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
680 "SubType %d", pos[3]);
681 return -1;
682 }
683 pos += 4;
684 pos += 32; /* Nonce */
685
686 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
687 os_memcpy(buf, crypto_tlv, 60);
688 os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
689 buf[60] = EAP_TYPE_PEAP;
690 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
691
692 if (os_memcmp_const(mac, pos, SHA1_MAC_LEN) != 0) {
693 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
694 "cryptobinding TLV");
695 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK", data->cmk, 20);
696 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding seed data",
697 buf, 61);
698 return -1;
699 }
700
701 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
702
703 return 0;
704 }
705
706
eap_peap_process_phase2_tlv(struct eap_sm * sm,struct eap_peap_data * data,struct wpabuf * in_data)707 static void eap_peap_process_phase2_tlv(struct eap_sm *sm,
708 struct eap_peap_data *data,
709 struct wpabuf *in_data)
710 {
711 const u8 *pos;
712 size_t left;
713 const u8 *result_tlv = NULL, *crypto_tlv = NULL;
714 size_t result_tlv_len = 0, crypto_tlv_len = 0;
715 int tlv_type, mandatory, tlv_len;
716
717 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, in_data, &left);
718 if (pos == NULL) {
719 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid EAP-TLV header");
720 return;
721 }
722
723 /* Parse TLVs */
724 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs", pos, left);
725 while (left >= 4) {
726 mandatory = !!(pos[0] & 0x80);
727 tlv_type = pos[0] & 0x3f;
728 tlv_type = (tlv_type << 8) | pos[1];
729 tlv_len = ((int) pos[2] << 8) | pos[3];
730 pos += 4;
731 left -= 4;
732 if ((size_t) tlv_len > left) {
733 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
734 "(tlv_len=%d left=%lu)", tlv_len,
735 (unsigned long) left);
736 eap_peap_state(data, FAILURE);
737 return;
738 }
739 switch (tlv_type) {
740 case EAP_TLV_RESULT_TLV:
741 result_tlv = pos;
742 result_tlv_len = tlv_len;
743 break;
744 case EAP_TLV_CRYPTO_BINDING_TLV:
745 crypto_tlv = pos;
746 crypto_tlv_len = tlv_len;
747 break;
748 default:
749 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
750 "%d%s", tlv_type,
751 mandatory ? " (mandatory)" : "");
752 if (mandatory) {
753 eap_peap_state(data, FAILURE);
754 return;
755 }
756 /* Ignore this TLV, but process other TLVs */
757 break;
758 }
759
760 pos += tlv_len;
761 left -= tlv_len;
762 }
763 if (left) {
764 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
765 "Request (left=%lu)", (unsigned long) left);
766 eap_peap_state(data, FAILURE);
767 return;
768 }
769
770 /* Process supported TLVs */
771 if (crypto_tlv && data->crypto_binding_sent) {
772 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
773 crypto_tlv, crypto_tlv_len);
774 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
775 crypto_tlv_len + 4) < 0) {
776 eap_peap_state(data, FAILURE);
777 return;
778 }
779 data->crypto_binding_used = 1;
780 } else if (!crypto_tlv && data->crypto_binding_sent &&
781 data->crypto_binding == REQUIRE_BINDING) {
782 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
783 eap_peap_state(data, FAILURE);
784 return;
785 }
786
787 if (result_tlv) {
788 int status;
789 const char *requested;
790
791 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Result TLV",
792 result_tlv, result_tlv_len);
793 if (result_tlv_len < 2) {
794 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Result TLV "
795 "(len=%lu)",
796 (unsigned long) result_tlv_len);
797 eap_peap_state(data, FAILURE);
798 return;
799 }
800 requested = data->tlv_request == TLV_REQ_SUCCESS ? "Success" :
801 "Failure";
802 status = WPA_GET_BE16(result_tlv);
803 if (status == EAP_TLV_RESULT_SUCCESS) {
804 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Success "
805 "- requested %s", requested);
806 if (data->tlv_request == TLV_REQ_SUCCESS) {
807 eap_peap_state(data, SUCCESS);
808 eap_peap_valid_session(sm, data);
809 } else {
810 eap_peap_state(data, FAILURE);
811 }
812
813 } else if (status == EAP_TLV_RESULT_FAILURE) {
814 wpa_printf(MSG_INFO, "EAP-PEAP: TLV Result - Failure "
815 "- requested %s", requested);
816 eap_peap_state(data, FAILURE);
817 } else {
818 wpa_printf(MSG_INFO, "EAP-PEAP: Unknown TLV Result "
819 "Status %d", status);
820 eap_peap_state(data, FAILURE);
821 }
822 }
823 }
824
825
826 #ifdef EAP_SERVER_TNC
eap_peap_process_phase2_soh(struct eap_sm * sm,struct eap_peap_data * data,struct wpabuf * in_data)827 static void eap_peap_process_phase2_soh(struct eap_sm *sm,
828 struct eap_peap_data *data,
829 struct wpabuf *in_data)
830 {
831 const u8 *pos, *vpos;
832 size_t left;
833 const u8 *soh_tlv = NULL;
834 size_t soh_tlv_len = 0;
835 int tlv_type, mandatory, tlv_len, vtlv_len;
836 u32 next_type;
837 u32 vendor_id;
838
839 pos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, in_data, &left);
840 if (pos == NULL) {
841 wpa_printf(MSG_DEBUG, "EAP-PEAP: Not a valid SoH EAP "
842 "Extensions Method header - skip TNC");
843 goto auth_method;
844 }
845
846 /* Parse TLVs */
847 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received TLVs (SoH)", pos, left);
848 while (left >= 4) {
849 mandatory = !!(pos[0] & 0x80);
850 tlv_type = pos[0] & 0x3f;
851 tlv_type = (tlv_type << 8) | pos[1];
852 tlv_len = ((int) pos[2] << 8) | pos[3];
853 pos += 4;
854 left -= 4;
855 if ((size_t) tlv_len > left) {
856 wpa_printf(MSG_DEBUG, "EAP-PEAP: TLV underrun "
857 "(tlv_len=%d left=%lu)", tlv_len,
858 (unsigned long) left);
859 eap_peap_state(data, FAILURE);
860 return;
861 }
862 switch (tlv_type) {
863 case EAP_TLV_VENDOR_SPECIFIC_TLV:
864 if (tlv_len < 4) {
865 wpa_printf(MSG_DEBUG, "EAP-PEAP: Too short "
866 "vendor specific TLV (len=%d)",
867 (int) tlv_len);
868 eap_peap_state(data, FAILURE);
869 return;
870 }
871
872 vendor_id = WPA_GET_BE32(pos);
873 if (vendor_id != EAP_VENDOR_MICROSOFT) {
874 if (mandatory) {
875 eap_peap_state(data, FAILURE);
876 return;
877 }
878 break;
879 }
880
881 vpos = pos + 4;
882 mandatory = !!(vpos[0] & 0x80);
883 tlv_type = vpos[0] & 0x3f;
884 tlv_type = (tlv_type << 8) | vpos[1];
885 vtlv_len = ((int) vpos[2] << 8) | vpos[3];
886 vpos += 4;
887 if (vpos + vtlv_len > pos + left) {
888 wpa_printf(MSG_DEBUG, "EAP-PEAP: Vendor TLV "
889 "underrun");
890 eap_peap_state(data, FAILURE);
891 return;
892 }
893
894 if (tlv_type == 1) {
895 soh_tlv = vpos;
896 soh_tlv_len = vtlv_len;
897 break;
898 }
899
900 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported MS-TLV "
901 "Type %d%s", tlv_type,
902 mandatory ? " (mandatory)" : "");
903 if (mandatory) {
904 eap_peap_state(data, FAILURE);
905 return;
906 }
907 /* Ignore this TLV, but process other TLVs */
908 break;
909 default:
910 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unsupported TLV Type "
911 "%d%s", tlv_type,
912 mandatory ? " (mandatory)" : "");
913 if (mandatory) {
914 eap_peap_state(data, FAILURE);
915 return;
916 }
917 /* Ignore this TLV, but process other TLVs */
918 break;
919 }
920
921 pos += tlv_len;
922 left -= tlv_len;
923 }
924 if (left) {
925 wpa_printf(MSG_DEBUG, "EAP-PEAP: Last TLV too short in "
926 "Request (left=%lu)", (unsigned long) left);
927 eap_peap_state(data, FAILURE);
928 return;
929 }
930
931 /* Process supported TLVs */
932 if (soh_tlv) {
933 int failure = 0;
934 wpabuf_free(data->soh_response);
935 data->soh_response = tncs_process_soh(soh_tlv, soh_tlv_len,
936 &failure);
937 if (failure) {
938 eap_peap_state(data, FAILURE);
939 return;
940 }
941 } else {
942 wpa_printf(MSG_DEBUG, "EAP-PEAP: No SoH TLV received");
943 eap_peap_state(data, FAILURE);
944 return;
945 }
946
947 auth_method:
948 eap_peap_state(data, PHASE2_METHOD);
949 next_type = sm->user->methods[0].method;
950 sm->user_eap_method_index = 1;
951 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type %d",
952 sm->user->methods[0].vendor, next_type);
953 eap_peap_phase2_init(sm, data, sm->user->methods[0].vendor, next_type);
954 }
955 #endif /* EAP_SERVER_TNC */
956
957
eap_peap_process_phase2_response(struct eap_sm * sm,struct eap_peap_data * data,struct wpabuf * in_data)958 static void eap_peap_process_phase2_response(struct eap_sm *sm,
959 struct eap_peap_data *data,
960 struct wpabuf *in_data)
961 {
962 int next_vendor = EAP_VENDOR_IETF;
963 u32 next_type = EAP_TYPE_NONE;
964 const struct eap_hdr *hdr;
965 const u8 *pos;
966 size_t left;
967
968 if (data->state == PHASE2_TLV) {
969 eap_peap_process_phase2_tlv(sm, data, in_data);
970 return;
971 }
972
973 #ifdef EAP_SERVER_TNC
974 if (data->state == PHASE2_SOH) {
975 eap_peap_process_phase2_soh(sm, data, in_data);
976 return;
977 }
978 #endif /* EAP_SERVER_TNC */
979
980 if (data->phase2_priv == NULL) {
981 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - Phase2 not "
982 "initialized?!", __func__);
983 return;
984 }
985
986 hdr = wpabuf_head(in_data);
987 pos = (const u8 *) (hdr + 1);
988
989 if (wpabuf_len(in_data) > sizeof(*hdr) && *pos == EAP_TYPE_NAK) {
990 left = wpabuf_len(in_data) - sizeof(*hdr);
991 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 type Nak'ed; "
992 "allowed types", pos + 1, left - 1);
993 eap_sm_process_nak(sm, pos + 1, left - 1);
994 if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS &&
995 (sm->user->methods[sm->user_eap_method_index].vendor !=
996 EAP_VENDOR_IETF ||
997 sm->user->methods[sm->user_eap_method_index].method !=
998 EAP_TYPE_NONE)) {
999 next_vendor = sm->user->methods[
1000 sm->user_eap_method_index].vendor;
1001 next_type = sm->user->methods[
1002 sm->user_eap_method_index++].method;
1003 wpa_printf(MSG_DEBUG,
1004 "EAP-PEAP: try EAP vendor %d type 0x%x",
1005 next_vendor, next_type);
1006 } else {
1007 eap_peap_req_failure(sm, data);
1008 next_vendor = EAP_VENDOR_IETF;
1009 next_type = EAP_TYPE_NONE;
1010 }
1011 eap_peap_phase2_init(sm, data, next_vendor, next_type);
1012 return;
1013 }
1014
1015 if (data->phase2_method->check(sm, data->phase2_priv, in_data)) {
1016 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to "
1017 "ignore the packet");
1018 return;
1019 }
1020
1021 data->phase2_method->process(sm, data->phase2_priv, in_data);
1022
1023 if (sm->method_pending == METHOD_PENDING_WAIT) {
1024 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method is in "
1025 "pending wait state - save decrypted response");
1026 wpabuf_free(data->pending_phase2_resp);
1027 data->pending_phase2_resp = wpabuf_dup(in_data);
1028 }
1029
1030 if (!data->phase2_method->isDone(sm, data->phase2_priv))
1031 return;
1032
1033 if (!data->phase2_method->isSuccess(sm, data->phase2_priv)) {
1034 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 method failed");
1035 eap_peap_req_failure(sm, data);
1036 next_vendor = EAP_VENDOR_IETF;
1037 next_type = EAP_TYPE_NONE;
1038 eap_peap_phase2_init(sm, data, next_vendor, next_type);
1039 return;
1040 }
1041
1042 os_free(data->phase2_key);
1043 if (data->phase2_method->getKey) {
1044 data->phase2_key = data->phase2_method->getKey(
1045 sm, data->phase2_priv, &data->phase2_key_len);
1046 if (data->phase2_key == NULL) {
1047 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 getKey "
1048 "failed");
1049 eap_peap_req_failure(sm, data);
1050 eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
1051 EAP_TYPE_NONE);
1052 return;
1053 }
1054 }
1055
1056 switch (data->state) {
1057 case PHASE1_ID2:
1058 case PHASE2_ID:
1059 case PHASE2_SOH:
1060 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1061 wpa_hexdump_ascii(MSG_DEBUG, "EAP_PEAP: Phase2 "
1062 "Identity not found in the user "
1063 "database",
1064 sm->identity, sm->identity_len);
1065 eap_peap_req_failure(sm, data);
1066 next_vendor = EAP_VENDOR_IETF;
1067 next_type = EAP_TYPE_NONE;
1068 break;
1069 }
1070
1071 #ifdef EAP_SERVER_TNC
1072 if (data->state != PHASE2_SOH && sm->cfg->tnc &&
1073 data->peap_version == 0) {
1074 eap_peap_state(data, PHASE2_SOH);
1075 wpa_printf(MSG_DEBUG, "EAP-PEAP: Try to initialize "
1076 "TNC (NAP SOH)");
1077 next_vendor = EAP_VENDOR_IETF;
1078 next_type = EAP_TYPE_NONE;
1079 break;
1080 }
1081 #endif /* EAP_SERVER_TNC */
1082
1083 eap_peap_state(data, PHASE2_METHOD);
1084 next_vendor = sm->user->methods[0].vendor;
1085 next_type = sm->user->methods[0].method;
1086 sm->user_eap_method_index = 1;
1087 wpa_printf(MSG_DEBUG, "EAP-PEAP: try EAP vendor %d type 0x%x",
1088 next_vendor, next_type);
1089 break;
1090 case PHASE2_METHOD:
1091 eap_peap_req_success(sm, data);
1092 next_vendor = EAP_VENDOR_IETF;
1093 next_type = EAP_TYPE_NONE;
1094 break;
1095 case FAILURE:
1096 break;
1097 default:
1098 wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d",
1099 __func__, data->state);
1100 break;
1101 }
1102
1103 eap_peap_phase2_init(sm, data, next_vendor, next_type);
1104 }
1105
1106
eap_peap_process_phase2(struct eap_sm * sm,struct eap_peap_data * data,const struct wpabuf * respData,struct wpabuf * in_buf)1107 static void eap_peap_process_phase2(struct eap_sm *sm,
1108 struct eap_peap_data *data,
1109 const struct wpabuf *respData,
1110 struct wpabuf *in_buf)
1111 {
1112 struct wpabuf *in_decrypted;
1113 const struct eap_hdr *hdr;
1114 size_t len;
1115
1116 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
1117 " Phase 2", (unsigned long) wpabuf_len(in_buf));
1118
1119 if (data->pending_phase2_resp) {
1120 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 response - "
1121 "skip decryption and use old data");
1122 eap_peap_process_phase2_response(sm, data,
1123 data->pending_phase2_resp);
1124 wpabuf_free(data->pending_phase2_resp);
1125 data->pending_phase2_resp = NULL;
1126 return;
1127 }
1128
1129 in_decrypted = tls_connection_decrypt(sm->cfg->ssl_ctx, data->ssl.conn,
1130 in_buf);
1131 if (in_decrypted == NULL) {
1132 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 "
1133 "data");
1134 eap_peap_state(data, FAILURE);
1135 return;
1136 }
1137
1138 wpa_hexdump_buf_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
1139 in_decrypted);
1140
1141 if (data->peap_version == 0 && data->state != PHASE2_TLV) {
1142 const struct eap_hdr *resp;
1143 struct eap_hdr *nhdr;
1144 struct wpabuf *nbuf =
1145 wpabuf_alloc(sizeof(struct eap_hdr) +
1146 wpabuf_len(in_decrypted));
1147 if (nbuf == NULL) {
1148 wpabuf_free(in_decrypted);
1149 return;
1150 }
1151
1152 resp = wpabuf_head(respData);
1153 nhdr = wpabuf_put(nbuf, sizeof(*nhdr));
1154 nhdr->code = resp->code;
1155 nhdr->identifier = resp->identifier;
1156 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
1157 wpabuf_len(in_decrypted));
1158 wpabuf_put_buf(nbuf, in_decrypted);
1159 wpabuf_free(in_decrypted);
1160
1161 in_decrypted = nbuf;
1162 }
1163
1164 hdr = wpabuf_head(in_decrypted);
1165 if (wpabuf_len(in_decrypted) < (int) sizeof(*hdr)) {
1166 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
1167 "EAP frame (len=%lu)",
1168 (unsigned long) wpabuf_len(in_decrypted));
1169 wpabuf_free(in_decrypted);
1170 eap_peap_req_failure(sm, data);
1171 return;
1172 }
1173 len = be_to_host16(hdr->length);
1174 if (len > wpabuf_len(in_decrypted)) {
1175 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
1176 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
1177 (unsigned long) wpabuf_len(in_decrypted),
1178 (unsigned long) len);
1179 wpabuf_free(in_decrypted);
1180 eap_peap_req_failure(sm, data);
1181 return;
1182 }
1183 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
1184 "identifier=%d length=%lu", hdr->code, hdr->identifier,
1185 (unsigned long) len);
1186 switch (hdr->code) {
1187 case EAP_CODE_RESPONSE:
1188 eap_peap_process_phase2_response(sm, data, in_decrypted);
1189 break;
1190 case EAP_CODE_SUCCESS:
1191 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
1192 if (data->state == SUCCESS_REQ) {
1193 eap_peap_state(data, SUCCESS);
1194 eap_peap_valid_session(sm, data);
1195 }
1196 break;
1197 case EAP_CODE_FAILURE:
1198 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1199 eap_peap_state(data, FAILURE);
1200 break;
1201 default:
1202 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1203 "Phase 2 EAP header", hdr->code);
1204 break;
1205 }
1206
1207 wpabuf_free(in_decrypted);
1208 }
1209
1210
eap_peap_process_version(struct eap_sm * sm,void * priv,int peer_version)1211 static int eap_peap_process_version(struct eap_sm *sm, void *priv,
1212 int peer_version)
1213 {
1214 struct eap_peap_data *data = priv;
1215
1216 data->recv_version = peer_version;
1217 if (data->force_version >= 0 && peer_version != data->force_version) {
1218 wpa_printf(MSG_INFO, "EAP-PEAP: peer did not select the forced"
1219 " version (forced=%d peer=%d) - reject",
1220 data->force_version, peer_version);
1221 return -1;
1222 }
1223 if (peer_version < data->peap_version) {
1224 wpa_printf(MSG_DEBUG, "EAP-PEAP: peer ver=%d, own ver=%d; "
1225 "use version %d",
1226 peer_version, data->peap_version, peer_version);
1227 data->peap_version = peer_version;
1228 }
1229
1230 return 0;
1231 }
1232
1233
eap_peap_process_msg(struct eap_sm * sm,void * priv,const struct wpabuf * respData)1234 static void eap_peap_process_msg(struct eap_sm *sm, void *priv,
1235 const struct wpabuf *respData)
1236 {
1237 struct eap_peap_data *data = priv;
1238
1239 switch (data->state) {
1240 case PHASE1:
1241 if (eap_server_tls_phase1(sm, &data->ssl) < 0) {
1242 eap_peap_state(data, FAILURE);
1243 break;
1244 }
1245 break;
1246 case PHASE2_START:
1247 eap_peap_state(data, PHASE2_ID);
1248 eap_peap_phase2_init(sm, data, EAP_VENDOR_IETF,
1249 EAP_TYPE_IDENTITY);
1250 break;
1251 case PHASE1_ID2:
1252 case PHASE2_ID:
1253 case PHASE2_METHOD:
1254 case PHASE2_SOH:
1255 case PHASE2_TLV:
1256 eap_peap_process_phase2(sm, data, respData, data->ssl.tls_in);
1257 break;
1258 case SUCCESS_REQ:
1259 eap_peap_state(data, SUCCESS);
1260 eap_peap_valid_session(sm, data);
1261 break;
1262 case FAILURE_REQ:
1263 eap_peap_state(data, FAILURE);
1264 break;
1265 default:
1266 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected state %d in %s",
1267 data->state, __func__);
1268 break;
1269 }
1270 }
1271
1272
eap_peap_process(struct eap_sm * sm,void * priv,struct wpabuf * respData)1273 static void eap_peap_process(struct eap_sm *sm, void *priv,
1274 struct wpabuf *respData)
1275 {
1276 struct eap_peap_data *data = priv;
1277 const struct wpabuf *buf;
1278 const u8 *pos;
1279 u8 id_len;
1280
1281 if (eap_server_tls_process(sm, &data->ssl, respData, data,
1282 EAP_TYPE_PEAP, eap_peap_process_version,
1283 eap_peap_process_msg) < 0) {
1284 eap_peap_state(data, FAILURE);
1285 return;
1286 }
1287
1288 if (data->state == SUCCESS ||
1289 !tls_connection_established(sm->cfg->ssl_ctx, data->ssl.conn) ||
1290 !tls_connection_resumed(sm->cfg->ssl_ctx, data->ssl.conn))
1291 return;
1292
1293 buf = tls_connection_get_success_data(data->ssl.conn);
1294 if (!buf || wpabuf_len(buf) < 2) {
1295 wpa_printf(MSG_DEBUG,
1296 "EAP-PEAP: No success data in resumed session - reject attempt");
1297 eap_peap_state(data, FAILURE);
1298 return;
1299 }
1300
1301 pos = wpabuf_head(buf);
1302 if (*pos != EAP_TYPE_PEAP) {
1303 wpa_printf(MSG_DEBUG,
1304 "EAP-PEAP: Resumed session for another EAP type (%u) - reject attempt",
1305 *pos);
1306 eap_peap_state(data, FAILURE);
1307 return;
1308 }
1309
1310 pos++;
1311 id_len = *pos++;
1312 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Identity from cached session",
1313 pos, id_len);
1314 os_free(sm->identity);
1315 sm->identity = os_malloc(id_len ? id_len : 1);
1316 if (!sm->identity) {
1317 sm->identity_len = 0;
1318 eap_peap_state(data, FAILURE);
1319 return;
1320 }
1321
1322 os_memcpy(sm->identity, pos, id_len);
1323 sm->identity_len = id_len;
1324
1325 if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) {
1326 wpa_hexdump_ascii(MSG_DEBUG, "EAP-PEAP: Phase2 Identity not found in the user database",
1327 sm->identity, sm->identity_len);
1328 eap_peap_state(data, FAILURE);
1329 return;
1330 }
1331
1332 wpa_printf(MSG_DEBUG,
1333 "EAP-PEAP: Resuming previous session - skip Phase2");
1334 eap_peap_req_success(sm, data);
1335 if (data->state == SUCCESS_REQ)
1336 tls_connection_set_success_data_resumed(data->ssl.conn);
1337 }
1338
1339
eap_peap_isDone(struct eap_sm * sm,void * priv)1340 static bool eap_peap_isDone(struct eap_sm *sm, void *priv)
1341 {
1342 struct eap_peap_data *data = priv;
1343 return data->state == SUCCESS || data->state == FAILURE;
1344 }
1345
1346
eap_peap_getKey(struct eap_sm * sm,void * priv,size_t * len)1347 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1348 {
1349 struct eap_peap_data *data = priv;
1350 u8 *eapKeyData;
1351 const char *label;
1352 const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
1353 const u8 *context = NULL;
1354 size_t context_len = 0;
1355
1356 if (data->state != SUCCESS)
1357 return NULL;
1358
1359 if (data->crypto_binding_used) {
1360 u8 csk[128];
1361 /*
1362 * Note: It looks like Microsoft implementation requires null
1363 * termination for this label while the one used for deriving
1364 * IPMK|CMK did not use null termination.
1365 */
1366 if (peap_prfplus(data->peap_version, data->ipmk, 40,
1367 "Session Key Generating Function",
1368 (u8 *) "\00", 1, csk, sizeof(csk)) < 0)
1369 return NULL;
1370 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1371 eapKeyData = os_malloc(EAP_TLS_KEY_LEN);
1372 if (eapKeyData) {
1373 os_memcpy(eapKeyData, csk, EAP_TLS_KEY_LEN);
1374 *len = EAP_TLS_KEY_LEN;
1375 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1376 eapKeyData, EAP_TLS_KEY_LEN);
1377 } else {
1378 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive "
1379 "key");
1380 }
1381
1382 forced_memzero(csk, sizeof(csk));
1383
1384 return eapKeyData;
1385 }
1386
1387 if (data->ssl.tls_v13) {
1388 label = "EXPORTER_EAP_TLS_Key_Material";
1389 context = eap_tls13_context;
1390 context_len = sizeof(eap_tls13_context);
1391 } else {
1392 /* TODO: PEAPv1 - different label in some cases */
1393 label = "client EAP encryption";
1394 }
1395
1396 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1397 label, context, context_len,
1398 EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1399 if (eapKeyData) {
1400 os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
1401 *len = EAP_TLS_KEY_LEN;
1402 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1403 eapKeyData, EAP_TLS_KEY_LEN);
1404 } else {
1405 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive key");
1406 }
1407
1408 return eapKeyData;
1409 }
1410
1411
eap_peap_get_emsk(struct eap_sm * sm,void * priv,size_t * len)1412 static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1413 {
1414 struct eap_peap_data *data = priv;
1415 u8 *eapKeyData, *emsk;
1416 const char *label;
1417 const u8 eap_tls13_context[1] = { EAP_TYPE_PEAP };
1418 const u8 *context = NULL;
1419 size_t context_len = 0;
1420
1421 if (data->state != SUCCESS)
1422 return NULL;
1423
1424 if (data->crypto_binding_used) {
1425 /* [MS-PEAP] does not define EMSK derivation */
1426 return NULL;
1427 }
1428
1429 if (data->ssl.tls_v13) {
1430 label = "EXPORTER_EAP_TLS_Key_Material";
1431 context = eap_tls13_context;
1432 context_len = sizeof(eap_tls13_context);
1433 } else {
1434 /* TODO: PEAPv1 - different label in some cases */
1435 label = "client EAP encryption";
1436 }
1437
1438 eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
1439 label, context, context_len,
1440 EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1441 if (eapKeyData) {
1442 emsk = os_memdup(eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
1443 bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
1444 if (!emsk)
1445 return NULL;
1446 *len = EAP_EMSK_LEN;
1447 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived EMSK",
1448 emsk, EAP_EMSK_LEN);
1449 } else {
1450 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to derive EMSK");
1451 emsk = NULL;
1452 }
1453
1454 return emsk;
1455 }
1456
1457
eap_peap_isSuccess(struct eap_sm * sm,void * priv)1458 static bool eap_peap_isSuccess(struct eap_sm *sm, void *priv)
1459 {
1460 struct eap_peap_data *data = priv;
1461 return data->state == SUCCESS;
1462 }
1463
1464
eap_peap_get_session_id(struct eap_sm * sm,void * priv,size_t * len)1465 static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1466 {
1467 struct eap_peap_data *data = priv;
1468
1469 if (data->state != SUCCESS)
1470 return NULL;
1471
1472 return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_PEAP,
1473 len);
1474 }
1475
1476
eap_server_peap_register(void)1477 int eap_server_peap_register(void)
1478 {
1479 struct eap_method *eap;
1480
1481 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
1482 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1483 if (eap == NULL)
1484 return -1;
1485
1486 eap->init = eap_peap_init;
1487 eap->reset = eap_peap_reset;
1488 eap->buildReq = eap_peap_buildReq;
1489 eap->check = eap_peap_check;
1490 eap->process = eap_peap_process;
1491 eap->isDone = eap_peap_isDone;
1492 eap->getKey = eap_peap_getKey;
1493 eap->get_emsk = eap_peap_get_emsk;
1494 eap->isSuccess = eap_peap_isSuccess;
1495 eap->getSessionId = eap_peap_get_session_id;
1496
1497 return eap_server_method_register(eap);
1498 }
1499