2 * EAP peer: EAP-SIM/AKA shared routines
3 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
22 #include "eap_sim_common.h"
25 static int eap_sim_prf(const u8
*key
, u8
*x
, size_t xlen
)
27 return fips186_2_prf(key
, EAP_SIM_MK_LEN
, x
, xlen
);
31 void eap_sim_derive_mk(const u8
*identity
, size_t identity_len
,
32 const u8
*nonce_mt
, u16 selected_version
,
33 const u8
*ver_list
, size_t ver_list_len
,
34 int num_chal
, const u8
*kc
, u8
*mk
)
37 const unsigned char *addr
[5];
41 len
[0] = identity_len
;
43 len
[1] = num_chal
* EAP_SIM_KC_LEN
;
45 len
[2] = EAP_SIM_NONCE_MT_LEN
;
47 len
[3] = ver_list_len
;
51 WPA_PUT_BE16(sel_ver
, selected_version
);
53 /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
54 sha1_vector(5, addr
, len
, mk
);
55 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: MK", mk
, EAP_SIM_MK_LEN
);
59 void eap_aka_derive_mk(const u8
*identity
, size_t identity_len
,
60 const u8
*ik
, const u8
*ck
, u8
*mk
)
66 len
[0] = identity_len
;
68 len
[1] = EAP_AKA_IK_LEN
;
70 len
[2] = EAP_AKA_CK_LEN
;
72 /* MK = SHA1(Identity|IK|CK) */
73 sha1_vector(3, addr
, len
, mk
);
74 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA: IK", ik
, EAP_AKA_IK_LEN
);
75 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA: CK", ck
, EAP_AKA_CK_LEN
);
76 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA: MK", mk
, EAP_SIM_MK_LEN
);
80 int eap_sim_derive_keys(const u8
*mk
, u8
*k_encr
, u8
*k_aut
, u8
*msk
, u8
*emsk
)
82 u8 buf
[EAP_SIM_K_ENCR_LEN
+ EAP_SIM_K_AUT_LEN
+
83 EAP_SIM_KEYING_DATA_LEN
+ EAP_EMSK_LEN
], *pos
;
84 if (eap_sim_prf(mk
, buf
, sizeof(buf
)) < 0) {
85 wpa_printf(MSG_ERROR
, "EAP-SIM: Failed to derive keys");
89 os_memcpy(k_encr
, pos
, EAP_SIM_K_ENCR_LEN
);
90 pos
+= EAP_SIM_K_ENCR_LEN
;
91 os_memcpy(k_aut
, pos
, EAP_SIM_K_AUT_LEN
);
92 pos
+= EAP_SIM_K_AUT_LEN
;
93 os_memcpy(msk
, pos
, EAP_SIM_KEYING_DATA_LEN
);
94 pos
+= EAP_SIM_KEYING_DATA_LEN
;
95 os_memcpy(emsk
, pos
, EAP_EMSK_LEN
);
97 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: K_encr",
98 k_encr
, EAP_SIM_K_ENCR_LEN
);
99 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: K_aut",
100 k_aut
, EAP_SIM_K_AUT_LEN
);
101 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: keying material (MSK)",
102 msk
, EAP_SIM_KEYING_DATA_LEN
);
103 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: EMSK", emsk
, EAP_EMSK_LEN
);
104 os_memset(buf
, 0, sizeof(buf
));
110 int eap_sim_derive_keys_reauth(u16 _counter
,
111 const u8
*identity
, size_t identity_len
,
112 const u8
*nonce_s
, const u8
*mk
, u8
*msk
,
115 u8 xkey
[SHA1_MAC_LEN
];
116 u8 buf
[EAP_SIM_KEYING_DATA_LEN
+ EAP_EMSK_LEN
+ 32];
122 len
[0] = identity_len
;
126 len
[2] = EAP_SIM_NONCE_S_LEN
;
128 len
[3] = EAP_SIM_MK_LEN
;
130 WPA_PUT_BE16(counter
, _counter
);
132 wpa_printf(MSG_DEBUG
, "EAP-SIM: Deriving keying data from reauth");
133 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM: Identity",
134 identity
, identity_len
);
135 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: counter", counter
, 2);
136 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: NONCE_S", nonce_s
,
137 EAP_SIM_NONCE_S_LEN
);
138 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: MK", mk
, EAP_SIM_MK_LEN
);
140 /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */
141 sha1_vector(4, addr
, len
, xkey
);
142 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: XKEY'", xkey
, SHA1_MAC_LEN
);
144 if (eap_sim_prf(xkey
, buf
, sizeof(buf
)) < 0) {
145 wpa_printf(MSG_ERROR
, "EAP-SIM: Failed to derive keys");
149 os_memcpy(msk
, buf
, EAP_SIM_KEYING_DATA_LEN
);
150 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: keying material (MSK)",
151 msk
, EAP_SIM_KEYING_DATA_LEN
);
154 os_memcpy(emsk
, buf
+ EAP_SIM_KEYING_DATA_LEN
, EAP_EMSK_LEN
);
155 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: EMSK", emsk
, EAP_EMSK_LEN
);
157 os_memset(buf
, 0, sizeof(buf
));
163 int eap_sim_verify_mac(const u8
*k_aut
, const u8
*req
, size_t req_len
,
164 const u8
*mac
, const u8
*extra
, size_t extra_len
)
166 unsigned char hmac
[SHA1_MAC_LEN
];
171 if (mac
== NULL
|| req_len
< EAP_SIM_MAC_LEN
|| mac
< req
||
172 mac
> req
+ req_len
- EAP_SIM_MAC_LEN
)
175 tmp
= os_malloc(req_len
);
185 os_memcpy(tmp
, req
, req_len
);
186 os_memset(tmp
+ (mac
- req
), 0, EAP_SIM_MAC_LEN
);
187 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Verify MAC - msg", tmp
, req_len
);
188 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Verify MAC - extra data",
190 wpa_hexdump_key(MSG_MSGDUMP
, "EAP-SIM: Verify MAC - K_aut",
191 k_aut
, EAP_SIM_K_AUT_LEN
);
192 hmac_sha1_vector(k_aut
, EAP_SIM_K_AUT_LEN
, 2, addr
, len
, hmac
);
193 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Verify MAC: MAC",
194 hmac
, EAP_SIM_MAC_LEN
);
197 return (os_memcmp(hmac
, mac
, EAP_SIM_MAC_LEN
) == 0) ? 0 : 1;
201 void eap_sim_add_mac(const u8
*k_aut
, u8
*msg
, size_t msg_len
, u8
*mac
,
202 const u8
*extra
, size_t extra_len
)
204 unsigned char hmac
[SHA1_MAC_LEN
];
214 os_memset(mac
, 0, EAP_SIM_MAC_LEN
);
215 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Add MAC - msg", msg
, msg_len
);
216 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Add MAC - extra data",
218 wpa_hexdump_key(MSG_MSGDUMP
, "EAP-SIM: Add MAC - K_aut",
219 k_aut
, EAP_SIM_K_AUT_LEN
);
220 hmac_sha1_vector(k_aut
, EAP_SIM_K_AUT_LEN
, 2, addr
, len
, hmac
);
221 os_memcpy(mac
, hmac
, EAP_SIM_MAC_LEN
);
222 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Add MAC: MAC",
223 mac
, EAP_SIM_MAC_LEN
);
227 int eap_sim_parse_attr(const u8
*start
, const u8
*end
,
228 struct eap_sim_attrs
*attr
, int aka
, int encr
)
230 const u8
*pos
= start
, *apos
;
231 size_t alen
, plen
, i
, list_len
;
233 os_memset(attr
, 0, sizeof(*attr
));
234 attr
->id_req
= NO_ID_REQ
;
235 attr
->notification
= -1;
237 attr
->selected_version
= -1;
238 attr
->client_error_code
= -1;
242 wpa_printf(MSG_INFO
, "EAP-SIM: Attribute overflow(1)");
245 wpa_printf(MSG_MSGDUMP
, "EAP-SIM: Attribute: Type=%d Len=%d",
247 if (pos
+ pos
[1] * 4 > end
) {
248 wpa_printf(MSG_INFO
, "EAP-SIM: Attribute overflow "
249 "(pos=%p len=%d end=%p)",
250 pos
, pos
[1] * 4, end
);
254 alen
= pos
[1] * 4 - 2;
255 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Attribute data",
259 case EAP_SIM_AT_RAND
:
260 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_RAND");
263 if ((!aka
&& (alen
% GSM_RAND_LEN
)) ||
264 (aka
&& alen
!= EAP_AKA_RAND_LEN
)) {
265 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_RAND"
267 (unsigned long) alen
);
271 attr
->num_chal
= alen
/ GSM_RAND_LEN
;
273 case EAP_SIM_AT_AUTN
:
274 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_AUTN");
276 wpa_printf(MSG_DEBUG
, "EAP-SIM: "
277 "Unexpected AT_AUTN");
282 if (alen
!= EAP_AKA_AUTN_LEN
) {
283 wpa_printf(MSG_INFO
, "EAP-AKA: Invalid AT_AUTN"
285 (unsigned long) alen
);
290 case EAP_SIM_AT_PADDING
:
292 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
296 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) AT_PADDING");
297 for (i
= 2; i
< alen
; i
++) {
299 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) "
300 "AT_PADDING used a non-zero"
302 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: "
303 "(encr) padding bytes",
309 case EAP_SIM_AT_NONCE_MT
:
310 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_NONCE_MT");
311 if (alen
!= 2 + EAP_SIM_NONCE_MT_LEN
) {
312 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
313 "AT_NONCE_MT length");
316 attr
->nonce_mt
= apos
+ 2;
318 case EAP_SIM_AT_PERMANENT_ID_REQ
:
319 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_PERMANENT_ID_REQ");
320 attr
->id_req
= PERMANENT_ID
;
323 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_MAC");
324 if (alen
!= 2 + EAP_SIM_MAC_LEN
) {
325 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_MAC "
329 attr
->mac
= apos
+ 2;
331 case EAP_SIM_AT_NOTIFICATION
:
333 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
334 "AT_NOTIFICATION length %lu",
335 (unsigned long) alen
);
338 attr
->notification
= apos
[0] * 256 + apos
[1];
339 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_NOTIFICATION %d",
342 case EAP_SIM_AT_ANY_ID_REQ
:
343 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_ANY_ID_REQ");
344 attr
->id_req
= ANY_ID
;
346 case EAP_SIM_AT_IDENTITY
:
347 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_IDENTITY");
348 attr
->identity
= apos
+ 2;
349 attr
->identity_len
= alen
- 2;
351 case EAP_SIM_AT_VERSION_LIST
:
353 wpa_printf(MSG_DEBUG
, "EAP-AKA: "
354 "Unexpected AT_VERSION_LIST");
357 list_len
= apos
[0] * 256 + apos
[1];
358 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_VERSION_LIST");
359 if (list_len
< 2 || list_len
> alen
- 2) {
360 wpa_printf(MSG_WARNING
, "EAP-SIM: Invalid "
361 "AT_VERSION_LIST (list_len=%lu "
363 (unsigned long) list_len
,
364 (unsigned long) alen
);
367 attr
->version_list
= apos
+ 2;
368 attr
->version_list_len
= list_len
;
370 case EAP_SIM_AT_SELECTED_VERSION
:
371 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_SELECTED_VERSION");
373 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
374 "AT_SELECTED_VERSION length %lu",
375 (unsigned long) alen
);
378 attr
->selected_version
= apos
[0] * 256 + apos
[1];
379 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_SELECTED_VERSION "
380 "%d", attr
->selected_version
);
382 case EAP_SIM_AT_FULLAUTH_ID_REQ
:
383 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_FULLAUTH_ID_REQ");
384 attr
->id_req
= FULLAUTH_ID
;
386 case EAP_SIM_AT_COUNTER
:
388 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
393 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid "
394 "AT_COUNTER (alen=%lu)",
395 (unsigned long) alen
);
398 attr
->counter
= apos
[0] * 256 + apos
[1];
399 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) AT_COUNTER %d",
402 case EAP_SIM_AT_COUNTER_TOO_SMALL
:
404 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
405 "AT_COUNTER_TOO_SMALL");
409 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid "
410 "AT_COUNTER_TOO_SMALL (alen=%lu)",
411 (unsigned long) alen
);
414 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
415 "AT_COUNTER_TOO_SMALL");
416 attr
->counter_too_small
= 1;
418 case EAP_SIM_AT_NONCE_S
:
420 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
424 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
426 if (alen
!= 2 + EAP_SIM_NONCE_S_LEN
) {
427 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid "
428 "AT_NONCE_S (alen=%lu)",
429 (unsigned long) alen
);
432 attr
->nonce_s
= apos
+ 2;
434 case EAP_SIM_AT_CLIENT_ERROR_CODE
:
436 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
437 "AT_CLIENT_ERROR_CODE length %lu",
438 (unsigned long) alen
);
441 attr
->client_error_code
= apos
[0] * 256 + apos
[1];
442 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_CLIENT_ERROR_CODE "
443 "%d", attr
->client_error_code
);
446 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_IV");
447 if (alen
!= 2 + EAP_SIM_MAC_LEN
) {
448 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_IV "
449 "length %lu", (unsigned long) alen
);
454 case EAP_SIM_AT_ENCR_DATA
:
455 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_ENCR_DATA");
456 attr
->encr_data
= apos
+ 2;
457 attr
->encr_data_len
= alen
- 2;
458 if (attr
->encr_data_len
% 16) {
459 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
460 "AT_ENCR_DATA length %lu",
462 attr
->encr_data_len
);
466 case EAP_SIM_AT_NEXT_PSEUDONYM
:
468 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
469 "AT_NEXT_PSEUDONYM");
472 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
473 "AT_NEXT_PSEUDONYM");
474 plen
= apos
[0] * 256 + apos
[1];
475 if (plen
> alen
- 2) {
476 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid"
477 " AT_NEXT_PSEUDONYM (actual"
478 " len %lu, attr len %lu)",
479 (unsigned long) plen
,
480 (unsigned long) alen
);
483 attr
->next_pseudonym
= pos
+ 4;
484 attr
->next_pseudonym_len
= plen
;
486 case EAP_SIM_AT_NEXT_REAUTH_ID
:
488 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
489 "AT_NEXT_REAUTH_ID");
492 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
493 "AT_NEXT_REAUTH_ID");
494 plen
= apos
[0] * 256 + apos
[1];
495 if (plen
> alen
- 2) {
496 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid"
497 " AT_NEXT_REAUTH_ID (actual"
498 " len %lu, attr len %lu)",
499 (unsigned long) plen
,
500 (unsigned long) alen
);
503 attr
->next_reauth_id
= pos
+ 4;
504 attr
->next_reauth_id_len
= plen
;
507 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_RES");
510 if (!aka
|| alen
< EAP_AKA_MIN_RES_LEN
||
511 alen
> EAP_AKA_MAX_RES_LEN
) {
512 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_RES "
514 (unsigned long) alen
);
518 attr
->res_len
= alen
;
520 case EAP_SIM_AT_AUTS
:
521 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_AUTS");
523 wpa_printf(MSG_DEBUG
, "EAP-SIM: "
524 "Unexpected AT_AUTS");
527 if (alen
!= EAP_AKA_AUTS_LEN
) {
528 wpa_printf(MSG_INFO
, "EAP-AKA: Invalid AT_AUTS"
530 (unsigned long) alen
);
537 wpa_printf(MSG_INFO
, "EAP-SIM: Unrecognized "
538 "non-skippable attribute %d",
543 wpa_printf(MSG_DEBUG
, "EAP-SIM: Unrecognized skippable"
544 " attribute %d ignored", pos
[0]);
551 wpa_printf(MSG_DEBUG
, "EAP-SIM: Attributes parsed successfully "
552 "(aka=%d encr=%d)", aka
, encr
);
558 u8
* eap_sim_parse_encr(const u8
*k_encr
, const u8
*encr_data
,
559 size_t encr_data_len
, const u8
*iv
,
560 struct eap_sim_attrs
*attr
, int aka
)
565 wpa_printf(MSG_INFO
, "EAP-SIM: Encrypted data, but no IV");
569 decrypted
= os_malloc(encr_data_len
);
570 if (decrypted
== NULL
)
572 os_memcpy(decrypted
, encr_data
, encr_data_len
);
574 aes_128_cbc_decrypt(k_encr
, iv
, decrypted
, encr_data_len
);
575 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Decrypted AT_ENCR_DATA",
576 decrypted
, encr_data_len
);
578 if (eap_sim_parse_attr(decrypted
, decrypted
+ encr_data_len
, attr
,
580 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Failed to parse "
581 "decrypted AT_ENCR_DATA");
590 #define EAP_SIM_INIT_LEN 128
594 size_t buf_len
, used
;
595 size_t mac
, iv
, encr
; /* index from buf */
599 struct eap_sim_msg
* eap_sim_msg_init(int code
, int id
, int type
, int subtype
)
601 struct eap_sim_msg
*msg
;
605 msg
= os_zalloc(sizeof(*msg
));
609 msg
->buf
= os_zalloc(EAP_SIM_INIT_LEN
);
610 if (msg
->buf
== NULL
) {
614 msg
->buf_len
= EAP_SIM_INIT_LEN
;
615 eap
= (struct eap_hdr
*) msg
->buf
;
617 eap
->identifier
= id
;
618 msg
->used
= sizeof(*eap
);
620 pos
= (u8
*) (eap
+ 1);
623 *pos
++ = 0; /* Reserved */
624 *pos
++ = 0; /* Reserved */
631 u8
* eap_sim_msg_finish(struct eap_sim_msg
*msg
, size_t *len
, const u8
*k_aut
,
632 const u8
*extra
, size_t extra_len
)
640 eap
= (struct eap_hdr
*) msg
->buf
;
641 eap
->length
= host_to_be16(msg
->used
);
643 if (k_aut
&& msg
->mac
) {
644 eap_sim_add_mac(k_aut
, msg
->buf
, msg
->used
,
645 msg
->buf
+ msg
->mac
, extra
, extra_len
);
655 void eap_sim_msg_free(struct eap_sim_msg
*msg
)
664 static int eap_sim_msg_resize(struct eap_sim_msg
*msg
, size_t add_len
)
666 if (msg
->used
+ add_len
> msg
->buf_len
) {
667 u8
*nbuf
= os_realloc(msg
->buf
, msg
->used
+ add_len
);
671 msg
->buf_len
= msg
->used
+ add_len
;
677 u8
* eap_sim_msg_add_full(struct eap_sim_msg
*msg
, u8 attr
,
678 const u8
*data
, size_t len
)
680 int attr_len
= 2 + len
;
687 pad_len
= (4 - attr_len
% 4) % 4;
689 if (eap_sim_msg_resize(msg
, attr_len
))
691 start
= pos
= msg
->buf
+ msg
->used
;
693 *pos
++ = attr_len
/ 4;
694 os_memcpy(pos
, data
, len
);
697 os_memset(pos
, 0, pad_len
);
699 msg
->used
+= attr_len
;
704 u8
* eap_sim_msg_add(struct eap_sim_msg
*msg
, u8 attr
, u16 value
,
705 const u8
*data
, size_t len
)
707 int attr_len
= 4 + len
;
714 pad_len
= (4 - attr_len
% 4) % 4;
716 if (eap_sim_msg_resize(msg
, attr_len
))
718 start
= pos
= msg
->buf
+ msg
->used
;
720 *pos
++ = attr_len
/ 4;
721 WPA_PUT_BE16(pos
, value
);
724 os_memcpy(pos
, data
, len
);
727 os_memset(pos
, 0, pad_len
);
729 msg
->used
+= attr_len
;
734 u8
* eap_sim_msg_add_mac(struct eap_sim_msg
*msg
, u8 attr
)
736 u8
*pos
= eap_sim_msg_add(msg
, attr
, 0, NULL
, EAP_SIM_MAC_LEN
);
738 msg
->mac
= (pos
- msg
->buf
) + 4;
743 int eap_sim_msg_add_encr_start(struct eap_sim_msg
*msg
, u8 attr_iv
,
746 u8
*pos
= eap_sim_msg_add(msg
, attr_iv
, 0, NULL
, EAP_SIM_IV_LEN
);
749 msg
->iv
= (pos
- msg
->buf
) + 4;
750 if (hostapd_get_rand(msg
->buf
+ msg
->iv
, EAP_SIM_IV_LEN
)) {
755 pos
= eap_sim_msg_add(msg
, attr_encr
, 0, NULL
, 0);
760 msg
->encr
= pos
- msg
->buf
;
766 int eap_sim_msg_add_encr_end(struct eap_sim_msg
*msg
, u8
*k_encr
, int attr_pad
)
770 if (msg
== NULL
|| k_encr
== NULL
|| msg
->iv
== 0 || msg
->encr
== 0)
773 encr_len
= msg
->used
- msg
->encr
- 4;
776 int pad_len
= 16 - (encr_len
% 16);
778 wpa_printf(MSG_WARNING
, "EAP-SIM: "
779 "eap_sim_msg_add_encr_end - invalid pad_len"
783 wpa_printf(MSG_DEBUG
, " *AT_PADDING");
784 pos
= eap_sim_msg_add(msg
, attr_pad
, 0, NULL
, pad_len
- 4);
787 os_memset(pos
+ 4, 0, pad_len
- 4);
790 wpa_printf(MSG_DEBUG
, " (AT_ENCR_DATA data len %lu)",
791 (unsigned long) encr_len
);
792 msg
->buf
[msg
->encr
+ 1] = encr_len
/ 4 + 1;
793 aes_128_cbc_encrypt(k_encr
, msg
->buf
+ msg
->iv
,
794 msg
->buf
+ msg
->encr
+ 4, encr_len
);
800 void eap_sim_report_notification(void *msg_ctx
, int notification
, int aka
)
802 #ifndef CONFIG_NO_STDOUT_DEBUG
803 const char *type
= aka
? "AKA" : "SIM";
804 #endif /* CONFIG_NO_STDOUT_DEBUG */
806 switch (notification
) {
807 case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH
:
808 wpa_printf(MSG_WARNING
, "EAP-%s: General failure "
809 "notification (after authentication)", type
);
811 case EAP_SIM_TEMPORARILY_DENIED
:
812 wpa_printf(MSG_WARNING
, "EAP-%s: Failure notification: "
813 "User has been temporarily denied access to the "
814 "requested service", type
);
816 case EAP_SIM_NOT_SUBSCRIBED
:
817 wpa_printf(MSG_WARNING
, "EAP-%s: Failure notification: "
818 "User has not subscribed to the requested service",
821 case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH
:
822 wpa_printf(MSG_WARNING
, "EAP-%s: General failure "
823 "notification (before authentication)", type
);
825 case EAP_SIM_SUCCESS
:
826 wpa_printf(MSG_INFO
, "EAP-%s: Successful authentication "
827 "notification", type
);
830 if (notification
>= 32768) {
831 wpa_printf(MSG_INFO
, "EAP-%s: Unrecognized "
832 "non-failure notification %d",
835 wpa_printf(MSG_WARNING
, "EAP-%s: Unrecognized "
836 "failure notification %d",