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