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