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