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