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