LCOV - code coverage report
Current view: top level - src/eap_peer - eap_sim.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 602 628 95.9 %
Date: 2016-10-02 Functions: 32 32 100.0 %

          Line data    Source code
       1             : /*
       2             :  * EAP peer method: EAP-SIM (RFC 4186)
       3             :  * Copyright (c) 2004-2012, 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 "pcsc_funcs.h"
      13             : #include "crypto/milenage.h"
      14             : #include "crypto/random.h"
      15             : #include "eap_peer/eap_i.h"
      16             : #include "eap_config.h"
      17             : #include "eap_common/eap_sim_common.h"
      18             : 
      19             : 
      20             : struct eap_sim_data {
      21             :         u8 *ver_list;
      22             :         size_t ver_list_len;
      23             :         int selected_version;
      24             :         size_t min_num_chal, num_chal;
      25             : 
      26             :         u8 kc[3][EAP_SIM_KC_LEN];
      27             :         u8 sres[3][EAP_SIM_SRES_LEN];
      28             :         u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN];
      29             :         u8 mk[EAP_SIM_MK_LEN];
      30             :         u8 k_aut[EAP_SIM_K_AUT_LEN];
      31             :         u8 k_encr[EAP_SIM_K_ENCR_LEN];
      32             :         u8 msk[EAP_SIM_KEYING_DATA_LEN];
      33             :         u8 emsk[EAP_EMSK_LEN];
      34             :         u8 rand[3][GSM_RAND_LEN];
      35             : 
      36             :         int num_id_req, num_notification;
      37             :         u8 *pseudonym;
      38             :         size_t pseudonym_len;
      39             :         u8 *reauth_id;
      40             :         size_t reauth_id_len;
      41             :         int reauth;
      42             :         unsigned int counter, counter_too_small;
      43             :         u8 *last_eap_identity;
      44             :         size_t last_eap_identity_len;
      45             :         enum {
      46             :                 CONTINUE, RESULT_SUCCESS, SUCCESS, FAILURE
      47             :         } state;
      48             :         int result_ind, use_result_ind;
      49             : };
      50             : 
      51             : 
      52             : #ifndef CONFIG_NO_STDOUT_DEBUG
      53         492 : static const char * eap_sim_state_txt(int state)
      54             : {
      55         492 :         switch (state) {
      56             :         case CONTINUE:
      57         340 :                 return "CONTINUE";
      58             :         case RESULT_SUCCESS:
      59          19 :                 return "RESULT_SUCCESS";
      60             :         case SUCCESS:
      61          72 :                 return "SUCCESS";
      62             :         case FAILURE:
      63          61 :                 return "FAILURE";
      64             :         default:
      65           0 :                 return "?";
      66             :         }
      67             : }
      68             : #endif /* CONFIG_NO_STDOUT_DEBUG */
      69             : 
      70             : 
      71         246 : static void eap_sim_state(struct eap_sim_data *data, int state)
      72             : {
      73         492 :         wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s",
      74         246 :                    eap_sim_state_txt(data->state),
      75             :                    eap_sim_state_txt(state));
      76         246 :         data->state = state;
      77         246 : }
      78             : 
      79             : 
      80         107 : static void * eap_sim_init(struct eap_sm *sm)
      81             : {
      82             :         struct eap_sim_data *data;
      83         107 :         struct eap_peer_config *config = eap_get_config(sm);
      84             : 
      85         107 :         data = os_zalloc(sizeof(*data));
      86         107 :         if (data == NULL)
      87           1 :                 return NULL;
      88             : 
      89         106 :         if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
      90           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
      91             :                            "for NONCE_MT");
      92           1 :                 os_free(data);
      93           1 :                 return NULL;
      94             :         }
      95             : 
      96         105 :         data->min_num_chal = 2;
      97         105 :         if (config && config->phase1) {
      98           9 :                 char *pos = os_strstr(config->phase1, "sim_min_num_chal=");
      99           9 :                 if (pos) {
     100           3 :                         data->min_num_chal = atoi(pos + 17);
     101           3 :                         if (data->min_num_chal < 2 || data->min_num_chal > 3) {
     102           2 :                                 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
     103             :                                            "sim_min_num_chal configuration "
     104             :                                            "(%lu, expected 2 or 3)",
     105             :                                            (unsigned long) data->min_num_chal);
     106           2 :                                 os_free(data);
     107           2 :                                 return NULL;
     108             :                         }
     109           1 :                         wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of "
     110             :                                    "challenges to %lu",
     111             :                                    (unsigned long) data->min_num_chal);
     112             :                 }
     113             : 
     114           7 :                 data->result_ind = os_strstr(config->phase1, "result_ind=1") !=
     115             :                         NULL;
     116             :         }
     117             : 
     118         103 :         if (config && config->anonymous_identity) {
     119           3 :                 data->pseudonym = os_malloc(config->anonymous_identity_len);
     120           3 :                 if (data->pseudonym) {
     121           3 :                         os_memcpy(data->pseudonym, config->anonymous_identity,
     122             :                                   config->anonymous_identity_len);
     123           3 :                         data->pseudonym_len = config->anonymous_identity_len;
     124             :                 }
     125             :         }
     126             : 
     127         103 :         eap_sim_state(data, CONTINUE);
     128             : 
     129         103 :         return data;
     130             : }
     131             : 
     132             : 
     133         123 : static void eap_sim_clear_keys(struct eap_sim_data *data, int reauth)
     134             : {
     135         123 :         if (!reauth) {
     136         103 :                 os_memset(data->mk, 0, EAP_SIM_MK_LEN);
     137         103 :                 os_memset(data->k_aut, 0, EAP_SIM_K_AUT_LEN);
     138         103 :                 os_memset(data->k_encr, 0, EAP_SIM_K_ENCR_LEN);
     139             :         }
     140         123 :         os_memset(data->kc, 0, 3 * EAP_SIM_KC_LEN);
     141         123 :         os_memset(data->sres, 0, 3 * EAP_SIM_SRES_LEN);
     142         123 :         os_memset(data->msk, 0, EAP_SIM_KEYING_DATA_LEN);
     143         123 :         os_memset(data->emsk, 0, EAP_EMSK_LEN);
     144         123 : }
     145             : 
     146             : 
     147         103 : static void eap_sim_deinit(struct eap_sm *sm, void *priv)
     148             : {
     149         103 :         struct eap_sim_data *data = priv;
     150         103 :         if (data) {
     151         103 :                 os_free(data->ver_list);
     152         103 :                 os_free(data->pseudonym);
     153         103 :                 os_free(data->reauth_id);
     154         103 :                 os_free(data->last_eap_identity);
     155         103 :                 eap_sim_clear_keys(data, 0);
     156         103 :                 os_free(data);
     157             :         }
     158         103 : }
     159             : 
     160             : 
     161          20 : static int eap_sim_ext_sim_req(struct eap_sm *sm, struct eap_sim_data *data)
     162             : {
     163             :         char req[200], *pos, *end;
     164             :         size_t i;
     165             : 
     166          20 :         wpa_printf(MSG_DEBUG, "EAP-SIM: Use external SIM processing");
     167          20 :         pos = req;
     168          20 :         end = pos + sizeof(req);
     169          20 :         pos += os_snprintf(pos, end - pos, "GSM-AUTH");
     170          80 :         for (i = 0; i < data->num_chal; i++) {
     171          60 :                 pos += os_snprintf(pos, end - pos, ":");
     172          60 :                 pos += wpa_snprintf_hex(pos, end - pos, data->rand[i],
     173             :                                         GSM_RAND_LEN);
     174             :         }
     175             : 
     176          20 :         eap_sm_request_sim(sm, req);
     177          20 :         return 1;
     178             : }
     179             : 
     180             : 
     181          20 : static int eap_sim_ext_sim_result(struct eap_sm *sm, struct eap_sim_data *data,
     182             :                                   struct eap_peer_config *conf)
     183             : {
     184             :         char *resp, *pos;
     185             :         size_t i;
     186             : 
     187          20 :         wpa_printf(MSG_DEBUG,
     188             :                    "EAP-SIM: Use result from external SIM processing");
     189             : 
     190          20 :         resp = conf->external_sim_resp;
     191          20 :         conf->external_sim_resp = NULL;
     192             : 
     193          20 :         if (os_strncmp(resp, "GSM-AUTH:", 9) != 0) {
     194           2 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized external SIM processing response");
     195           2 :                 os_free(resp);
     196           2 :                 return -1;
     197             :         }
     198             : 
     199          18 :         pos = resp + 9;
     200          55 :         for (i = 0; i < data->num_chal; i++) {
     201          43 :                 wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND",
     202          43 :                             data->rand[i], GSM_RAND_LEN);
     203             : 
     204          43 :                 if (hexstr2bin(pos, data->kc[i], EAP_SIM_KC_LEN) < 0)
     205           3 :                         goto invalid;
     206          40 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc",
     207          40 :                                 data->kc[i], EAP_SIM_KC_LEN);
     208          40 :                 pos += EAP_SIM_KC_LEN * 2;
     209          40 :                 if (*pos != ':')
     210           1 :                         goto invalid;
     211          39 :                 pos++;
     212             : 
     213          39 :                 if (hexstr2bin(pos, data->sres[i], EAP_SIM_SRES_LEN) < 0)
     214           1 :                         goto invalid;
     215          38 :                 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES",
     216          38 :                                 data->sres[i], EAP_SIM_SRES_LEN);
     217          38 :                 pos += EAP_SIM_SRES_LEN * 2;
     218          38 :                 if (i + 1 < data->num_chal) {
     219          26 :                         if (*pos != ':')
     220           1 :                                 goto invalid;
     221          25 :                         pos++;
     222             :                 }
     223             :         }
     224             : 
     225          12 :         os_free(resp);
     226          12 :         return 0;
     227             : 
     228             : invalid:
     229           6 :         wpa_printf(MSG_DEBUG, "EAP-SIM: Invalid external SIM processing GSM-AUTH response");
     230           6 :         os_free(resp);
     231           6 :         return -1;
     232             : }
     233             : 
     234             : 
     235          95 : static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data)
     236             : {
     237             :         struct eap_peer_config *conf;
     238             : 
     239          95 :         wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm");
     240             : 
     241          95 :         conf = eap_get_config(sm);
     242          95 :         if (conf == NULL)
     243           0 :                 return -1;
     244             : 
     245          95 :         if (sm->external_sim) {
     246          40 :                 if (conf->external_sim_resp)
     247          20 :                         return eap_sim_ext_sim_result(sm, data, conf);
     248             :                 else
     249          20 :                         return eap_sim_ext_sim_req(sm, data);
     250             :         }
     251             : 
     252             : #ifdef PCSC_FUNCS
     253             :         if (conf->pcsc) {
     254             :                 if (scard_gsm_auth(sm->scard_ctx, data->rand[0],
     255             :                                    data->sres[0], data->kc[0]) ||
     256             :                     scard_gsm_auth(sm->scard_ctx, data->rand[1],
     257             :                                    data->sres[1], data->kc[1]) ||
     258             :                     (data->num_chal > 2 &&
     259             :                      scard_gsm_auth(sm->scard_ctx, data->rand[2],
     260             :                                     data->sres[2], data->kc[2]))) {
     261             :                         wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM "
     262             :                                    "authentication could not be completed");
     263             :                         return -1;
     264             :                 }
     265             :                 return 0;
     266             :         }
     267             : #endif /* PCSC_FUNCS */
     268             : 
     269             : #ifdef CONFIG_SIM_SIMULATOR
     270          55 :         if (conf->password) {
     271             :                 u8 opc[16], k[16];
     272             :                 const char *pos;
     273             :                 size_t i;
     274          54 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage "
     275             :                            "implementation for authentication");
     276          54 :                 if (conf->password_len < 65) {
     277           1 :                         wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-Milenage "
     278             :                                    "password");
     279           1 :                         return -1;
     280             :                 }
     281          53 :                 pos = (const char *) conf->password;
     282          53 :                 if (hexstr2bin(pos, k, 16))
     283           1 :                         return -1;
     284          52 :                 pos += 32;
     285          52 :                 if (*pos != ':')
     286           1 :                         return -1;
     287          51 :                 pos++;
     288             : 
     289          51 :                 if (hexstr2bin(pos, opc, 16))
     290           1 :                         return -1;
     291             : 
     292         176 :                 for (i = 0; i < data->num_chal; i++) {
     293         138 :                         if (gsm_milenage(opc, k, data->rand[i],
     294         138 :                                          data->sres[i], data->kc[i])) {
     295          12 :                                 wpa_printf(MSG_DEBUG, "EAP-SIM: "
     296             :                                            "GSM-Milenage authentication "
     297             :                                            "could not be completed");
     298          12 :                                 return -1;
     299             :                         }
     300         126 :                         wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND",
     301         126 :                                     data->rand[i], GSM_RAND_LEN);
     302         126 :                         wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES",
     303         126 :                                         data->sres[i], EAP_SIM_SRES_LEN);
     304         126 :                         wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc",
     305         126 :                                         data->kc[i], EAP_SIM_KC_LEN);
     306             :                 }
     307          38 :                 return 0;
     308             :         }
     309             : #endif /* CONFIG_SIM_SIMULATOR */
     310             : 
     311             : #ifdef CONFIG_SIM_HARDCODED
     312             :         /* These hardcoded Kc and SRES values are used for testing. RAND to
     313             :          * KC/SREC mapping is very bogus as far as real authentication is
     314             :          * concerned, but it is quite useful for cases where the AS is rotating
     315             :          * the order of pre-configured values. */
     316             :         {
     317             :                 size_t i;
     318             : 
     319             :                 wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES "
     320             :                            "values for testing");
     321             : 
     322             :                 for (i = 0; i < data->num_chal; i++) {
     323             :                         if (data->rand[i][0] == 0xaa) {
     324             :                                 os_memcpy(data->kc[i],
     325             :                                           "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7",
     326             :                                           EAP_SIM_KC_LEN);
     327             :                                 os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4",
     328             :                                           EAP_SIM_SRES_LEN);
     329             :                         } else if (data->rand[i][0] == 0xbb) {
     330             :                                 os_memcpy(data->kc[i],
     331             :                                           "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7",
     332             :                                           EAP_SIM_KC_LEN);
     333             :                                 os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4",
     334             :                                           EAP_SIM_SRES_LEN);
     335             :                         } else {
     336             :                                 os_memcpy(data->kc[i],
     337             :                                           "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7",
     338             :                                           EAP_SIM_KC_LEN);
     339             :                                 os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4",
     340             :                                           EAP_SIM_SRES_LEN);
     341             :                         }
     342             :                 }
     343             :         }
     344             : 
     345             :         return 0;
     346             : 
     347             : #else /* CONFIG_SIM_HARDCODED */
     348             : 
     349           1 :         wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm "
     350             :                    "enabled");
     351           1 :         return -1;
     352             : 
     353             : #endif /* CONFIG_SIM_HARDCODED */
     354             : }
     355             : 
     356             : 
     357         110 : static int eap_sim_supported_ver(int version)
     358             : {
     359         110 :         return version == EAP_SIM_VERSION;
     360             : }
     361             : 
     362             : 
     363             : #define CLEAR_PSEUDONYM 0x01
     364             : #define CLEAR_REAUTH_ID 0x02
     365             : #define CLEAR_EAP_ID    0x04
     366             : 
     367         271 : static void eap_sim_clear_identities(struct eap_sm *sm,
     368             :                                      struct eap_sim_data *data, int id)
     369             : {
     370         271 :         if ((id & CLEAR_PSEUDONYM) && data->pseudonym) {
     371           2 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old pseudonym");
     372           2 :                 os_free(data->pseudonym);
     373           2 :                 data->pseudonym = NULL;
     374           2 :                 data->pseudonym_len = 0;
     375           2 :                 eap_set_anon_id(sm, NULL, 0);
     376             :         }
     377         271 :         if ((id & CLEAR_REAUTH_ID) && data->reauth_id) {
     378          14 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old reauth_id");
     379          14 :                 os_free(data->reauth_id);
     380          14 :                 data->reauth_id = NULL;
     381          14 :                 data->reauth_id_len = 0;
     382             :         }
     383         271 :         if ((id & CLEAR_EAP_ID) && data->last_eap_identity) {
     384           1 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old eap_id");
     385           1 :                 os_free(data->last_eap_identity);
     386           1 :                 data->last_eap_identity = NULL;
     387           1 :                 data->last_eap_identity_len = 0;
     388             :         }
     389         271 : }
     390             : 
     391             : 
     392          57 : static int eap_sim_learn_ids(struct eap_sm *sm, struct eap_sim_data *data,
     393             :                              struct eap_sim_attrs *attr)
     394             : {
     395          57 :         if (attr->next_pseudonym) {
     396          45 :                 const u8 *identity = NULL;
     397          45 :                 size_t identity_len = 0;
     398          45 :                 const u8 *realm = NULL;
     399          45 :                 size_t realm_len = 0;
     400             : 
     401          90 :                 wpa_hexdump_ascii(MSG_DEBUG,
     402             :                                   "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
     403          45 :                                   attr->next_pseudonym,
     404             :                                   attr->next_pseudonym_len);
     405          45 :                 os_free(data->pseudonym);
     406             :                 /* Look for the realm of the permanent identity */
     407          45 :                 identity = eap_get_config_identity(sm, &identity_len);
     408          45 :                 if (identity) {
     409         810 :                         for (realm = identity, realm_len = identity_len;
     410         720 :                              realm_len > 0; realm_len--, realm++) {
     411         729 :                                 if (*realm == '@')
     412           9 :                                         break;
     413             :                         }
     414             :                 }
     415          45 :                 data->pseudonym = os_malloc(attr->next_pseudonym_len +
     416             :                                             realm_len);
     417          45 :                 if (data->pseudonym == NULL) {
     418           1 :                         wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
     419             :                                    "next pseudonym");
     420           1 :                         data->pseudonym_len = 0;
     421           1 :                         return -1;
     422             :                 }
     423          44 :                 os_memcpy(data->pseudonym, attr->next_pseudonym,
     424             :                           attr->next_pseudonym_len);
     425          44 :                 if (realm_len) {
     426           9 :                         os_memcpy(data->pseudonym + attr->next_pseudonym_len,
     427             :                                   realm, realm_len);
     428             :                 }
     429          44 :                 data->pseudonym_len = attr->next_pseudonym_len + realm_len;
     430          44 :                 eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len);
     431             :         }
     432             : 
     433          56 :         if (attr->next_reauth_id) {
     434          55 :                 os_free(data->reauth_id);
     435          55 :                 data->reauth_id = os_malloc(attr->next_reauth_id_len);
     436          55 :                 if (data->reauth_id == NULL) {
     437           1 :                         wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for "
     438             :                                    "next reauth_id");
     439           1 :                         data->reauth_id_len = 0;
     440           1 :                         return -1;
     441             :                 }
     442          54 :                 os_memcpy(data->reauth_id, attr->next_reauth_id,
     443             :                           attr->next_reauth_id_len);
     444          54 :                 data->reauth_id_len = attr->next_reauth_id_len;
     445         108 :                 wpa_hexdump_ascii(MSG_DEBUG,
     446             :                                   "EAP-SIM: (encr) AT_NEXT_REAUTH_ID",
     447          54 :                                   data->reauth_id,
     448             :                                   data->reauth_id_len);
     449             :         }
     450             : 
     451          55 :         return 0;
     452             : }
     453             : 
     454             : 
     455          56 : static struct wpabuf * eap_sim_client_error(struct eap_sim_data *data, u8 id,
     456             :                                             int err)
     457             : {
     458             :         struct eap_sim_msg *msg;
     459             : 
     460          56 :         eap_sim_state(data, FAILURE);
     461          56 :         data->num_id_req = 0;
     462          56 :         data->num_notification = 0;
     463             : 
     464          56 :         wpa_printf(MSG_DEBUG, "EAP-SIM: Send Client-Error (error code %d)",
     465             :                    err);
     466          56 :         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
     467             :                                EAP_SIM_SUBTYPE_CLIENT_ERROR);
     468          56 :         eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0);
     469          56 :         return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
     470             : }
     471             : 
     472             : 
     473         106 : static struct wpabuf * eap_sim_response_start(struct eap_sm *sm,
     474             :                                               struct eap_sim_data *data, u8 id,
     475             :                                               enum eap_sim_id_req id_req)
     476             : {
     477         106 :         const u8 *identity = NULL;
     478         106 :         size_t identity_len = 0;
     479             :         struct eap_sim_msg *msg;
     480             : 
     481         106 :         data->reauth = 0;
     482         106 :         if (id_req == ANY_ID && data->reauth_id) {
     483          17 :                 identity = data->reauth_id;
     484          17 :                 identity_len = data->reauth_id_len;
     485          17 :                 data->reauth = 1;
     486         173 :         } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) &&
     487          84 :                    data->pseudonym) {
     488           5 :                 identity = data->pseudonym;
     489           5 :                 identity_len = data->pseudonym_len;
     490           5 :                 eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID);
     491          84 :         } else if (id_req != NO_ID_REQ) {
     492          82 :                 identity = eap_get_config_identity(sm, &identity_len);
     493          82 :                 if (identity) {
     494          82 :                         eap_sim_clear_identities(sm, data, CLEAR_PSEUDONYM |
     495             :                                                  CLEAR_REAUTH_ID);
     496             :                 }
     497             :         }
     498         106 :         if (id_req != NO_ID_REQ)
     499         104 :                 eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
     500             : 
     501         106 :         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id);
     502         106 :         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
     503             :                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START);
     504         106 :         if (!data->reauth) {
     505          89 :                 wpa_hexdump(MSG_DEBUG, "   AT_NONCE_MT",
     506          89 :                             data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
     507          89 :                 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0,
     508          89 :                                 data->nonce_mt, EAP_SIM_NONCE_MT_LEN);
     509          89 :                 wpa_printf(MSG_DEBUG, "   AT_SELECTED_VERSION %d",
     510             :                            data->selected_version);
     511          89 :                 eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION,
     512          89 :                                 data->selected_version, NULL, 0);
     513             :         }
     514             : 
     515         106 :         if (identity) {
     516         104 :                 wpa_hexdump_ascii(MSG_DEBUG, "   AT_IDENTITY",
     517             :                                   identity, identity_len);
     518         104 :                 eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len,
     519             :                                 identity, identity_len);
     520             :         }
     521             : 
     522         106 :         return eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0);
     523             : }
     524             : 
     525             : 
     526          45 : static struct wpabuf * eap_sim_response_challenge(struct eap_sim_data *data,
     527             :                                                   u8 id)
     528             : {
     529             :         struct eap_sim_msg *msg;
     530             : 
     531          45 :         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", id);
     532          45 :         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
     533             :                                EAP_SIM_SUBTYPE_CHALLENGE);
     534          45 :         if (data->use_result_ind) {
     535           6 :                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
     536           6 :                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
     537             :         }
     538          45 :         wpa_printf(MSG_DEBUG, "   AT_MAC");
     539          45 :         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
     540          90 :         return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut,
     541          45 :                                   (u8 *) data->sres,
     542          45 :                                   data->num_chal * EAP_SIM_SRES_LEN);
     543             : }
     544             : 
     545             : 
     546          13 : static struct wpabuf * eap_sim_response_reauth(struct eap_sim_data *data,
     547             :                                                u8 id, int counter_too_small,
     548             :                                                const u8 *nonce_s)
     549             : {
     550             :         struct eap_sim_msg *msg;
     551             :         unsigned int counter;
     552             : 
     553          13 :         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)",
     554             :                    id);
     555          13 :         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM,
     556             :                                EAP_SIM_SUBTYPE_REAUTHENTICATION);
     557          13 :         wpa_printf(MSG_DEBUG, "   AT_IV");
     558          13 :         wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
     559          13 :         eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
     560             : 
     561          13 :         if (counter_too_small) {
     562           1 :                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER_TOO_SMALL");
     563           1 :                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0);
     564           1 :                 counter = data->counter_too_small;
     565             :         } else
     566          12 :                 counter = data->counter;
     567             : 
     568          13 :         wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", counter);
     569          13 :         eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
     570             : 
     571          13 :         if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
     572           2 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
     573             :                            "AT_ENCR_DATA");
     574           2 :                 eap_sim_msg_free(msg);
     575           2 :                 return NULL;
     576             :         }
     577          11 :         if (data->use_result_ind) {
     578           4 :                 wpa_printf(MSG_DEBUG, "   AT_RESULT_IND");
     579           4 :                 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
     580             :         }
     581          11 :         wpa_printf(MSG_DEBUG, "   AT_MAC");
     582          11 :         eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
     583          11 :         return eap_sim_msg_finish(msg, EAP_TYPE_SIM, data->k_aut, nonce_s,
     584             :                                   EAP_SIM_NONCE_S_LEN);
     585             : }
     586             : 
     587             : 
     588          14 : static struct wpabuf * eap_sim_response_notification(struct eap_sim_data *data,
     589             :                                                      u8 id, u16 notification)
     590             : {
     591             :         struct eap_sim_msg *msg;
     592          14 :         u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL;
     593             : 
     594          14 :         wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", id);
     595          14 :         msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id,
     596             :                                EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION);
     597          14 :         if (k_aut && data->reauth) {
     598           3 :                 wpa_printf(MSG_DEBUG, "   AT_IV");
     599           3 :                 wpa_printf(MSG_DEBUG, "   AT_ENCR_DATA");
     600           3 :                 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
     601             :                                            EAP_SIM_AT_ENCR_DATA);
     602           3 :                 wpa_printf(MSG_DEBUG, "   *AT_COUNTER %d", data->counter);
     603           3 :                 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
     604             :                                 NULL, 0);
     605           3 :                 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
     606             :                                              EAP_SIM_AT_PADDING)) {
     607           2 :                         wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
     608             :                                    "AT_ENCR_DATA");
     609           2 :                         eap_sim_msg_free(msg);
     610           2 :                         return NULL;
     611             :                 }
     612             :         }
     613          12 :         if (k_aut) {
     614           6 :                 wpa_printf(MSG_DEBUG, "   AT_MAC");
     615           6 :                 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
     616             :         }
     617          12 :         return eap_sim_msg_finish(msg, EAP_TYPE_SIM, k_aut, (u8 *) "", 0);
     618             : }
     619             : 
     620             : 
     621         112 : static struct wpabuf * eap_sim_process_start(struct eap_sm *sm,
     622             :                                              struct eap_sim_data *data, u8 id,
     623             :                                              struct eap_sim_attrs *attr)
     624             : {
     625         112 :         int selected_version = -1, id_error;
     626             :         size_t i;
     627             :         u8 *pos;
     628             : 
     629         112 :         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start");
     630         112 :         if (attr->version_list == NULL) {
     631           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in "
     632             :                            "SIM/Start");
     633           1 :                 return eap_sim_client_error(data, id,
     634             :                                             EAP_SIM_UNSUPPORTED_VERSION);
     635             :         }
     636             : 
     637         111 :         os_free(data->ver_list);
     638         111 :         data->ver_list = os_malloc(attr->version_list_len);
     639         111 :         if (data->ver_list == NULL) {
     640           1 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate "
     641             :                            "memory for version list");
     642           1 :                 return eap_sim_client_error(data, id,
     643             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     644             :         }
     645         110 :         os_memcpy(data->ver_list, attr->version_list, attr->version_list_len);
     646         110 :         data->ver_list_len = attr->version_list_len;
     647         110 :         pos = data->ver_list;
     648         111 :         for (i = 0; i < data->ver_list_len / 2; i++) {
     649         110 :                 int ver = pos[0] * 256 + pos[1];
     650         110 :                 pos += 2;
     651         110 :                 if (eap_sim_supported_ver(ver)) {
     652         109 :                         selected_version = ver;
     653         109 :                         break;
     654             :                 }
     655             :         }
     656         110 :         if (selected_version < 0) {
     657           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported "
     658             :                            "version");
     659           1 :                 return eap_sim_client_error(data, id,
     660             :                                             EAP_SIM_UNSUPPORTED_VERSION);
     661             :         }
     662         109 :         wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d",
     663             :                    selected_version);
     664         109 :         data->selected_version = selected_version;
     665             : 
     666         109 :         id_error = 0;
     667         109 :         switch (attr->id_req) {
     668             :         case NO_ID_REQ:
     669           2 :                 break;
     670             :         case ANY_ID:
     671          98 :                 if (data->num_id_req > 0)
     672           1 :                         id_error++;
     673          98 :                 data->num_id_req++;
     674          98 :                 break;
     675             :         case FULLAUTH_ID:
     676           5 :                 if (data->num_id_req > 1)
     677           1 :                         id_error++;
     678           5 :                 data->num_id_req++;
     679           5 :                 break;
     680             :         case PERMANENT_ID:
     681           4 :                 if (data->num_id_req > 2)
     682           1 :                         id_error++;
     683           4 :                 data->num_id_req++;
     684           4 :                 break;
     685             :         }
     686         109 :         if (id_error) {
     687           3 :                 wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests "
     688             :                            "used within one authentication");
     689           3 :                 return eap_sim_client_error(data, id,
     690             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     691             :         }
     692             : 
     693         106 :         return eap_sim_response_start(sm, data, id, attr->id_req);
     694             : }
     695             : 
     696             : 
     697         100 : static struct wpabuf * eap_sim_process_challenge(struct eap_sm *sm,
     698             :                                                  struct eap_sim_data *data,
     699             :                                                  u8 id,
     700             :                                                  const struct wpabuf *reqData,
     701             :                                                  struct eap_sim_attrs *attr)
     702             : {
     703             :         const u8 *identity;
     704             :         size_t identity_len;
     705             :         struct eap_sim_attrs eattr;
     706             :         int res;
     707             : 
     708         100 :         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge");
     709         100 :         data->reauth = 0;
     710         100 :         if (!attr->mac || !attr->rand) {
     711           4 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
     712             :                            "did not include%s%s",
     713           2 :                            !attr->mac ? " AT_MAC" : "",
     714           2 :                            !attr->rand ? " AT_RAND" : "");
     715           2 :                 return eap_sim_client_error(data, id,
     716             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     717             :         }
     718             : 
     719          98 :         wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges",
     720             :                    (unsigned long) attr->num_chal);
     721          98 :         if (attr->num_chal < data->min_num_chal) {
     722           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of "
     723             :                            "challenges (%lu)", (unsigned long) attr->num_chal);
     724           1 :                 return eap_sim_client_error(data, id,
     725             :                                             EAP_SIM_INSUFFICIENT_NUM_OF_CHAL);
     726             :         }
     727          97 :         if (attr->num_chal > 3) {
     728           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges "
     729             :                            "(%lu)", (unsigned long) attr->num_chal);
     730           1 :                 return eap_sim_client_error(data, id,
     731             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     732             :         }
     733             : 
     734             :         /* Verify that RANDs are different */
     735          96 :         if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN,
     736          96 :                    GSM_RAND_LEN) == 0 ||
     737         192 :             (attr->num_chal > 2 &&
     738          96 :              (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN,
     739          95 :                         GSM_RAND_LEN) == 0 ||
     740          95 :               os_memcmp(attr->rand + GSM_RAND_LEN,
     741             :                         attr->rand + 2 * GSM_RAND_LEN,
     742             :                         GSM_RAND_LEN) == 0))) {
     743           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times");
     744           1 :                 return eap_sim_client_error(data, id,
     745             :                                             EAP_SIM_RAND_NOT_FRESH);
     746             :         }
     747             : 
     748          95 :         os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN);
     749          95 :         data->num_chal = attr->num_chal;
     750             : 
     751          95 :         res = eap_sim_gsm_auth(sm, data);
     752          95 :         if (res > 0) {
     753          20 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: Wait for external SIM processing");
     754          20 :                 return NULL;
     755             :         }
     756          75 :         if (res) {
     757          25 :                 wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed");
     758          25 :                 return eap_sim_client_error(data, id,
     759             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     760             :         }
     761          50 :         if (data->last_eap_identity) {
     762           1 :                 identity = data->last_eap_identity;
     763           1 :                 identity_len = data->last_eap_identity_len;
     764          49 :         } else if (data->pseudonym) {
     765           3 :                 identity = data->pseudonym;
     766           3 :                 identity_len = data->pseudonym_len;
     767             :         } else
     768          46 :                 identity = eap_get_config_identity(sm, &identity_len);
     769          50 :         wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
     770             :                           "derivation", identity, identity_len);
     771         100 :         eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
     772          50 :                           data->selected_version, data->ver_list,
     773          50 :                           data->ver_list_len, data->num_chal,
     774          50 :                           (const u8 *) data->kc, data->mk);
     775          50 :         eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
     776          50 :                             data->emsk);
     777          50 :         if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, data->nonce_mt,
     778             :                                EAP_SIM_NONCE_MT_LEN)) {
     779           3 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
     780             :                            "used invalid AT_MAC");
     781           3 :                 return eap_sim_client_error(data, id,
     782             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     783             :         }
     784             : 
     785             :         /* Old reauthentication identity must not be used anymore. In
     786             :          * other words, if no new reauth identity is received, full
     787             :          * authentication will be used on next reauthentication (using
     788             :          * pseudonym identity or permanent identity). */
     789          47 :         eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
     790             : 
     791          47 :         if (attr->encr_data) {
     792             :                 u8 *decrypted;
     793          47 :                 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
     794             :                                                attr->encr_data_len, attr->iv,
     795             :                                                &eattr, 0);
     796          47 :                 if (decrypted == NULL) {
     797           2 :                         return eap_sim_client_error(
     798             :                                 data, id, EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     799             :                 }
     800          45 :                 eap_sim_learn_ids(sm, data, &eattr);
     801          45 :                 os_free(decrypted);
     802             :         }
     803             : 
     804          45 :         if (data->result_ind && attr->result_ind)
     805           6 :                 data->use_result_ind = 1;
     806             : 
     807          45 :         if (data->state != FAILURE) {
     808          45 :                 eap_sim_state(data, data->use_result_ind ?
     809             :                               RESULT_SUCCESS : SUCCESS);
     810             :         }
     811             : 
     812          45 :         data->num_id_req = 0;
     813          45 :         data->num_notification = 0;
     814             :         /* RFC 4186 specifies that counter is initialized to one after
     815             :          * fullauth, but initializing it to zero makes it easier to implement
     816             :          * reauth verification. */
     817          45 :         data->counter = 0;
     818          45 :         return eap_sim_response_challenge(data, id);
     819             : }
     820             : 
     821             : 
     822           4 : static int eap_sim_process_notification_reauth(struct eap_sim_data *data,
     823             :                                                struct eap_sim_attrs *attr)
     824             : {
     825             :         struct eap_sim_attrs eattr;
     826             :         u8 *decrypted;
     827             : 
     828           4 :         if (attr->encr_data == NULL || attr->iv == NULL) {
     829           0 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after "
     830             :                            "reauth did not include encrypted data");
     831           0 :                 return -1;
     832             :         }
     833             : 
     834           4 :         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
     835             :                                        attr->encr_data_len, attr->iv, &eattr,
     836             :                                        0);
     837           4 :         if (decrypted == NULL) {
     838           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
     839             :                            "data from notification message");
     840           1 :                 return -1;
     841             :         }
     842             : 
     843           3 :         if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) {
     844           0 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification "
     845             :                            "message does not match with counter in reauth "
     846             :                            "message");
     847           0 :                 os_free(decrypted);
     848           0 :                 return -1;
     849             :         }
     850             : 
     851           3 :         os_free(decrypted);
     852           3 :         return 0;
     853             : }
     854             : 
     855             : 
     856          11 : static int eap_sim_process_notification_auth(struct eap_sim_data *data,
     857             :                                              const struct wpabuf *reqData,
     858             :                                              struct eap_sim_attrs *attr)
     859             : {
     860          11 :         if (attr->mac == NULL) {
     861           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth "
     862             :                            "Notification message");
     863           1 :                 return -1;
     864             :         }
     865             : 
     866          10 :         if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
     867             :         {
     868           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Notification message "
     869             :                            "used invalid AT_MAC");
     870           1 :                 return -1;
     871             :         }
     872             : 
     873          13 :         if (data->reauth &&
     874           4 :             eap_sim_process_notification_reauth(data, attr)) {
     875           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification "
     876             :                            "message after reauth");
     877           1 :                 return -1;
     878             :         }
     879             : 
     880           8 :         return 0;
     881             : }
     882             : 
     883             : 
     884          19 : static struct wpabuf * eap_sim_process_notification(
     885             :         struct eap_sm *sm, struct eap_sim_data *data, u8 id,
     886             :         const struct wpabuf *reqData, struct eap_sim_attrs *attr)
     887             : {
     888          19 :         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification");
     889          19 :         if (data->num_notification > 0) {
     890           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: too many notification "
     891             :                            "rounds (only one allowed)");
     892           1 :                 return eap_sim_client_error(data, id,
     893             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     894             :         }
     895          18 :         data->num_notification++;
     896          18 :         if (attr->notification == -1) {
     897           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in "
     898             :                            "Notification message");
     899           1 :                 return eap_sim_client_error(data, id,
     900             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     901             :         }
     902             : 
     903          28 :         if ((attr->notification & 0x4000) == 0 &&
     904          11 :             eap_sim_process_notification_auth(data, reqData, attr)) {
     905           3 :                 return eap_sim_client_error(data, id,
     906             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     907             :         }
     908             : 
     909          14 :         eap_sim_report_notification(sm->msg_ctx, attr->notification, 0);
     910          14 :         if (attr->notification >= 0 && attr->notification < 32768) {
     911           5 :                 eap_sim_state(data, FAILURE);
     912          17 :         } else if (attr->notification == EAP_SIM_SUCCESS &&
     913           8 :                    data->state == RESULT_SUCCESS)
     914           8 :                 eap_sim_state(data, SUCCESS);
     915          14 :         return eap_sim_response_notification(data, id, attr->notification);
     916             : }
     917             : 
     918             : 
     919          16 : static struct wpabuf * eap_sim_process_reauthentication(
     920             :         struct eap_sm *sm, struct eap_sim_data *data, u8 id,
     921             :         const struct wpabuf *reqData, struct eap_sim_attrs *attr)
     922             : {
     923             :         struct eap_sim_attrs eattr;
     924             :         u8 *decrypted;
     925             : 
     926          16 :         wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication");
     927             : 
     928          16 :         if (data->reauth_id == NULL) {
     929           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying "
     930             :                            "reauthentication, but no reauth_id available");
     931           1 :                 return eap_sim_client_error(data, id,
     932             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     933             :         }
     934             : 
     935          15 :         data->reauth = 1;
     936          15 :         if (eap_sim_verify_mac(data->k_aut, reqData, attr->mac, (u8 *) "", 0))
     937             :         {
     938           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
     939             :                            "did not have valid AT_MAC");
     940           1 :                 return eap_sim_client_error(data, id,
     941             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     942             :         }
     943             : 
     944          14 :         if (attr->encr_data == NULL || attr->iv == NULL) {
     945           0 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
     946             :                            "message did not include encrypted data");
     947           0 :                 return eap_sim_client_error(data, id,
     948             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     949             :         }
     950             : 
     951          14 :         decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
     952             :                                        attr->encr_data_len, attr->iv, &eattr,
     953             :                                        0);
     954          14 :         if (decrypted == NULL) {
     955           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
     956             :                            "data from reauthentication message");
     957           1 :                 return eap_sim_client_error(data, id,
     958             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     959             :         }
     960             : 
     961          13 :         if (eattr.nonce_s == NULL || eattr.counter < 0) {
     962           0 :                 wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet",
     963           0 :                            !eattr.nonce_s ? " AT_NONCE_S" : "",
     964           0 :                            eattr.counter < 0 ? " AT_COUNTER" : "");
     965           0 :                 os_free(decrypted);
     966           0 :                 return eap_sim_client_error(data, id,
     967             :                                             EAP_SIM_UNABLE_TO_PROCESS_PACKET);
     968             :         }
     969             : 
     970          13 :         if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) {
     971             :                 struct wpabuf *res;
     972           1 :                 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter "
     973             :                            "(%d <= %d)", eattr.counter, data->counter);
     974           1 :                 data->counter_too_small = eattr.counter;
     975             : 
     976             :                 /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current
     977             :                  * reauth_id must not be used to start a new reauthentication.
     978             :                  * However, since it was used in the last EAP-Response-Identity
     979             :                  * packet, it has to saved for the following fullauth to be
     980             :                  * used in MK derivation. */
     981           1 :                 os_free(data->last_eap_identity);
     982           1 :                 data->last_eap_identity = data->reauth_id;
     983           1 :                 data->last_eap_identity_len = data->reauth_id_len;
     984           1 :                 data->reauth_id = NULL;
     985           1 :                 data->reauth_id_len = 0;
     986             : 
     987           1 :                 res = eap_sim_response_reauth(data, id, 1, eattr.nonce_s);
     988           1 :                 os_free(decrypted);
     989             : 
     990           1 :                 return res;
     991             :         }
     992          12 :         data->counter = eattr.counter;
     993             : 
     994          12 :         os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN);
     995          12 :         wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S",
     996          12 :                     data->nonce_s, EAP_SIM_NONCE_S_LEN);
     997             : 
     998          24 :         eap_sim_derive_keys_reauth(data->counter,
     999          12 :                                    data->reauth_id, data->reauth_id_len,
    1000          12 :                                    data->nonce_s, data->mk, data->msk,
    1001          12 :                                    data->emsk);
    1002          12 :         eap_sim_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID);
    1003          12 :         eap_sim_learn_ids(sm, data, &eattr);
    1004             : 
    1005          12 :         if (data->result_ind && attr->result_ind)
    1006           4 :                 data->use_result_ind = 1;
    1007             : 
    1008          12 :         if (data->state != FAILURE) {
    1009          12 :                 eap_sim_state(data, data->use_result_ind ?
    1010             :                               RESULT_SUCCESS : SUCCESS);
    1011             :         }
    1012             : 
    1013          12 :         data->num_id_req = 0;
    1014          12 :         data->num_notification = 0;
    1015          12 :         if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) {
    1016           1 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of "
    1017             :                            "fast reauths performed - force fullauth");
    1018           1 :                 eap_sim_clear_identities(sm, data,
    1019             :                                          CLEAR_REAUTH_ID | CLEAR_EAP_ID);
    1020             :         }
    1021          12 :         os_free(decrypted);
    1022          12 :         return eap_sim_response_reauth(data, id, 0, data->nonce_s);
    1023             : }
    1024             : 
    1025             : 
    1026         255 : static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv,
    1027             :                                        struct eap_method_ret *ret,
    1028             :                                        const struct wpabuf *reqData)
    1029             : {
    1030         255 :         struct eap_sim_data *data = priv;
    1031             :         const struct eap_hdr *req;
    1032             :         u8 subtype, id;
    1033             :         struct wpabuf *res;
    1034             :         const u8 *pos;
    1035             :         struct eap_sim_attrs attr;
    1036             :         size_t len;
    1037             : 
    1038         255 :         wpa_hexdump_buf(MSG_DEBUG, "EAP-SIM: EAP data", reqData);
    1039         255 :         if (eap_get_config_identity(sm, &len) == NULL) {
    1040           0 :                 wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured");
    1041           0 :                 eap_sm_request_identity(sm);
    1042           0 :                 ret->ignore = TRUE;
    1043           0 :                 return NULL;
    1044             :         }
    1045             : 
    1046         255 :         pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len);
    1047         255 :         if (pos == NULL || len < 3) {
    1048           1 :                 ret->ignore = TRUE;
    1049           1 :                 return NULL;
    1050             :         }
    1051         254 :         req = wpabuf_head(reqData);
    1052         254 :         id = req->identifier;
    1053         254 :         len = be_to_host16(req->length);
    1054             : 
    1055         254 :         ret->ignore = FALSE;
    1056         254 :         ret->methodState = METHOD_MAY_CONT;
    1057         254 :         ret->decision = DECISION_FAIL;
    1058         254 :         ret->allowNotifications = TRUE;
    1059             : 
    1060         254 :         subtype = *pos++;
    1061         254 :         wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype);
    1062         254 :         pos += 2; /* Reserved */
    1063             : 
    1064         254 :         if (eap_sim_parse_attr(pos, wpabuf_head_u8(reqData) + len, &attr, 0,
    1065             :                                0)) {
    1066           5 :                 res = eap_sim_client_error(data, id,
    1067             :                                            EAP_SIM_UNABLE_TO_PROCESS_PACKET);
    1068           5 :                 goto done;
    1069             :         }
    1070             : 
    1071         249 :         switch (subtype) {
    1072             :         case EAP_SIM_SUBTYPE_START:
    1073         112 :                 res = eap_sim_process_start(sm, data, id, &attr);
    1074         112 :                 break;
    1075             :         case EAP_SIM_SUBTYPE_CHALLENGE:
    1076         100 :                 res = eap_sim_process_challenge(sm, data, id, reqData, &attr);
    1077         100 :                 break;
    1078             :         case EAP_SIM_SUBTYPE_NOTIFICATION:
    1079          19 :                 res = eap_sim_process_notification(sm, data, id, reqData,
    1080             :                                                    &attr);
    1081          19 :                 break;
    1082             :         case EAP_SIM_SUBTYPE_REAUTHENTICATION:
    1083          16 :                 res = eap_sim_process_reauthentication(sm, data, id, reqData,
    1084             :                                                        &attr);
    1085          16 :                 break;
    1086             :         case EAP_SIM_SUBTYPE_CLIENT_ERROR:
    1087           1 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error");
    1088           1 :                 res = eap_sim_client_error(data, id,
    1089             :                                            EAP_SIM_UNABLE_TO_PROCESS_PACKET);
    1090           1 :                 break;
    1091             :         default:
    1092           1 :                 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype);
    1093           1 :                 res = eap_sim_client_error(data, id,
    1094             :                                            EAP_SIM_UNABLE_TO_PROCESS_PACKET);
    1095           1 :                 break;
    1096             :         }
    1097             : 
    1098             : done:
    1099         254 :         if (data->state == FAILURE) {
    1100          61 :                 ret->decision = DECISION_FAIL;
    1101          61 :                 ret->methodState = METHOD_DONE;
    1102         193 :         } else if (data->state == SUCCESS) {
    1103          55 :                 ret->decision = data->use_result_ind ?
    1104             :                         DECISION_UNCOND_SUCC : DECISION_COND_SUCC;
    1105          55 :                 ret->methodState = data->use_result_ind ?
    1106             :                         METHOD_DONE : METHOD_MAY_CONT;
    1107         138 :         } else if (data->state == RESULT_SUCCESS)
    1108          10 :                 ret->methodState = METHOD_CONT;
    1109             : 
    1110         254 :         if (ret->methodState == METHOD_DONE) {
    1111          69 :                 ret->allowNotifications = FALSE;
    1112             :         }
    1113             : 
    1114         254 :         return res;
    1115             : }
    1116             : 
    1117             : 
    1118          47 : static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv)
    1119             : {
    1120          47 :         struct eap_sim_data *data = priv;
    1121          47 :         return data->pseudonym || data->reauth_id;
    1122             : }
    1123             : 
    1124             : 
    1125          20 : static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv)
    1126             : {
    1127          20 :         struct eap_sim_data *data = priv;
    1128          20 :         eap_sim_clear_identities(sm, data, CLEAR_EAP_ID);
    1129          20 :         data->use_result_ind = 0;
    1130          20 :         eap_sim_clear_keys(data, 1);
    1131          20 : }
    1132             : 
    1133             : 
    1134          18 : static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv)
    1135             : {
    1136          18 :         struct eap_sim_data *data = priv;
    1137          18 :         if (random_get_bytes(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) {
    1138           1 :                 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data "
    1139             :                            "for NONCE_MT");
    1140           1 :                 eap_sim_deinit(sm, data);
    1141           1 :                 return NULL;
    1142             :         }
    1143          17 :         data->num_id_req = 0;
    1144          17 :         data->num_notification = 0;
    1145          17 :         eap_sim_state(data, CONTINUE);
    1146          17 :         return priv;
    1147             : }
    1148             : 
    1149             : 
    1150          18 : static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv,
    1151             :                                        size_t *len)
    1152             : {
    1153          18 :         struct eap_sim_data *data = priv;
    1154             : 
    1155          18 :         if (data->reauth_id) {
    1156          18 :                 *len = data->reauth_id_len;
    1157          18 :                 return data->reauth_id;
    1158             :         }
    1159             : 
    1160           0 :         if (data->pseudonym) {
    1161           0 :                 *len = data->pseudonym_len;
    1162           0 :                 return data->pseudonym;
    1163             :         }
    1164             : 
    1165           0 :         return NULL;
    1166             : }
    1167             : 
    1168             : 
    1169         254 : static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv)
    1170             : {
    1171         254 :         struct eap_sim_data *data = priv;
    1172         254 :         return data->state == SUCCESS;
    1173             : }
    1174             : 
    1175             : 
    1176          55 : static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
    1177             : {
    1178          55 :         struct eap_sim_data *data = priv;
    1179             :         u8 *key;
    1180             : 
    1181          55 :         if (data->state != SUCCESS)
    1182           0 :                 return NULL;
    1183             : 
    1184          55 :         key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
    1185          55 :         if (key == NULL)
    1186           1 :                 return NULL;
    1187             : 
    1188          54 :         *len = EAP_SIM_KEYING_DATA_LEN;
    1189          54 :         os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
    1190             : 
    1191          54 :         return key;
    1192             : }
    1193             : 
    1194             : 
    1195          55 : static u8 * eap_sim_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
    1196             : {
    1197          55 :         struct eap_sim_data *data = priv;
    1198             :         u8 *id;
    1199             : 
    1200          55 :         if (data->state != SUCCESS)
    1201           0 :                 return NULL;
    1202             : 
    1203          55 :         *len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN;
    1204          55 :         id = os_malloc(*len);
    1205          55 :         if (id == NULL)
    1206           1 :                 return NULL;
    1207             : 
    1208          54 :         id[0] = EAP_TYPE_SIM;
    1209          54 :         os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN);
    1210          54 :         os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN, data->nonce_mt,
    1211             :                   EAP_SIM_NONCE_MT_LEN);
    1212          54 :         wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len);
    1213             : 
    1214          54 :         return id;
    1215             : }
    1216             : 
    1217             : 
    1218           7 : static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
    1219             : {
    1220           7 :         struct eap_sim_data *data = priv;
    1221             :         u8 *key;
    1222             : 
    1223           7 :         if (data->state != SUCCESS)
    1224           0 :                 return NULL;
    1225             : 
    1226           7 :         key = os_malloc(EAP_EMSK_LEN);
    1227           7 :         if (key == NULL)
    1228           1 :                 return NULL;
    1229             : 
    1230           6 :         *len = EAP_EMSK_LEN;
    1231           6 :         os_memcpy(key, data->emsk, EAP_EMSK_LEN);
    1232             : 
    1233           6 :         return key;
    1234             : }
    1235             : 
    1236             : 
    1237          49 : int eap_peer_sim_register(void)
    1238             : {
    1239             :         struct eap_method *eap;
    1240             : 
    1241          49 :         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
    1242             :                                     EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
    1243          49 :         if (eap == NULL)
    1244           0 :                 return -1;
    1245             : 
    1246          49 :         eap->init = eap_sim_init;
    1247          49 :         eap->deinit = eap_sim_deinit;
    1248          49 :         eap->process = eap_sim_process;
    1249          49 :         eap->isKeyAvailable = eap_sim_isKeyAvailable;
    1250          49 :         eap->getKey = eap_sim_getKey;
    1251          49 :         eap->getSessionId = eap_sim_get_session_id;
    1252          49 :         eap->has_reauth_data = eap_sim_has_reauth_data;
    1253          49 :         eap->deinit_for_reauth = eap_sim_deinit_for_reauth;
    1254          49 :         eap->init_for_reauth = eap_sim_init_for_reauth;
    1255          49 :         eap->get_identity = eap_sim_get_identity;
    1256          49 :         eap->get_emsk = eap_sim_get_emsk;
    1257             : 
    1258          49 :         return eap_peer_method_register(eap);
    1259             : }

Generated by: LCOV version 1.10