LCOV - code coverage report
Current view: top level - src/eap_server - eap_server_mschapv2.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1426431149 Lines: 223 277 80.5 %
Date: 2015-03-15 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / EAP-MSCHAPv2 (draft-kamath-pppext-eap-mschapv2-00.txt) server
       3             :  * Copyright (c) 2004-2007, 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/random.h"
      14             : #include "eap_i.h"
      15             : 
      16             : 
      17             : struct eap_mschapv2_hdr {
      18             :         u8 op_code; /* MSCHAPV2_OP_* */
      19             :         u8 mschapv2_id; /* must be changed for challenges, but not for
      20             :                          * success/failure */
      21             :         u8 ms_length[2]; /* Note: misaligned; length - 5 */
      22             :         /* followed by data */
      23             : } STRUCT_PACKED;
      24             : 
      25             : #define MSCHAPV2_OP_CHALLENGE 1
      26             : #define MSCHAPV2_OP_RESPONSE 2
      27             : #define MSCHAPV2_OP_SUCCESS 3
      28             : #define MSCHAPV2_OP_FAILURE 4
      29             : #define MSCHAPV2_OP_CHANGE_PASSWORD 7
      30             : 
      31             : #define MSCHAPV2_RESP_LEN 49
      32             : 
      33             : #define ERROR_RESTRICTED_LOGON_HOURS 646
      34             : #define ERROR_ACCT_DISABLED 647
      35             : #define ERROR_PASSWD_EXPIRED 648
      36             : #define ERROR_NO_DIALIN_PERMISSION 649
      37             : #define ERROR_AUTHENTICATION_FAILURE 691
      38             : #define ERROR_CHANGING_PASSWORD 709
      39             : 
      40             : #define PASSWD_CHANGE_CHAL_LEN 16
      41             : #define MSCHAPV2_KEY_LEN 16
      42             : 
      43             : 
      44             : #define CHALLENGE_LEN 16
      45             : 
      46             : struct eap_mschapv2_data {
      47             :         u8 auth_challenge[CHALLENGE_LEN];
      48             :         int auth_challenge_from_tls;
      49             :         u8 *peer_challenge;
      50             :         u8 auth_response[20];
      51             :         enum { CHALLENGE, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE } state;
      52             :         u8 resp_mschapv2_id;
      53             :         u8 master_key[16];
      54             :         int master_key_valid;
      55             : };
      56             : 
      57             : 
      58          77 : static void * eap_mschapv2_init(struct eap_sm *sm)
      59             : {
      60             :         struct eap_mschapv2_data *data;
      61             : 
      62          77 :         data = os_zalloc(sizeof(*data));
      63          77 :         if (data == NULL)
      64           1 :                 return NULL;
      65          76 :         data->state = CHALLENGE;
      66             : 
      67          76 :         if (sm->auth_challenge) {
      68           4 :                 os_memcpy(data->auth_challenge, sm->auth_challenge,
      69             :                           CHALLENGE_LEN);
      70           4 :                 data->auth_challenge_from_tls = 1;
      71             :         }
      72             : 
      73          76 :         if (sm->peer_challenge) {
      74           4 :                 data->peer_challenge = os_malloc(CHALLENGE_LEN);
      75           4 :                 if (data->peer_challenge == NULL) {
      76           0 :                         os_free(data);
      77           0 :                         return NULL;
      78             :                 }
      79           4 :                 os_memcpy(data->peer_challenge, sm->peer_challenge,
      80             :                           CHALLENGE_LEN);
      81             :         }
      82             : 
      83          76 :         return data;
      84             : }
      85             : 
      86             : 
      87          76 : static void eap_mschapv2_reset(struct eap_sm *sm, void *priv)
      88             : {
      89          76 :         struct eap_mschapv2_data *data = priv;
      90          76 :         if (data == NULL)
      91          76 :                 return;
      92             : 
      93          76 :         os_free(data->peer_challenge);
      94          76 :         bin_clear_free(data, sizeof(*data));
      95             : }
      96             : 
      97             : 
      98          76 : static struct wpabuf * eap_mschapv2_build_challenge(
      99             :         struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
     100             : {
     101             :         struct wpabuf *req;
     102             :         struct eap_mschapv2_hdr *ms;
     103             :         size_t ms_len;
     104             : 
     105         148 :         if (!data->auth_challenge_from_tls &&
     106          72 :             random_get_bytes(data->auth_challenge, CHALLENGE_LEN)) {
     107           0 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to get random "
     108             :                            "data");
     109           0 :                 data->state = FAILURE;
     110           0 :                 return NULL;
     111             :         }
     112             : 
     113          76 :         ms_len = sizeof(*ms) + 1 + CHALLENGE_LEN + sm->server_id_len;
     114          76 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     115             :                             EAP_CODE_REQUEST, id);
     116          76 :         if (req == NULL) {
     117           1 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     118             :                            " for request");
     119           1 :                 data->state = FAILURE;
     120           1 :                 return NULL;
     121             :         }
     122             : 
     123          75 :         ms = wpabuf_put(req, sizeof(*ms));
     124          75 :         ms->op_code = MSCHAPV2_OP_CHALLENGE;
     125          75 :         ms->mschapv2_id = id;
     126          75 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     127             : 
     128          75 :         wpabuf_put_u8(req, CHALLENGE_LEN);
     129          75 :         if (!data->auth_challenge_from_tls)
     130          71 :                 wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN);
     131             :         else
     132           4 :                 wpabuf_put(req, CHALLENGE_LEN);
     133          75 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge",
     134          75 :                     data->auth_challenge, CHALLENGE_LEN);
     135          75 :         wpabuf_put_data(req, sm->server_id, sm->server_id_len);
     136             : 
     137          75 :         return req;
     138             : }
     139             : 
     140             : 
     141          49 : static struct wpabuf * eap_mschapv2_build_success_req(
     142             :         struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
     143             : {
     144             :         struct wpabuf *req;
     145             :         struct eap_mschapv2_hdr *ms;
     146             :         u8 *msg;
     147          49 :         char *message = "OK";
     148             :         size_t ms_len;
     149             : 
     150          49 :         ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 +
     151          49 :                 os_strlen(message);
     152          49 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     153             :                             EAP_CODE_REQUEST, id);
     154          49 :         if (req == NULL) {
     155           1 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     156             :                            " for request");
     157           1 :                 data->state = FAILURE;
     158           1 :                 return NULL;
     159             :         }
     160             : 
     161          48 :         ms = wpabuf_put(req, sizeof(*ms));
     162          48 :         ms->op_code = MSCHAPV2_OP_SUCCESS;
     163          48 :         ms->mschapv2_id = data->resp_mschapv2_id;
     164          48 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     165          48 :         msg = (u8 *) (ms + 1);
     166             : 
     167          48 :         wpabuf_put_u8(req, 'S');
     168          48 :         wpabuf_put_u8(req, '=');
     169          48 :         wpa_snprintf_hex_uppercase(
     170          48 :                 wpabuf_put(req, sizeof(data->auth_response) * 2),
     171             :                 sizeof(data->auth_response) * 2 + 1,
     172          48 :                 data->auth_response, sizeof(data->auth_response));
     173          48 :         wpabuf_put_u8(req, ' ');
     174          48 :         wpabuf_put_u8(req, 'M');
     175          48 :         wpabuf_put_u8(req, '=');
     176          48 :         wpabuf_put_data(req, message, os_strlen(message));
     177             : 
     178          48 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message",
     179             :                           msg, ms_len - sizeof(*ms));
     180             : 
     181          48 :         return req;
     182             : }
     183             : 
     184             : 
     185           4 : static struct wpabuf * eap_mschapv2_build_failure_req(
     186             :         struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id)
     187             : {
     188             :         struct wpabuf *req;
     189             :         struct eap_mschapv2_hdr *ms;
     190           4 :         char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 "
     191             :                 "M=FAILED";
     192             :         size_t ms_len;
     193             : 
     194           4 :         ms_len = sizeof(*ms) + os_strlen(message);
     195           4 :         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     196             :                             EAP_CODE_REQUEST, id);
     197           4 :         if (req == NULL) {
     198           1 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory"
     199             :                            " for request");
     200           1 :                 data->state = FAILURE;
     201           1 :                 return NULL;
     202             :         }
     203             : 
     204           3 :         ms = wpabuf_put(req, sizeof(*ms));
     205           3 :         ms->op_code = MSCHAPV2_OP_FAILURE;
     206           3 :         ms->mschapv2_id = data->resp_mschapv2_id;
     207           3 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     208             : 
     209           3 :         wpabuf_put_data(req, message, os_strlen(message));
     210             : 
     211           3 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message",
     212             :                           (u8 *) message, os_strlen(message));
     213             : 
     214           3 :         return req;
     215             : }
     216             : 
     217             : 
     218         129 : static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv,
     219             :                                              u8 id)
     220             : {
     221         129 :         struct eap_mschapv2_data *data = priv;
     222             : 
     223         129 :         switch (data->state) {
     224             :         case CHALLENGE:
     225          76 :                 return eap_mschapv2_build_challenge(sm, data, id);
     226             :         case SUCCESS_REQ:
     227          49 :                 return eap_mschapv2_build_success_req(sm, data, id);
     228             :         case FAILURE_REQ:
     229           4 :                 return eap_mschapv2_build_failure_req(sm, data, id);
     230             :         default:
     231           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in "
     232           0 :                            "buildReq", data->state);
     233           0 :                 break;
     234             :         }
     235           0 :         return NULL;
     236             : }
     237             : 
     238             : 
     239         105 : static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv,
     240             :                                   struct wpabuf *respData)
     241             : {
     242         105 :         struct eap_mschapv2_data *data = priv;
     243             :         struct eap_mschapv2_hdr *resp;
     244             :         const u8 *pos;
     245             :         size_t len;
     246             : 
     247         105 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     248             :                                &len);
     249         105 :         if (pos == NULL || len < 1) {
     250           0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame");
     251           0 :                 return TRUE;
     252             :         }
     253             : 
     254         105 :         resp = (struct eap_mschapv2_hdr *) pos;
     255         159 :         if (data->state == CHALLENGE &&
     256          54 :             resp->op_code != MSCHAPV2_OP_RESPONSE) {
     257           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Response - "
     258           0 :                            "ignore op %d", resp->op_code);
     259           0 :                 return TRUE;
     260             :         }
     261             : 
     262         153 :         if (data->state == SUCCESS_REQ &&
     263          48 :             resp->op_code != MSCHAPV2_OP_SUCCESS &&
     264           0 :             resp->op_code != MSCHAPV2_OP_FAILURE) {
     265           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Success or "
     266           0 :                            "Failure - ignore op %d", resp->op_code);
     267           0 :                 return TRUE;
     268             :         }
     269             : 
     270         108 :         if (data->state == FAILURE_REQ &&
     271           3 :             resp->op_code != MSCHAPV2_OP_FAILURE) {
     272           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Failure "
     273           0 :                            "- ignore op %d", resp->op_code);
     274           0 :                 return TRUE;
     275             :         }
     276             : 
     277         105 :         return FALSE;
     278             : }
     279             : 
     280             : 
     281          53 : static void eap_mschapv2_process_response(struct eap_sm *sm,
     282             :                                           struct eap_mschapv2_data *data,
     283             :                                           struct wpabuf *respData)
     284             : {
     285             :         struct eap_mschapv2_hdr *resp;
     286             :         const u8 *pos, *end, *peer_challenge, *nt_response, *name;
     287             :         u8 flags;
     288             :         size_t len, name_len, i;
     289             :         u8 expected[24];
     290             :         const u8 *username, *user;
     291             :         size_t username_len, user_len;
     292             :         int res;
     293             :         char *buf;
     294             : 
     295          53 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     296             :                                &len);
     297          53 :         if (pos == NULL || len < 1)
     298           0 :                 return; /* Should not happen - frame already validated */
     299             : 
     300          53 :         end = pos + len;
     301          53 :         resp = (struct eap_mschapv2_hdr *) pos;
     302          53 :         pos = (u8 *) (resp + 1);
     303             : 
     304         106 :         if (len < sizeof(*resp) + 1 + 49 ||
     305         106 :             resp->op_code != MSCHAPV2_OP_RESPONSE ||
     306          53 :             pos[0] != 49) {
     307           0 :                 wpa_hexdump_buf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid response",
     308             :                                 respData);
     309           0 :                 data->state = FAILURE;
     310           0 :                 return;
     311             :         }
     312          53 :         data->resp_mschapv2_id = resp->mschapv2_id;
     313          53 :         pos++;
     314          53 :         peer_challenge = pos;
     315          53 :         pos += 16 + 8;
     316          53 :         nt_response = pos;
     317          53 :         pos += 24;
     318          53 :         flags = *pos++;
     319          53 :         name = pos;
     320          53 :         name_len = end - name;
     321             : 
     322          53 :         if (data->peer_challenge) {
     323           4 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using pre-configured "
     324             :                            "Peer-Challenge");
     325           4 :                 peer_challenge = data->peer_challenge;
     326             :         }
     327          53 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Peer-Challenge",
     328             :                     peer_challenge, 16);
     329          53 :         wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: NT-Response", nt_response, 24);
     330          53 :         wpa_printf(MSG_MSGDUMP, "EAP-MSCHAPV2: Flags 0x%x", flags);
     331          53 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Name", name, name_len);
     332             : 
     333          53 :         buf = os_malloc(name_len * 4 + 1);
     334          53 :         if (buf) {
     335          53 :                 printf_encode(buf, name_len * 4 + 1, name, name_len);
     336          53 :                 eap_log_msg(sm, "EAP-MSCHAPV2 Name '%s'", buf);
     337          53 :                 os_free(buf);
     338             :         }
     339             : 
     340             :         /* MSCHAPv2 does not include optional domain name in the
     341             :          * challenge-response calculation, so remove domain prefix
     342             :          * (if present). */
     343          53 :         username = sm->identity;
     344          53 :         username_len = sm->identity_len;
     345         265 :         for (i = 0; i < username_len; i++) {
     346         212 :                 if (username[i] == '\\') {
     347           0 :                         username_len -= i + 1;
     348           0 :                         username += i + 1;
     349           0 :                         break;
     350             :                 }
     351             :         }
     352             : 
     353          53 :         user = name;
     354          53 :         user_len = name_len;
     355         265 :         for (i = 0; i < user_len; i++) {
     356         212 :                 if (user[i] == '\\') {
     357           0 :                         user_len -= i + 1;
     358           0 :                         user += i + 1;
     359           0 :                         break;
     360             :                 }
     361             :         }
     362             : 
     363         106 :         if (username_len != user_len ||
     364          53 :             os_memcmp(username, user, username_len) != 0) {
     365           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Mismatch in user names");
     366           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Expected user "
     367             :                                   "name", username, username_len);
     368           0 :                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Received user "
     369             :                                   "name", user, user_len);
     370           0 :                 data->state = FAILURE;
     371           0 :                 return;
     372             :         }
     373             : 
     374          53 :         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: User name",
     375             :                           username, username_len);
     376             : 
     377          53 :         if (sm->user->password_hash) {
     378           0 :                 res = generate_nt_response_pwhash(data->auth_challenge,
     379             :                                                   peer_challenge,
     380             :                                                   username, username_len,
     381           0 :                                                   sm->user->password,
     382             :                                                   expected);
     383             :         } else {
     384         106 :                 res = generate_nt_response(data->auth_challenge,
     385             :                                            peer_challenge,
     386             :                                            username, username_len,
     387          53 :                                            sm->user->password,
     388          53 :                                            sm->user->password_len,
     389             :                                            expected);
     390             :         }
     391          53 :         if (res) {
     392           0 :                 data->state = FAILURE;
     393           0 :                 return;
     394             :         }
     395             : 
     396          53 :         if (os_memcmp_const(nt_response, expected, 24) == 0) {
     397             :                 const u8 *pw_hash;
     398             :                 u8 pw_hash_buf[16], pw_hash_hash[16];
     399             : 
     400          49 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Correct NT-Response");
     401          49 :                 data->state = SUCCESS_REQ;
     402             : 
     403             :                 /* Authenticator response is not really needed yet, but
     404             :                  * calculate it here so that peer_challenge and username need
     405             :                  * not be saved. */
     406          49 :                 if (sm->user->password_hash) {
     407           0 :                         pw_hash = sm->user->password;
     408             :                 } else {
     409          49 :                         if (nt_password_hash(sm->user->password,
     410          49 :                                              sm->user->password_len,
     411             :                                              pw_hash_buf) < 0) {
     412           0 :                                 data->state = FAILURE;
     413           0 :                                 return;
     414             :                         }
     415          49 :                         pw_hash = pw_hash_buf;
     416             :                 }
     417          49 :                 if (generate_authenticator_response_pwhash(
     418          49 :                             pw_hash, peer_challenge, data->auth_challenge,
     419             :                             username, username_len, nt_response,
     420          98 :                             data->auth_response) < 0 ||
     421          98 :                     hash_nt_password_hash(pw_hash, pw_hash_hash) < 0 ||
     422          49 :                     get_master_key(pw_hash_hash, nt_response,
     423          49 :                                    data->master_key)) {
     424           0 :                         data->state = FAILURE;
     425           0 :                         return;
     426             :                 }
     427          49 :                 data->master_key_valid = 1;
     428          49 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived Master Key",
     429          49 :                                 data->master_key, MSCHAPV2_KEY_LEN);
     430             :         } else {
     431           4 :                 wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Expected NT-Response",
     432             :                             expected, 24);
     433           4 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response");
     434           4 :                 data->state = FAILURE_REQ;
     435             :         }
     436             : }
     437             : 
     438             : 
     439          48 : static void eap_mschapv2_process_success_resp(struct eap_sm *sm,
     440             :                                               struct eap_mschapv2_data *data,
     441             :                                               struct wpabuf *respData)
     442             : {
     443             :         struct eap_mschapv2_hdr *resp;
     444             :         const u8 *pos;
     445             :         size_t len;
     446             : 
     447          48 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     448             :                                &len);
     449          48 :         if (pos == NULL || len < 1)
     450          48 :                 return; /* Should not happen - frame already validated */
     451             : 
     452          48 :         resp = (struct eap_mschapv2_hdr *) pos;
     453             : 
     454          48 :         if (resp->op_code == MSCHAPV2_OP_SUCCESS) {
     455          48 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Success Response"
     456             :                            " - authentication completed successfully");
     457          48 :                 data->state = SUCCESS;
     458             :         } else {
     459           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Success "
     460             :                            "Response - peer rejected authentication");
     461           0 :                 data->state = FAILURE;
     462             :         }
     463             : }
     464             : 
     465             : 
     466           3 : static void eap_mschapv2_process_failure_resp(struct eap_sm *sm,
     467             :                                               struct eap_mschapv2_data *data,
     468             :                                               struct wpabuf *respData)
     469             : {
     470             :         struct eap_mschapv2_hdr *resp;
     471             :         const u8 *pos;
     472             :         size_t len;
     473             : 
     474           3 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData,
     475             :                                &len);
     476           3 :         if (pos == NULL || len < 1)
     477           3 :                 return; /* Should not happen - frame already validated */
     478             : 
     479           3 :         resp = (struct eap_mschapv2_hdr *) pos;
     480             : 
     481           3 :         if (resp->op_code == MSCHAPV2_OP_FAILURE) {
     482           3 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received Failure Response"
     483             :                            " - authentication failed");
     484             :         } else {
     485           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Did not receive Failure "
     486             :                            "Response - authentication failed");
     487             :         }
     488             : 
     489           3 :         data->state = FAILURE;
     490             : }
     491             : 
     492             : 
     493         105 : static void eap_mschapv2_process(struct eap_sm *sm, void *priv,
     494             :                                  struct wpabuf *respData)
     495             : {
     496         105 :         struct eap_mschapv2_data *data = priv;
     497             : 
     498         105 :         if (sm->user == NULL || sm->user->password == NULL) {
     499           1 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
     500           1 :                 data->state = FAILURE;
     501         106 :                 return;
     502             :         }
     503             : 
     504         104 :         switch (data->state) {
     505             :         case CHALLENGE:
     506          53 :                 eap_mschapv2_process_response(sm, data, respData);
     507          53 :                 break;
     508             :         case SUCCESS_REQ:
     509          48 :                 eap_mschapv2_process_success_resp(sm, data, respData);
     510          48 :                 break;
     511             :         case FAILURE_REQ:
     512           3 :                 eap_mschapv2_process_failure_resp(sm, data, respData);
     513           3 :                 break;
     514             :         default:
     515           0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Unknown state %d in "
     516           0 :                            "process", data->state);
     517           0 :                 break;
     518             :         }
     519             : }
     520             : 
     521             : 
     522         105 : static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv)
     523             : {
     524         105 :         struct eap_mschapv2_data *data = priv;
     525         105 :         return data->state == SUCCESS || data->state == FAILURE;
     526             : }
     527             : 
     528             : 
     529          41 : static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
     530             : {
     531          41 :         struct eap_mschapv2_data *data = priv;
     532             :         u8 *key;
     533             : 
     534          41 :         if (data->state != SUCCESS || !data->master_key_valid)
     535           0 :                 return NULL;
     536             : 
     537          41 :         *len = 2 * MSCHAPV2_KEY_LEN;
     538          41 :         key = os_malloc(*len);
     539          41 :         if (key == NULL)
     540           1 :                 return NULL;
     541             :         /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key */
     542          40 :         get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 1);
     543          40 :         get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
     544             :                                 MSCHAPV2_KEY_LEN, 1, 1);
     545          40 :         wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", key, *len);
     546             : 
     547          40 :         return key;
     548             : }
     549             : 
     550             : 
     551          52 : static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv)
     552             : {
     553          52 :         struct eap_mschapv2_data *data = priv;
     554          52 :         return data->state == SUCCESS;
     555             : }
     556             : 
     557             : 
     558          10 : int eap_server_mschapv2_register(void)
     559             : {
     560             :         struct eap_method *eap;
     561             :         int ret;
     562             : 
     563          10 :         eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
     564             :                                       EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
     565             :                                       "MSCHAPV2");
     566          10 :         if (eap == NULL)
     567           0 :                 return -1;
     568             : 
     569          10 :         eap->init = eap_mschapv2_init;
     570          10 :         eap->reset = eap_mschapv2_reset;
     571          10 :         eap->buildReq = eap_mschapv2_buildReq;
     572          10 :         eap->check = eap_mschapv2_check;
     573          10 :         eap->process = eap_mschapv2_process;
     574          10 :         eap->isDone = eap_mschapv2_isDone;
     575          10 :         eap->getKey = eap_mschapv2_getKey;
     576          10 :         eap->isSuccess = eap_mschapv2_isSuccess;
     577             : 
     578          10 :         ret = eap_server_method_register(eap);
     579          10 :         if (ret)
     580           0 :                 eap_server_method_free(eap);
     581          10 :         return ret;
     582             : }

Generated by: LCOV version 1.10