Line data Source code
1 : /*
2 : * EAP peer method: EAP-TTLS (RFC 5281)
3 : * Copyright (c) 2004-2011, 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/ms_funcs.h"
13 : #include "crypto/sha1.h"
14 : #include "crypto/tls.h"
15 : #include "eap_common/chap.h"
16 : #include "eap_common/eap_ttls.h"
17 : #include "mschapv2.h"
18 : #include "eap_i.h"
19 : #include "eap_tls_common.h"
20 : #include "eap_config.h"
21 :
22 :
23 : #define EAP_TTLS_VERSION 0
24 :
25 :
26 : static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
27 :
28 :
29 : struct eap_ttls_data {
30 : struct eap_ssl_data ssl;
31 :
32 : int ttls_version;
33 :
34 : const struct eap_method *phase2_method;
35 : void *phase2_priv;
36 : int phase2_success;
37 : int phase2_start;
38 :
39 : enum phase2_types {
40 : EAP_TTLS_PHASE2_EAP,
41 : EAP_TTLS_PHASE2_MSCHAPV2,
42 : EAP_TTLS_PHASE2_MSCHAP,
43 : EAP_TTLS_PHASE2_PAP,
44 : EAP_TTLS_PHASE2_CHAP
45 : } phase2_type;
46 : struct eap_method_type phase2_eap_type;
47 : struct eap_method_type *phase2_eap_types;
48 : size_t num_phase2_eap_types;
49 :
50 : u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN];
51 : int auth_response_valid;
52 : u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */
53 : u8 ident;
54 : int resuming; /* starting a resumed session */
55 : int reauth; /* reauthentication */
56 : u8 *key_data;
57 : u8 *session_id;
58 : size_t id_len;
59 :
60 : struct wpabuf *pending_phase2_req;
61 :
62 : #ifdef EAP_TNC
63 : int ready_for_tnc;
64 : int tnc_started;
65 : #endif /* EAP_TNC */
66 : };
67 :
68 :
69 171 : static void * eap_ttls_init(struct eap_sm *sm)
70 : {
71 : struct eap_ttls_data *data;
72 171 : struct eap_peer_config *config = eap_get_config(sm);
73 : char *selected;
74 :
75 171 : data = os_zalloc(sizeof(*data));
76 171 : if (data == NULL)
77 0 : return NULL;
78 171 : data->ttls_version = EAP_TTLS_VERSION;
79 171 : selected = "EAP";
80 171 : data->phase2_type = EAP_TTLS_PHASE2_EAP;
81 :
82 171 : if (config && config->phase2) {
83 166 : if (os_strstr(config->phase2, "autheap=")) {
84 23 : selected = "EAP";
85 23 : data->phase2_type = EAP_TTLS_PHASE2_EAP;
86 143 : } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
87 94 : selected = "MSCHAPV2";
88 94 : data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
89 49 : } else if (os_strstr(config->phase2, "auth=MSCHAP")) {
90 13 : selected = "MSCHAP";
91 13 : data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
92 36 : } else if (os_strstr(config->phase2, "auth=PAP")) {
93 28 : selected = "PAP";
94 28 : data->phase2_type = EAP_TTLS_PHASE2_PAP;
95 8 : } else if (os_strstr(config->phase2, "auth=CHAP")) {
96 8 : selected = "CHAP";
97 8 : data->phase2_type = EAP_TTLS_PHASE2_CHAP;
98 : }
99 : }
100 171 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
101 :
102 171 : if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
103 28 : if (eap_peer_select_phase2_methods(config, "autheap=",
104 : &data->phase2_eap_types,
105 : &data->num_phase2_eap_types)
106 : < 0) {
107 0 : eap_ttls_deinit(sm, data);
108 0 : return NULL;
109 : }
110 :
111 28 : data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
112 28 : data->phase2_eap_type.method = EAP_TYPE_NONE;
113 : }
114 :
115 171 : if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TTLS)) {
116 3 : wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
117 3 : eap_ttls_deinit(sm, data);
118 3 : return NULL;
119 : }
120 :
121 168 : return data;
122 : }
123 :
124 :
125 171 : static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,
126 : struct eap_ttls_data *data)
127 : {
128 171 : if (data->phase2_priv && data->phase2_method) {
129 19 : data->phase2_method->deinit(sm, data->phase2_priv);
130 19 : data->phase2_method = NULL;
131 19 : data->phase2_priv = NULL;
132 : }
133 171 : }
134 :
135 :
136 340 : static void eap_ttls_free_key(struct eap_ttls_data *data)
137 : {
138 340 : if (data->key_data) {
139 157 : bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
140 157 : data->key_data = NULL;
141 : }
142 340 : }
143 :
144 :
145 171 : static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
146 : {
147 171 : struct eap_ttls_data *data = priv;
148 171 : if (data == NULL)
149 171 : return;
150 171 : eap_ttls_phase2_eap_deinit(sm, data);
151 171 : os_free(data->phase2_eap_types);
152 171 : eap_peer_tls_ssl_deinit(sm, &data->ssl);
153 171 : eap_ttls_free_key(data);
154 171 : os_free(data->session_id);
155 171 : wpabuf_free(data->pending_phase2_req);
156 171 : os_free(data);
157 : }
158 :
159 :
160 453 : static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
161 : int mandatory, size_t len)
162 : {
163 : struct ttls_avp_vendor *avp;
164 : u8 flags;
165 : size_t hdrlen;
166 :
167 453 : avp = (struct ttls_avp_vendor *) avphdr;
168 453 : flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
169 453 : if (vendor_id) {
170 190 : flags |= AVP_FLAGS_VENDOR;
171 190 : hdrlen = sizeof(*avp);
172 190 : avp->vendor_id = host_to_be32(vendor_id);
173 : } else {
174 263 : hdrlen = sizeof(struct ttls_avp);
175 : }
176 :
177 453 : avp->avp_code = host_to_be32(avp_code);
178 453 : avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len));
179 :
180 453 : return avphdr + hdrlen;
181 : }
182 :
183 :
184 232 : static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code,
185 : u32 vendor_id, int mandatory,
186 : const u8 *data, size_t len)
187 : {
188 : u8 *pos;
189 232 : pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);
190 232 : os_memcpy(pos, data, len);
191 232 : pos += len;
192 232 : AVP_PAD(start, pos);
193 232 : return pos;
194 : }
195 :
196 :
197 94 : static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
198 : int mandatory)
199 : {
200 : struct wpabuf *msg;
201 : u8 *avp, *pos;
202 :
203 94 : msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
204 94 : if (msg == NULL) {
205 0 : wpabuf_free(*resp);
206 0 : *resp = NULL;
207 0 : return -1;
208 : }
209 :
210 94 : avp = wpabuf_mhead(msg);
211 94 : pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp));
212 94 : os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
213 94 : pos += wpabuf_len(*resp);
214 94 : AVP_PAD(avp, pos);
215 94 : wpabuf_free(*resp);
216 94 : wpabuf_put(msg, pos - avp);
217 94 : *resp = msg;
218 94 : return 0;
219 : }
220 :
221 :
222 157 : static int eap_ttls_v0_derive_key(struct eap_sm *sm,
223 : struct eap_ttls_data *data)
224 : {
225 157 : eap_ttls_free_key(data);
226 157 : data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
227 : "ttls keying material",
228 : EAP_TLS_KEY_LEN +
229 : EAP_EMSK_LEN);
230 157 : if (!data->key_data) {
231 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key");
232 0 : return -1;
233 : }
234 :
235 157 : wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
236 157 : data->key_data, EAP_TLS_KEY_LEN);
237 157 : wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived EMSK",
238 157 : data->key_data + EAP_TLS_KEY_LEN,
239 : EAP_EMSK_LEN);
240 :
241 157 : os_free(data->session_id);
242 157 : data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl,
243 : EAP_TYPE_TTLS,
244 : &data->id_len);
245 157 : if (data->session_id) {
246 314 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Derived Session-Id",
247 157 : data->session_id, data->id_len);
248 : } else {
249 0 : wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive Session-Id");
250 : }
251 :
252 157 : return 0;
253 : }
254 :
255 :
256 105 : static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
257 : struct eap_ttls_data *data, size_t len)
258 : {
259 105 : return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
260 : }
261 :
262 :
263 28 : static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
264 : u8 method)
265 : {
266 : size_t i;
267 78 : for (i = 0; i < data->num_phase2_eap_types; i++) {
268 56 : if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||
269 28 : data->phase2_eap_types[i].method != method)
270 11 : continue;
271 :
272 17 : data->phase2_eap_type.vendor =
273 17 : data->phase2_eap_types[i].vendor;
274 17 : data->phase2_eap_type.method =
275 17 : data->phase2_eap_types[i].method;
276 17 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
277 : "Phase 2 EAP vendor %d method %d",
278 : data->phase2_eap_type.vendor,
279 : data->phase2_eap_type.method);
280 17 : break;
281 : }
282 28 : }
283 :
284 :
285 53 : static int eap_ttls_phase2_eap_process(struct eap_sm *sm,
286 : struct eap_ttls_data *data,
287 : struct eap_method_ret *ret,
288 : struct eap_hdr *hdr, size_t len,
289 : struct wpabuf **resp)
290 : {
291 : struct wpabuf msg;
292 : struct eap_method_ret iret;
293 :
294 53 : os_memset(&iret, 0, sizeof(iret));
295 53 : wpabuf_set(&msg, hdr, len);
296 53 : *resp = data->phase2_method->process(sm, data->phase2_priv, &iret,
297 : &msg);
298 90 : if ((iret.methodState == METHOD_DONE ||
299 71 : iret.methodState == METHOD_MAY_CONT) &&
300 60 : (iret.decision == DECISION_UNCOND_SUCC ||
301 42 : iret.decision == DECISION_COND_SUCC ||
302 16 : iret.decision == DECISION_FAIL)) {
303 34 : ret->methodState = iret.methodState;
304 34 : ret->decision = iret.decision;
305 : }
306 :
307 53 : return 0;
308 : }
309 :
310 :
311 66 : static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
312 : struct eap_ttls_data *data,
313 : struct eap_method_ret *ret,
314 : struct eap_hdr *hdr, size_t len,
315 : u8 method, struct wpabuf **resp)
316 : {
317 : #ifdef EAP_TNC
318 87 : if (data->tnc_started && data->phase2_method &&
319 63 : data->phase2_priv && method == EAP_TYPE_TNC &&
320 21 : data->phase2_eap_type.method == EAP_TYPE_TNC)
321 21 : return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
322 : resp);
323 :
324 45 : if (data->ready_for_tnc && !data->tnc_started &&
325 : method == EAP_TYPE_TNC) {
326 0 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
327 : "EAP method");
328 0 : data->tnc_started = 1;
329 : }
330 :
331 45 : if (data->tnc_started) {
332 4 : if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF ||
333 2 : data->phase2_eap_type.method == EAP_TYPE_TNC) {
334 0 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected EAP "
335 : "type %d for TNC", method);
336 0 : return -1;
337 : }
338 :
339 2 : data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
340 2 : data->phase2_eap_type.method = method;
341 2 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
342 : "Phase 2 EAP vendor %d method %d (TNC)",
343 : data->phase2_eap_type.vendor,
344 : data->phase2_eap_type.method);
345 :
346 2 : if (data->phase2_type == EAP_TTLS_PHASE2_EAP)
347 0 : eap_ttls_phase2_eap_deinit(sm, data);
348 : }
349 : #endif /* EAP_TNC */
350 :
351 90 : if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
352 45 : data->phase2_eap_type.method == EAP_TYPE_NONE)
353 28 : eap_ttls_phase2_select_eap_method(data, method);
354 :
355 45 : if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE)
356 : {
357 13 : if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
358 : data->num_phase2_eap_types,
359 : hdr, resp))
360 0 : return -1;
361 13 : return 0;
362 : }
363 :
364 32 : if (data->phase2_priv == NULL) {
365 19 : data->phase2_method = eap_peer_get_eap_method(
366 : EAP_VENDOR_IETF, method);
367 19 : if (data->phase2_method) {
368 19 : sm->init_phase2 = 1;
369 19 : data->phase2_priv = data->phase2_method->init(sm);
370 19 : sm->init_phase2 = 0;
371 : }
372 : }
373 32 : if (data->phase2_priv == NULL || data->phase2_method == NULL) {
374 0 : wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
375 : "Phase 2 EAP method %d", method);
376 0 : return -1;
377 : }
378 :
379 32 : return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp);
380 : }
381 :
382 :
383 96 : static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
384 : struct eap_ttls_data *data,
385 : struct eap_method_ret *ret,
386 : struct eap_hdr *hdr,
387 : struct wpabuf **resp)
388 : {
389 96 : size_t len = be_to_host16(hdr->length);
390 : u8 *pos;
391 96 : struct eap_peer_config *config = eap_get_config(sm);
392 :
393 96 : if (len <= sizeof(struct eap_hdr)) {
394 0 : wpa_printf(MSG_INFO, "EAP-TTLS: too short "
395 : "Phase 2 request (len=%lu)", (unsigned long) len);
396 0 : return -1;
397 : }
398 96 : pos = (u8 *) (hdr + 1);
399 96 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);
400 96 : switch (*pos) {
401 : case EAP_TYPE_IDENTITY:
402 30 : *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
403 30 : break;
404 : default:
405 66 : if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
406 66 : *pos, resp) < 0)
407 0 : return -1;
408 66 : break;
409 : }
410 :
411 98 : if (*resp == NULL &&
412 4 : (config->pending_req_identity || config->pending_req_password ||
413 0 : config->pending_req_otp)) {
414 2 : return 0;
415 : }
416 :
417 94 : if (*resp == NULL)
418 0 : return -1;
419 :
420 94 : wpa_hexdump_buf(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response",
421 : *resp);
422 94 : return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1);
423 : }
424 :
425 :
426 84 : static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
427 : struct eap_ttls_data *data,
428 : struct eap_method_ret *ret,
429 : struct wpabuf **resp)
430 : {
431 : #ifdef EAP_MSCHAPv2
432 : struct wpabuf *msg;
433 : u8 *buf, *pos, *challenge, *peer_challenge;
434 : const u8 *identity, *password;
435 : size_t identity_len, password_len;
436 : int pwhash;
437 :
438 84 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");
439 :
440 84 : identity = eap_get_config_identity(sm, &identity_len);
441 84 : password = eap_get_config_password2(sm, &password_len, &pwhash);
442 84 : if (identity == NULL || password == NULL)
443 0 : return -1;
444 :
445 84 : msg = wpabuf_alloc(identity_len + 1000);
446 84 : if (msg == NULL) {
447 0 : wpa_printf(MSG_ERROR,
448 : "EAP-TTLS/MSCHAPV2: Failed to allocate memory");
449 0 : return -1;
450 : }
451 84 : pos = buf = wpabuf_mhead(msg);
452 :
453 : /* User-Name */
454 84 : pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
455 : identity, identity_len);
456 :
457 : /* MS-CHAP-Challenge */
458 84 : challenge = eap_ttls_implicit_challenge(
459 : sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
460 84 : if (challenge == NULL) {
461 0 : wpabuf_free(msg);
462 0 : wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
463 : "implicit challenge");
464 0 : return -1;
465 : }
466 :
467 84 : pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
468 : RADIUS_VENDOR_ID_MICROSOFT, 1,
469 : challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
470 :
471 : /* MS-CHAP2-Response */
472 84 : pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE,
473 : RADIUS_VENDOR_ID_MICROSOFT, 1,
474 : EAP_TTLS_MSCHAPV2_RESPONSE_LEN);
475 84 : data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];
476 84 : *pos++ = data->ident;
477 84 : *pos++ = 0; /* Flags */
478 84 : if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) {
479 0 : os_free(challenge);
480 0 : wpabuf_free(msg);
481 0 : wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get "
482 : "random data for peer challenge");
483 0 : return -1;
484 : }
485 84 : peer_challenge = pos;
486 84 : pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
487 84 : os_memset(pos, 0, 8); /* Reserved, must be zero */
488 84 : pos += 8;
489 84 : if (mschapv2_derive_response(identity, identity_len, password,
490 : password_len, pwhash, challenge,
491 84 : peer_challenge, pos, data->auth_response,
492 84 : data->master_key)) {
493 0 : os_free(challenge);
494 0 : wpabuf_free(msg);
495 0 : wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
496 : "response");
497 0 : return -1;
498 : }
499 84 : data->auth_response_valid = 1;
500 :
501 84 : pos += 24;
502 84 : os_free(challenge);
503 84 : AVP_PAD(buf, pos);
504 :
505 84 : wpabuf_put(msg, pos - buf);
506 84 : *resp = msg;
507 :
508 84 : return 0;
509 : #else /* EAP_MSCHAPv2 */
510 : wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build");
511 : return -1;
512 : #endif /* EAP_MSCHAPv2 */
513 : }
514 :
515 :
516 11 : static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
517 : struct eap_ttls_data *data,
518 : struct eap_method_ret *ret,
519 : struct wpabuf **resp)
520 : {
521 : struct wpabuf *msg;
522 : u8 *buf, *pos, *challenge;
523 : const u8 *identity, *password;
524 : size_t identity_len, password_len;
525 : int pwhash;
526 :
527 11 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");
528 :
529 11 : identity = eap_get_config_identity(sm, &identity_len);
530 11 : password = eap_get_config_password2(sm, &password_len, &pwhash);
531 11 : if (identity == NULL || password == NULL)
532 0 : return -1;
533 :
534 11 : msg = wpabuf_alloc(identity_len + 1000);
535 11 : if (msg == NULL) {
536 0 : wpa_printf(MSG_ERROR,
537 : "EAP-TTLS/MSCHAP: Failed to allocate memory");
538 0 : return -1;
539 : }
540 11 : pos = buf = wpabuf_mhead(msg);
541 :
542 : /* User-Name */
543 11 : pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
544 : identity, identity_len);
545 :
546 : /* MS-CHAP-Challenge */
547 11 : challenge = eap_ttls_implicit_challenge(
548 : sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
549 11 : if (challenge == NULL) {
550 0 : wpabuf_free(msg);
551 0 : wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
552 : "implicit challenge");
553 0 : return -1;
554 : }
555 :
556 11 : pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
557 : RADIUS_VENDOR_ID_MICROSOFT, 1,
558 : challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
559 :
560 : /* MS-CHAP-Response */
561 11 : pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE,
562 : RADIUS_VENDOR_ID_MICROSOFT, 1,
563 : EAP_TTLS_MSCHAP_RESPONSE_LEN);
564 11 : data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN];
565 11 : *pos++ = data->ident;
566 11 : *pos++ = 1; /* Flags: Use NT style passwords */
567 11 : os_memset(pos, 0, 24); /* LM-Response */
568 11 : pos += 24;
569 11 : if (pwhash) {
570 0 : challenge_response(challenge, password, pos); /* NT-Response */
571 0 : wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
572 : password, 16);
573 : } else {
574 11 : nt_challenge_response(challenge, password, password_len,
575 : pos); /* NT-Response */
576 11 : wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
577 : password, password_len);
578 : }
579 11 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge",
580 : challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
581 11 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);
582 11 : pos += 24;
583 11 : os_free(challenge);
584 11 : AVP_PAD(buf, pos);
585 :
586 11 : wpabuf_put(msg, pos - buf);
587 11 : *resp = msg;
588 :
589 : /* EAP-TTLS/MSCHAP does not provide tunneled success
590 : * notification, so assume that Phase2 succeeds. */
591 11 : ret->methodState = METHOD_DONE;
592 11 : ret->decision = DECISION_COND_SUCC;
593 :
594 11 : return 0;
595 : }
596 :
597 :
598 22 : static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
599 : struct eap_ttls_data *data,
600 : struct eap_method_ret *ret,
601 : struct wpabuf **resp)
602 : {
603 : struct wpabuf *msg;
604 : u8 *buf, *pos;
605 : size_t pad;
606 : const u8 *identity, *password;
607 : size_t identity_len, password_len;
608 :
609 22 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");
610 :
611 22 : identity = eap_get_config_identity(sm, &identity_len);
612 22 : password = eap_get_config_password(sm, &password_len);
613 22 : if (identity == NULL || password == NULL)
614 0 : return -1;
615 :
616 22 : msg = wpabuf_alloc(identity_len + password_len + 100);
617 22 : if (msg == NULL) {
618 0 : wpa_printf(MSG_ERROR,
619 : "EAP-TTLS/PAP: Failed to allocate memory");
620 0 : return -1;
621 : }
622 22 : pos = buf = wpabuf_mhead(msg);
623 :
624 : /* User-Name */
625 22 : pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
626 : identity, identity_len);
627 :
628 : /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts
629 : * the data, so no separate encryption is used in the AVP itself.
630 : * However, the password is padded to obfuscate its length. */
631 22 : pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15;
632 22 : pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,
633 : password_len + pad);
634 22 : os_memcpy(pos, password, password_len);
635 22 : pos += password_len;
636 22 : os_memset(pos, 0, pad);
637 22 : pos += pad;
638 22 : AVP_PAD(buf, pos);
639 :
640 22 : wpabuf_put(msg, pos - buf);
641 22 : *resp = msg;
642 :
643 : /* EAP-TTLS/PAP does not provide tunneled success notification,
644 : * so assume that Phase2 succeeds. */
645 22 : ret->methodState = METHOD_DONE;
646 22 : ret->decision = DECISION_COND_SUCC;
647 :
648 22 : return 0;
649 : }
650 :
651 :
652 10 : static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
653 : struct eap_ttls_data *data,
654 : struct eap_method_ret *ret,
655 : struct wpabuf **resp)
656 : {
657 : struct wpabuf *msg;
658 : u8 *buf, *pos, *challenge;
659 : const u8 *identity, *password;
660 : size_t identity_len, password_len;
661 :
662 10 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");
663 :
664 10 : identity = eap_get_config_identity(sm, &identity_len);
665 10 : password = eap_get_config_password(sm, &password_len);
666 10 : if (identity == NULL || password == NULL)
667 0 : return -1;
668 :
669 10 : msg = wpabuf_alloc(identity_len + 1000);
670 10 : if (msg == NULL) {
671 0 : wpa_printf(MSG_ERROR,
672 : "EAP-TTLS/CHAP: Failed to allocate memory");
673 0 : return -1;
674 : }
675 10 : pos = buf = wpabuf_mhead(msg);
676 :
677 : /* User-Name */
678 10 : pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
679 : identity, identity_len);
680 :
681 : /* CHAP-Challenge */
682 10 : challenge = eap_ttls_implicit_challenge(
683 : sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
684 10 : if (challenge == NULL) {
685 0 : wpabuf_free(msg);
686 0 : wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
687 : "implicit challenge");
688 0 : return -1;
689 : }
690 :
691 10 : pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1,
692 : challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
693 :
694 : /* CHAP-Password */
695 10 : pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1,
696 : 1 + EAP_TTLS_CHAP_PASSWORD_LEN);
697 10 : data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN];
698 10 : *pos++ = data->ident;
699 :
700 : /* MD5(Ident + Password + Challenge) */
701 10 : chap_md5(data->ident, password, password_len, challenge,
702 : EAP_TTLS_CHAP_CHALLENGE_LEN, pos);
703 :
704 10 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",
705 : identity, identity_len);
706 10 : wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",
707 : password, password_len);
708 10 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",
709 : challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
710 10 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",
711 : pos, EAP_TTLS_CHAP_PASSWORD_LEN);
712 10 : pos += EAP_TTLS_CHAP_PASSWORD_LEN;
713 10 : os_free(challenge);
714 10 : AVP_PAD(buf, pos);
715 :
716 10 : wpabuf_put(msg, pos - buf);
717 10 : *resp = msg;
718 :
719 : /* EAP-TTLS/CHAP does not provide tunneled success
720 : * notification, so assume that Phase2 succeeds. */
721 10 : ret->methodState = METHOD_DONE;
722 10 : ret->decision = DECISION_COND_SUCC;
723 :
724 10 : return 0;
725 : }
726 :
727 :
728 227 : static int eap_ttls_phase2_request(struct eap_sm *sm,
729 : struct eap_ttls_data *data,
730 : struct eap_method_ret *ret,
731 : struct eap_hdr *hdr,
732 : struct wpabuf **resp)
733 : {
734 227 : int res = 0;
735 : size_t len;
736 227 : enum phase2_types phase2_type = data->phase2_type;
737 :
738 : #ifdef EAP_TNC
739 227 : if (data->tnc_started) {
740 23 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC");
741 23 : phase2_type = EAP_TTLS_PHASE2_EAP;
742 : }
743 : #endif /* EAP_TNC */
744 :
745 227 : if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||
746 129 : phase2_type == EAP_TTLS_PHASE2_MSCHAP ||
747 106 : phase2_type == EAP_TTLS_PHASE2_PAP ||
748 : phase2_type == EAP_TTLS_PHASE2_CHAP) {
749 131 : if (eap_get_config_identity(sm, &len) == NULL) {
750 1 : wpa_printf(MSG_INFO,
751 : "EAP-TTLS: Identity not configured");
752 1 : eap_sm_request_identity(sm);
753 1 : if (eap_get_config_password(sm, &len) == NULL)
754 1 : eap_sm_request_password(sm);
755 1 : return 0;
756 : }
757 :
758 130 : if (eap_get_config_password(sm, &len) == NULL) {
759 3 : wpa_printf(MSG_INFO,
760 : "EAP-TTLS: Password not configured");
761 3 : eap_sm_request_password(sm);
762 3 : return 0;
763 : }
764 : }
765 :
766 223 : switch (phase2_type) {
767 : case EAP_TTLS_PHASE2_EAP:
768 96 : res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp);
769 96 : break;
770 : case EAP_TTLS_PHASE2_MSCHAPV2:
771 84 : res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp);
772 84 : break;
773 : case EAP_TTLS_PHASE2_MSCHAP:
774 11 : res = eap_ttls_phase2_request_mschap(sm, data, ret, resp);
775 11 : break;
776 : case EAP_TTLS_PHASE2_PAP:
777 22 : res = eap_ttls_phase2_request_pap(sm, data, ret, resp);
778 22 : break;
779 : case EAP_TTLS_PHASE2_CHAP:
780 10 : res = eap_ttls_phase2_request_chap(sm, data, ret, resp);
781 10 : break;
782 : default:
783 0 : wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown");
784 0 : res = -1;
785 0 : break;
786 : }
787 :
788 223 : if (res < 0) {
789 0 : ret->methodState = METHOD_DONE;
790 0 : ret->decision = DECISION_FAIL;
791 : }
792 :
793 223 : return res;
794 : }
795 :
796 :
797 : struct ttls_parse_avp {
798 : u8 *mschapv2;
799 : u8 *eapdata;
800 : size_t eap_len;
801 : int mschapv2_error;
802 : };
803 :
804 :
805 66 : static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen,
806 : struct ttls_parse_avp *parse)
807 : {
808 66 : wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
809 66 : if (parse->eapdata == NULL) {
810 66 : parse->eapdata = os_malloc(dlen);
811 66 : if (parse->eapdata == NULL) {
812 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
813 : "memory for Phase 2 EAP data");
814 0 : return -1;
815 : }
816 66 : os_memcpy(parse->eapdata, dpos, dlen);
817 66 : parse->eap_len = dlen;
818 : } else {
819 0 : u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen);
820 0 : if (neweap == NULL) {
821 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
822 : "memory for Phase 2 EAP data");
823 0 : return -1;
824 : }
825 0 : os_memcpy(neweap + parse->eap_len, dpos, dlen);
826 0 : parse->eapdata = neweap;
827 0 : parse->eap_len += dlen;
828 : }
829 :
830 66 : return 0;
831 : }
832 :
833 :
834 149 : static int eap_ttls_parse_avp(u8 *pos, size_t left,
835 : struct ttls_parse_avp *parse)
836 : {
837 : struct ttls_avp *avp;
838 149 : u32 avp_code, avp_length, vendor_id = 0;
839 : u8 avp_flags, *dpos;
840 : size_t dlen;
841 :
842 149 : avp = (struct ttls_avp *) pos;
843 149 : avp_code = be_to_host32(avp->avp_code);
844 149 : avp_length = be_to_host32(avp->avp_length);
845 149 : avp_flags = (avp_length >> 24) & 0xff;
846 149 : avp_length &= 0xffffff;
847 149 : wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
848 : "length=%d", (int) avp_code, avp_flags,
849 : (int) avp_length);
850 :
851 149 : if (avp_length > left) {
852 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
853 : "(len=%d, left=%lu) - dropped",
854 : (int) avp_length, (unsigned long) left);
855 0 : return -1;
856 : }
857 :
858 149 : if (avp_length < sizeof(*avp)) {
859 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length %d",
860 : avp_length);
861 0 : return -1;
862 : }
863 :
864 149 : dpos = (u8 *) (avp + 1);
865 149 : dlen = avp_length - sizeof(*avp);
866 149 : if (avp_flags & AVP_FLAGS_VENDOR) {
867 83 : if (dlen < 4) {
868 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Vendor AVP "
869 : "underflow");
870 0 : return -1;
871 : }
872 83 : vendor_id = WPA_GET_BE32(dpos);
873 83 : wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
874 : (int) vendor_id);
875 83 : dpos += 4;
876 83 : dlen -= 4;
877 : }
878 :
879 149 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
880 :
881 149 : if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
882 132 : if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0)
883 0 : return -1;
884 83 : } else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) {
885 : /* This is an optional message that can be displayed to
886 : * the user. */
887 0 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: AVP - Reply-Message",
888 : dpos, dlen);
889 83 : } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
890 : avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) {
891 82 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP2-Success",
892 : dpos, dlen);
893 82 : if (dlen != 43) {
894 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected "
895 : "MS-CHAP2-Success length "
896 : "(len=%lu, expected 43)",
897 : (unsigned long) dlen);
898 0 : return -1;
899 : }
900 82 : parse->mschapv2 = dpos;
901 1 : } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
902 : avp_code == RADIUS_ATTR_MS_CHAP_ERROR) {
903 1 : wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP-Error",
904 : dpos, dlen);
905 1 : parse->mschapv2_error = 1;
906 0 : } else if (avp_flags & AVP_FLAGS_MANDATORY) {
907 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported mandatory AVP "
908 : "code %d vendor_id %d - dropped",
909 : (int) avp_code, (int) vendor_id);
910 0 : return -1;
911 : } else {
912 0 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported AVP "
913 : "code %d vendor_id %d",
914 : (int) avp_code, (int) vendor_id);
915 : }
916 :
917 149 : return avp_length;
918 : }
919 :
920 :
921 149 : static int eap_ttls_parse_avps(struct wpabuf *in_decrypted,
922 : struct ttls_parse_avp *parse)
923 : {
924 : u8 *pos;
925 : size_t left, pad;
926 : int avp_length;
927 :
928 149 : pos = wpabuf_mhead(in_decrypted);
929 149 : left = wpabuf_len(in_decrypted);
930 149 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", pos, left);
931 149 : if (left < sizeof(struct ttls_avp)) {
932 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame"
933 : " len=%lu expected %lu or more - dropped",
934 : (unsigned long) left,
935 : (unsigned long) sizeof(struct ttls_avp));
936 0 : return -1;
937 : }
938 :
939 : /* Parse AVPs */
940 149 : os_memset(parse, 0, sizeof(*parse));
941 :
942 447 : while (left > 0) {
943 149 : avp_length = eap_ttls_parse_avp(pos, left, parse);
944 149 : if (avp_length < 0)
945 0 : return -1;
946 :
947 149 : pad = (4 - (avp_length & 3)) & 3;
948 149 : pos += avp_length + pad;
949 149 : if (left < avp_length + pad)
950 82 : left = 0;
951 : else
952 67 : left -= avp_length + pad;
953 : }
954 :
955 149 : return 0;
956 : }
957 :
958 :
959 161 : static u8 * eap_ttls_fake_identity_request(void)
960 : {
961 : struct eap_hdr *hdr;
962 : u8 *buf;
963 :
964 161 : wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of "
965 : "Phase 2 - use fake EAP-Request Identity");
966 161 : buf = os_malloc(sizeof(*hdr) + 1);
967 161 : if (buf == NULL) {
968 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate "
969 : "memory for fake EAP-Identity Request");
970 0 : return NULL;
971 : }
972 :
973 161 : hdr = (struct eap_hdr *) buf;
974 161 : hdr->code = EAP_CODE_REQUEST;
975 161 : hdr->identifier = 0;
976 161 : hdr->length = host_to_be16(sizeof(*hdr) + 1);
977 161 : buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY;
978 :
979 161 : return buf;
980 : }
981 :
982 :
983 225 : static int eap_ttls_encrypt_response(struct eap_sm *sm,
984 : struct eap_ttls_data *data,
985 : struct wpabuf *resp, u8 identifier,
986 : struct wpabuf **out_data)
987 : {
988 225 : if (resp == NULL)
989 4 : return 0;
990 :
991 221 : wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data",
992 : resp);
993 221 : if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
994 : data->ttls_version, identifier,
995 : resp, out_data)) {
996 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 "
997 : "frame");
998 0 : wpabuf_free(resp);
999 0 : return -1;
1000 : }
1001 221 : wpabuf_free(resp);
1002 :
1003 221 : return 0;
1004 : }
1005 :
1006 :
1007 66 : static int eap_ttls_process_phase2_eap(struct eap_sm *sm,
1008 : struct eap_ttls_data *data,
1009 : struct eap_method_ret *ret,
1010 : struct ttls_parse_avp *parse,
1011 : struct wpabuf **resp)
1012 : {
1013 : struct eap_hdr *hdr;
1014 : size_t len;
1015 :
1016 66 : if (parse->eapdata == NULL) {
1017 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in the "
1018 : "packet - dropped");
1019 0 : return -1;
1020 : }
1021 :
1022 132 : wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP",
1023 66 : parse->eapdata, parse->eap_len);
1024 66 : hdr = (struct eap_hdr *) parse->eapdata;
1025 :
1026 66 : if (parse->eap_len < sizeof(*hdr)) {
1027 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 EAP "
1028 : "frame (len=%lu, expected %lu or more) - dropped",
1029 : (unsigned long) parse->eap_len,
1030 : (unsigned long) sizeof(*hdr));
1031 0 : return -1;
1032 : }
1033 66 : len = be_to_host16(hdr->length);
1034 66 : if (len > parse->eap_len) {
1035 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in Phase 2 "
1036 : "EAP frame (EAP hdr len=%lu, EAP data len in "
1037 : "AVP=%lu)",
1038 : (unsigned long) len,
1039 : (unsigned long) parse->eap_len);
1040 0 : return -1;
1041 : }
1042 132 : wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d "
1043 : "identifier=%d length=%lu",
1044 132 : hdr->code, hdr->identifier, (unsigned long) len);
1045 66 : switch (hdr->code) {
1046 : case EAP_CODE_REQUEST:
1047 66 : if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) {
1048 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
1049 : "processing failed");
1050 0 : return -1;
1051 : }
1052 66 : break;
1053 : default:
1054 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in "
1055 0 : "Phase 2 EAP header", hdr->code);
1056 0 : return -1;
1057 : }
1058 :
1059 66 : return 0;
1060 : }
1061 :
1062 :
1063 85 : static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
1064 : struct eap_ttls_data *data,
1065 : struct eap_method_ret *ret,
1066 : struct ttls_parse_avp *parse)
1067 : {
1068 : #ifdef EAP_MSCHAPv2
1069 85 : if (parse->mschapv2_error) {
1070 1 : wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received "
1071 : "MS-CHAP-Error - failed");
1072 1 : ret->methodState = METHOD_DONE;
1073 1 : ret->decision = DECISION_FAIL;
1074 : /* Reply with empty data to ACK error */
1075 1 : return 1;
1076 : }
1077 :
1078 84 : if (parse->mschapv2 == NULL) {
1079 : #ifdef EAP_TNC
1080 2 : if (data->phase2_success && parse->eapdata) {
1081 : /*
1082 : * Allow EAP-TNC to be started after successfully
1083 : * completed MSCHAPV2.
1084 : */
1085 2 : return 1;
1086 : }
1087 : #endif /* EAP_TNC */
1088 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP "
1089 : "received for Phase2 MSCHAPV2");
1090 0 : return -1;
1091 : }
1092 82 : if (parse->mschapv2[0] != data->ident) {
1093 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch for Phase 2 "
1094 : "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)",
1095 0 : parse->mschapv2[0], data->ident);
1096 0 : return -1;
1097 : }
1098 164 : if (!data->auth_response_valid ||
1099 82 : mschapv2_verify_auth_response(data->auth_response,
1100 82 : parse->mschapv2 + 1, 42)) {
1101 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid authenticator "
1102 : "response in Phase 2 MSCHAPV2 success request");
1103 0 : return -1;
1104 : }
1105 :
1106 82 : wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
1107 : "authentication succeeded");
1108 82 : ret->methodState = METHOD_DONE;
1109 82 : ret->decision = DECISION_UNCOND_SUCC;
1110 82 : data->phase2_success = 1;
1111 :
1112 : /*
1113 : * Reply with empty data; authentication server will reply
1114 : * with EAP-Success after this.
1115 : */
1116 82 : return 1;
1117 : #else /* EAP_MSCHAPv2 */
1118 : wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build");
1119 : return -1;
1120 : #endif /* EAP_MSCHAPv2 */
1121 : }
1122 :
1123 :
1124 : #ifdef EAP_TNC
1125 2 : static int eap_ttls_process_tnc_start(struct eap_sm *sm,
1126 : struct eap_ttls_data *data,
1127 : struct eap_method_ret *ret,
1128 : struct ttls_parse_avp *parse,
1129 : struct wpabuf **resp)
1130 : {
1131 : /* TNC uses inner EAP method after non-EAP TTLS phase 2. */
1132 2 : if (parse->eapdata == NULL) {
1133 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
1134 : "unexpected tunneled data (no EAP)");
1135 0 : return -1;
1136 : }
1137 :
1138 2 : if (!data->ready_for_tnc) {
1139 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
1140 : "EAP after non-EAP, but not ready for TNC");
1141 0 : return -1;
1142 : }
1143 :
1144 2 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
1145 : "non-EAP method");
1146 2 : data->tnc_started = 1;
1147 :
1148 2 : if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0)
1149 0 : return -1;
1150 :
1151 2 : return 0;
1152 : }
1153 : #endif /* EAP_TNC */
1154 :
1155 :
1156 149 : static int eap_ttls_process_decrypted(struct eap_sm *sm,
1157 : struct eap_ttls_data *data,
1158 : struct eap_method_ret *ret,
1159 : u8 identifier,
1160 : struct ttls_parse_avp *parse,
1161 : struct wpabuf *in_decrypted,
1162 : struct wpabuf **out_data)
1163 : {
1164 149 : struct wpabuf *resp = NULL;
1165 149 : struct eap_peer_config *config = eap_get_config(sm);
1166 : int res;
1167 149 : enum phase2_types phase2_type = data->phase2_type;
1168 :
1169 : #ifdef EAP_TNC
1170 149 : if (data->tnc_started)
1171 21 : phase2_type = EAP_TTLS_PHASE2_EAP;
1172 : #endif /* EAP_TNC */
1173 :
1174 149 : switch (phase2_type) {
1175 : case EAP_TTLS_PHASE2_EAP:
1176 64 : if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) <
1177 : 0)
1178 0 : return -1;
1179 64 : break;
1180 : case EAP_TTLS_PHASE2_MSCHAPV2:
1181 85 : res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse);
1182 : #ifdef EAP_TNC
1183 85 : if (res == 1 && parse->eapdata && data->phase2_success) {
1184 : /*
1185 : * TNC may be required as the next
1186 : * authentication method within the tunnel.
1187 : */
1188 2 : ret->methodState = METHOD_MAY_CONT;
1189 2 : data->ready_for_tnc = 1;
1190 2 : if (eap_ttls_process_tnc_start(sm, data, ret, parse,
1191 : &resp) == 0)
1192 2 : break;
1193 : }
1194 : #endif /* EAP_TNC */
1195 83 : return res;
1196 : case EAP_TTLS_PHASE2_MSCHAP:
1197 : case EAP_TTLS_PHASE2_PAP:
1198 : case EAP_TTLS_PHASE2_CHAP:
1199 : #ifdef EAP_TNC
1200 0 : if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) <
1201 : 0)
1202 0 : return -1;
1203 0 : break;
1204 : #else /* EAP_TNC */
1205 : /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled
1206 : * requests to the supplicant */
1207 : wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected "
1208 : "tunneled data");
1209 : return -1;
1210 : #endif /* EAP_TNC */
1211 : }
1212 :
1213 66 : if (resp) {
1214 64 : if (eap_ttls_encrypt_response(sm, data, resp, identifier,
1215 : out_data) < 0)
1216 0 : return -1;
1217 4 : } else if (config->pending_req_identity ||
1218 2 : config->pending_req_password ||
1219 0 : config->pending_req_otp ||
1220 0 : config->pending_req_new_password) {
1221 2 : wpabuf_free(data->pending_phase2_req);
1222 2 : data->pending_phase2_req = wpabuf_dup(in_decrypted);
1223 : }
1224 :
1225 66 : return 0;
1226 : }
1227 :
1228 :
1229 161 : static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
1230 : struct eap_ttls_data *data,
1231 : struct eap_method_ret *ret,
1232 : u8 identifier,
1233 : struct wpabuf **out_data)
1234 : {
1235 161 : int retval = 0;
1236 : struct eap_hdr *hdr;
1237 : struct wpabuf *resp;
1238 :
1239 161 : hdr = (struct eap_hdr *) eap_ttls_fake_identity_request();
1240 161 : if (hdr == NULL) {
1241 0 : ret->methodState = METHOD_DONE;
1242 0 : ret->decision = DECISION_FAIL;
1243 0 : return -1;
1244 : }
1245 :
1246 161 : resp = NULL;
1247 161 : if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) {
1248 0 : wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
1249 : "processing failed");
1250 0 : retval = -1;
1251 : } else {
1252 161 : struct eap_peer_config *config = eap_get_config(sm);
1253 165 : if (resp == NULL &&
1254 7 : (config->pending_req_identity ||
1255 3 : config->pending_req_password ||
1256 0 : config->pending_req_otp ||
1257 0 : config->pending_req_new_password)) {
1258 : /*
1259 : * Use empty buffer to force implicit request
1260 : * processing when EAP request is re-processed after
1261 : * user input.
1262 : */
1263 4 : wpabuf_free(data->pending_phase2_req);
1264 4 : data->pending_phase2_req = wpabuf_alloc(0);
1265 : }
1266 :
1267 161 : retval = eap_ttls_encrypt_response(sm, data, resp, identifier,
1268 : out_data);
1269 : }
1270 :
1271 161 : os_free(hdr);
1272 :
1273 161 : if (retval < 0) {
1274 0 : ret->methodState = METHOD_DONE;
1275 0 : ret->decision = DECISION_FAIL;
1276 : }
1277 :
1278 161 : return retval;
1279 : }
1280 :
1281 :
1282 157 : static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data,
1283 : struct eap_method_ret *ret, u8 identifier,
1284 : struct wpabuf **out_data)
1285 : {
1286 157 : data->phase2_start = 0;
1287 :
1288 : /*
1289 : * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only
1290 : * if TLS part was indeed resuming a previous session. Most
1291 : * Authentication Servers terminate EAP-TTLS before reaching this
1292 : * point, but some do not. Make wpa_supplicant stop phase 2 here, if
1293 : * needed.
1294 : */
1295 169 : if (data->reauth &&
1296 12 : tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
1297 0 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - "
1298 : "skip phase 2");
1299 0 : *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS,
1300 : data->ttls_version);
1301 0 : ret->methodState = METHOD_DONE;
1302 0 : ret->decision = DECISION_UNCOND_SUCC;
1303 0 : data->phase2_success = 1;
1304 0 : return 0;
1305 : }
1306 :
1307 157 : return eap_ttls_implicit_identity_request(sm, data, ret, identifier,
1308 : out_data);
1309 : }
1310 :
1311 :
1312 316 : static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
1313 : struct eap_method_ret *ret, u8 identifier,
1314 : const struct wpabuf *in_data,
1315 : struct wpabuf **out_data)
1316 : {
1317 316 : struct wpabuf *in_decrypted = NULL;
1318 316 : int retval = 0;
1319 : struct ttls_parse_avp parse;
1320 :
1321 316 : os_memset(&parse, 0, sizeof(parse));
1322 :
1323 316 : wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
1324 : " Phase 2",
1325 : in_data ? (unsigned long) wpabuf_len(in_data) : 0);
1326 :
1327 316 : if (data->pending_phase2_req) {
1328 6 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - "
1329 : "skip decryption and use old data");
1330 : /* Clear TLS reassembly state. */
1331 6 : eap_peer_tls_reset_input(&data->ssl);
1332 :
1333 6 : in_decrypted = data->pending_phase2_req;
1334 6 : data->pending_phase2_req = NULL;
1335 6 : if (wpabuf_len(in_decrypted) == 0) {
1336 4 : wpabuf_free(in_decrypted);
1337 4 : return eap_ttls_implicit_identity_request(
1338 : sm, data, ret, identifier, out_data);
1339 : }
1340 2 : goto continue_req;
1341 : }
1342 :
1343 473 : if ((in_data == NULL || wpabuf_len(in_data) == 0) &&
1344 163 : data->phase2_start) {
1345 157 : return eap_ttls_phase2_start(sm, data, ret, identifier,
1346 : out_data);
1347 : }
1348 :
1349 153 : if (in_data == NULL || wpabuf_len(in_data) == 0) {
1350 : /* Received TLS ACK - requesting more fragments */
1351 6 : return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
1352 : data->ttls_version,
1353 : identifier, NULL, out_data);
1354 : }
1355 :
1356 147 : retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
1357 147 : if (retval)
1358 0 : goto done;
1359 :
1360 : continue_req:
1361 149 : data->phase2_start = 0;
1362 :
1363 149 : if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) {
1364 0 : retval = -1;
1365 0 : goto done;
1366 : }
1367 :
1368 149 : retval = eap_ttls_process_decrypted(sm, data, ret, identifier,
1369 : &parse, in_decrypted, out_data);
1370 :
1371 : done:
1372 149 : wpabuf_free(in_decrypted);
1373 149 : os_free(parse.eapdata);
1374 :
1375 149 : if (retval < 0) {
1376 0 : ret->methodState = METHOD_DONE;
1377 0 : ret->decision = DECISION_FAIL;
1378 : }
1379 :
1380 149 : return retval;
1381 : }
1382 :
1383 :
1384 727 : static int eap_ttls_process_handshake(struct eap_sm *sm,
1385 : struct eap_ttls_data *data,
1386 : struct eap_method_ret *ret,
1387 : u8 identifier,
1388 : const u8 *in_data, size_t in_len,
1389 : struct wpabuf **out_data)
1390 : {
1391 : int res;
1392 :
1393 727 : res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
1394 : data->ttls_version, identifier,
1395 : in_data, in_len, out_data);
1396 :
1397 727 : if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
1398 157 : wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
1399 : "Phase 2");
1400 157 : if (data->resuming) {
1401 12 : wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may "
1402 : "skip Phase 2");
1403 12 : ret->decision = DECISION_COND_SUCC;
1404 12 : ret->methodState = METHOD_MAY_CONT;
1405 : }
1406 157 : data->phase2_start = 1;
1407 157 : eap_ttls_v0_derive_key(sm, data);
1408 :
1409 157 : if (*out_data == NULL || wpabuf_len(*out_data) == 0) {
1410 157 : if (eap_ttls_decrypt(sm, data, ret, identifier,
1411 : NULL, out_data)) {
1412 0 : wpa_printf(MSG_WARNING, "EAP-TTLS: "
1413 : "failed to process early "
1414 : "start for Phase 2");
1415 : }
1416 157 : res = 0;
1417 : }
1418 157 : data->resuming = 0;
1419 : }
1420 :
1421 727 : if (res == 2) {
1422 : struct wpabuf msg;
1423 : /*
1424 : * Application data included in the handshake message.
1425 : */
1426 0 : wpabuf_free(data->pending_phase2_req);
1427 0 : data->pending_phase2_req = *out_data;
1428 0 : *out_data = NULL;
1429 0 : wpabuf_set(&msg, in_data, in_len);
1430 0 : res = eap_ttls_decrypt(sm, data, ret, identifier, &msg,
1431 : out_data);
1432 : }
1433 :
1434 727 : return res;
1435 : }
1436 :
1437 :
1438 886 : static void eap_ttls_check_auth_status(struct eap_sm *sm,
1439 : struct eap_ttls_data *data,
1440 : struct eap_method_ret *ret)
1441 : {
1442 886 : if (ret->methodState == METHOD_DONE) {
1443 142 : ret->allowNotifications = FALSE;
1444 196 : if (ret->decision == DECISION_UNCOND_SUCC ||
1445 54 : ret->decision == DECISION_COND_SUCC) {
1446 140 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
1447 : "completed successfully");
1448 140 : data->phase2_success = 1;
1449 : #ifdef EAP_TNC
1450 140 : if (!data->ready_for_tnc && !data->tnc_started) {
1451 : /*
1452 : * TNC may be required as the next
1453 : * authentication method within the tunnel.
1454 : */
1455 140 : ret->methodState = METHOD_MAY_CONT;
1456 140 : data->ready_for_tnc = 1;
1457 : }
1458 : #endif /* EAP_TNC */
1459 : }
1460 1488 : } else if (ret->methodState == METHOD_MAY_CONT &&
1461 1486 : (ret->decision == DECISION_UNCOND_SUCC ||
1462 742 : ret->decision == DECISION_COND_SUCC)) {
1463 10 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
1464 : "completed successfully (MAY_CONT)");
1465 10 : data->phase2_success = 1;
1466 : }
1467 886 : }
1468 :
1469 :
1470 886 : static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
1471 : struct eap_method_ret *ret,
1472 : const struct wpabuf *reqData)
1473 : {
1474 : size_t left;
1475 : int res;
1476 : u8 flags, id;
1477 : struct wpabuf *resp;
1478 : const u8 *pos;
1479 886 : struct eap_ttls_data *data = priv;
1480 :
1481 886 : pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret,
1482 : reqData, &left, &flags);
1483 886 : if (pos == NULL)
1484 0 : return NULL;
1485 886 : id = eap_get_id(reqData);
1486 :
1487 886 : if (flags & EAP_TLS_FLAGS_START) {
1488 180 : wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own "
1489 : "ver=%d)", flags & EAP_TLS_VERSION_MASK,
1490 : data->ttls_version);
1491 :
1492 : /* RFC 5281, Ch. 9.2:
1493 : * "This packet MAY contain additional information in the form
1494 : * of AVPs, which may provide useful hints to the client"
1495 : * For now, ignore any potential extra data.
1496 : */
1497 180 : left = 0;
1498 : }
1499 :
1500 886 : resp = NULL;
1501 1057 : if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1502 330 : !data->resuming) {
1503 : struct wpabuf msg;
1504 159 : wpabuf_set(&msg, pos, left);
1505 159 : res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp);
1506 : } else {
1507 727 : res = eap_ttls_process_handshake(sm, data, ret, id,
1508 : pos, left, &resp);
1509 : }
1510 :
1511 886 : eap_ttls_check_auth_status(sm, data, ret);
1512 :
1513 : /* FIX: what about res == -1? Could just move all error processing into
1514 : * the other functions and get rid of this res==1 case here. */
1515 886 : if (res == 1) {
1516 245 : wpabuf_free(resp);
1517 245 : return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
1518 : data->ttls_version);
1519 : }
1520 641 : return resp;
1521 : }
1522 :
1523 :
1524 35 : static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
1525 : {
1526 35 : struct eap_ttls_data *data = priv;
1527 70 : return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
1528 35 : data->phase2_success;
1529 : }
1530 :
1531 :
1532 18 : static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
1533 : {
1534 18 : struct eap_ttls_data *data = priv;
1535 18 : wpabuf_free(data->pending_phase2_req);
1536 18 : data->pending_phase2_req = NULL;
1537 : #ifdef EAP_TNC
1538 18 : data->ready_for_tnc = 0;
1539 18 : data->tnc_started = 0;
1540 : #endif /* EAP_TNC */
1541 18 : }
1542 :
1543 :
1544 12 : static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
1545 : {
1546 12 : struct eap_ttls_data *data = priv;
1547 12 : eap_ttls_free_key(data);
1548 12 : os_free(data->session_id);
1549 12 : data->session_id = NULL;
1550 12 : if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
1551 0 : os_free(data);
1552 0 : return NULL;
1553 : }
1554 15 : if (data->phase2_priv && data->phase2_method &&
1555 3 : data->phase2_method->init_for_reauth)
1556 0 : data->phase2_method->init_for_reauth(sm, data->phase2_priv);
1557 12 : data->phase2_start = 0;
1558 12 : data->phase2_success = 0;
1559 12 : data->resuming = 1;
1560 12 : data->reauth = 1;
1561 12 : return priv;
1562 : }
1563 :
1564 :
1565 86 : static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf,
1566 : size_t buflen, int verbose)
1567 : {
1568 86 : struct eap_ttls_data *data = priv;
1569 : int len, ret;
1570 :
1571 86 : len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
1572 86 : ret = os_snprintf(buf + len, buflen - len,
1573 : "EAP-TTLSv%d Phase2 method=",
1574 : data->ttls_version);
1575 86 : if (os_snprintf_error(buflen - len, ret))
1576 0 : return len;
1577 86 : len += ret;
1578 86 : switch (data->phase2_type) {
1579 : case EAP_TTLS_PHASE2_EAP:
1580 24 : ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n",
1581 12 : data->phase2_method ?
1582 12 : data->phase2_method->name : "?");
1583 12 : break;
1584 : case EAP_TTLS_PHASE2_MSCHAPV2:
1585 49 : ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n");
1586 49 : break;
1587 : case EAP_TTLS_PHASE2_MSCHAP:
1588 5 : ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n");
1589 5 : break;
1590 : case EAP_TTLS_PHASE2_PAP:
1591 12 : ret = os_snprintf(buf + len, buflen - len, "PAP\n");
1592 12 : break;
1593 : case EAP_TTLS_PHASE2_CHAP:
1594 8 : ret = os_snprintf(buf + len, buflen - len, "CHAP\n");
1595 8 : break;
1596 : default:
1597 0 : ret = 0;
1598 0 : break;
1599 : }
1600 86 : if (os_snprintf_error(buflen - len, ret))
1601 0 : return len;
1602 86 : len += ret;
1603 :
1604 86 : return len;
1605 : }
1606 :
1607 :
1608 886 : static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv)
1609 : {
1610 886 : struct eap_ttls_data *data = priv;
1611 886 : return data->key_data != NULL && data->phase2_success;
1612 : }
1613 :
1614 :
1615 180 : static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
1616 : {
1617 180 : struct eap_ttls_data *data = priv;
1618 : u8 *key;
1619 :
1620 180 : if (data->key_data == NULL || !data->phase2_success)
1621 0 : return NULL;
1622 :
1623 180 : key = os_malloc(EAP_TLS_KEY_LEN);
1624 180 : if (key == NULL)
1625 0 : return NULL;
1626 :
1627 180 : *len = EAP_TLS_KEY_LEN;
1628 180 : os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
1629 :
1630 180 : return key;
1631 : }
1632 :
1633 :
1634 180 : static u8 * eap_ttls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
1635 : {
1636 180 : struct eap_ttls_data *data = priv;
1637 : u8 *id;
1638 :
1639 180 : if (data->session_id == NULL || !data->phase2_success)
1640 0 : return NULL;
1641 :
1642 180 : id = os_malloc(data->id_len);
1643 180 : if (id == NULL)
1644 0 : return NULL;
1645 :
1646 180 : *len = data->id_len;
1647 180 : os_memcpy(id, data->session_id, data->id_len);
1648 :
1649 180 : return id;
1650 : }
1651 :
1652 :
1653 2 : static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
1654 : {
1655 2 : struct eap_ttls_data *data = priv;
1656 : u8 *key;
1657 :
1658 2 : if (data->key_data == NULL)
1659 0 : return NULL;
1660 :
1661 2 : key = os_malloc(EAP_EMSK_LEN);
1662 2 : if (key == NULL)
1663 0 : return NULL;
1664 :
1665 2 : *len = EAP_EMSK_LEN;
1666 2 : os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
1667 :
1668 2 : return key;
1669 : }
1670 :
1671 :
1672 30 : int eap_peer_ttls_register(void)
1673 : {
1674 : struct eap_method *eap;
1675 : int ret;
1676 :
1677 30 : eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
1678 : EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
1679 30 : if (eap == NULL)
1680 0 : return -1;
1681 :
1682 30 : eap->init = eap_ttls_init;
1683 30 : eap->deinit = eap_ttls_deinit;
1684 30 : eap->process = eap_ttls_process;
1685 30 : eap->isKeyAvailable = eap_ttls_isKeyAvailable;
1686 30 : eap->getKey = eap_ttls_getKey;
1687 30 : eap->getSessionId = eap_ttls_get_session_id;
1688 30 : eap->get_status = eap_ttls_get_status;
1689 30 : eap->has_reauth_data = eap_ttls_has_reauth_data;
1690 30 : eap->deinit_for_reauth = eap_ttls_deinit_for_reauth;
1691 30 : eap->init_for_reauth = eap_ttls_init_for_reauth;
1692 30 : eap->get_emsk = eap_ttls_get_emsk;
1693 :
1694 30 : ret = eap_peer_method_register(eap);
1695 30 : if (ret)
1696 0 : eap_peer_method_free(eap);
1697 30 : return ret;
1698 : }
|