139beb93cSSam Leffler /*
239beb93cSSam Leffler * EAP peer method: LEAP
339beb93cSSam Leffler * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler *
5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo * See README for more details.
739beb93cSSam Leffler */
839beb93cSSam Leffler
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler
1139beb93cSSam Leffler #include "common.h"
12e28a4053SRui Paulo #include "crypto/ms_funcs.h"
13e28a4053SRui Paulo #include "crypto/crypto.h"
14f05cddf9SRui Paulo #include "crypto/random.h"
1539beb93cSSam Leffler #include "eap_i.h"
1639beb93cSSam Leffler
1739beb93cSSam Leffler #define LEAP_VERSION 1
1839beb93cSSam Leffler #define LEAP_CHALLENGE_LEN 8
1939beb93cSSam Leffler #define LEAP_RESPONSE_LEN 24
2039beb93cSSam Leffler #define LEAP_KEY_LEN 16
2139beb93cSSam Leffler
2239beb93cSSam Leffler
2339beb93cSSam Leffler struct eap_leap_data {
2439beb93cSSam Leffler enum {
2539beb93cSSam Leffler LEAP_WAIT_CHALLENGE,
2639beb93cSSam Leffler LEAP_WAIT_SUCCESS,
2739beb93cSSam Leffler LEAP_WAIT_RESPONSE,
2839beb93cSSam Leffler LEAP_DONE
2939beb93cSSam Leffler } state;
3039beb93cSSam Leffler
3139beb93cSSam Leffler u8 peer_challenge[LEAP_CHALLENGE_LEN];
3239beb93cSSam Leffler u8 peer_response[LEAP_RESPONSE_LEN];
3339beb93cSSam Leffler
3439beb93cSSam Leffler u8 ap_challenge[LEAP_CHALLENGE_LEN];
3539beb93cSSam Leffler u8 ap_response[LEAP_RESPONSE_LEN];
3639beb93cSSam Leffler };
3739beb93cSSam Leffler
3839beb93cSSam Leffler
eap_leap_init(struct eap_sm * sm)3939beb93cSSam Leffler static void * eap_leap_init(struct eap_sm *sm)
4039beb93cSSam Leffler {
4139beb93cSSam Leffler struct eap_leap_data *data;
4239beb93cSSam Leffler
4339beb93cSSam Leffler data = os_zalloc(sizeof(*data));
4439beb93cSSam Leffler if (data == NULL)
4539beb93cSSam Leffler return NULL;
4639beb93cSSam Leffler data->state = LEAP_WAIT_CHALLENGE;
4739beb93cSSam Leffler
48*c1d255d3SCy Schubert sm->leap_done = false;
4939beb93cSSam Leffler return data;
5039beb93cSSam Leffler }
5139beb93cSSam Leffler
5239beb93cSSam Leffler
eap_leap_deinit(struct eap_sm * sm,void * priv)5339beb93cSSam Leffler static void eap_leap_deinit(struct eap_sm *sm, void *priv)
5439beb93cSSam Leffler {
5539beb93cSSam Leffler os_free(priv);
5639beb93cSSam Leffler }
5739beb93cSSam Leffler
5839beb93cSSam Leffler
eap_leap_process_request(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)5939beb93cSSam Leffler static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv,
6039beb93cSSam Leffler struct eap_method_ret *ret,
6139beb93cSSam Leffler const struct wpabuf *reqData)
6239beb93cSSam Leffler {
6339beb93cSSam Leffler struct eap_leap_data *data = priv;
6439beb93cSSam Leffler struct wpabuf *resp;
6539beb93cSSam Leffler const u8 *pos, *challenge, *identity, *password;
6639beb93cSSam Leffler u8 challenge_len, *rpos;
6739beb93cSSam Leffler size_t identity_len, password_len, len;
6839beb93cSSam Leffler int pwhash;
6939beb93cSSam Leffler
7039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request");
7139beb93cSSam Leffler
7239beb93cSSam Leffler identity = eap_get_config_identity(sm, &identity_len);
7339beb93cSSam Leffler password = eap_get_config_password2(sm, &password_len, &pwhash);
7439beb93cSSam Leffler if (identity == NULL || password == NULL)
7539beb93cSSam Leffler return NULL;
7639beb93cSSam Leffler
7739beb93cSSam Leffler pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len);
7839beb93cSSam Leffler if (pos == NULL || len < 3) {
7939beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame");
80*c1d255d3SCy Schubert ret->ignore = true;
8139beb93cSSam Leffler return NULL;
8239beb93cSSam Leffler }
8339beb93cSSam Leffler
8439beb93cSSam Leffler if (*pos != LEAP_VERSION) {
8539beb93cSSam Leffler wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version "
8639beb93cSSam Leffler "%d", *pos);
87*c1d255d3SCy Schubert ret->ignore = true;
8839beb93cSSam Leffler return NULL;
8939beb93cSSam Leffler }
9039beb93cSSam Leffler pos++;
9139beb93cSSam Leffler
9239beb93cSSam Leffler pos++; /* skip unused byte */
9339beb93cSSam Leffler
9439beb93cSSam Leffler challenge_len = *pos++;
9539beb93cSSam Leffler if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > len - 3) {
9639beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge "
9739beb93cSSam Leffler "(challenge_len=%d reqDataLen=%lu)",
9839beb93cSSam Leffler challenge_len, (unsigned long) wpabuf_len(reqData));
99*c1d255d3SCy Schubert ret->ignore = true;
10039beb93cSSam Leffler return NULL;
10139beb93cSSam Leffler }
10239beb93cSSam Leffler challenge = pos;
10339beb93cSSam Leffler os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN);
10439beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP",
10539beb93cSSam Leffler challenge, LEAP_CHALLENGE_LEN);
10639beb93cSSam Leffler
10739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response");
10839beb93cSSam Leffler
10939beb93cSSam Leffler resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP,
11039beb93cSSam Leffler 3 + LEAP_RESPONSE_LEN + identity_len,
11139beb93cSSam Leffler EAP_CODE_RESPONSE, eap_get_id(reqData));
11239beb93cSSam Leffler if (resp == NULL)
11339beb93cSSam Leffler return NULL;
11439beb93cSSam Leffler wpabuf_put_u8(resp, LEAP_VERSION);
11539beb93cSSam Leffler wpabuf_put_u8(resp, 0); /* unused */
11639beb93cSSam Leffler wpabuf_put_u8(resp, LEAP_RESPONSE_LEN);
11739beb93cSSam Leffler rpos = wpabuf_put(resp, LEAP_RESPONSE_LEN);
11885732ac8SCy Schubert if ((pwhash && challenge_response(challenge, password, rpos)) ||
11985732ac8SCy Schubert (!pwhash &&
12085732ac8SCy Schubert nt_challenge_response(challenge, password, password_len, rpos))) {
12185732ac8SCy Schubert wpa_printf(MSG_DEBUG, "EAP-LEAP: Failed to derive response");
122*c1d255d3SCy Schubert ret->ignore = true;
12385732ac8SCy Schubert wpabuf_free(resp);
12485732ac8SCy Schubert return NULL;
12585732ac8SCy Schubert }
12639beb93cSSam Leffler os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN);
12739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response",
12839beb93cSSam Leffler rpos, LEAP_RESPONSE_LEN);
12939beb93cSSam Leffler wpabuf_put_data(resp, identity, identity_len);
13039beb93cSSam Leffler
13139beb93cSSam Leffler data->state = LEAP_WAIT_SUCCESS;
13239beb93cSSam Leffler
13339beb93cSSam Leffler return resp;
13439beb93cSSam Leffler }
13539beb93cSSam Leffler
13639beb93cSSam Leffler
eap_leap_process_success(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)13739beb93cSSam Leffler static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv,
13839beb93cSSam Leffler struct eap_method_ret *ret,
13939beb93cSSam Leffler const struct wpabuf *reqData)
14039beb93cSSam Leffler {
14139beb93cSSam Leffler struct eap_leap_data *data = priv;
14239beb93cSSam Leffler struct wpabuf *resp;
14339beb93cSSam Leffler u8 *pos;
14439beb93cSSam Leffler const u8 *identity;
14539beb93cSSam Leffler size_t identity_len;
14639beb93cSSam Leffler
14739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success");
14839beb93cSSam Leffler
14939beb93cSSam Leffler identity = eap_get_config_identity(sm, &identity_len);
15039beb93cSSam Leffler if (identity == NULL)
15139beb93cSSam Leffler return NULL;
15239beb93cSSam Leffler
15339beb93cSSam Leffler if (data->state != LEAP_WAIT_SUCCESS) {
15439beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in "
15539beb93cSSam Leffler "unexpected state (%d) - ignored", data->state);
156*c1d255d3SCy Schubert ret->ignore = true;
15739beb93cSSam Leffler return NULL;
15839beb93cSSam Leffler }
15939beb93cSSam Leffler
16039beb93cSSam Leffler resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP,
16139beb93cSSam Leffler 3 + LEAP_CHALLENGE_LEN + identity_len,
16239beb93cSSam Leffler EAP_CODE_REQUEST, eap_get_id(reqData));
16339beb93cSSam Leffler if (resp == NULL)
16439beb93cSSam Leffler return NULL;
16539beb93cSSam Leffler wpabuf_put_u8(resp, LEAP_VERSION);
16639beb93cSSam Leffler wpabuf_put_u8(resp, 0); /* unused */
16739beb93cSSam Leffler wpabuf_put_u8(resp, LEAP_CHALLENGE_LEN);
16839beb93cSSam Leffler pos = wpabuf_put(resp, LEAP_CHALLENGE_LEN);
169f05cddf9SRui Paulo if (random_get_bytes(pos, LEAP_CHALLENGE_LEN)) {
17039beb93cSSam Leffler wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data "
17139beb93cSSam Leffler "for challenge");
17239beb93cSSam Leffler wpabuf_free(resp);
173*c1d255d3SCy Schubert ret->ignore = true;
17439beb93cSSam Leffler return NULL;
17539beb93cSSam Leffler }
17639beb93cSSam Leffler os_memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN);
17739beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge to AP/AS", pos,
17839beb93cSSam Leffler LEAP_CHALLENGE_LEN);
17939beb93cSSam Leffler wpabuf_put_data(resp, identity, identity_len);
18039beb93cSSam Leffler
18139beb93cSSam Leffler data->state = LEAP_WAIT_RESPONSE;
18239beb93cSSam Leffler
18339beb93cSSam Leffler return resp;
18439beb93cSSam Leffler }
18539beb93cSSam Leffler
18639beb93cSSam Leffler
eap_leap_process_response(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)18739beb93cSSam Leffler static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv,
18839beb93cSSam Leffler struct eap_method_ret *ret,
18939beb93cSSam Leffler const struct wpabuf *reqData)
19039beb93cSSam Leffler {
19139beb93cSSam Leffler struct eap_leap_data *data = priv;
19239beb93cSSam Leffler const u8 *pos, *password;
19339beb93cSSam Leffler u8 response_len, pw_hash[16], pw_hash_hash[16],
19439beb93cSSam Leffler expected[LEAP_RESPONSE_LEN];
19539beb93cSSam Leffler size_t password_len, len;
19639beb93cSSam Leffler int pwhash;
19739beb93cSSam Leffler
19839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response");
19939beb93cSSam Leffler
20039beb93cSSam Leffler password = eap_get_config_password2(sm, &password_len, &pwhash);
20139beb93cSSam Leffler if (password == NULL)
20239beb93cSSam Leffler return NULL;
20339beb93cSSam Leffler
20439beb93cSSam Leffler pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len);
20539beb93cSSam Leffler if (pos == NULL || len < 3) {
20639beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame");
207*c1d255d3SCy Schubert ret->ignore = true;
20839beb93cSSam Leffler return NULL;
20939beb93cSSam Leffler }
21039beb93cSSam Leffler
21139beb93cSSam Leffler if (*pos != LEAP_VERSION) {
21239beb93cSSam Leffler wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version "
21339beb93cSSam Leffler "%d", *pos);
214*c1d255d3SCy Schubert ret->ignore = true;
21539beb93cSSam Leffler return NULL;
21639beb93cSSam Leffler }
21739beb93cSSam Leffler pos++;
21839beb93cSSam Leffler
21939beb93cSSam Leffler pos++; /* skip unused byte */
22039beb93cSSam Leffler
22139beb93cSSam Leffler response_len = *pos++;
22239beb93cSSam Leffler if (response_len != LEAP_RESPONSE_LEN || response_len > len - 3) {
22339beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response "
22439beb93cSSam Leffler "(response_len=%d reqDataLen=%lu)",
22539beb93cSSam Leffler response_len, (unsigned long) wpabuf_len(reqData));
226*c1d255d3SCy Schubert ret->ignore = true;
22739beb93cSSam Leffler return NULL;
22839beb93cSSam Leffler }
22939beb93cSSam Leffler
23039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Response from AP",
23139beb93cSSam Leffler pos, LEAP_RESPONSE_LEN);
23239beb93cSSam Leffler os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN);
23339beb93cSSam Leffler
23439beb93cSSam Leffler if (pwhash) {
235e28a4053SRui Paulo if (hash_nt_password_hash(password, pw_hash_hash)) {
236*c1d255d3SCy Schubert ret->ignore = true;
237e28a4053SRui Paulo return NULL;
238e28a4053SRui Paulo }
23939beb93cSSam Leffler } else {
240e28a4053SRui Paulo if (nt_password_hash(password, password_len, pw_hash) ||
241e28a4053SRui Paulo hash_nt_password_hash(pw_hash, pw_hash_hash)) {
242*c1d255d3SCy Schubert ret->ignore = true;
243e28a4053SRui Paulo return NULL;
244e28a4053SRui Paulo }
24539beb93cSSam Leffler }
24685732ac8SCy Schubert if (challenge_response(data->ap_challenge, pw_hash_hash, expected)) {
247*c1d255d3SCy Schubert ret->ignore = true;
24885732ac8SCy Schubert return NULL;
24985732ac8SCy Schubert }
25039beb93cSSam Leffler
25139beb93cSSam Leffler ret->methodState = METHOD_DONE;
252*c1d255d3SCy Schubert ret->allowNotifications = false;
25339beb93cSSam Leffler
2545b9c547cSRui Paulo if (os_memcmp_const(pos, expected, LEAP_RESPONSE_LEN) != 0) {
25539beb93cSSam Leffler wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid "
25639beb93cSSam Leffler "response - authentication failed");
25739beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP",
25839beb93cSSam Leffler expected, LEAP_RESPONSE_LEN);
25939beb93cSSam Leffler ret->decision = DECISION_FAIL;
26039beb93cSSam Leffler return NULL;
26139beb93cSSam Leffler }
26239beb93cSSam Leffler
26339beb93cSSam Leffler ret->decision = DECISION_UNCOND_SUCC;
26439beb93cSSam Leffler
26539beb93cSSam Leffler /* LEAP is somewhat odd method since it sends EAP-Success in the middle
26639beb93cSSam Leffler * of the authentication. Use special variable to transit EAP state
26739beb93cSSam Leffler * machine to SUCCESS state. */
268*c1d255d3SCy Schubert sm->leap_done = true;
26939beb93cSSam Leffler data->state = LEAP_DONE;
27039beb93cSSam Leffler
27139beb93cSSam Leffler /* No more authentication messages expected; AP will send EAPOL-Key
27239beb93cSSam Leffler * frames if encryption is enabled. */
27339beb93cSSam Leffler return NULL;
27439beb93cSSam Leffler }
27539beb93cSSam Leffler
27639beb93cSSam Leffler
eap_leap_process(struct eap_sm * sm,void * priv,struct eap_method_ret * ret,const struct wpabuf * reqData)27739beb93cSSam Leffler static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv,
27839beb93cSSam Leffler struct eap_method_ret *ret,
27939beb93cSSam Leffler const struct wpabuf *reqData)
28039beb93cSSam Leffler {
28139beb93cSSam Leffler const struct eap_hdr *eap;
28239beb93cSSam Leffler size_t password_len;
28339beb93cSSam Leffler const u8 *password;
28439beb93cSSam Leffler
28539beb93cSSam Leffler password = eap_get_config_password(sm, &password_len);
28639beb93cSSam Leffler if (password == NULL) {
28739beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured");
28839beb93cSSam Leffler eap_sm_request_password(sm);
289*c1d255d3SCy Schubert ret->ignore = true;
29039beb93cSSam Leffler return NULL;
29139beb93cSSam Leffler }
29239beb93cSSam Leffler
29339beb93cSSam Leffler /*
29439beb93cSSam Leffler * LEAP needs to be able to handle EAP-Success frame which does not
29539beb93cSSam Leffler * include Type field. Consequently, eap_hdr_validate() cannot be used
29639beb93cSSam Leffler * here. This validation will be done separately for EAP-Request and
29739beb93cSSam Leffler * EAP-Response frames.
29839beb93cSSam Leffler */
29939beb93cSSam Leffler eap = wpabuf_head(reqData);
30039beb93cSSam Leffler if (wpabuf_len(reqData) < sizeof(*eap) ||
30139beb93cSSam Leffler be_to_host16(eap->length) > wpabuf_len(reqData)) {
30239beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame");
303*c1d255d3SCy Schubert ret->ignore = true;
30439beb93cSSam Leffler return NULL;
30539beb93cSSam Leffler }
30639beb93cSSam Leffler
307*c1d255d3SCy Schubert ret->ignore = false;
308*c1d255d3SCy Schubert ret->allowNotifications = true;
30939beb93cSSam Leffler ret->methodState = METHOD_MAY_CONT;
31039beb93cSSam Leffler ret->decision = DECISION_FAIL;
31139beb93cSSam Leffler
312*c1d255d3SCy Schubert sm->leap_done = false;
31339beb93cSSam Leffler
31439beb93cSSam Leffler switch (eap->code) {
31539beb93cSSam Leffler case EAP_CODE_REQUEST:
31639beb93cSSam Leffler return eap_leap_process_request(sm, priv, ret, reqData);
31739beb93cSSam Leffler case EAP_CODE_SUCCESS:
31839beb93cSSam Leffler return eap_leap_process_success(sm, priv, ret, reqData);
31939beb93cSSam Leffler case EAP_CODE_RESPONSE:
32039beb93cSSam Leffler return eap_leap_process_response(sm, priv, ret, reqData);
32139beb93cSSam Leffler default:
32239beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - "
32339beb93cSSam Leffler "ignored", eap->code);
324*c1d255d3SCy Schubert ret->ignore = true;
32539beb93cSSam Leffler return NULL;
32639beb93cSSam Leffler }
32739beb93cSSam Leffler }
32839beb93cSSam Leffler
32939beb93cSSam Leffler
eap_leap_isKeyAvailable(struct eap_sm * sm,void * priv)330*c1d255d3SCy Schubert static bool eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv)
33139beb93cSSam Leffler {
33239beb93cSSam Leffler struct eap_leap_data *data = priv;
33339beb93cSSam Leffler return data->state == LEAP_DONE;
33439beb93cSSam Leffler }
33539beb93cSSam Leffler
33639beb93cSSam Leffler
eap_leap_getKey(struct eap_sm * sm,void * priv,size_t * len)33739beb93cSSam Leffler static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
33839beb93cSSam Leffler {
33939beb93cSSam Leffler struct eap_leap_data *data = priv;
34039beb93cSSam Leffler u8 *key, pw_hash_hash[16], pw_hash[16];
34139beb93cSSam Leffler const u8 *addr[5], *password;
34239beb93cSSam Leffler size_t elen[5], password_len;
34339beb93cSSam Leffler int pwhash;
34439beb93cSSam Leffler
34539beb93cSSam Leffler if (data->state != LEAP_DONE)
34639beb93cSSam Leffler return NULL;
34739beb93cSSam Leffler
34839beb93cSSam Leffler password = eap_get_config_password2(sm, &password_len, &pwhash);
34939beb93cSSam Leffler if (password == NULL)
35039beb93cSSam Leffler return NULL;
35139beb93cSSam Leffler
35239beb93cSSam Leffler key = os_malloc(LEAP_KEY_LEN);
35339beb93cSSam Leffler if (key == NULL)
35439beb93cSSam Leffler return NULL;
35539beb93cSSam Leffler
356e28a4053SRui Paulo if (pwhash) {
357e28a4053SRui Paulo if (hash_nt_password_hash(password, pw_hash_hash)) {
358e28a4053SRui Paulo os_free(key);
359e28a4053SRui Paulo return NULL;
360e28a4053SRui Paulo }
361e28a4053SRui Paulo } else {
362e28a4053SRui Paulo if (nt_password_hash(password, password_len, pw_hash) ||
363e28a4053SRui Paulo hash_nt_password_hash(pw_hash, pw_hash_hash)) {
364e28a4053SRui Paulo os_free(key);
365e28a4053SRui Paulo return NULL;
366e28a4053SRui Paulo }
36739beb93cSSam Leffler }
36839beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash",
36939beb93cSSam Leffler pw_hash_hash, 16);
37039beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge",
37139beb93cSSam Leffler data->peer_challenge, LEAP_CHALLENGE_LEN);
37239beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response",
37339beb93cSSam Leffler data->peer_response, LEAP_RESPONSE_LEN);
37439beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge",
37539beb93cSSam Leffler data->ap_challenge, LEAP_CHALLENGE_LEN);
37639beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response",
37739beb93cSSam Leffler data->ap_response, LEAP_RESPONSE_LEN);
37839beb93cSSam Leffler
37939beb93cSSam Leffler addr[0] = pw_hash_hash;
38039beb93cSSam Leffler elen[0] = 16;
38139beb93cSSam Leffler addr[1] = data->ap_challenge;
38239beb93cSSam Leffler elen[1] = LEAP_CHALLENGE_LEN;
38339beb93cSSam Leffler addr[2] = data->ap_response;
38439beb93cSSam Leffler elen[2] = LEAP_RESPONSE_LEN;
38539beb93cSSam Leffler addr[3] = data->peer_challenge;
38639beb93cSSam Leffler elen[3] = LEAP_CHALLENGE_LEN;
38739beb93cSSam Leffler addr[4] = data->peer_response;
38839beb93cSSam Leffler elen[4] = LEAP_RESPONSE_LEN;
38939beb93cSSam Leffler md5_vector(5, addr, elen, key);
39039beb93cSSam Leffler wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
39139beb93cSSam Leffler *len = LEAP_KEY_LEN;
39239beb93cSSam Leffler
393206b73d0SCy Schubert forced_memzero(pw_hash, sizeof(pw_hash));
394206b73d0SCy Schubert forced_memzero(pw_hash_hash, sizeof(pw_hash_hash));
3955b9c547cSRui Paulo
39639beb93cSSam Leffler return key;
39739beb93cSSam Leffler }
39839beb93cSSam Leffler
39939beb93cSSam Leffler
eap_peer_leap_register(void)40039beb93cSSam Leffler int eap_peer_leap_register(void)
40139beb93cSSam Leffler {
40239beb93cSSam Leffler struct eap_method *eap;
40339beb93cSSam Leffler
40439beb93cSSam Leffler eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
40539beb93cSSam Leffler EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP");
40639beb93cSSam Leffler if (eap == NULL)
40739beb93cSSam Leffler return -1;
40839beb93cSSam Leffler
40939beb93cSSam Leffler eap->init = eap_leap_init;
41039beb93cSSam Leffler eap->deinit = eap_leap_deinit;
41139beb93cSSam Leffler eap->process = eap_leap_process;
41239beb93cSSam Leffler eap->isKeyAvailable = eap_leap_isKeyAvailable;
41339beb93cSSam Leffler eap->getKey = eap_leap_getKey;
41439beb93cSSam Leffler
415780fb4a2SCy Schubert return eap_peer_method_register(eap);
41639beb93cSSam Leffler }
417