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