Coverage Report

Created: 2025-04-24 06:18

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