]> git.ipfire.org Git - thirdparty/hostap.git/blob - src/eap_peer/eap_peap.c
44c619d62b7640cfabfa2d6d30ab2bbe742d0c6e
[thirdparty/hostap.git] / src / eap_peer / eap_peap.c
1 /*
2 * EAP peer method: 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 "crypto/sha1.h"
19 #include "eap_i.h"
20 #include "eap_tls_common.h"
21 #include "eap_config.h"
22 #include "tls.h"
23 #include "eap_common/eap_tlv_common.h"
24 #include "tncc.h"
25
26
27 /* Maximum supported PEAP version
28 * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
29 * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
30 * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
31 */
32 #define EAP_PEAP_VERSION 1
33
34
35 static void eap_peap_deinit(struct eap_sm *sm, void *priv);
36
37
38 struct eap_peap_data {
39 struct eap_ssl_data ssl;
40
41 int peap_version, force_peap_version, force_new_label;
42
43 const struct eap_method *phase2_method;
44 void *phase2_priv;
45 int phase2_success;
46 int phase2_eap_success;
47 int phase2_eap_started;
48
49 struct eap_method_type phase2_type;
50 struct eap_method_type *phase2_types;
51 size_t num_phase2_types;
52
53 int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner
54 * EAP-Success
55 * 1 = reply with tunneled EAP-Success to inner
56 * EAP-Success and expect AS to send outer
57 * (unencrypted) EAP-Success after this
58 * 2 = reply with PEAP/TLS ACK to inner
59 * EAP-Success and expect AS to send outer
60 * (unencrypted) EAP-Success after this */
61 int resuming; /* starting a resumed session */
62 u8 *key_data;
63
64 struct wpabuf *pending_phase2_req;
65 enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
66 int crypto_binding_used;
67 u8 ipmk[40];
68 u8 cmk[20];
69 int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP)
70 * is enabled. */
71 };
72
73
74 static int eap_peap_parse_phase1(struct eap_peap_data *data,
75 const char *phase1)
76 {
77 const char *pos;
78
79 pos = os_strstr(phase1, "peapver=");
80 if (pos) {
81 data->force_peap_version = atoi(pos + 8);
82 data->peap_version = data->force_peap_version;
83 wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d",
84 data->force_peap_version);
85 }
86
87 if (os_strstr(phase1, "peaplabel=1")) {
88 data->force_new_label = 1;
89 wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key "
90 "derivation");
91 }
92
93 if (os_strstr(phase1, "peap_outer_success=0")) {
94 data->peap_outer_success = 0;
95 wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on "
96 "tunneled EAP-Success");
97 } else if (os_strstr(phase1, "peap_outer_success=1")) {
98 data->peap_outer_success = 1;
99 wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success "
100 "after receiving tunneled EAP-Success");
101 } else if (os_strstr(phase1, "peap_outer_success=2")) {
102 data->peap_outer_success = 2;
103 wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after "
104 "receiving tunneled EAP-Success");
105 }
106
107 if (os_strstr(phase1, "crypto_binding=0")) {
108 data->crypto_binding = NO_BINDING;
109 wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding");
110 } else if (os_strstr(phase1, "crypto_binding=1")) {
111 data->crypto_binding = OPTIONAL_BINDING;
112 wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding");
113 } else if (os_strstr(phase1, "crypto_binding=2")) {
114 data->crypto_binding = REQUIRE_BINDING;
115 wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding");
116 }
117
118 #ifdef EAP_TNC
119 if (os_strstr(phase1, "tnc=soh")) {
120 data->soh = 1;
121 wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH enabled");
122 }
123 #endif /* EAP_TNC */
124
125 return 0;
126 }
127
128
129 static void * eap_peap_init(struct eap_sm *sm)
130 {
131 struct eap_peap_data *data;
132 struct eap_peer_config *config = eap_get_config(sm);
133
134 data = os_zalloc(sizeof(*data));
135 if (data == NULL)
136 return NULL;
137 sm->peap_done = FALSE;
138 data->peap_version = EAP_PEAP_VERSION;
139 data->force_peap_version = -1;
140 data->peap_outer_success = 2;
141 data->crypto_binding = OPTIONAL_BINDING;
142
143 if (config && config->phase1 &&
144 eap_peap_parse_phase1(data, config->phase1) < 0) {
145 eap_peap_deinit(sm, data);
146 return NULL;
147 }
148
149 if (eap_peer_select_phase2_methods(config, "auth=",
150 &data->phase2_types,
151 &data->num_phase2_types) < 0) {
152 eap_peap_deinit(sm, data);
153 return NULL;
154 }
155
156 data->phase2_type.vendor = EAP_VENDOR_IETF;
157 data->phase2_type.method = EAP_TYPE_NONE;
158
159 if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
160 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
161 eap_peap_deinit(sm, data);
162 return NULL;
163 }
164
165 return data;
166 }
167
168
169 static void eap_peap_deinit(struct eap_sm *sm, void *priv)
170 {
171 struct eap_peap_data *data = priv;
172 if (data == NULL)
173 return;
174 if (data->phase2_priv && data->phase2_method)
175 data->phase2_method->deinit(sm, data->phase2_priv);
176 os_free(data->phase2_types);
177 eap_peer_tls_ssl_deinit(sm, &data->ssl);
178 os_free(data->key_data);
179 wpabuf_free(data->pending_phase2_req);
180 os_free(data);
181 }
182
183
184 /**
185 * eap_tlv_build_nak - Build EAP-TLV NAK message
186 * @id: EAP identifier for the header
187 * @nak_type: TLV type (EAP_TLV_*)
188 * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure
189 *
190 * This funtion builds an EAP-TLV NAK message. The caller is responsible for
191 * freeing the returned buffer.
192 */
193 static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type)
194 {
195 struct wpabuf *msg;
196
197 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10,
198 EAP_CODE_RESPONSE, id);
199 if (msg == NULL)
200 return NULL;
201
202 wpabuf_put_u8(msg, 0x80); /* Mandatory */
203 wpabuf_put_u8(msg, EAP_TLV_NAK_TLV);
204 wpabuf_put_be16(msg, 6); /* Length */
205 wpabuf_put_be32(msg, 0); /* Vendor-Id */
206 wpabuf_put_be16(msg, nak_type); /* NAK-Type */
207
208 return msg;
209 }
210
211
212 static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data,
213 u8 *isk, size_t isk_len)
214 {
215 u8 *key;
216 size_t key_len;
217
218 os_memset(isk, 0, isk_len);
219 if (data->phase2_method == NULL || data->phase2_priv == NULL ||
220 data->phase2_method->isKeyAvailable == NULL ||
221 data->phase2_method->getKey == NULL)
222 return 0;
223
224 if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) ||
225 (key = data->phase2_method->getKey(sm, data->phase2_priv,
226 &key_len)) == NULL) {
227 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material "
228 "from Phase 2");
229 return -1;
230 }
231
232 if (key_len == 32 &&
233 data->phase2_method->vendor == EAP_VENDOR_IETF &&
234 data->phase2_method->method == EAP_TYPE_MSCHAPV2) {
235 /*
236 * Microsoft uses reverse order for MS-MPPE keys in
237 * EAP-PEAP when compared to EAP-FAST derivation of
238 * ISK. Swap the keys here to get the correct ISK for
239 * EAP-PEAPv0 cryptobinding.
240 */
241 u8 tmp[16];
242 os_memcpy(tmp, key, 16);
243 os_memcpy(key, key + 16, 16);
244 os_memcpy(key + 16, tmp, 16);
245 }
246
247 if (key_len > isk_len)
248 key_len = isk_len;
249 os_memcpy(isk, key, key_len);
250 os_free(key);
251
252 return 0;
253 }
254
255
256 void peap_prfplus(int version, const u8 *key, size_t key_len,
257 const char *label, const u8 *seed, size_t seed_len,
258 u8 *buf, size_t buf_len)
259 {
260 unsigned char counter = 0;
261 size_t pos, plen;
262 u8 hash[SHA1_MAC_LEN];
263 size_t label_len = os_strlen(label);
264 u8 extra[2];
265 const unsigned char *addr[5];
266 size_t len[5];
267
268 addr[0] = hash;
269 len[0] = 0;
270 addr[1] = (unsigned char *) label;
271 len[1] = label_len;
272 addr[2] = seed;
273 len[2] = seed_len;
274
275 if (version == 0) {
276 /*
277 * PRF+(K, S, LEN) = T1 | T2 | ... | Tn
278 * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00)
279 * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00)
280 * ...
281 * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00)
282 */
283
284 extra[0] = 0;
285 extra[1] = 0;
286
287 addr[3] = &counter;
288 len[3] = 1;
289 addr[4] = extra;
290 len[4] = 2;
291 } else {
292 /*
293 * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where:
294 * T1 = HMAC-SHA1(K, S | LEN | 0x01)
295 * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02)
296 * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03)
297 * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04)
298 * ...
299 */
300
301 extra[0] = buf_len & 0xff;
302
303 addr[3] = extra;
304 len[3] = 1;
305 addr[4] = &counter;
306 len[4] = 1;
307 }
308
309 pos = 0;
310 while (pos < buf_len) {
311 counter++;
312 plen = buf_len - pos;
313 hmac_sha1_vector(key, key_len, 5, addr, len, hash);
314 if (plen >= SHA1_MAC_LEN) {
315 os_memcpy(&buf[pos], hash, SHA1_MAC_LEN);
316 pos += SHA1_MAC_LEN;
317 } else {
318 os_memcpy(&buf[pos], hash, plen);
319 break;
320 }
321 len[0] = SHA1_MAC_LEN;
322 }
323 }
324
325
326 static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
327 {
328 u8 *tk;
329 u8 isk[32], imck[60];
330
331 /*
332 * Tunnel key (TK) is the first 60 octets of the key generated by
333 * phase 1 of PEAP (based on TLS).
334 */
335 tk = data->key_data;
336 if (tk == NULL)
337 return -1;
338 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
339
340 if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0)
341 return -1;
342 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
343
344 /*
345 * IPMK Seed = "Inner Methods Compound Keys" | ISK
346 * TempKey = First 40 octets of TK
347 * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
348 * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
349 * in the end of the label just before ISK; is that just a typo?)
350 */
351 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
352 peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
353 isk, sizeof(isk), imck, sizeof(imck));
354 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
355 imck, sizeof(imck));
356
357 /* TODO: fast-connect: IPMK|CMK = TK */
358 os_memcpy(data->ipmk, imck, 40);
359 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
360 os_memcpy(data->cmk, imck + 40, 20);
361 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
362
363 return 0;
364 }
365
366
367 static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
368 struct eap_peap_data *data,
369 struct wpabuf *buf)
370 {
371 u8 *mac;
372 u8 eap_type = EAP_TYPE_PEAP;
373 const u8 *addr[2];
374 size_t len[2];
375 u16 tlv_type;
376 u8 binding_nonce[32];
377
378 /* FIX: should binding_nonce be copied from request? */
379 if (os_get_random(binding_nonce, 32))
380 return -1;
381
382 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
383 addr[0] = wpabuf_put(buf, 0);
384 len[0] = 60;
385 addr[1] = &eap_type;
386 len[1] = 1;
387
388 tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
389 if (data->peap_version >= 2)
390 tlv_type |= EAP_TLV_TYPE_MANDATORY;
391 wpabuf_put_be16(buf, tlv_type);
392 wpabuf_put_be16(buf, 56);
393
394 wpabuf_put_u8(buf, 0); /* Reserved */
395 wpabuf_put_u8(buf, data->peap_version); /* Version */
396 wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */
397 wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */
398 wpabuf_put_data(buf, binding_nonce, 32); /* Nonce */
399 mac = wpabuf_put(buf, 20); /* Compound_MAC */
400 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20);
401 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
402 addr[0], len[0]);
403 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
404 addr[1], len[1]);
405 hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
406 wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
407 data->crypto_binding_used = 1;
408
409 return 0;
410 }
411
412
413 /**
414 * eap_tlv_build_result - Build EAP-TLV Result message
415 * @id: EAP identifier for the header
416 * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE)
417 * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure
418 *
419 * This funtion builds an EAP-TLV Result message. The caller is responsible for
420 * freeing the returned buffer.
421 */
422 static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm,
423 struct eap_peap_data *data,
424 int crypto_tlv_used,
425 int id, u16 status)
426 {
427 struct wpabuf *msg;
428 size_t len;
429
430 if (data->crypto_binding == NO_BINDING)
431 crypto_tlv_used = 0;
432
433 len = 6;
434 if (crypto_tlv_used)
435 len += 60; /* Cryptobinding TLV */
436 msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
437 EAP_CODE_RESPONSE, id);
438 if (msg == NULL)
439 return NULL;
440
441 wpabuf_put_u8(msg, 0x80); /* Mandatory */
442 wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV);
443 wpabuf_put_be16(msg, 2); /* Length */
444 wpabuf_put_be16(msg, status); /* Status */
445
446 if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
447 wpabuf_free(msg);
448 return NULL;
449 }
450
451 return msg;
452 }
453
454
455 static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
456 struct eap_peap_data *data,
457 const u8 *crypto_tlv,
458 size_t crypto_tlv_len)
459 {
460 u8 buf[61], mac[SHA1_MAC_LEN];
461 const u8 *pos;
462
463 if (eap_peap_derive_cmk(sm, data) < 0) {
464 wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK");
465 return -1;
466 }
467
468 if (crypto_tlv_len != 4 + 56) {
469 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
470 "length %d", (int) crypto_tlv_len);
471 return -1;
472 }
473
474 pos = crypto_tlv;
475 pos += 4; /* TLV header */
476 if (pos[1] != data->peap_version) {
477 wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
478 "mismatch (was %d; expected %d)",
479 pos[1], data->peap_version);
480 return -1;
481 }
482
483 if (pos[3] != 0) {
484 wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
485 "SubType %d", pos[3]);
486 return -1;
487 }
488 pos += 4;
489 pos += 32; /* Nonce */
490
491 /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
492 os_memcpy(buf, crypto_tlv, 60);
493 os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
494 buf[60] = EAP_TYPE_PEAP;
495 hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
496
497 if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
498 wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
499 "cryptobinding TLV");
500 return -1;
501 }
502
503 wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
504
505 return 0;
506 }
507
508
509 /**
510 * eap_tlv_process - Process a received EAP-TLV message and generate a response
511 * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
512 * @ret: Return values from EAP request validation and processing
513 * @req: EAP-TLV request to be processed. The caller must have validated that
514 * the buffer is large enough to contain full request (hdr->length bytes) and
515 * that the EAP type is EAP_TYPE_TLV.
516 * @resp: Buffer to return a pointer to the allocated response message. This
517 * field should be initialized to %NULL before the call. The value will be
518 * updated if a response message is generated. The caller is responsible for
519 * freeing the allocated message.
520 * @force_failure: Force negotiation to fail
521 * Returns: 0 on success, -1 on failure
522 */
523 static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data,
524 struct eap_method_ret *ret,
525 const struct wpabuf *req, struct wpabuf **resp,
526 int force_failure)
527 {
528 size_t left, tlv_len;
529 const u8 *pos;
530 const u8 *result_tlv = NULL, *crypto_tlv = NULL;
531 size_t result_tlv_len = 0, crypto_tlv_len = 0;
532 int tlv_type, mandatory;
533
534 /* Parse TLVs */
535 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left);
536 if (pos == NULL)
537 return -1;
538 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
539 while (left >= 4) {
540 mandatory = !!(pos[0] & 0x80);
541 tlv_type = WPA_GET_BE16(pos) & 0x3fff;
542 pos += 2;
543 tlv_len = WPA_GET_BE16(pos);
544 pos += 2;
545 left -= 4;
546 if (tlv_len > left) {
547 wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
548 "(tlv_len=%lu left=%lu)",
549 (unsigned long) tlv_len,
550 (unsigned long) left);
551 return -1;
552 }
553 switch (tlv_type) {
554 case EAP_TLV_RESULT_TLV:
555 result_tlv = pos;
556 result_tlv_len = tlv_len;
557 break;
558 case EAP_TLV_CRYPTO_BINDING_TLV:
559 crypto_tlv = pos;
560 crypto_tlv_len = tlv_len;
561 break;
562 default:
563 wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
564 "%d%s", tlv_type,
565 mandatory ? " (mandatory)" : "");
566 if (mandatory) {
567 /* NAK TLV and ignore all TLVs in this packet.
568 */
569 *resp = eap_tlv_build_nak(eap_get_id(req),
570 tlv_type);
571 return *resp == NULL ? -1 : 0;
572 }
573 /* Ignore this TLV, but process other TLVs */
574 break;
575 }
576
577 pos += tlv_len;
578 left -= tlv_len;
579 }
580 if (left) {
581 wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
582 "Request (left=%lu)", (unsigned long) left);
583 return -1;
584 }
585
586 /* Process supported TLVs */
587 if (crypto_tlv && data->crypto_binding != NO_BINDING) {
588 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
589 crypto_tlv, crypto_tlv_len);
590 if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
591 crypto_tlv_len + 4) < 0) {
592 if (result_tlv == NULL)
593 return -1;
594 force_failure = 1;
595 }
596 } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) {
597 wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
598 return -1;
599 }
600
601 if (result_tlv) {
602 int status, resp_status;
603 wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
604 result_tlv, result_tlv_len);
605 if (result_tlv_len < 2) {
606 wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
607 "(len=%lu)",
608 (unsigned long) result_tlv_len);
609 return -1;
610 }
611 status = WPA_GET_BE16(result_tlv);
612 if (status == EAP_TLV_RESULT_SUCCESS) {
613 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
614 "- EAP-TLV/Phase2 Completed");
615 if (force_failure) {
616 wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure"
617 " - force failed Phase 2");
618 resp_status = EAP_TLV_RESULT_FAILURE;
619 ret->decision = DECISION_FAIL;
620 } else {
621 resp_status = EAP_TLV_RESULT_SUCCESS;
622 ret->decision = DECISION_UNCOND_SUCC;
623 }
624 } else if (status == EAP_TLV_RESULT_FAILURE) {
625 wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
626 resp_status = EAP_TLV_RESULT_FAILURE;
627 ret->decision = DECISION_FAIL;
628 } else {
629 wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
630 "Status %d", status);
631 resp_status = EAP_TLV_RESULT_FAILURE;
632 ret->decision = DECISION_FAIL;
633 }
634 ret->methodState = METHOD_DONE;
635
636 *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL,
637 eap_get_id(req), resp_status);
638 }
639
640 return 0;
641 }
642
643
644 static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
645 {
646 struct wpabuf *e;
647 struct eap_tlv_hdr *tlv;
648
649 if (buf == NULL)
650 return NULL;
651
652 /* Encapsulate EAP packet in EAP-Payload TLV */
653 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
654 e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
655 if (e == NULL) {
656 wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
657 "for TLV encapsulation");
658 wpabuf_free(buf);
659 return NULL;
660 }
661 tlv = wpabuf_put(e, sizeof(*tlv));
662 tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
663 EAP_TLV_EAP_PAYLOAD_TLV);
664 tlv->length = host_to_be16(wpabuf_len(buf));
665 wpabuf_put_buf(e, buf);
666 wpabuf_free(buf);
667 return e;
668 }
669
670
671 static int eap_peap_phase2_request(struct eap_sm *sm,
672 struct eap_peap_data *data,
673 struct eap_method_ret *ret,
674 struct wpabuf *req,
675 struct wpabuf **resp)
676 {
677 struct eap_hdr *hdr = wpabuf_mhead(req);
678 size_t len = be_to_host16(hdr->length);
679 u8 *pos;
680 struct eap_method_ret iret;
681 struct eap_peer_config *config = eap_get_config(sm);
682
683 if (len <= sizeof(struct eap_hdr)) {
684 wpa_printf(MSG_INFO, "EAP-PEAP: too short "
685 "Phase 2 request (len=%lu)", (unsigned long) len);
686 return -1;
687 }
688 pos = (u8 *) (hdr + 1);
689 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
690 switch (*pos) {
691 case EAP_TYPE_IDENTITY:
692 *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
693 break;
694 case EAP_TYPE_TLV:
695 os_memset(&iret, 0, sizeof(iret));
696 if (eap_tlv_process(sm, data, &iret, req, resp,
697 data->phase2_eap_started &&
698 !data->phase2_eap_success)) {
699 ret->methodState = METHOD_DONE;
700 ret->decision = DECISION_FAIL;
701 return -1;
702 }
703 if (iret.methodState == METHOD_DONE ||
704 iret.methodState == METHOD_MAY_CONT) {
705 ret->methodState = iret.methodState;
706 ret->decision = iret.decision;
707 data->phase2_success = 1;
708 }
709 break;
710 case EAP_TYPE_EXPANDED:
711 #ifdef EAP_TNC
712 if (data->soh) {
713 const u8 *epos;
714 size_t eleft;
715
716 epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21,
717 req, &eleft);
718 if (epos) {
719 struct wpabuf *buf;
720 wpa_printf(MSG_DEBUG,
721 "EAP-PEAP: SoH EAP Extensions");
722 buf = tncc_process_soh_request(epos, eleft);
723 if (buf) {
724 *resp = eap_msg_alloc(
725 EAP_VENDOR_MICROSOFT, 0x21,
726 wpabuf_len(buf),
727 EAP_CODE_RESPONSE,
728 hdr->identifier);
729 if (*resp == NULL) {
730 ret->methodState = METHOD_DONE;
731 ret->decision = DECISION_FAIL;
732 return -1;
733 }
734 wpabuf_put_buf(*resp, buf);
735 wpabuf_free(buf);
736 break;
737 }
738 }
739 }
740 #endif /* EAP_TNC */
741 /* fall through */
742 default:
743 if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
744 data->phase2_type.method == EAP_TYPE_NONE) {
745 size_t i;
746 for (i = 0; i < data->num_phase2_types; i++) {
747 if (data->phase2_types[i].vendor !=
748 EAP_VENDOR_IETF ||
749 data->phase2_types[i].method != *pos)
750 continue;
751
752 data->phase2_type.vendor =
753 data->phase2_types[i].vendor;
754 data->phase2_type.method =
755 data->phase2_types[i].method;
756 wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
757 "Phase 2 EAP vendor %d method %d",
758 data->phase2_type.vendor,
759 data->phase2_type.method);
760 break;
761 }
762 }
763 if (*pos != data->phase2_type.method ||
764 *pos == EAP_TYPE_NONE) {
765 if (eap_peer_tls_phase2_nak(data->phase2_types,
766 data->num_phase2_types,
767 hdr, resp))
768 return -1;
769 return 0;
770 }
771
772 if (data->phase2_priv == NULL) {
773 data->phase2_method = eap_peer_get_eap_method(
774 data->phase2_type.vendor,
775 data->phase2_type.method);
776 if (data->phase2_method) {
777 sm->init_phase2 = 1;
778 sm->mschapv2_full_key = 1;
779 data->phase2_priv =
780 data->phase2_method->init(sm);
781 sm->init_phase2 = 0;
782 sm->mschapv2_full_key = 0;
783 }
784 }
785 if (data->phase2_priv == NULL || data->phase2_method == NULL) {
786 wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize "
787 "Phase 2 EAP method %d", *pos);
788 ret->methodState = METHOD_DONE;
789 ret->decision = DECISION_FAIL;
790 return -1;
791 }
792 data->phase2_eap_started = 1;
793 os_memset(&iret, 0, sizeof(iret));
794 *resp = data->phase2_method->process(sm, data->phase2_priv,
795 &iret, req);
796 if ((iret.methodState == METHOD_DONE ||
797 iret.methodState == METHOD_MAY_CONT) &&
798 (iret.decision == DECISION_UNCOND_SUCC ||
799 iret.decision == DECISION_COND_SUCC)) {
800 data->phase2_eap_success = 1;
801 data->phase2_success = 1;
802 }
803 break;
804 }
805
806 if (*resp == NULL &&
807 (config->pending_req_identity || config->pending_req_password ||
808 config->pending_req_otp || config->pending_req_new_password)) {
809 wpabuf_free(data->pending_phase2_req);
810 data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
811 }
812
813 return 0;
814 }
815
816
817 static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
818 struct eap_method_ret *ret,
819 const struct eap_hdr *req,
820 const struct wpabuf *in_data,
821 struct wpabuf **out_data)
822 {
823 struct wpabuf *in_decrypted = NULL;
824 int res, skip_change = 0;
825 struct eap_hdr *hdr, *rhdr;
826 struct wpabuf *resp = NULL;
827 size_t len;
828
829 wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
830 " Phase 2", (unsigned long) wpabuf_len(in_data));
831
832 if (data->pending_phase2_req) {
833 wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
834 "skip decryption and use old data");
835 /* Clear TLS reassembly state. */
836 eap_peer_tls_reset_input(&data->ssl);
837 in_decrypted = data->pending_phase2_req;
838 data->pending_phase2_req = NULL;
839 skip_change = 1;
840 goto continue_req;
841 }
842
843 if (wpabuf_len(in_data) == 0 && sm->workaround &&
844 data->phase2_success) {
845 /*
846 * Cisco ACS seems to be using TLS ACK to terminate
847 * EAP-PEAPv0/GTC. Try to reply with TLS ACK.
848 */
849 wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but "
850 "expected data - acknowledge with TLS ACK since "
851 "Phase 2 has been completed");
852 ret->decision = DECISION_COND_SUCC;
853 ret->methodState = METHOD_DONE;
854 return 1;
855 } else if (wpabuf_len(in_data) == 0) {
856 /* Received TLS ACK - requesting more fragments */
857 return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
858 data->peap_version,
859 req->identifier, NULL, out_data);
860 }
861
862 res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
863 if (res)
864 return res;
865
866 continue_req:
867 wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
868 in_decrypted);
869
870 hdr = wpabuf_mhead(in_decrypted);
871 if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST &&
872 be_to_host16(hdr->length) == 5 &&
873 eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) {
874 /* At least FreeRADIUS seems to send full EAP header with
875 * EAP Request Identity */
876 skip_change = 1;
877 }
878 if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST &&
879 eap_get_type(in_decrypted) == EAP_TYPE_TLV) {
880 skip_change = 1;
881 }
882
883 if (data->peap_version == 0 && !skip_change) {
884 struct eap_hdr *nhdr;
885 struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
886 wpabuf_len(in_decrypted));
887 if (nmsg == NULL) {
888 wpabuf_free(in_decrypted);
889 return 0;
890 }
891 nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
892 wpabuf_put_buf(nmsg, in_decrypted);
893 nhdr->code = req->code;
894 nhdr->identifier = req->identifier;
895 nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
896 wpabuf_len(in_decrypted));
897
898 wpabuf_free(in_decrypted);
899 in_decrypted = nmsg;
900 }
901
902 if (data->peap_version >= 2) {
903 struct eap_tlv_hdr *tlv;
904 struct wpabuf *nmsg;
905
906 if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
907 wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
908 "EAP TLV");
909 wpabuf_free(in_decrypted);
910 return 0;
911 }
912 tlv = wpabuf_mhead(in_decrypted);
913 if ((be_to_host16(tlv->tlv_type) & 0x3fff) !=
914 EAP_TLV_EAP_PAYLOAD_TLV) {
915 wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
916 wpabuf_free(in_decrypted);
917 return 0;
918 }
919 if (sizeof(*tlv) + be_to_host16(tlv->length) >
920 wpabuf_len(in_decrypted)) {
921 wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
922 "length");
923 wpabuf_free(in_decrypted);
924 return 0;
925 }
926 hdr = (struct eap_hdr *) (tlv + 1);
927 if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
928 wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
929 "EAP packet in EAP TLV");
930 wpabuf_free(in_decrypted);
931 return 0;
932 }
933
934 nmsg = wpabuf_alloc(be_to_host16(hdr->length));
935 if (nmsg == NULL) {
936 wpabuf_free(in_decrypted);
937 return 0;
938 }
939
940 wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
941 wpabuf_free(in_decrypted);
942 in_decrypted = nmsg;
943 }
944
945 hdr = wpabuf_mhead(in_decrypted);
946 if (wpabuf_len(in_decrypted) < sizeof(*hdr)) {
947 wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
948 "EAP frame (len=%lu)",
949 (unsigned long) wpabuf_len(in_decrypted));
950 wpabuf_free(in_decrypted);
951 return 0;
952 }
953 len = be_to_host16(hdr->length);
954 if (len > wpabuf_len(in_decrypted)) {
955 wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
956 "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
957 (unsigned long) wpabuf_len(in_decrypted),
958 (unsigned long) len);
959 wpabuf_free(in_decrypted);
960 return 0;
961 }
962 if (len < wpabuf_len(in_decrypted)) {
963 wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
964 "shorter length than full decrypted data "
965 "(%lu < %lu)",
966 (unsigned long) len,
967 (unsigned long) wpabuf_len(in_decrypted));
968 }
969 wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
970 "identifier=%d length=%lu", hdr->code, hdr->identifier,
971 (unsigned long) len);
972 switch (hdr->code) {
973 case EAP_CODE_REQUEST:
974 if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
975 &resp)) {
976 wpabuf_free(in_decrypted);
977 wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
978 "processing failed");
979 return 0;
980 }
981 break;
982 case EAP_CODE_SUCCESS:
983 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
984 if (data->peap_version == 1) {
985 /* EAP-Success within TLS tunnel is used to indicate
986 * shutdown of the TLS channel. The authentication has
987 * been completed. */
988 if (data->phase2_eap_started &&
989 !data->phase2_eap_success) {
990 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
991 "Success used to indicate success, "
992 "but Phase 2 EAP was not yet "
993 "completed successfully");
994 ret->methodState = METHOD_DONE;
995 ret->decision = DECISION_FAIL;
996 wpabuf_free(in_decrypted);
997 return 0;
998 }
999 wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
1000 "EAP-Success within TLS tunnel - "
1001 "authentication completed");
1002 ret->decision = DECISION_UNCOND_SUCC;
1003 ret->methodState = METHOD_DONE;
1004 data->phase2_success = 1;
1005 if (data->peap_outer_success == 2) {
1006 wpabuf_free(in_decrypted);
1007 wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
1008 "to finish authentication");
1009 return 1;
1010 } else if (data->peap_outer_success == 1) {
1011 /* Reply with EAP-Success within the TLS
1012 * channel to complete the authentication. */
1013 resp = wpabuf_alloc(sizeof(struct eap_hdr));
1014 if (resp) {
1015 rhdr = wpabuf_put(resp, sizeof(*rhdr));
1016 rhdr->code = EAP_CODE_SUCCESS;
1017 rhdr->identifier = hdr->identifier;
1018 rhdr->length =
1019 host_to_be16(sizeof(*rhdr));
1020 }
1021 } else {
1022 /* No EAP-Success expected for Phase 1 (outer,
1023 * unencrypted auth), so force EAP state
1024 * machine to SUCCESS state. */
1025 sm->peap_done = TRUE;
1026 }
1027 } else {
1028 /* FIX: ? */
1029 }
1030 break;
1031 case EAP_CODE_FAILURE:
1032 wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
1033 ret->decision = DECISION_FAIL;
1034 ret->methodState = METHOD_MAY_CONT;
1035 ret->allowNotifications = FALSE;
1036 /* Reply with EAP-Failure within the TLS channel to complete
1037 * failure reporting. */
1038 resp = wpabuf_alloc(sizeof(struct eap_hdr));
1039 if (resp) {
1040 rhdr = wpabuf_put(resp, sizeof(*rhdr));
1041 rhdr->code = EAP_CODE_FAILURE;
1042 rhdr->identifier = hdr->identifier;
1043 rhdr->length = host_to_be16(sizeof(*rhdr));
1044 }
1045 break;
1046 default:
1047 wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
1048 "Phase 2 EAP header", hdr->code);
1049 break;
1050 }
1051
1052 wpabuf_free(in_decrypted);
1053
1054 if (resp) {
1055 int skip_change2 = 0;
1056 struct wpabuf *rmsg, buf;
1057
1058 wpa_hexdump_buf_key(MSG_DEBUG,
1059 "EAP-PEAP: Encrypting Phase 2 data", resp);
1060 /* PEAP version changes */
1061 if (data->peap_version >= 2) {
1062 resp = eap_peapv2_tlv_eap_payload(resp);
1063 if (resp == NULL)
1064 return -1;
1065 }
1066 if (wpabuf_len(resp) >= 5 &&
1067 wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE &&
1068 eap_get_type(resp) == EAP_TYPE_TLV)
1069 skip_change2 = 1;
1070 rmsg = resp;
1071 if (data->peap_version == 0 && !skip_change2) {
1072 wpabuf_set(&buf, wpabuf_head_u8(resp) +
1073 sizeof(struct eap_hdr),
1074 wpabuf_len(resp) - sizeof(struct eap_hdr));
1075 rmsg = &buf;
1076 }
1077
1078 if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
1079 data->peap_version, req->identifier,
1080 rmsg, out_data)) {
1081 wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
1082 "a Phase 2 frame");
1083 }
1084 wpabuf_free(resp);
1085 }
1086
1087 return 0;
1088 }
1089
1090
1091 static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
1092 struct eap_method_ret *ret,
1093 const struct wpabuf *reqData)
1094 {
1095 const struct eap_hdr *req;
1096 size_t left;
1097 int res;
1098 u8 flags, id;
1099 struct wpabuf *resp;
1100 const u8 *pos;
1101 struct eap_peap_data *data = priv;
1102
1103 pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,
1104 reqData, &left, &flags);
1105 if (pos == NULL)
1106 return NULL;
1107 req = wpabuf_head(reqData);
1108 id = req->identifier;
1109
1110 if (flags & EAP_TLS_FLAGS_START) {
1111 wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
1112 "ver=%d)", flags & EAP_PEAP_VERSION_MASK,
1113 data->peap_version);
1114 if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version)
1115 data->peap_version = flags & EAP_PEAP_VERSION_MASK;
1116 if (data->force_peap_version >= 0 &&
1117 data->force_peap_version != data->peap_version) {
1118 wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
1119 "forced PEAP version %d",
1120 data->force_peap_version);
1121 ret->methodState = METHOD_DONE;
1122 ret->decision = DECISION_FAIL;
1123 ret->allowNotifications = FALSE;
1124 return NULL;
1125 }
1126 wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",
1127 data->peap_version);
1128 left = 0; /* make sure that this frame is empty, even though it
1129 * should always be, anyway */
1130 }
1131
1132 resp = NULL;
1133 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1134 !data->resuming) {
1135 struct wpabuf msg;
1136 wpabuf_set(&msg, pos, left);
1137 res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
1138 } else {
1139 res = eap_peer_tls_process_helper(sm, &data->ssl,
1140 EAP_TYPE_PEAP,
1141 data->peap_version, id, pos,
1142 left, &resp);
1143
1144 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1145 char *label;
1146 wpa_printf(MSG_DEBUG,
1147 "EAP-PEAP: TLS done, proceed to Phase 2");
1148 os_free(data->key_data);
1149 /* draft-josefsson-ppext-eap-tls-eap-05.txt
1150 * specifies that PEAPv1 would use "client PEAP
1151 * encryption" as the label. However, most existing
1152 * PEAPv1 implementations seem to be using the old
1153 * label, "client EAP encryption", instead. Use the old
1154 * label by default, but allow it to be configured with
1155 * phase1 parameter peaplabel=1. */
1156 if (data->peap_version > 1 || data->force_new_label)
1157 label = "client PEAP encryption";
1158 else
1159 label = "client EAP encryption";
1160 wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
1161 "key derivation", label);
1162 data->key_data =
1163 eap_peer_tls_derive_key(sm, &data->ssl, label,
1164 EAP_TLS_KEY_LEN);
1165 if (data->key_data) {
1166 wpa_hexdump_key(MSG_DEBUG,
1167 "EAP-PEAP: Derived key",
1168 data->key_data,
1169 EAP_TLS_KEY_LEN);
1170 } else {
1171 wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
1172 "derive key");
1173 }
1174
1175 if (sm->workaround && data->resuming) {
1176 /*
1177 * At least few RADIUS servers (Aegis v1.1.6;
1178 * but not v1.1.4; and Cisco ACS) seem to be
1179 * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco
1180 * ACS) session resumption with outer
1181 * EAP-Success. This does not seem to follow
1182 * draft-josefsson-pppext-eap-tls-eap-05.txt
1183 * section 4.2, so only allow this if EAP
1184 * workarounds are enabled.
1185 */
1186 wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "
1187 "allow outer EAP-Success to "
1188 "terminate PEAP resumption");
1189 ret->decision = DECISION_COND_SUCC;
1190 data->phase2_success = 1;
1191 }
1192
1193 data->resuming = 0;
1194 }
1195
1196 if (res == 2) {
1197 struct wpabuf msg;
1198 /*
1199 * Application data included in the handshake message.
1200 */
1201 wpabuf_free(data->pending_phase2_req);
1202 data->pending_phase2_req = resp;
1203 resp = NULL;
1204 wpabuf_set(&msg, pos, left);
1205 res = eap_peap_decrypt(sm, data, ret, req, &msg,
1206 &resp);
1207 }
1208 }
1209
1210 if (ret->methodState == METHOD_DONE) {
1211 ret->allowNotifications = FALSE;
1212 }
1213
1214 if (res == 1) {
1215 wpabuf_free(resp);
1216 return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
1217 data->peap_version);
1218 }
1219
1220 return resp;
1221 }
1222
1223
1224 static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
1225 {
1226 struct eap_peap_data *data = priv;
1227 return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1228 data->phase2_success;
1229 }
1230
1231
1232 static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
1233 {
1234 struct eap_peap_data *data = priv;
1235 wpabuf_free(data->pending_phase2_req);
1236 data->pending_phase2_req = NULL;
1237 data->crypto_binding_used = 0;
1238 }
1239
1240
1241 static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
1242 {
1243 struct eap_peap_data *data = priv;
1244 os_free(data->key_data);
1245 data->key_data = NULL;
1246 if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1247 os_free(data);
1248 return NULL;
1249 }
1250 if (data->phase2_priv && data->phase2_method &&
1251 data->phase2_method->init_for_reauth)
1252 data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1253 data->phase2_success = 0;
1254 data->phase2_eap_success = 0;
1255 data->phase2_eap_started = 0;
1256 data->resuming = 1;
1257 sm->peap_done = FALSE;
1258 return priv;
1259 }
1260
1261
1262 static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,
1263 size_t buflen, int verbose)
1264 {
1265 struct eap_peap_data *data = priv;
1266 int len, ret;
1267
1268 len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1269 if (data->phase2_method) {
1270 ret = os_snprintf(buf + len, buflen - len,
1271 "EAP-PEAPv%d Phase2 method=%s\n",
1272 data->peap_version,
1273 data->phase2_method->name);
1274 if (ret < 0 || (size_t) ret >= buflen - len)
1275 return len;
1276 len += ret;
1277 }
1278 return len;
1279 }
1280
1281
1282 static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv)
1283 {
1284 struct eap_peap_data *data = priv;
1285 return data->key_data != NULL && data->phase2_success;
1286 }
1287
1288
1289 static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
1290 {
1291 struct eap_peap_data *data = priv;
1292 u8 *key;
1293
1294 if (data->key_data == NULL || !data->phase2_success)
1295 return NULL;
1296
1297 key = os_malloc(EAP_TLS_KEY_LEN);
1298 if (key == NULL)
1299 return NULL;
1300
1301 *len = EAP_TLS_KEY_LEN;
1302
1303 if (data->crypto_binding_used) {
1304 u8 csk[128];
1305 /*
1306 * Note: It looks like Microsoft implementation requires null
1307 * termination for this label while the one used for deriving
1308 * IPMK|CMK did not use null termination.
1309 */
1310 peap_prfplus(data->peap_version, data->ipmk, 40,
1311 "Session Key Generating Function",
1312 (u8 *) "\00", 1, csk, sizeof(csk));
1313 wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
1314 os_memcpy(key, csk, EAP_TLS_KEY_LEN);
1315 wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
1316 key, EAP_TLS_KEY_LEN);
1317 } else
1318 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
1319
1320 return key;
1321 }
1322
1323
1324 int eap_peer_peap_register(void)
1325 {
1326 struct eap_method *eap;
1327 int ret;
1328
1329 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1330 EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
1331 if (eap == NULL)
1332 return -1;
1333
1334 eap->init = eap_peap_init;
1335 eap->deinit = eap_peap_deinit;
1336 eap->process = eap_peap_process;
1337 eap->isKeyAvailable = eap_peap_isKeyAvailable;
1338 eap->getKey = eap_peap_getKey;
1339 eap->get_status = eap_peap_get_status;
1340 eap->has_reauth_data = eap_peap_has_reauth_data;
1341 eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
1342 eap->init_for_reauth = eap_peap_init_for_reauth;
1343
1344 ret = eap_peer_method_register(eap);
1345 if (ret)
1346 eap_peer_method_free(eap);
1347 return ret;
1348 }