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