1*6d49e1aeSJan Lentfer /* 2*6d49e1aeSJan Lentfer * EAP peer method: LEAP 3*6d49e1aeSJan Lentfer * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 4*6d49e1aeSJan Lentfer * 5*6d49e1aeSJan Lentfer * This program is free software; you can redistribute it and/or modify 6*6d49e1aeSJan Lentfer * it under the terms of the GNU General Public License version 2 as 7*6d49e1aeSJan Lentfer * published by the Free Software Foundation. 8*6d49e1aeSJan Lentfer * 9*6d49e1aeSJan Lentfer * Alternatively, this software may be distributed under the terms of BSD 10*6d49e1aeSJan Lentfer * license. 11*6d49e1aeSJan Lentfer * 12*6d49e1aeSJan Lentfer * See README and COPYING for more details. 13*6d49e1aeSJan Lentfer */ 14*6d49e1aeSJan Lentfer 15*6d49e1aeSJan Lentfer #include "includes.h" 16*6d49e1aeSJan Lentfer 17*6d49e1aeSJan Lentfer #include "common.h" 18*6d49e1aeSJan Lentfer #include "eap_i.h" 19*6d49e1aeSJan Lentfer #include "ms_funcs.h" 20*6d49e1aeSJan Lentfer #include "crypto.h" 21*6d49e1aeSJan Lentfer 22*6d49e1aeSJan Lentfer #define LEAP_VERSION 1 23*6d49e1aeSJan Lentfer #define LEAP_CHALLENGE_LEN 8 24*6d49e1aeSJan Lentfer #define LEAP_RESPONSE_LEN 24 25*6d49e1aeSJan Lentfer #define LEAP_KEY_LEN 16 26*6d49e1aeSJan Lentfer 27*6d49e1aeSJan Lentfer 28*6d49e1aeSJan Lentfer struct eap_leap_data { 29*6d49e1aeSJan Lentfer enum { 30*6d49e1aeSJan Lentfer LEAP_WAIT_CHALLENGE, 31*6d49e1aeSJan Lentfer LEAP_WAIT_SUCCESS, 32*6d49e1aeSJan Lentfer LEAP_WAIT_RESPONSE, 33*6d49e1aeSJan Lentfer LEAP_DONE 34*6d49e1aeSJan Lentfer } state; 35*6d49e1aeSJan Lentfer 36*6d49e1aeSJan Lentfer u8 peer_challenge[LEAP_CHALLENGE_LEN]; 37*6d49e1aeSJan Lentfer u8 peer_response[LEAP_RESPONSE_LEN]; 38*6d49e1aeSJan Lentfer 39*6d49e1aeSJan Lentfer u8 ap_challenge[LEAP_CHALLENGE_LEN]; 40*6d49e1aeSJan Lentfer u8 ap_response[LEAP_RESPONSE_LEN]; 41*6d49e1aeSJan Lentfer }; 42*6d49e1aeSJan Lentfer 43*6d49e1aeSJan Lentfer 44*6d49e1aeSJan Lentfer static void * eap_leap_init(struct eap_sm *sm) 45*6d49e1aeSJan Lentfer { 46*6d49e1aeSJan Lentfer struct eap_leap_data *data; 47*6d49e1aeSJan Lentfer 48*6d49e1aeSJan Lentfer data = os_zalloc(sizeof(*data)); 49*6d49e1aeSJan Lentfer if (data == NULL) 50*6d49e1aeSJan Lentfer return NULL; 51*6d49e1aeSJan Lentfer data->state = LEAP_WAIT_CHALLENGE; 52*6d49e1aeSJan Lentfer 53*6d49e1aeSJan Lentfer sm->leap_done = FALSE; 54*6d49e1aeSJan Lentfer return data; 55*6d49e1aeSJan Lentfer } 56*6d49e1aeSJan Lentfer 57*6d49e1aeSJan Lentfer 58*6d49e1aeSJan Lentfer static void eap_leap_deinit(struct eap_sm *sm, void *priv) 59*6d49e1aeSJan Lentfer { 60*6d49e1aeSJan Lentfer os_free(priv); 61*6d49e1aeSJan Lentfer } 62*6d49e1aeSJan Lentfer 63*6d49e1aeSJan Lentfer 64*6d49e1aeSJan Lentfer static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, 65*6d49e1aeSJan Lentfer struct eap_method_ret *ret, 66*6d49e1aeSJan Lentfer const struct wpabuf *reqData) 67*6d49e1aeSJan Lentfer { 68*6d49e1aeSJan Lentfer struct eap_leap_data *data = priv; 69*6d49e1aeSJan Lentfer struct wpabuf *resp; 70*6d49e1aeSJan Lentfer const u8 *pos, *challenge, *identity, *password; 71*6d49e1aeSJan Lentfer u8 challenge_len, *rpos; 72*6d49e1aeSJan Lentfer size_t identity_len, password_len, len; 73*6d49e1aeSJan Lentfer int pwhash; 74*6d49e1aeSJan Lentfer 75*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); 76*6d49e1aeSJan Lentfer 77*6d49e1aeSJan Lentfer identity = eap_get_config_identity(sm, &identity_len); 78*6d49e1aeSJan Lentfer password = eap_get_config_password2(sm, &password_len, &pwhash); 79*6d49e1aeSJan Lentfer if (identity == NULL || password == NULL) 80*6d49e1aeSJan Lentfer return NULL; 81*6d49e1aeSJan Lentfer 82*6d49e1aeSJan Lentfer pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); 83*6d49e1aeSJan Lentfer if (pos == NULL || len < 3) { 84*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); 85*6d49e1aeSJan Lentfer ret->ignore = TRUE; 86*6d49e1aeSJan Lentfer return NULL; 87*6d49e1aeSJan Lentfer } 88*6d49e1aeSJan Lentfer 89*6d49e1aeSJan Lentfer if (*pos != LEAP_VERSION) { 90*6d49e1aeSJan Lentfer wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " 91*6d49e1aeSJan Lentfer "%d", *pos); 92*6d49e1aeSJan Lentfer ret->ignore = TRUE; 93*6d49e1aeSJan Lentfer return NULL; 94*6d49e1aeSJan Lentfer } 95*6d49e1aeSJan Lentfer pos++; 96*6d49e1aeSJan Lentfer 97*6d49e1aeSJan Lentfer pos++; /* skip unused byte */ 98*6d49e1aeSJan Lentfer 99*6d49e1aeSJan Lentfer challenge_len = *pos++; 100*6d49e1aeSJan Lentfer if (challenge_len != LEAP_CHALLENGE_LEN || challenge_len > len - 3) { 101*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " 102*6d49e1aeSJan Lentfer "(challenge_len=%d reqDataLen=%lu)", 103*6d49e1aeSJan Lentfer challenge_len, (unsigned long) wpabuf_len(reqData)); 104*6d49e1aeSJan Lentfer ret->ignore = TRUE; 105*6d49e1aeSJan Lentfer return NULL; 106*6d49e1aeSJan Lentfer } 107*6d49e1aeSJan Lentfer challenge = pos; 108*6d49e1aeSJan Lentfer os_memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN); 109*6d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP", 110*6d49e1aeSJan Lentfer challenge, LEAP_CHALLENGE_LEN); 111*6d49e1aeSJan Lentfer 112*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response"); 113*6d49e1aeSJan Lentfer 114*6d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, 115*6d49e1aeSJan Lentfer 3 + LEAP_RESPONSE_LEN + identity_len, 116*6d49e1aeSJan Lentfer EAP_CODE_RESPONSE, eap_get_id(reqData)); 117*6d49e1aeSJan Lentfer if (resp == NULL) 118*6d49e1aeSJan Lentfer return NULL; 119*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, LEAP_VERSION); 120*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, 0); /* unused */ 121*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, LEAP_RESPONSE_LEN); 122*6d49e1aeSJan Lentfer rpos = wpabuf_put(resp, LEAP_RESPONSE_LEN); 123*6d49e1aeSJan Lentfer if (pwhash) 124*6d49e1aeSJan Lentfer challenge_response(challenge, password, rpos); 125*6d49e1aeSJan Lentfer else 126*6d49e1aeSJan Lentfer nt_challenge_response(challenge, password, password_len, rpos); 127*6d49e1aeSJan Lentfer os_memcpy(data->peer_response, rpos, LEAP_RESPONSE_LEN); 128*6d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", 129*6d49e1aeSJan Lentfer rpos, LEAP_RESPONSE_LEN); 130*6d49e1aeSJan Lentfer wpabuf_put_data(resp, identity, identity_len); 131*6d49e1aeSJan Lentfer 132*6d49e1aeSJan Lentfer data->state = LEAP_WAIT_SUCCESS; 133*6d49e1aeSJan Lentfer 134*6d49e1aeSJan Lentfer return resp; 135*6d49e1aeSJan Lentfer } 136*6d49e1aeSJan Lentfer 137*6d49e1aeSJan Lentfer 138*6d49e1aeSJan Lentfer static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv, 139*6d49e1aeSJan Lentfer struct eap_method_ret *ret, 140*6d49e1aeSJan Lentfer const struct wpabuf *reqData) 141*6d49e1aeSJan Lentfer { 142*6d49e1aeSJan Lentfer struct eap_leap_data *data = priv; 143*6d49e1aeSJan Lentfer struct wpabuf *resp; 144*6d49e1aeSJan Lentfer u8 *pos; 145*6d49e1aeSJan Lentfer const u8 *identity; 146*6d49e1aeSJan Lentfer size_t identity_len; 147*6d49e1aeSJan Lentfer 148*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success"); 149*6d49e1aeSJan Lentfer 150*6d49e1aeSJan Lentfer identity = eap_get_config_identity(sm, &identity_len); 151*6d49e1aeSJan Lentfer if (identity == NULL) 152*6d49e1aeSJan Lentfer return NULL; 153*6d49e1aeSJan Lentfer 154*6d49e1aeSJan Lentfer if (data->state != LEAP_WAIT_SUCCESS) { 155*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in " 156*6d49e1aeSJan Lentfer "unexpected state (%d) - ignored", data->state); 157*6d49e1aeSJan Lentfer ret->ignore = TRUE; 158*6d49e1aeSJan Lentfer return NULL; 159*6d49e1aeSJan Lentfer } 160*6d49e1aeSJan Lentfer 161*6d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, 162*6d49e1aeSJan Lentfer 3 + LEAP_CHALLENGE_LEN + identity_len, 163*6d49e1aeSJan Lentfer EAP_CODE_REQUEST, eap_get_id(reqData)); 164*6d49e1aeSJan Lentfer if (resp == NULL) 165*6d49e1aeSJan Lentfer return NULL; 166*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, LEAP_VERSION); 167*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, 0); /* unused */ 168*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, LEAP_CHALLENGE_LEN); 169*6d49e1aeSJan Lentfer pos = wpabuf_put(resp, LEAP_CHALLENGE_LEN); 170*6d49e1aeSJan Lentfer if (os_get_random(pos, LEAP_CHALLENGE_LEN)) { 171*6d49e1aeSJan Lentfer wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " 172*6d49e1aeSJan Lentfer "for challenge"); 173*6d49e1aeSJan Lentfer wpabuf_free(resp); 174*6d49e1aeSJan Lentfer ret->ignore = TRUE; 175*6d49e1aeSJan Lentfer return NULL; 176*6d49e1aeSJan Lentfer } 177*6d49e1aeSJan Lentfer os_memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN); 178*6d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge to AP/AS", pos, 179*6d49e1aeSJan Lentfer LEAP_CHALLENGE_LEN); 180*6d49e1aeSJan Lentfer wpabuf_put_data(resp, identity, identity_len); 181*6d49e1aeSJan Lentfer 182*6d49e1aeSJan Lentfer data->state = LEAP_WAIT_RESPONSE; 183*6d49e1aeSJan Lentfer 184*6d49e1aeSJan Lentfer return resp; 185*6d49e1aeSJan Lentfer } 186*6d49e1aeSJan Lentfer 187*6d49e1aeSJan Lentfer 188*6d49e1aeSJan Lentfer static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, 189*6d49e1aeSJan Lentfer struct eap_method_ret *ret, 190*6d49e1aeSJan Lentfer const struct wpabuf *reqData) 191*6d49e1aeSJan Lentfer { 192*6d49e1aeSJan Lentfer struct eap_leap_data *data = priv; 193*6d49e1aeSJan Lentfer const u8 *pos, *password; 194*6d49e1aeSJan Lentfer u8 response_len, pw_hash[16], pw_hash_hash[16], 195*6d49e1aeSJan Lentfer expected[LEAP_RESPONSE_LEN]; 196*6d49e1aeSJan Lentfer size_t password_len, len; 197*6d49e1aeSJan Lentfer int pwhash; 198*6d49e1aeSJan Lentfer 199*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response"); 200*6d49e1aeSJan Lentfer 201*6d49e1aeSJan Lentfer password = eap_get_config_password2(sm, &password_len, &pwhash); 202*6d49e1aeSJan Lentfer if (password == NULL) 203*6d49e1aeSJan Lentfer return NULL; 204*6d49e1aeSJan Lentfer 205*6d49e1aeSJan Lentfer pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); 206*6d49e1aeSJan Lentfer if (pos == NULL || len < 3) { 207*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame"); 208*6d49e1aeSJan Lentfer ret->ignore = TRUE; 209*6d49e1aeSJan Lentfer return NULL; 210*6d49e1aeSJan Lentfer } 211*6d49e1aeSJan Lentfer 212*6d49e1aeSJan Lentfer if (*pos != LEAP_VERSION) { 213*6d49e1aeSJan Lentfer wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " 214*6d49e1aeSJan Lentfer "%d", *pos); 215*6d49e1aeSJan Lentfer ret->ignore = TRUE; 216*6d49e1aeSJan Lentfer return NULL; 217*6d49e1aeSJan Lentfer } 218*6d49e1aeSJan Lentfer pos++; 219*6d49e1aeSJan Lentfer 220*6d49e1aeSJan Lentfer pos++; /* skip unused byte */ 221*6d49e1aeSJan Lentfer 222*6d49e1aeSJan Lentfer response_len = *pos++; 223*6d49e1aeSJan Lentfer if (response_len != LEAP_RESPONSE_LEN || response_len > len - 3) { 224*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response " 225*6d49e1aeSJan Lentfer "(response_len=%d reqDataLen=%lu)", 226*6d49e1aeSJan Lentfer response_len, (unsigned long) wpabuf_len(reqData)); 227*6d49e1aeSJan Lentfer ret->ignore = TRUE; 228*6d49e1aeSJan Lentfer return NULL; 229*6d49e1aeSJan Lentfer } 230*6d49e1aeSJan Lentfer 231*6d49e1aeSJan Lentfer wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Response from AP", 232*6d49e1aeSJan Lentfer pos, LEAP_RESPONSE_LEN); 233*6d49e1aeSJan Lentfer os_memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN); 234*6d49e1aeSJan Lentfer 235*6d49e1aeSJan Lentfer if (pwhash) { 236*6d49e1aeSJan Lentfer hash_nt_password_hash(password, pw_hash_hash); 237*6d49e1aeSJan Lentfer } else { 238*6d49e1aeSJan Lentfer nt_password_hash(password, password_len, pw_hash); 239*6d49e1aeSJan Lentfer hash_nt_password_hash(pw_hash, pw_hash_hash); 240*6d49e1aeSJan Lentfer } 241*6d49e1aeSJan Lentfer challenge_response(data->ap_challenge, pw_hash_hash, expected); 242*6d49e1aeSJan Lentfer 243*6d49e1aeSJan Lentfer ret->methodState = METHOD_DONE; 244*6d49e1aeSJan Lentfer ret->allowNotifications = FALSE; 245*6d49e1aeSJan Lentfer 246*6d49e1aeSJan Lentfer if (os_memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) { 247*6d49e1aeSJan Lentfer wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid " 248*6d49e1aeSJan Lentfer "response - authentication failed"); 249*6d49e1aeSJan Lentfer wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP", 250*6d49e1aeSJan Lentfer expected, LEAP_RESPONSE_LEN); 251*6d49e1aeSJan Lentfer ret->decision = DECISION_FAIL; 252*6d49e1aeSJan Lentfer return NULL; 253*6d49e1aeSJan Lentfer } 254*6d49e1aeSJan Lentfer 255*6d49e1aeSJan Lentfer ret->decision = DECISION_UNCOND_SUCC; 256*6d49e1aeSJan Lentfer 257*6d49e1aeSJan Lentfer /* LEAP is somewhat odd method since it sends EAP-Success in the middle 258*6d49e1aeSJan Lentfer * of the authentication. Use special variable to transit EAP state 259*6d49e1aeSJan Lentfer * machine to SUCCESS state. */ 260*6d49e1aeSJan Lentfer sm->leap_done = TRUE; 261*6d49e1aeSJan Lentfer data->state = LEAP_DONE; 262*6d49e1aeSJan Lentfer 263*6d49e1aeSJan Lentfer /* No more authentication messages expected; AP will send EAPOL-Key 264*6d49e1aeSJan Lentfer * frames if encryption is enabled. */ 265*6d49e1aeSJan Lentfer return NULL; 266*6d49e1aeSJan Lentfer } 267*6d49e1aeSJan Lentfer 268*6d49e1aeSJan Lentfer 269*6d49e1aeSJan Lentfer static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, 270*6d49e1aeSJan Lentfer struct eap_method_ret *ret, 271*6d49e1aeSJan Lentfer const struct wpabuf *reqData) 272*6d49e1aeSJan Lentfer { 273*6d49e1aeSJan Lentfer const struct eap_hdr *eap; 274*6d49e1aeSJan Lentfer size_t password_len; 275*6d49e1aeSJan Lentfer const u8 *password; 276*6d49e1aeSJan Lentfer 277*6d49e1aeSJan Lentfer password = eap_get_config_password(sm, &password_len); 278*6d49e1aeSJan Lentfer if (password == NULL) { 279*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured"); 280*6d49e1aeSJan Lentfer eap_sm_request_password(sm); 281*6d49e1aeSJan Lentfer ret->ignore = TRUE; 282*6d49e1aeSJan Lentfer return NULL; 283*6d49e1aeSJan Lentfer } 284*6d49e1aeSJan Lentfer 285*6d49e1aeSJan Lentfer /* 286*6d49e1aeSJan Lentfer * LEAP needs to be able to handle EAP-Success frame which does not 287*6d49e1aeSJan Lentfer * include Type field. Consequently, eap_hdr_validate() cannot be used 288*6d49e1aeSJan Lentfer * here. This validation will be done separately for EAP-Request and 289*6d49e1aeSJan Lentfer * EAP-Response frames. 290*6d49e1aeSJan Lentfer */ 291*6d49e1aeSJan Lentfer eap = wpabuf_head(reqData); 292*6d49e1aeSJan Lentfer if (wpabuf_len(reqData) < sizeof(*eap) || 293*6d49e1aeSJan Lentfer be_to_host16(eap->length) > wpabuf_len(reqData)) { 294*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame"); 295*6d49e1aeSJan Lentfer ret->ignore = TRUE; 296*6d49e1aeSJan Lentfer return NULL; 297*6d49e1aeSJan Lentfer } 298*6d49e1aeSJan Lentfer 299*6d49e1aeSJan Lentfer ret->ignore = FALSE; 300*6d49e1aeSJan Lentfer ret->allowNotifications = TRUE; 301*6d49e1aeSJan Lentfer ret->methodState = METHOD_MAY_CONT; 302*6d49e1aeSJan Lentfer ret->decision = DECISION_FAIL; 303*6d49e1aeSJan Lentfer 304*6d49e1aeSJan Lentfer sm->leap_done = FALSE; 305*6d49e1aeSJan Lentfer 306*6d49e1aeSJan Lentfer switch (eap->code) { 307*6d49e1aeSJan Lentfer case EAP_CODE_REQUEST: 308*6d49e1aeSJan Lentfer return eap_leap_process_request(sm, priv, ret, reqData); 309*6d49e1aeSJan Lentfer case EAP_CODE_SUCCESS: 310*6d49e1aeSJan Lentfer return eap_leap_process_success(sm, priv, ret, reqData); 311*6d49e1aeSJan Lentfer case EAP_CODE_RESPONSE: 312*6d49e1aeSJan Lentfer return eap_leap_process_response(sm, priv, ret, reqData); 313*6d49e1aeSJan Lentfer default: 314*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - " 315*6d49e1aeSJan Lentfer "ignored", eap->code); 316*6d49e1aeSJan Lentfer ret->ignore = TRUE; 317*6d49e1aeSJan Lentfer return NULL; 318*6d49e1aeSJan Lentfer } 319*6d49e1aeSJan Lentfer } 320*6d49e1aeSJan Lentfer 321*6d49e1aeSJan Lentfer 322*6d49e1aeSJan Lentfer static Boolean eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) 323*6d49e1aeSJan Lentfer { 324*6d49e1aeSJan Lentfer struct eap_leap_data *data = priv; 325*6d49e1aeSJan Lentfer return data->state == LEAP_DONE; 326*6d49e1aeSJan Lentfer } 327*6d49e1aeSJan Lentfer 328*6d49e1aeSJan Lentfer 329*6d49e1aeSJan Lentfer static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len) 330*6d49e1aeSJan Lentfer { 331*6d49e1aeSJan Lentfer struct eap_leap_data *data = priv; 332*6d49e1aeSJan Lentfer u8 *key, pw_hash_hash[16], pw_hash[16]; 333*6d49e1aeSJan Lentfer const u8 *addr[5], *password; 334*6d49e1aeSJan Lentfer size_t elen[5], password_len; 335*6d49e1aeSJan Lentfer int pwhash; 336*6d49e1aeSJan Lentfer 337*6d49e1aeSJan Lentfer if (data->state != LEAP_DONE) 338*6d49e1aeSJan Lentfer return NULL; 339*6d49e1aeSJan Lentfer 340*6d49e1aeSJan Lentfer password = eap_get_config_password2(sm, &password_len, &pwhash); 341*6d49e1aeSJan Lentfer if (password == NULL) 342*6d49e1aeSJan Lentfer return NULL; 343*6d49e1aeSJan Lentfer 344*6d49e1aeSJan Lentfer key = os_malloc(LEAP_KEY_LEN); 345*6d49e1aeSJan Lentfer if (key == NULL) 346*6d49e1aeSJan Lentfer return NULL; 347*6d49e1aeSJan Lentfer 348*6d49e1aeSJan Lentfer if (pwhash) 349*6d49e1aeSJan Lentfer hash_nt_password_hash(password, pw_hash_hash); 350*6d49e1aeSJan Lentfer else { 351*6d49e1aeSJan Lentfer nt_password_hash(password, password_len, pw_hash); 352*6d49e1aeSJan Lentfer hash_nt_password_hash(pw_hash, pw_hash_hash); 353*6d49e1aeSJan Lentfer } 354*6d49e1aeSJan Lentfer wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash", 355*6d49e1aeSJan Lentfer pw_hash_hash, 16); 356*6d49e1aeSJan Lentfer wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge", 357*6d49e1aeSJan Lentfer data->peer_challenge, LEAP_CHALLENGE_LEN); 358*6d49e1aeSJan Lentfer wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response", 359*6d49e1aeSJan Lentfer data->peer_response, LEAP_RESPONSE_LEN); 360*6d49e1aeSJan Lentfer wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge", 361*6d49e1aeSJan Lentfer data->ap_challenge, LEAP_CHALLENGE_LEN); 362*6d49e1aeSJan Lentfer wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response", 363*6d49e1aeSJan Lentfer data->ap_response, LEAP_RESPONSE_LEN); 364*6d49e1aeSJan Lentfer 365*6d49e1aeSJan Lentfer addr[0] = pw_hash_hash; 366*6d49e1aeSJan Lentfer elen[0] = 16; 367*6d49e1aeSJan Lentfer addr[1] = data->ap_challenge; 368*6d49e1aeSJan Lentfer elen[1] = LEAP_CHALLENGE_LEN; 369*6d49e1aeSJan Lentfer addr[2] = data->ap_response; 370*6d49e1aeSJan Lentfer elen[2] = LEAP_RESPONSE_LEN; 371*6d49e1aeSJan Lentfer addr[3] = data->peer_challenge; 372*6d49e1aeSJan Lentfer elen[3] = LEAP_CHALLENGE_LEN; 373*6d49e1aeSJan Lentfer addr[4] = data->peer_response; 374*6d49e1aeSJan Lentfer elen[4] = LEAP_RESPONSE_LEN; 375*6d49e1aeSJan Lentfer md5_vector(5, addr, elen, key); 376*6d49e1aeSJan Lentfer wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN); 377*6d49e1aeSJan Lentfer *len = LEAP_KEY_LEN; 378*6d49e1aeSJan Lentfer 379*6d49e1aeSJan Lentfer return key; 380*6d49e1aeSJan Lentfer } 381*6d49e1aeSJan Lentfer 382*6d49e1aeSJan Lentfer 383*6d49e1aeSJan Lentfer int eap_peer_leap_register(void) 384*6d49e1aeSJan Lentfer { 385*6d49e1aeSJan Lentfer struct eap_method *eap; 386*6d49e1aeSJan Lentfer int ret; 387*6d49e1aeSJan Lentfer 388*6d49e1aeSJan Lentfer eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 389*6d49e1aeSJan Lentfer EAP_VENDOR_IETF, EAP_TYPE_LEAP, "LEAP"); 390*6d49e1aeSJan Lentfer if (eap == NULL) 391*6d49e1aeSJan Lentfer return -1; 392*6d49e1aeSJan Lentfer 393*6d49e1aeSJan Lentfer eap->init = eap_leap_init; 394*6d49e1aeSJan Lentfer eap->deinit = eap_leap_deinit; 395*6d49e1aeSJan Lentfer eap->process = eap_leap_process; 396*6d49e1aeSJan Lentfer eap->isKeyAvailable = eap_leap_isKeyAvailable; 397*6d49e1aeSJan Lentfer eap->getKey = eap_leap_getKey; 398*6d49e1aeSJan Lentfer 399*6d49e1aeSJan Lentfer ret = eap_peer_method_register(eap); 400*6d49e1aeSJan Lentfer if (ret) 401*6d49e1aeSJan Lentfer eap_peer_method_free(eap); 402*6d49e1aeSJan Lentfer return ret; 403*6d49e1aeSJan Lentfer } 404