1 /*
2 * hostapd / EAP-SIM (RFC 4186)
3 * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10
11 #include "common.h"
12 #include "crypto/random.h"
13 #include "eap_server/eap_i.h"
14 #include "eap_common/eap_sim_common.h"
15 #include "eap_server/eap_sim_db.h"
16
17
18 struct eap_sim_data {
19 u8 mk[EAP_SIM_MK_LEN];
20 u8 nonce_mt[EAP_SIM_NONCE_MT_LEN];
21 u8 nonce_s[EAP_SIM_NONCE_S_LEN];
22 u8 k_aut[EAP_SIM_K_AUT_LEN];
23 u8 k_encr[EAP_SIM_K_ENCR_LEN];
24 u8 msk[EAP_SIM_KEYING_DATA_LEN];
25 u8 emsk[EAP_EMSK_LEN];
26 u8 kc[EAP_SIM_MAX_CHAL][EAP_SIM_KC_LEN];
27 u8 sres[EAP_SIM_MAX_CHAL][EAP_SIM_SRES_LEN];
28 u8 rand[EAP_SIM_MAX_CHAL][GSM_RAND_LEN];
29 int num_chal;
30 enum {
31 START, CHALLENGE, REAUTH, NOTIFICATION, SUCCESS, FAILURE
32 } state;
33 char *next_pseudonym;
34 char *next_reauth_id;
35 u16 counter;
36 struct eap_sim_reauth *reauth;
37 u16 notification;
38 int use_result_ind;
39 };
40
41
eap_sim_state_txt(int state)42 static const char * eap_sim_state_txt(int state)
43 {
44 switch (state) {
45 case START:
46 return "START";
47 case CHALLENGE:
48 return "CHALLENGE";
49 case REAUTH:
50 return "REAUTH";
51 case SUCCESS:
52 return "SUCCESS";
53 case FAILURE:
54 return "FAILURE";
55 case NOTIFICATION:
56 return "NOTIFICATION";
57 default:
58 return "Unknown?!";
59 }
60 }
61
62
eap_sim_state(struct eap_sim_data * data,int state)63 static void eap_sim_state(struct eap_sim_data *data, int state)
64 {
65 wpa_printf(MSG_DEBUG, "EAP-SIM: %s -> %s",
66 eap_sim_state_txt(data->state),
67 eap_sim_state_txt(state));
68 data->state = state;
69 }
70
71
eap_sim_init(struct eap_sm * sm)72 static void * eap_sim_init(struct eap_sm *sm)
73 {
74 struct eap_sim_data *data;
75
76 if (sm->eap_sim_db_priv == NULL) {
77 wpa_printf(MSG_WARNING, "EAP-SIM: eap_sim_db not configured");
78 return NULL;
79 }
80
81 data = os_zalloc(sizeof(*data));
82 if (data == NULL)
83 return NULL;
84 data->state = START;
85
86 return data;
87 }
88
89
eap_sim_reset(struct eap_sm * sm,void * priv)90 static void eap_sim_reset(struct eap_sm *sm, void *priv)
91 {
92 struct eap_sim_data *data = priv;
93 os_free(data->next_pseudonym);
94 os_free(data->next_reauth_id);
95 os_free(data);
96 }
97
98
eap_sim_build_start(struct eap_sm * sm,struct eap_sim_data * data,u8 id)99 static struct wpabuf * eap_sim_build_start(struct eap_sm *sm,
100 struct eap_sim_data *data, u8 id)
101 {
102 struct eap_sim_msg *msg;
103 u8 ver[2];
104
105 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Start");
106 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
107 EAP_SIM_SUBTYPE_START);
108 if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
109 sm->identity_len)) {
110 wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
111 eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
112 } else {
113 /*
114 * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is
115 * ignored and the SIM/Start is used to request the identity.
116 */
117 wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ");
118 eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
119 }
120 wpa_printf(MSG_DEBUG, " AT_VERSION_LIST");
121 ver[0] = 0;
122 ver[1] = EAP_SIM_VERSION;
123 eap_sim_msg_add(msg, EAP_SIM_AT_VERSION_LIST, sizeof(ver),
124 ver, sizeof(ver));
125 return eap_sim_msg_finish(msg, NULL, NULL, 0);
126 }
127
128
eap_sim_build_encr(struct eap_sm * sm,struct eap_sim_data * data,struct eap_sim_msg * msg,u16 counter,const u8 * nonce_s)129 static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data,
130 struct eap_sim_msg *msg, u16 counter,
131 const u8 *nonce_s)
132 {
133 os_free(data->next_pseudonym);
134 data->next_pseudonym =
135 eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0);
136 os_free(data->next_reauth_id);
137 if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) {
138 data->next_reauth_id =
139 eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0);
140 } else {
141 wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication "
142 "count exceeded - force full authentication");
143 data->next_reauth_id = NULL;
144 }
145
146 if (data->next_pseudonym == NULL && data->next_reauth_id == NULL &&
147 counter == 0 && nonce_s == NULL)
148 return 0;
149
150 wpa_printf(MSG_DEBUG, " AT_IV");
151 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
152 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA);
153
154 if (counter > 0) {
155 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)", counter);
156 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0);
157 }
158
159 if (nonce_s) {
160 wpa_printf(MSG_DEBUG, " *AT_NONCE_S");
161 eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_S, 0, nonce_s,
162 EAP_SIM_NONCE_S_LEN);
163 }
164
165 if (data->next_pseudonym) {
166 wpa_printf(MSG_DEBUG, " *AT_NEXT_PSEUDONYM (%s)",
167 data->next_pseudonym);
168 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_PSEUDONYM,
169 os_strlen(data->next_pseudonym),
170 (u8 *) data->next_pseudonym,
171 os_strlen(data->next_pseudonym));
172 }
173
174 if (data->next_reauth_id) {
175 wpa_printf(MSG_DEBUG, " *AT_NEXT_REAUTH_ID (%s)",
176 data->next_reauth_id);
177 eap_sim_msg_add(msg, EAP_SIM_AT_NEXT_REAUTH_ID,
178 os_strlen(data->next_reauth_id),
179 (u8 *) data->next_reauth_id,
180 os_strlen(data->next_reauth_id));
181 }
182
183 if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) {
184 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt "
185 "AT_ENCR_DATA");
186 return -1;
187 }
188
189 return 0;
190 }
191
192
eap_sim_build_challenge(struct eap_sm * sm,struct eap_sim_data * data,u8 id)193 static struct wpabuf * eap_sim_build_challenge(struct eap_sm *sm,
194 struct eap_sim_data *data,
195 u8 id)
196 {
197 struct eap_sim_msg *msg;
198
199 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Challenge");
200 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
201 EAP_SIM_SUBTYPE_CHALLENGE);
202 wpa_printf(MSG_DEBUG, " AT_RAND");
203 eap_sim_msg_add(msg, EAP_SIM_AT_RAND, 0, (u8 *) data->rand,
204 data->num_chal * GSM_RAND_LEN);
205
206 if (eap_sim_build_encr(sm, data, msg, 0, NULL)) {
207 eap_sim_msg_free(msg);
208 return NULL;
209 }
210
211 if (sm->eap_sim_aka_result_ind) {
212 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
213 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
214 }
215
216 wpa_printf(MSG_DEBUG, " AT_MAC");
217 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
218 return eap_sim_msg_finish(msg, data->k_aut, data->nonce_mt,
219 EAP_SIM_NONCE_MT_LEN);
220 }
221
222
eap_sim_build_reauth(struct eap_sm * sm,struct eap_sim_data * data,u8 id)223 static struct wpabuf * eap_sim_build_reauth(struct eap_sm *sm,
224 struct eap_sim_data *data, u8 id)
225 {
226 struct eap_sim_msg *msg;
227
228 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication");
229
230 if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
231 return NULL;
232 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: NONCE_S",
233 data->nonce_s, EAP_SIM_NONCE_S_LEN);
234
235 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
236 data->emsk);
237 eap_sim_derive_keys_reauth(data->counter, sm->identity,
238 sm->identity_len, data->nonce_s, data->mk,
239 data->msk, data->emsk);
240
241 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
242 EAP_SIM_SUBTYPE_REAUTHENTICATION);
243
244 if (eap_sim_build_encr(sm, data, msg, data->counter, data->nonce_s)) {
245 eap_sim_msg_free(msg);
246 return NULL;
247 }
248
249 if (sm->eap_sim_aka_result_ind) {
250 wpa_printf(MSG_DEBUG, " AT_RESULT_IND");
251 eap_sim_msg_add(msg, EAP_SIM_AT_RESULT_IND, 0, NULL, 0);
252 }
253
254 wpa_printf(MSG_DEBUG, " AT_MAC");
255 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
256 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
257 }
258
259
eap_sim_build_notification(struct eap_sm * sm,struct eap_sim_data * data,u8 id)260 static struct wpabuf * eap_sim_build_notification(struct eap_sm *sm,
261 struct eap_sim_data *data,
262 u8 id)
263 {
264 struct eap_sim_msg *msg;
265
266 wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Notification");
267 msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_SIM,
268 EAP_SIM_SUBTYPE_NOTIFICATION);
269 wpa_printf(MSG_DEBUG, " AT_NOTIFICATION (%d)", data->notification);
270 eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification,
271 NULL, 0);
272 if (data->use_result_ind) {
273 if (data->reauth) {
274 wpa_printf(MSG_DEBUG, " AT_IV");
275 wpa_printf(MSG_DEBUG, " AT_ENCR_DATA");
276 eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV,
277 EAP_SIM_AT_ENCR_DATA);
278 wpa_printf(MSG_DEBUG, " *AT_COUNTER (%u)",
279 data->counter);
280 eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter,
281 NULL, 0);
282
283 if (eap_sim_msg_add_encr_end(msg, data->k_encr,
284 EAP_SIM_AT_PADDING)) {
285 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to "
286 "encrypt AT_ENCR_DATA");
287 eap_sim_msg_free(msg);
288 return NULL;
289 }
290 }
291
292 wpa_printf(MSG_DEBUG, " AT_MAC");
293 eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
294 }
295 return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
296 }
297
298
eap_sim_buildReq(struct eap_sm * sm,void * priv,u8 id)299 static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id)
300 {
301 struct eap_sim_data *data = priv;
302
303 switch (data->state) {
304 case START:
305 return eap_sim_build_start(sm, data, id);
306 case CHALLENGE:
307 return eap_sim_build_challenge(sm, data, id);
308 case REAUTH:
309 return eap_sim_build_reauth(sm, data, id);
310 case NOTIFICATION:
311 return eap_sim_build_notification(sm, data, id);
312 default:
313 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in "
314 "buildReq", data->state);
315 break;
316 }
317 return NULL;
318 }
319
320
eap_sim_check(struct eap_sm * sm,void * priv,struct wpabuf * respData)321 static Boolean eap_sim_check(struct eap_sm *sm, void *priv,
322 struct wpabuf *respData)
323 {
324 struct eap_sim_data *data = priv;
325 const u8 *pos;
326 size_t len;
327 u8 subtype;
328
329 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len);
330 if (pos == NULL || len < 3) {
331 wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame");
332 return TRUE;
333 }
334 subtype = *pos;
335
336 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR)
337 return FALSE;
338
339 switch (data->state) {
340 case START:
341 if (subtype != EAP_SIM_SUBTYPE_START) {
342 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
343 "subtype %d", subtype);
344 return TRUE;
345 }
346 break;
347 case CHALLENGE:
348 if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) {
349 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
350 "subtype %d", subtype);
351 return TRUE;
352 }
353 break;
354 case REAUTH:
355 if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) {
356 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
357 "subtype %d", subtype);
358 return TRUE;
359 }
360 break;
361 case NOTIFICATION:
362 if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) {
363 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response "
364 "subtype %d", subtype);
365 return TRUE;
366 }
367 break;
368 default:
369 wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for "
370 "processing a response", data->state);
371 return TRUE;
372 }
373
374 return FALSE;
375 }
376
377
eap_sim_supported_ver(struct eap_sim_data * data,int version)378 static int eap_sim_supported_ver(struct eap_sim_data *data, int version)
379 {
380 return version == EAP_SIM_VERSION;
381 }
382
383
eap_sim_process_start(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)384 static void eap_sim_process_start(struct eap_sm *sm,
385 struct eap_sim_data *data,
386 struct wpabuf *respData,
387 struct eap_sim_attrs *attr)
388 {
389 const u8 *identity;
390 size_t identity_len;
391 u8 ver_list[2];
392
393 wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response");
394
395 if (attr->identity) {
396 os_free(sm->identity);
397 sm->identity = os_malloc(attr->identity_len);
398 if (sm->identity) {
399 os_memcpy(sm->identity, attr->identity,
400 attr->identity_len);
401 sm->identity_len = attr->identity_len;
402 }
403 }
404
405 identity = NULL;
406 identity_len = 0;
407
408 if (sm->identity && sm->identity_len > 0 &&
409 sm->identity[0] == EAP_SIM_PERMANENT_PREFIX) {
410 identity = sm->identity;
411 identity_len = sm->identity_len;
412 } else {
413 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
414 sm->identity,
415 sm->identity_len,
416 &identity_len);
417 if (identity == NULL) {
418 data->reauth = eap_sim_db_get_reauth_entry(
419 sm->eap_sim_db_priv, sm->identity,
420 sm->identity_len);
421 if (data->reauth) {
422 wpa_printf(MSG_DEBUG, "EAP-SIM: Using fast "
423 "re-authentication");
424 identity = data->reauth->identity;
425 identity_len = data->reauth->identity_len;
426 data->counter = data->reauth->counter;
427 os_memcpy(data->mk, data->reauth->mk,
428 EAP_SIM_MK_LEN);
429 }
430 }
431 }
432
433 if (identity == NULL) {
434 wpa_printf(MSG_DEBUG, "EAP-SIM: Could not get proper permanent"
435 " user name");
436 eap_sim_state(data, FAILURE);
437 return;
438 }
439
440 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
441 identity, identity_len);
442
443 if (data->reauth) {
444 eap_sim_state(data, REAUTH);
445 return;
446 }
447
448 if (attr->nonce_mt == NULL || attr->selected_version < 0) {
449 wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing "
450 "required attributes");
451 eap_sim_state(data, FAILURE);
452 return;
453 }
454
455 if (!eap_sim_supported_ver(data, attr->selected_version)) {
456 wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported "
457 "version %d", attr->selected_version);
458 eap_sim_state(data, FAILURE);
459 return;
460 }
461
462 data->counter = 0; /* reset re-auth counter since this is full auth */
463 data->reauth = NULL;
464
465 data->num_chal = eap_sim_db_get_gsm_triplets(
466 sm->eap_sim_db_priv, identity, identity_len,
467 EAP_SIM_MAX_CHAL,
468 (u8 *) data->rand, (u8 *) data->kc, (u8 *) data->sres, sm);
469 if (data->num_chal == EAP_SIM_DB_PENDING) {
470 wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication triplets "
471 "not yet available - pending request");
472 sm->method_pending = METHOD_PENDING_WAIT;
473 return;
474 }
475 if (data->num_chal < 2) {
476 wpa_printf(MSG_INFO, "EAP-SIM: Failed to get GSM "
477 "authentication triplets for the peer");
478 eap_sim_state(data, FAILURE);
479 return;
480 }
481
482 identity_len = sm->identity_len;
483 while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') {
484 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null "
485 "character from identity");
486 identity_len--;
487 }
488 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation",
489 sm->identity, identity_len);
490
491 os_memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN);
492 WPA_PUT_BE16(ver_list, EAP_SIM_VERSION);
493 eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt,
494 attr->selected_version, ver_list, sizeof(ver_list),
495 data->num_chal, (const u8 *) data->kc, data->mk);
496 eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk,
497 data->emsk);
498
499 eap_sim_state(data, CHALLENGE);
500 }
501
502
eap_sim_process_challenge(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)503 static void eap_sim_process_challenge(struct eap_sm *sm,
504 struct eap_sim_data *data,
505 struct wpabuf *respData,
506 struct eap_sim_attrs *attr)
507 {
508 const u8 *identity;
509 size_t identity_len;
510
511 if (attr->mac == NULL ||
512 eap_sim_verify_mac(data->k_aut, respData, attr->mac,
513 (u8 *) data->sres,
514 data->num_chal * EAP_SIM_SRES_LEN)) {
515 wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message "
516 "did not include valid AT_MAC");
517 eap_sim_state(data, FAILURE);
518 return;
519 }
520
521 wpa_printf(MSG_DEBUG, "EAP-SIM: Challenge response includes the "
522 "correct AT_MAC");
523 if (sm->eap_sim_aka_result_ind && attr->result_ind) {
524 data->use_result_ind = 1;
525 data->notification = EAP_SIM_SUCCESS;
526 eap_sim_state(data, NOTIFICATION);
527 } else
528 eap_sim_state(data, SUCCESS);
529
530 identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
531 sm->identity_len, &identity_len);
532 if (identity == NULL) {
533 identity = sm->identity;
534 identity_len = sm->identity_len;
535 }
536
537 if (data->next_pseudonym) {
538 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
539 identity_len,
540 data->next_pseudonym);
541 data->next_pseudonym = NULL;
542 }
543 if (data->next_reauth_id) {
544 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
545 identity_len,
546 data->next_reauth_id, data->counter + 1,
547 data->mk);
548 data->next_reauth_id = NULL;
549 }
550 }
551
552
eap_sim_process_reauth(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)553 static void eap_sim_process_reauth(struct eap_sm *sm,
554 struct eap_sim_data *data,
555 struct wpabuf *respData,
556 struct eap_sim_attrs *attr)
557 {
558 struct eap_sim_attrs eattr;
559 u8 *decrypted = NULL;
560 const u8 *identity, *id2;
561 size_t identity_len, id2_len;
562
563 if (attr->mac == NULL ||
564 eap_sim_verify_mac(data->k_aut, respData, attr->mac, data->nonce_s,
565 EAP_SIM_NONCE_S_LEN)) {
566 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message "
567 "did not include valid AT_MAC");
568 goto fail;
569 }
570
571 if (attr->encr_data == NULL || attr->iv == NULL) {
572 wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication "
573 "message did not include encrypted data");
574 goto fail;
575 }
576
577 decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data,
578 attr->encr_data_len, attr->iv, &eattr,
579 0);
580 if (decrypted == NULL) {
581 wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted "
582 "data from reauthentication message");
583 goto fail;
584 }
585
586 if (eattr.counter != data->counter) {
587 wpa_printf(MSG_WARNING, "EAP-SIM: Re-authentication message "
588 "used incorrect counter %u, expected %u",
589 eattr.counter, data->counter);
590 goto fail;
591 }
592 os_free(decrypted);
593 decrypted = NULL;
594
595 wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes "
596 "the correct AT_MAC");
597 if (sm->eap_sim_aka_result_ind && attr->result_ind) {
598 data->use_result_ind = 1;
599 data->notification = EAP_SIM_SUCCESS;
600 eap_sim_state(data, NOTIFICATION);
601 } else
602 eap_sim_state(data, SUCCESS);
603
604 if (data->reauth) {
605 identity = data->reauth->identity;
606 identity_len = data->reauth->identity_len;
607 } else {
608 identity = sm->identity;
609 identity_len = sm->identity_len;
610 }
611
612 id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
613 identity_len, &id2_len);
614 if (id2) {
615 identity = id2;
616 identity_len = id2_len;
617 }
618
619 if (data->next_pseudonym) {
620 eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
621 identity_len, data->next_pseudonym);
622 data->next_pseudonym = NULL;
623 }
624 if (data->next_reauth_id) {
625 eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
626 identity_len, data->next_reauth_id,
627 data->counter + 1, data->mk);
628 data->next_reauth_id = NULL;
629 } else {
630 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
631 data->reauth = NULL;
632 }
633
634 return;
635
636 fail:
637 eap_sim_state(data, FAILURE);
638 eap_sim_db_remove_reauth(sm->eap_sim_db_priv, data->reauth);
639 data->reauth = NULL;
640 os_free(decrypted);
641 }
642
643
eap_sim_process_client_error(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)644 static void eap_sim_process_client_error(struct eap_sm *sm,
645 struct eap_sim_data *data,
646 struct wpabuf *respData,
647 struct eap_sim_attrs *attr)
648 {
649 wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d",
650 attr->client_error_code);
651 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
652 eap_sim_state(data, SUCCESS);
653 else
654 eap_sim_state(data, FAILURE);
655 }
656
657
eap_sim_process_notification(struct eap_sm * sm,struct eap_sim_data * data,struct wpabuf * respData,struct eap_sim_attrs * attr)658 static void eap_sim_process_notification(struct eap_sm *sm,
659 struct eap_sim_data *data,
660 struct wpabuf *respData,
661 struct eap_sim_attrs *attr)
662 {
663 wpa_printf(MSG_DEBUG, "EAP-SIM: Client replied to notification");
664 if (data->notification == EAP_SIM_SUCCESS && data->use_result_ind)
665 eap_sim_state(data, SUCCESS);
666 else
667 eap_sim_state(data, FAILURE);
668 }
669
670
eap_sim_process(struct eap_sm * sm,void * priv,struct wpabuf * respData)671 static void eap_sim_process(struct eap_sm *sm, void *priv,
672 struct wpabuf *respData)
673 {
674 struct eap_sim_data *data = priv;
675 const u8 *pos, *end;
676 u8 subtype;
677 size_t len;
678 struct eap_sim_attrs attr;
679
680 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len);
681 if (pos == NULL || len < 3)
682 return;
683
684 end = pos + len;
685 subtype = *pos;
686 pos += 3;
687
688 if (eap_sim_parse_attr(pos, end, &attr, 0, 0)) {
689 wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to parse attributes");
690 eap_sim_state(data, FAILURE);
691 return;
692 }
693
694 if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) {
695 eap_sim_process_client_error(sm, data, respData, &attr);
696 return;
697 }
698
699 switch (data->state) {
700 case START:
701 eap_sim_process_start(sm, data, respData, &attr);
702 break;
703 case CHALLENGE:
704 eap_sim_process_challenge(sm, data, respData, &attr);
705 break;
706 case REAUTH:
707 eap_sim_process_reauth(sm, data, respData, &attr);
708 break;
709 case NOTIFICATION:
710 eap_sim_process_notification(sm, data, respData, &attr);
711 break;
712 default:
713 wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown state %d in "
714 "process", data->state);
715 break;
716 }
717 }
718
719
eap_sim_isDone(struct eap_sm * sm,void * priv)720 static Boolean eap_sim_isDone(struct eap_sm *sm, void *priv)
721 {
722 struct eap_sim_data *data = priv;
723 return data->state == SUCCESS || data->state == FAILURE;
724 }
725
726
eap_sim_getKey(struct eap_sm * sm,void * priv,size_t * len)727 static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len)
728 {
729 struct eap_sim_data *data = priv;
730 u8 *key;
731
732 if (data->state != SUCCESS)
733 return NULL;
734
735 key = os_malloc(EAP_SIM_KEYING_DATA_LEN);
736 if (key == NULL)
737 return NULL;
738 os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN);
739 *len = EAP_SIM_KEYING_DATA_LEN;
740 return key;
741 }
742
743
eap_sim_get_emsk(struct eap_sm * sm,void * priv,size_t * len)744 static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
745 {
746 struct eap_sim_data *data = priv;
747 u8 *key;
748
749 if (data->state != SUCCESS)
750 return NULL;
751
752 key = os_malloc(EAP_EMSK_LEN);
753 if (key == NULL)
754 return NULL;
755 os_memcpy(key, data->emsk, EAP_EMSK_LEN);
756 *len = EAP_EMSK_LEN;
757 return key;
758 }
759
760
eap_sim_isSuccess(struct eap_sm * sm,void * priv)761 static Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv)
762 {
763 struct eap_sim_data *data = priv;
764 return data->state == SUCCESS;
765 }
766
767
eap_server_sim_register(void)768 int eap_server_sim_register(void)
769 {
770 struct eap_method *eap;
771 int ret;
772
773 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
774 EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM");
775 if (eap == NULL)
776 return -1;
777
778 eap->init = eap_sim_init;
779 eap->reset = eap_sim_reset;
780 eap->buildReq = eap_sim_buildReq;
781 eap->check = eap_sim_check;
782 eap->process = eap_sim_process;
783 eap->isDone = eap_sim_isDone;
784 eap->getKey = eap_sim_getKey;
785 eap->isSuccess = eap_sim_isSuccess;
786 eap->get_emsk = eap_sim_get_emsk;
787
788 ret = eap_server_method_register(eap);
789 if (ret)
790 eap_server_method_free(eap);
791 return ret;
792 }
793