LCOV - code coverage report
Current view: top level - src/eap_peer - eap_mschapv2.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1393793999 Lines: 226 380 59.5 %
Date: 2014-03-02 Functions: 14 16 87.5 %
Branches: 76 192 39.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt)
       3                 :            :  * Copyright (c) 2004-2008, 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                 :            :  * This file implements EAP peer part of EAP-MSCHAPV2 method (EAP type 26).
       9                 :            :  * draft-kamath-pppext-eap-mschapv2-00.txt defines the Microsoft EAP CHAP
      10                 :            :  * Extensions Protocol, Version 2, for mutual authentication and key
      11                 :            :  * derivation. This encapsulates MS-CHAP-v2 protocol which is defined in
      12                 :            :  * RFC 2759. Use of EAP-MSCHAPV2 derived keys with MPPE cipher is described in
      13                 :            :  * RFC 3079.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "includes.h"
      17                 :            : 
      18                 :            : #include "common.h"
      19                 :            : #include "crypto/ms_funcs.h"
      20                 :            : #include "crypto/random.h"
      21                 :            : #include "common/wpa_ctrl.h"
      22                 :            : #include "mschapv2.h"
      23                 :            : #include "eap_i.h"
      24                 :            : #include "eap_config.h"
      25                 :            : 
      26                 :            : 
      27                 :            : #ifdef _MSC_VER
      28                 :            : #pragma pack(push, 1)
      29                 :            : #endif /* _MSC_VER */
      30                 :            : 
      31                 :            : struct eap_mschapv2_hdr {
      32                 :            :         u8 op_code; /* MSCHAPV2_OP_* */
      33                 :            :         u8 mschapv2_id; /* usually same as EAP identifier; must be changed
      34                 :            :                          * for challenges, but not for success/failure */
      35                 :            :         u8 ms_length[2]; /* Note: misaligned; length - 5 */
      36                 :            :         /* followed by data */
      37                 :            : } STRUCT_PACKED;
      38                 :            : 
      39                 :            : /* Response Data field */
      40                 :            : struct ms_response {
      41                 :            :         u8 peer_challenge[MSCHAPV2_CHAL_LEN];
      42                 :            :         u8 reserved[8];
      43                 :            :         u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN];
      44                 :            :         u8 flags;
      45                 :            : } STRUCT_PACKED;
      46                 :            : 
      47                 :            : /* Change-Password Data field */
      48                 :            : struct ms_change_password {
      49                 :            :         u8 encr_password[516];
      50                 :            :         u8 encr_hash[16];
      51                 :            :         u8 peer_challenge[MSCHAPV2_CHAL_LEN];
      52                 :            :         u8 reserved[8];
      53                 :            :         u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN];
      54                 :            :         u8 flags[2];
      55                 :            : } STRUCT_PACKED;
      56                 :            : 
      57                 :            : #ifdef _MSC_VER
      58                 :            : #pragma pack(pop)
      59                 :            : #endif /* _MSC_VER */
      60                 :            : 
      61                 :            : #define MSCHAPV2_OP_CHALLENGE 1
      62                 :            : #define MSCHAPV2_OP_RESPONSE 2
      63                 :            : #define MSCHAPV2_OP_SUCCESS 3
      64                 :            : #define MSCHAPV2_OP_FAILURE 4
      65                 :            : #define MSCHAPV2_OP_CHANGE_PASSWORD 7
      66                 :            : 
      67                 :            : #define ERROR_RESTRICTED_LOGON_HOURS 646
      68                 :            : #define ERROR_ACCT_DISABLED 647
      69                 :            : #define ERROR_PASSWD_EXPIRED 648
      70                 :            : #define ERROR_NO_DIALIN_PERMISSION 649
      71                 :            : #define ERROR_AUTHENTICATION_FAILURE 691
      72                 :            : #define ERROR_CHANGING_PASSWORD 709
      73                 :            : 
      74                 :            : #define PASSWD_CHANGE_CHAL_LEN 16
      75                 :            : #define MSCHAPV2_KEY_LEN 16
      76                 :            : 
      77                 :            : 
      78                 :            : struct eap_mschapv2_data {
      79                 :            :         u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN];
      80                 :            :         int auth_response_valid;
      81                 :            : 
      82                 :            :         int prev_error;
      83                 :            :         u8 passwd_change_challenge[PASSWD_CHANGE_CHAL_LEN];
      84                 :            :         int passwd_change_challenge_valid;
      85                 :            :         int passwd_change_version;
      86                 :            : 
      87                 :            :         /* Optional challenge values generated in EAP-FAST Phase 1 negotiation
      88                 :            :          */
      89                 :            :         u8 *peer_challenge;
      90                 :            :         u8 *auth_challenge;
      91                 :            : 
      92                 :            :         int phase2;
      93                 :            :         u8 master_key[MSCHAPV2_MASTER_KEY_LEN];
      94                 :            :         int master_key_valid;
      95                 :            :         int success;
      96                 :            : 
      97                 :            :         struct wpabuf *prev_challenge;
      98                 :            : };
      99                 :            : 
     100                 :            : 
     101                 :            : static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv);
     102                 :            : 
     103                 :            : 
     104                 :         24 : static void * eap_mschapv2_init(struct eap_sm *sm)
     105                 :            : {
     106                 :            :         struct eap_mschapv2_data *data;
     107                 :         24 :         data = os_zalloc(sizeof(*data));
     108         [ -  + ]:         24 :         if (data == NULL)
     109                 :          0 :                 return NULL;
     110                 :            : 
     111         [ +  + ]:         24 :         if (sm->peer_challenge) {
     112                 :          1 :                 data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
     113         [ -  + ]:          1 :                 if (data->peer_challenge == NULL) {
     114                 :          0 :                         eap_mschapv2_deinit(sm, data);
     115                 :          0 :                         return NULL;
     116                 :            :                 }
     117                 :          1 :                 os_memcpy(data->peer_challenge, sm->peer_challenge,
     118                 :            :                           MSCHAPV2_CHAL_LEN);
     119                 :            :         }
     120                 :            : 
     121         [ +  + ]:         24 :         if (sm->auth_challenge) {
     122                 :          1 :                 data->auth_challenge = os_malloc(MSCHAPV2_CHAL_LEN);
     123         [ -  + ]:          1 :                 if (data->auth_challenge == NULL) {
     124                 :          0 :                         eap_mschapv2_deinit(sm, data);
     125                 :          0 :                         return NULL;
     126                 :            :                 }
     127                 :          1 :                 os_memcpy(data->auth_challenge, sm->auth_challenge,
     128                 :            :                           MSCHAPV2_CHAL_LEN);
     129                 :            :         }
     130                 :            : 
     131                 :         24 :         data->phase2 = sm->init_phase2;
     132                 :            : 
     133                 :         24 :         return data;
     134                 :            : }
     135                 :            : 
     136                 :            : 
     137                 :         24 : static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv)
     138                 :            : {
     139                 :         24 :         struct eap_mschapv2_data *data = priv;
     140                 :         24 :         os_free(data->peer_challenge);
     141                 :         24 :         os_free(data->auth_challenge);
     142                 :         24 :         wpabuf_free(data->prev_challenge);
     143                 :         24 :         os_free(data);
     144                 :         24 : }
     145                 :            : 
     146                 :            : 
     147                 :         28 : static struct wpabuf * eap_mschapv2_challenge_reply(
     148                 :            :         struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id,
     149                 :            :         u8 mschapv2_id, const u8 *auth_challenge)
     150                 :            : {
     151                 :            :         struct wpabuf *resp;
     152                 :            :         struct eap_mschapv2_hdr *ms;
     153                 :            :         u8 *peer_challenge;
     154                 :            :         int ms_len;
     155                 :            :         struct ms_response *r;
     156                 :            :         size_t identity_len, password_len;
     157                 :            :         const u8 *identity, *password;
     158                 :            :         int pwhash;
     159                 :            : 
     160                 :         28 :         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response");
     161                 :            : 
     162                 :         28 :         identity = eap_get_config_identity(sm, &identity_len);
     163                 :         28 :         password = eap_get_config_password2(sm, &password_len, &pwhash);
     164 [ +  - ][ -  + ]:         28 :         if (identity == NULL || password == NULL)
     165                 :          0 :                 return NULL;
     166                 :            : 
     167                 :         28 :         ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len;
     168                 :         28 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     169                 :            :                              EAP_CODE_RESPONSE, id);
     170         [ -  + ]:         28 :         if (resp == NULL)
     171                 :          0 :                 return NULL;
     172                 :            : 
     173                 :         28 :         ms = wpabuf_put(resp, sizeof(*ms));
     174                 :         28 :         ms->op_code = MSCHAPV2_OP_RESPONSE;
     175                 :         28 :         ms->mschapv2_id = mschapv2_id;
     176         [ -  + ]:         28 :         if (data->prev_error) {
     177                 :            :                 /*
     178                 :            :                  * TODO: this does not seem to be enough when processing two
     179                 :            :                  * or more failure messages. IAS did not increment mschapv2_id
     180                 :            :                  * in its own packets, but it seemed to expect the peer to
     181                 :            :                  * increment this for all packets(?).
     182                 :            :                  */
     183                 :          0 :                 ms->mschapv2_id++;
     184                 :            :         }
     185                 :         28 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     186                 :            : 
     187                 :         28 :         wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */
     188                 :            : 
     189                 :            :         /* Response */
     190                 :         28 :         r = wpabuf_put(resp, sizeof(*r));
     191                 :         28 :         peer_challenge = r->peer_challenge;
     192         [ +  + ]:         28 :         if (data->peer_challenge) {
     193                 :          1 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated "
     194                 :            :                            "in Phase 1");
     195                 :          1 :                 peer_challenge = data->peer_challenge;
     196                 :          1 :                 os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN);
     197         [ -  + ]:         27 :         } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) {
     198                 :          0 :                 wpabuf_free(resp);
     199                 :          0 :                 return NULL;
     200                 :            :         }
     201                 :         28 :         os_memset(r->reserved, 0, 8);
     202         [ +  + ]:         28 :         if (data->auth_challenge) {
     203                 :          1 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated "
     204                 :            :                            "in Phase 1");
     205                 :          1 :                 auth_challenge = data->auth_challenge;
     206                 :            :         }
     207         [ -  + ]:         28 :         if (mschapv2_derive_response(identity, identity_len, password,
     208                 :            :                                      password_len, pwhash, auth_challenge,
     209                 :         28 :                                      peer_challenge, r->nt_response,
     210                 :         28 :                                      data->auth_response, data->master_key)) {
     211                 :          0 :                 wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to derive "
     212                 :            :                            "response");
     213                 :          0 :                 wpabuf_free(resp);
     214                 :          0 :                 return NULL;
     215                 :            :         }
     216                 :         28 :         data->auth_response_valid = 1;
     217                 :         28 :         data->master_key_valid = 1;
     218                 :            : 
     219                 :         28 :         r->flags = 0; /* reserved, must be zero */
     220                 :            : 
     221                 :         28 :         wpabuf_put_data(resp, identity, identity_len);
     222                 :         28 :         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d "
     223                 :         28 :                    "(response)", id, ms->mschapv2_id);
     224                 :         28 :         return resp;
     225                 :            : }
     226                 :            : 
     227                 :            : 
     228                 :            : /**
     229                 :            :  * eap_mschapv2_process - Process an EAP-MSCHAPv2 challenge message
     230                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     231                 :            :  * @data: Pointer to private EAP method data from eap_mschapv2_init()
     232                 :            :  * @ret: Return values from EAP request validation and processing
     233                 :            :  * @req: Pointer to EAP-MSCHAPv2 header from the request
     234                 :            :  * @req_len: Length of the EAP-MSCHAPv2 data
     235                 :            :  * @id: EAP identifier used in the request
     236                 :            :  * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
     237                 :            :  * no reply available
     238                 :            :  */
     239                 :         28 : static struct wpabuf * eap_mschapv2_challenge(
     240                 :            :         struct eap_sm *sm, struct eap_mschapv2_data *data,
     241                 :            :         struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req,
     242                 :            :         size_t req_len, u8 id)
     243                 :            : {
     244                 :            :         size_t len, challenge_len;
     245                 :            :         const u8 *pos, *challenge;
     246                 :            : 
     247   [ +  -  -  + ]:         56 :         if (eap_get_config_identity(sm, &len) == NULL ||
     248                 :         28 :             eap_get_config_password(sm, &len) == NULL)
     249                 :          0 :                 return NULL;
     250                 :            : 
     251                 :         28 :         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received challenge");
     252         [ -  + ]:         28 :         if (req_len < sizeof(*req) + 1) {
     253                 :          0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data "
     254                 :            :                            "(len %lu)", (unsigned long) req_len);
     255                 :          0 :                 ret->ignore = TRUE;
     256                 :          0 :                 return NULL;
     257                 :            :         }
     258                 :         28 :         pos = (const u8 *) (req + 1);
     259                 :         28 :         challenge_len = *pos++;
     260                 :         28 :         len = req_len - sizeof(*req) - 1;
     261         [ -  + ]:         28 :         if (challenge_len != MSCHAPV2_CHAL_LEN) {
     262                 :          0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length "
     263                 :            :                            "%lu", (unsigned long) challenge_len);
     264                 :          0 :                 ret->ignore = TRUE;
     265                 :          0 :                 return NULL;
     266                 :            :         }
     267                 :            : 
     268         [ -  + ]:         28 :         if (len < challenge_len) {
     269                 :          0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge"
     270                 :            :                            " packet: len=%lu challenge_len=%lu",
     271                 :            :                            (unsigned long) len, (unsigned long) challenge_len);
     272                 :          0 :                 ret->ignore = TRUE;
     273                 :          0 :                 return NULL;
     274                 :            :         }
     275                 :            : 
     276         [ -  + ]:         28 :         if (data->passwd_change_challenge_valid) {
     277                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using challenge from the "
     278                 :            :                            "failure message");
     279                 :          0 :                 challenge = data->passwd_change_challenge;
     280                 :            :         } else
     281                 :         28 :                 challenge = pos;
     282                 :         28 :         pos += challenge_len;
     283                 :         28 :         len -= challenge_len;
     284                 :         28 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername",
     285                 :            :                     pos, len);
     286                 :            : 
     287                 :         28 :         ret->ignore = FALSE;
     288                 :         28 :         ret->methodState = METHOD_MAY_CONT;
     289                 :         28 :         ret->decision = DECISION_FAIL;
     290                 :         28 :         ret->allowNotifications = TRUE;
     291                 :            : 
     292                 :         28 :         return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id,
     293                 :            :                                             challenge);
     294                 :            : }
     295                 :            : 
     296                 :            : 
     297                 :          0 : static void eap_mschapv2_password_changed(struct eap_sm *sm,
     298                 :            :                                           struct eap_mschapv2_data *data)
     299                 :            : {
     300                 :          0 :         struct eap_peer_config *config = eap_get_config(sm);
     301 [ #  # ][ #  # ]:          0 :         if (config && config->new_password) {
     302                 :          0 :                 wpa_msg(sm->msg_ctx, MSG_INFO,
     303                 :            :                         WPA_EVENT_PASSWORD_CHANGED
     304                 :            :                         "EAP-MSCHAPV2: Password changed successfully");
     305                 :          0 :                 data->prev_error = 0;
     306                 :          0 :                 os_free(config->password);
     307         [ #  # ]:          0 :                 if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) {
     308                 :            :                         /* TODO: update external storage */
     309         [ #  # ]:          0 :                 } else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) {
     310                 :          0 :                         config->password = os_malloc(16);
     311                 :          0 :                         config->password_len = 16;
     312         [ #  # ]:          0 :                         if (config->password) {
     313                 :          0 :                                 nt_password_hash(config->new_password,
     314                 :            :                                                  config->new_password_len,
     315                 :            :                                                  config->password);
     316                 :            :                         }
     317                 :          0 :                         os_free(config->new_password);
     318                 :            :                 } else {
     319                 :          0 :                         config->password = config->new_password;
     320                 :          0 :                         config->password_len = config->new_password_len;
     321                 :            :                 }
     322                 :          0 :                 config->new_password = NULL;
     323                 :          0 :                 config->new_password_len = 0;
     324                 :            :         }
     325                 :          0 : }
     326                 :            : 
     327                 :            : 
     328                 :            : /**
     329                 :            :  * eap_mschapv2_process - Process an EAP-MSCHAPv2 success message
     330                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     331                 :            :  * @data: Pointer to private EAP method data from eap_mschapv2_init()
     332                 :            :  * @ret: Return values from EAP request validation and processing
     333                 :            :  * @req: Pointer to EAP-MSCHAPv2 header from the request
     334                 :            :  * @req_len: Length of the EAP-MSCHAPv2 data
     335                 :            :  * @id: EAP identifier used in th erequest
     336                 :            :  * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
     337                 :            :  * no reply available
     338                 :            :  */
     339                 :         26 : static struct wpabuf * eap_mschapv2_success(struct eap_sm *sm,
     340                 :            :                                             struct eap_mschapv2_data *data,
     341                 :            :                                             struct eap_method_ret *ret,
     342                 :            :                                             const struct eap_mschapv2_hdr *req,
     343                 :            :                                             size_t req_len, u8 id)
     344                 :            : {
     345                 :            :         struct wpabuf *resp;
     346                 :            :         const u8 *pos;
     347                 :            :         size_t len;
     348                 :            : 
     349                 :         26 :         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success");
     350                 :         26 :         len = req_len - sizeof(*req);
     351                 :         26 :         pos = (const u8 *) (req + 1);
     352   [ +  -  -  + ]:         52 :         if (!data->auth_response_valid ||
     353                 :         26 :             mschapv2_verify_auth_response(data->auth_response, pos, len)) {
     354                 :          0 :                 wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator "
     355                 :            :                            "response in success request");
     356                 :          0 :                 ret->methodState = METHOD_DONE;
     357                 :          0 :                 ret->decision = DECISION_FAIL;
     358                 :          0 :                 return NULL;
     359                 :            :         }
     360                 :         26 :         pos += 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN;
     361                 :         26 :         len -= 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN;
     362 [ +  - ][ +  + ]:         52 :         while (len > 0 && *pos == ' ') {
     363                 :         26 :                 pos++;
     364                 :         26 :                 len--;
     365                 :            :         }
     366                 :         26 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message",
     367                 :            :                           pos, len);
     368                 :         26 :         wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded");
     369                 :            : 
     370                 :            :         /* Note: Only op_code of the EAP-MSCHAPV2 header is included in success
     371                 :            :          * message. */
     372                 :         26 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1,
     373                 :            :                              EAP_CODE_RESPONSE, id);
     374         [ -  + ]:         26 :         if (resp == NULL) {
     375                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate "
     376                 :            :                            "buffer for success response");
     377                 :          0 :                 ret->ignore = TRUE;
     378                 :          0 :                 return NULL;
     379                 :            :         }
     380                 :            : 
     381                 :         26 :         wpabuf_put_u8(resp, MSCHAPV2_OP_SUCCESS); /* op_code */
     382                 :            : 
     383                 :         26 :         ret->methodState = METHOD_DONE;
     384                 :         26 :         ret->decision = DECISION_UNCOND_SUCC;
     385                 :         26 :         ret->allowNotifications = FALSE;
     386                 :         26 :         data->success = 1;
     387                 :            : 
     388         [ -  + ]:         26 :         if (data->prev_error == ERROR_PASSWD_EXPIRED)
     389                 :          0 :                 eap_mschapv2_password_changed(sm, data);
     390                 :            : 
     391                 :         26 :         return resp;
     392                 :            : }
     393                 :            : 
     394                 :            : 
     395                 :          2 : static int eap_mschapv2_failure_txt(struct eap_sm *sm,
     396                 :            :                                     struct eap_mschapv2_data *data, char *txt)
     397                 :            : {
     398                 :          2 :         char *pos, *msg = "";
     399                 :          2 :         int retry = 1;
     400                 :          2 :         struct eap_peer_config *config = eap_get_config(sm);
     401                 :            : 
     402                 :            :         /* For example:
     403                 :            :          * E=691 R=1 C=<32 octets hex challenge> V=3 M=Authentication Failure
     404                 :            :          */
     405                 :            : 
     406                 :          2 :         pos = txt;
     407                 :            : 
     408 [ +  - ][ +  - ]:          2 :         if (pos && os_strncmp(pos, "E=", 2) == 0) {
     409                 :          2 :                 pos += 2;
     410                 :          2 :                 data->prev_error = atoi(pos);
     411                 :          2 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d",
     412                 :            :                            data->prev_error);
     413                 :          2 :                 pos = os_strchr(pos, ' ');
     414         [ +  - ]:          2 :                 if (pos)
     415                 :          2 :                         pos++;
     416                 :            :         }
     417                 :            : 
     418 [ +  - ][ +  - ]:          2 :         if (pos && os_strncmp(pos, "R=", 2) == 0) {
     419                 :          2 :                 pos += 2;
     420                 :          2 :                 retry = atoi(pos);
     421         [ -  + ]:          2 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed",
     422                 :            :                            retry == 1 ? "" : "not ");
     423                 :          2 :                 pos = os_strchr(pos, ' ');
     424         [ +  - ]:          2 :                 if (pos)
     425                 :          2 :                         pos++;
     426                 :            :         }
     427                 :            : 
     428 [ +  - ][ +  - ]:          4 :         if (pos && os_strncmp(pos, "C=", 2) == 0) {
     429                 :            :                 int hex_len;
     430                 :          2 :                 pos += 2;
     431                 :          2 :                 hex_len = os_strchr(pos, ' ') - (char *) pos;
     432         [ +  - ]:          2 :                 if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) {
     433         [ -  + ]:          2 :                         if (hexstr2bin(pos, data->passwd_change_challenge,
     434                 :            :                                        PASSWD_CHANGE_CHAL_LEN)) {
     435                 :          0 :                                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid "
     436                 :            :                                            "failure challenge");
     437                 :            :                         } else {
     438                 :          2 :                                 wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: failure "
     439                 :            :                                             "challenge",
     440                 :          2 :                                             data->passwd_change_challenge,
     441                 :            :                                             PASSWD_CHANGE_CHAL_LEN);
     442                 :          2 :                                 data->passwd_change_challenge_valid = 1;
     443                 :            :                         }
     444                 :            :                 } else {
     445                 :          0 :                         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure "
     446                 :            :                                    "challenge len %d", hex_len);
     447                 :            :                 }
     448                 :          2 :                 pos = os_strchr(pos, ' ');
     449         [ +  - ]:          2 :                 if (pos)
     450                 :          2 :                         pos++;
     451                 :            :         } else {
     452                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: required challenge field "
     453                 :            :                            "was not present in failure message");
     454                 :            :         }
     455                 :            : 
     456 [ +  - ][ +  - ]:          2 :         if (pos && os_strncmp(pos, "V=", 2) == 0) {
     457                 :          2 :                 pos += 2;
     458                 :          2 :                 data->passwd_change_version = atoi(pos);
     459                 :          2 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing "
     460                 :            :                            "protocol version %d", data->passwd_change_version);
     461                 :          2 :                 pos = os_strchr(pos, ' ');
     462         [ +  - ]:          2 :                 if (pos)
     463                 :          2 :                         pos++;
     464                 :            :         }
     465                 :            : 
     466 [ +  - ][ +  - ]:          2 :         if (pos && os_strncmp(pos, "M=", 2) == 0) {
     467                 :          2 :                 pos += 2;
     468                 :          2 :                 msg = pos;
     469                 :            :         }
     470         [ -  + ]:          2 :         wpa_msg(sm->msg_ctx, MSG_WARNING,
     471                 :            :                 "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error "
     472                 :            :                 "%d)",
     473                 :            :                 msg, retry == 1 ? "" : "not ", data->prev_error);
     474 [ -  + ][ #  # ]:          2 :         if (data->prev_error == ERROR_PASSWD_EXPIRED &&
     475         [ #  # ]:          0 :             data->passwd_change_version == 3 && config) {
     476         [ #  # ]:          0 :                 if (config->new_password == NULL) {
     477                 :          0 :                         wpa_msg(sm->msg_ctx, MSG_INFO,
     478                 :            :                                 "EAP-MSCHAPV2: Password expired - password "
     479                 :            :                                 "change required");
     480                 :          0 :                         eap_sm_request_new_password(sm);
     481                 :            :                 }
     482 [ -  + ][ #  # ]:          2 :         } else if (retry == 1 && config) {
     483                 :            :                 /* TODO: could prevent the current password from being used
     484                 :            :                  * again at least for some period of time */
     485         [ #  # ]:          0 :                 if (!config->mschapv2_retry)
     486                 :          0 :                         eap_sm_request_identity(sm);
     487                 :          0 :                 eap_sm_request_password(sm);
     488                 :          0 :                 config->mschapv2_retry = 1;
     489         [ +  - ]:          2 :         } else if (config) {
     490                 :            :                 /* TODO: prevent retries using same username/password */
     491                 :          2 :                 config->mschapv2_retry = 0;
     492                 :            :         }
     493                 :            : 
     494                 :          2 :         return retry == 1;
     495                 :            : }
     496                 :            : 
     497                 :            : 
     498                 :          0 : static struct wpabuf * eap_mschapv2_change_password(
     499                 :            :         struct eap_sm *sm, struct eap_mschapv2_data *data,
     500                 :            :         struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id)
     501                 :            : {
     502                 :            :         struct wpabuf *resp;
     503                 :            :         int ms_len;
     504                 :            :         const u8 *username, *password, *new_password;
     505                 :            :         size_t username_len, password_len, new_password_len;
     506                 :            :         struct eap_mschapv2_hdr *ms;
     507                 :            :         struct ms_change_password *cp;
     508                 :            :         u8 password_hash[16], password_hash_hash[16];
     509                 :            :         int pwhash;
     510                 :            : 
     511                 :          0 :         username = eap_get_config_identity(sm, &username_len);
     512                 :          0 :         password = eap_get_config_password2(sm, &password_len, &pwhash);
     513                 :          0 :         new_password = eap_get_config_new_password(sm, &new_password_len);
     514 [ #  # ][ #  # ]:          0 :         if (username == NULL || password == NULL || new_password == NULL)
                 [ #  # ]
     515                 :          0 :                 return NULL;
     516                 :            : 
     517                 :          0 :         username = mschapv2_remove_domain(username, &username_len);
     518                 :            : 
     519                 :          0 :         ret->ignore = FALSE;
     520                 :          0 :         ret->methodState = METHOD_MAY_CONT;
     521                 :          0 :         ret->decision = DECISION_COND_SUCC;
     522                 :          0 :         ret->allowNotifications = TRUE;
     523                 :            : 
     524                 :          0 :         ms_len = sizeof(*ms) + sizeof(*cp);
     525                 :          0 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len,
     526                 :            :                              EAP_CODE_RESPONSE, id);
     527         [ #  # ]:          0 :         if (resp == NULL)
     528                 :          0 :                 return NULL;
     529                 :            : 
     530                 :          0 :         ms = wpabuf_put(resp, sizeof(*ms));
     531                 :          0 :         ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD;
     532                 :          0 :         ms->mschapv2_id = req->mschapv2_id + 1;
     533                 :          0 :         WPA_PUT_BE16(ms->ms_length, ms_len);
     534                 :          0 :         cp = wpabuf_put(resp, sizeof(*cp));
     535                 :            : 
     536                 :            :         /* Encrypted-Password */
     537         [ #  # ]:          0 :         if (pwhash) {
     538         [ #  # ]:          0 :                 if (encrypt_pw_block_with_password_hash(
     539                 :            :                             new_password, new_password_len,
     540                 :          0 :                             password, cp->encr_password))
     541                 :          0 :                         goto fail;
     542                 :            :         } else {
     543         [ #  # ]:          0 :                 if (new_password_encrypted_with_old_nt_password_hash(
     544                 :            :                             new_password, new_password_len,
     545                 :          0 :                             password, password_len, cp->encr_password))
     546                 :          0 :                         goto fail;
     547                 :            :         }
     548                 :            : 
     549                 :            :         /* Encrypted-Hash */
     550         [ #  # ]:          0 :         if (pwhash) {
     551                 :            :                 u8 new_password_hash[16];
     552                 :          0 :                 nt_password_hash(new_password, new_password_len,
     553                 :            :                                  new_password_hash);
     554                 :          0 :                 nt_password_hash_encrypted_with_block(password,
     555                 :            :                                                       new_password_hash,
     556                 :          0 :                                                       cp->encr_hash);
     557                 :            :         } else {
     558                 :          0 :                 old_nt_password_hash_encrypted_with_new_nt_password_hash(
     559                 :            :                         new_password, new_password_len,
     560                 :          0 :                         password, password_len, cp->encr_hash);
     561                 :            :         }
     562                 :            : 
     563                 :            :         /* Peer-Challenge */
     564         [ #  # ]:          0 :         if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN))
     565                 :          0 :                 goto fail;
     566                 :            : 
     567                 :            :         /* Reserved, must be zero */
     568                 :          0 :         os_memset(cp->reserved, 0, 8);
     569                 :            : 
     570                 :            :         /* NT-Response */
     571                 :          0 :         wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge",
     572                 :          0 :                     data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN);
     573                 :          0 :         wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge",
     574                 :          0 :                     cp->peer_challenge, MSCHAPV2_CHAL_LEN);
     575                 :          0 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username",
     576                 :            :                           username, username_len);
     577                 :          0 :         wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password",
     578                 :            :                               new_password, new_password_len);
     579                 :          0 :         generate_nt_response(data->passwd_change_challenge, cp->peer_challenge,
     580                 :            :                              username, username_len,
     581                 :            :                              new_password, new_password_len,
     582                 :          0 :                              cp->nt_response);
     583                 :          0 :         wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response",
     584                 :          0 :                     cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN);
     585                 :            : 
     586                 :            :         /* Authenticator response is not really needed yet, but calculate it
     587                 :            :          * here so that challenges need not be saved. */
     588                 :          0 :         generate_authenticator_response(new_password, new_password_len,
     589                 :          0 :                                         cp->peer_challenge,
     590                 :          0 :                                         data->passwd_change_challenge,
     591                 :            :                                         username, username_len,
     592                 :          0 :                                         cp->nt_response, data->auth_response);
     593                 :          0 :         data->auth_response_valid = 1;
     594                 :            : 
     595                 :            :         /* Likewise, generate master_key here since we have the needed data
     596                 :            :          * available. */
     597                 :          0 :         nt_password_hash(new_password, new_password_len, password_hash);
     598                 :          0 :         hash_nt_password_hash(password_hash, password_hash_hash);
     599                 :          0 :         get_master_key(password_hash_hash, cp->nt_response, data->master_key);
     600                 :          0 :         data->master_key_valid = 1;
     601                 :            : 
     602                 :            :         /* Flags */
     603                 :          0 :         os_memset(cp->flags, 0, 2);
     604                 :            : 
     605                 :          0 :         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d "
     606                 :          0 :                    "(change pw)", id, ms->mschapv2_id);
     607                 :            : 
     608                 :          0 :         return resp;
     609                 :            : 
     610                 :            : fail:
     611                 :          0 :         wpabuf_free(resp);
     612                 :          0 :         return NULL;
     613                 :            : }
     614                 :            : 
     615                 :            : 
     616                 :            : /**
     617                 :            :  * eap_mschapv2_process - Process an EAP-MSCHAPv2 failure message
     618                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     619                 :            :  * @data: Pointer to private EAP method data from eap_mschapv2_init()
     620                 :            :  * @ret: Return values from EAP request validation and processing
     621                 :            :  * @req: Pointer to EAP-MSCHAPv2 header from the request
     622                 :            :  * @req_len: Length of the EAP-MSCHAPv2 data
     623                 :            :  * @id: EAP identifier used in th erequest
     624                 :            :  * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
     625                 :            :  * no reply available
     626                 :            :  */
     627                 :          2 : static struct wpabuf * eap_mschapv2_failure(struct eap_sm *sm,
     628                 :            :                                             struct eap_mschapv2_data *data,
     629                 :            :                                             struct eap_method_ret *ret,
     630                 :            :                                             const struct eap_mschapv2_hdr *req,
     631                 :            :                                             size_t req_len, u8 id)
     632                 :            : {
     633                 :            :         struct wpabuf *resp;
     634                 :          2 :         const u8 *msdata = (const u8 *) (req + 1);
     635                 :            :         char *buf;
     636                 :          2 :         size_t len = req_len - sizeof(*req);
     637                 :          2 :         int retry = 0;
     638                 :            : 
     639                 :          2 :         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure");
     640                 :          2 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data",
     641                 :            :                           msdata, len);
     642                 :            :         /*
     643                 :            :          * eap_mschapv2_failure_txt() expects a nul terminated string, so we
     644                 :            :          * must allocate a large enough temporary buffer to create that since
     645                 :            :          * the received message does not include nul termination.
     646                 :            :          */
     647                 :          2 :         buf = dup_binstr(msdata, len);
     648         [ +  - ]:          2 :         if (buf) {
     649                 :          2 :                 retry = eap_mschapv2_failure_txt(sm, data, buf);
     650                 :          2 :                 os_free(buf);
     651                 :            :         }
     652                 :            : 
     653                 :          2 :         ret->ignore = FALSE;
     654                 :          2 :         ret->methodState = METHOD_DONE;
     655                 :          2 :         ret->decision = DECISION_FAIL;
     656                 :          2 :         ret->allowNotifications = FALSE;
     657                 :            : 
     658 [ -  + ][ #  # ]:          2 :         if (data->prev_error == ERROR_PASSWD_EXPIRED &&
     659                 :          0 :             data->passwd_change_version == 3) {
     660                 :          0 :                 struct eap_peer_config *config = eap_get_config(sm);
     661 [ #  # ][ #  # ]:          0 :                 if (config && config->new_password)
     662                 :          0 :                         return eap_mschapv2_change_password(sm, data, ret, req,
     663                 :            :                                                             id);
     664 [ #  # ][ #  # ]:          0 :                 if (config && config->pending_req_new_password)
     665                 :          0 :                         return NULL;
     666 [ -  + ][ #  # ]:          2 :         } else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) {
     667                 :            :                 /* TODO: could try to retry authentication, e.g, after having
     668                 :            :                  * changed the username/password. In this case, EAP MS-CHAP-v2
     669                 :            :                  * Failure Response would not be sent here. */
     670                 :          0 :                 return NULL;
     671                 :            :         }
     672                 :            : 
     673                 :            :         /* Note: Only op_code of the EAP-MSCHAPV2 header is included in failure
     674                 :            :          * message. */
     675                 :          2 :         resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1,
     676                 :            :                              EAP_CODE_RESPONSE, id);
     677         [ -  + ]:          2 :         if (resp == NULL)
     678                 :          0 :                 return NULL;
     679                 :            : 
     680                 :          2 :         wpabuf_put_u8(resp, MSCHAPV2_OP_FAILURE); /* op_code */
     681                 :            : 
     682                 :          2 :         return resp;
     683                 :            : }
     684                 :            : 
     685                 :            : 
     686                 :         58 : static int eap_mschapv2_check_config(struct eap_sm *sm)
     687                 :            : {
     688                 :            :         size_t len;
     689                 :            : 
     690         [ -  + ]:         58 :         if (eap_get_config_identity(sm, &len) == NULL) {
     691                 :          0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured");
     692                 :          0 :                 eap_sm_request_identity(sm);
     693                 :          0 :                 return -1;
     694                 :            :         }
     695                 :            : 
     696         [ +  + ]:         58 :         if (eap_get_config_password(sm, &len) == NULL) {
     697                 :          2 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
     698                 :          2 :                 eap_sm_request_password(sm);
     699                 :          2 :                 return -1;
     700                 :            :         }
     701                 :            : 
     702                 :         58 :         return 0;
     703                 :            : }
     704                 :            : 
     705                 :            : 
     706                 :         56 : static int eap_mschapv2_check_mslen(struct eap_sm *sm, size_t len,
     707                 :            :                                     const struct eap_mschapv2_hdr *ms)
     708                 :            : {
     709                 :         56 :         size_t ms_len = WPA_GET_BE16(ms->ms_length);
     710                 :            : 
     711         [ +  - ]:         56 :         if (ms_len == len)
     712                 :         56 :                 return 0;
     713                 :            : 
     714                 :          0 :         wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu "
     715                 :            :                    "ms_len=%lu", (unsigned long) len, (unsigned long) ms_len);
     716         [ #  # ]:          0 :         if (sm->workaround) {
     717                 :            :                 /* Some authentication servers use invalid ms_len,
     718                 :            :                  * ignore it for interoperability. */
     719                 :          0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore"
     720                 :            :                            " invalid ms_len %lu (len %lu)",
     721                 :            :                            (unsigned long) ms_len,
     722                 :            :                            (unsigned long) len);
     723                 :          0 :                 return 0;
     724                 :            :         }
     725                 :            : 
     726                 :         56 :         return -1;
     727                 :            : }
     728                 :            : 
     729                 :            : 
     730                 :         28 : static void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data,
     731                 :            :                                         const struct wpabuf *reqData)
     732                 :            : {
     733                 :            :         /*
     734                 :            :          * Store a copy of the challenge message, so that it can be processed
     735                 :            :          * again in case retry is allowed after a possible failure.
     736                 :            :          */
     737                 :         28 :         wpabuf_free(data->prev_challenge);
     738                 :         28 :         data->prev_challenge = wpabuf_dup(reqData);
     739                 :         28 : }
     740                 :            : 
     741                 :            : 
     742                 :            : /**
     743                 :            :  * eap_mschapv2_process - Process an EAP-MSCHAPv2 request
     744                 :            :  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
     745                 :            :  * @priv: Pointer to private EAP method data from eap_mschapv2_init()
     746                 :            :  * @ret: Return values from EAP request validation and processing
     747                 :            :  * @reqData: EAP request to be processed (eapReqData)
     748                 :            :  * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if
     749                 :            :  * no reply available
     750                 :            :  */
     751                 :         58 : static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv,
     752                 :            :                                             struct eap_method_ret *ret,
     753                 :            :                                             const struct wpabuf *reqData)
     754                 :            : {
     755                 :         58 :         struct eap_mschapv2_data *data = priv;
     756                 :         58 :         struct eap_peer_config *config = eap_get_config(sm);
     757                 :            :         const struct eap_mschapv2_hdr *ms;
     758                 :         58 :         int using_prev_challenge = 0;
     759                 :            :         const u8 *pos;
     760                 :            :         size_t len;
     761                 :            :         u8 id;
     762                 :            : 
     763         [ +  + ]:         58 :         if (eap_mschapv2_check_config(sm)) {
     764                 :          2 :                 ret->ignore = TRUE;
     765                 :          2 :                 return NULL;
     766                 :            :         }
     767                 :            : 
     768 [ -  + ][ #  # ]:         56 :         if (config->mschapv2_retry && data->prev_challenge &&
                 [ #  # ]
     769                 :          0 :             data->prev_error == ERROR_AUTHENTICATION_FAILURE) {
     770                 :          0 :                 wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Replacing pending packet "
     771                 :            :                            "with the previous challenge");
     772                 :            : 
     773                 :          0 :                 reqData = data->prev_challenge;
     774                 :          0 :                 using_prev_challenge = 1;
     775                 :          0 :                 config->mschapv2_retry = 0;
     776                 :            :         }
     777                 :            : 
     778                 :         56 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqData,
     779                 :            :                                &len);
     780 [ +  - ][ -  + ]:         56 :         if (pos == NULL || len < sizeof(*ms) + 1) {
     781                 :          0 :                 ret->ignore = TRUE;
     782                 :          0 :                 return NULL;
     783                 :            :         }
     784                 :            : 
     785                 :         56 :         ms = (const struct eap_mschapv2_hdr *) pos;
     786         [ -  + ]:         56 :         if (eap_mschapv2_check_mslen(sm, len, ms)) {
     787                 :          0 :                 ret->ignore = TRUE;
     788                 :          0 :                 return NULL;
     789                 :            :         }
     790                 :            : 
     791                 :         56 :         id = eap_get_id(reqData);
     792                 :         56 :         wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d",
     793                 :         56 :                    id, ms->mschapv2_id);
     794                 :            : 
     795   [ +  +  +  - ]:         56 :         switch (ms->op_code) {
     796                 :            :         case MSCHAPV2_OP_CHALLENGE:
     797         [ +  - ]:         28 :                 if (!using_prev_challenge)
     798                 :         28 :                         eap_mschapv2_copy_challenge(data, reqData);
     799                 :         28 :                 return eap_mschapv2_challenge(sm, data, ret, ms, len, id);
     800                 :            :         case MSCHAPV2_OP_SUCCESS:
     801                 :         26 :                 return eap_mschapv2_success(sm, data, ret, ms, len, id);
     802                 :            :         case MSCHAPV2_OP_FAILURE:
     803                 :          2 :                 return eap_mschapv2_failure(sm, data, ret, ms, len, id);
     804                 :            :         default:
     805                 :          0 :                 wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored",
     806                 :          0 :                            ms->op_code);
     807                 :          0 :                 ret->ignore = TRUE;
     808                 :         58 :                 return NULL;
     809                 :            :         }
     810                 :            : }
     811                 :            : 
     812                 :            : 
     813                 :          6 : static Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv)
     814                 :            : {
     815                 :          6 :         struct eap_mschapv2_data *data = priv;
     816 [ +  - ][ +  - ]:          6 :         return data->success && data->master_key_valid;
     817                 :            : }
     818                 :            : 
     819                 :            : 
     820                 :          6 : static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len)
     821                 :            : {
     822                 :          6 :         struct eap_mschapv2_data *data = priv;
     823                 :            :         u8 *key;
     824                 :            :         int key_len;
     825                 :            : 
     826 [ +  - ][ -  + ]:          6 :         if (!data->master_key_valid || !data->success)
     827                 :          0 :                 return NULL;
     828                 :            : 
     829                 :          6 :         key_len = 2 * MSCHAPV2_KEY_LEN;
     830                 :            : 
     831                 :          6 :         key = os_malloc(key_len);
     832         [ -  + ]:          6 :         if (key == NULL)
     833                 :          0 :                 return NULL;
     834                 :            : 
     835                 :            :         /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e.,
     836                 :            :          *      peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */
     837                 :          6 :         get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0);
     838                 :          6 :         get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN,
     839                 :            :                                 MSCHAPV2_KEY_LEN, 0, 0);
     840                 :            : 
     841                 :          6 :         wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key",
     842                 :            :                         key, key_len);
     843                 :            : 
     844                 :          6 :         *len = key_len;
     845                 :          6 :         return key;
     846                 :            : }
     847                 :            : 
     848                 :            : 
     849                 :            : /**
     850                 :            :  * eap_peer_mschapv2_register - Register EAP-MSCHAPv2 peer method
     851                 :            :  * Returns: 0 on success, -1 on failure
     852                 :            :  *
     853                 :            :  * This function is used to register EAP-MSCHAPv2 peer method into the EAP
     854                 :            :  * method list.
     855                 :            :  */
     856                 :          4 : int eap_peer_mschapv2_register(void)
     857                 :            : {
     858                 :            :         struct eap_method *eap;
     859                 :            :         int ret;
     860                 :            : 
     861                 :          4 :         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
     862                 :            :                                     EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2,
     863                 :            :                                     "MSCHAPV2");
     864         [ -  + ]:          4 :         if (eap == NULL)
     865                 :          0 :                 return -1;
     866                 :            : 
     867                 :          4 :         eap->init = eap_mschapv2_init;
     868                 :          4 :         eap->deinit = eap_mschapv2_deinit;
     869                 :          4 :         eap->process = eap_mschapv2_process;
     870                 :          4 :         eap->isKeyAvailable = eap_mschapv2_isKeyAvailable;
     871                 :          4 :         eap->getKey = eap_mschapv2_getKey;
     872                 :            : 
     873                 :          4 :         ret = eap_peer_method_register(eap);
     874         [ -  + ]:          4 :         if (ret)
     875                 :          0 :                 eap_peer_method_free(eap);
     876                 :          4 :         return ret;
     877                 :            : }

Generated by: LCOV version 1.9