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