2 * EAP peer/server: EAP-SIM/AKA/AKA' shared routines
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
13 #include "crypto/aes_wrap.h"
14 #include "crypto/crypto.h"
15 #include "crypto/sha1.h"
16 #include "crypto/sha256.h"
17 #include "crypto/random.h"
18 #include "eap_common/eap_defs.h"
19 #include "eap_common/eap_sim_common.h"
22 static int eap_sim_prf(const u8
*key
, u8
*x
, size_t xlen
)
24 return fips186_2_prf(key
, EAP_SIM_MK_LEN
, x
, xlen
);
28 void eap_sim_derive_mk(const u8
*identity
, size_t identity_len
,
29 const u8
*nonce_mt
, u16 selected_version
,
30 const u8
*ver_list
, size_t ver_list_len
,
31 int num_chal
, const u8
*kc
, u8
*mk
)
34 const unsigned char *addr
[5];
38 len
[0] = identity_len
;
40 len
[1] = num_chal
* EAP_SIM_KC_LEN
;
42 len
[2] = EAP_SIM_NONCE_MT_LEN
;
44 len
[3] = ver_list_len
;
48 WPA_PUT_BE16(sel_ver
, selected_version
);
50 /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
51 sha1_vector(5, addr
, len
, mk
);
52 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: MK", mk
, EAP_SIM_MK_LEN
);
56 void eap_aka_derive_mk(const u8
*identity
, size_t identity_len
,
57 const u8
*ik
, const u8
*ck
, u8
*mk
)
63 len
[0] = identity_len
;
65 len
[1] = EAP_AKA_IK_LEN
;
67 len
[2] = EAP_AKA_CK_LEN
;
69 /* MK = SHA1(Identity|IK|CK) */
70 sha1_vector(3, addr
, len
, mk
);
71 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA: IK", ik
, EAP_AKA_IK_LEN
);
72 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA: CK", ck
, EAP_AKA_CK_LEN
);
73 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA: MK", mk
, EAP_SIM_MK_LEN
);
77 int eap_sim_derive_keys(const u8
*mk
, u8
*k_encr
, u8
*k_aut
, u8
*msk
, u8
*emsk
)
79 u8 buf
[EAP_SIM_K_ENCR_LEN
+ EAP_SIM_K_AUT_LEN
+
80 EAP_SIM_KEYING_DATA_LEN
+ EAP_EMSK_LEN
], *pos
;
81 if (eap_sim_prf(mk
, buf
, sizeof(buf
)) < 0) {
82 wpa_printf(MSG_ERROR
, "EAP-SIM: Failed to derive keys");
86 os_memcpy(k_encr
, pos
, EAP_SIM_K_ENCR_LEN
);
87 pos
+= EAP_SIM_K_ENCR_LEN
;
88 os_memcpy(k_aut
, pos
, EAP_SIM_K_AUT_LEN
);
89 pos
+= EAP_SIM_K_AUT_LEN
;
90 os_memcpy(msk
, pos
, EAP_SIM_KEYING_DATA_LEN
);
91 pos
+= EAP_SIM_KEYING_DATA_LEN
;
92 os_memcpy(emsk
, pos
, EAP_EMSK_LEN
);
94 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: K_encr",
95 k_encr
, EAP_SIM_K_ENCR_LEN
);
96 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: K_aut",
97 k_aut
, EAP_SIM_K_AUT_LEN
);
98 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: keying material (MSK)",
99 msk
, EAP_SIM_KEYING_DATA_LEN
);
100 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: EMSK", emsk
, EAP_EMSK_LEN
);
101 os_memset(buf
, 0, sizeof(buf
));
107 int eap_sim_derive_keys_reauth(u16 _counter
,
108 const u8
*identity
, size_t identity_len
,
109 const u8
*nonce_s
, const u8
*mk
, u8
*msk
,
112 u8 xkey
[SHA1_MAC_LEN
];
113 u8 buf
[EAP_SIM_KEYING_DATA_LEN
+ EAP_EMSK_LEN
+ 32];
118 while (identity_len
> 0 && identity
[identity_len
- 1] == 0) {
119 wpa_printf(MSG_DEBUG
, "EAP-SIM: Workaround - drop null "
120 "character from the end of identity");
124 len
[0] = identity_len
;
128 len
[2] = EAP_SIM_NONCE_S_LEN
;
130 len
[3] = EAP_SIM_MK_LEN
;
132 WPA_PUT_BE16(counter
, _counter
);
134 wpa_printf(MSG_DEBUG
, "EAP-SIM: Deriving keying data from reauth");
135 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-SIM: Identity",
136 identity
, identity_len
);
137 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: counter", counter
, 2);
138 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: NONCE_S", nonce_s
,
139 EAP_SIM_NONCE_S_LEN
);
140 wpa_hexdump_key(MSG_DEBUG
, "EAP-SIM: MK", mk
, EAP_SIM_MK_LEN
);
142 /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */
143 sha1_vector(4, addr
, len
, xkey
);
144 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: XKEY'", xkey
, SHA1_MAC_LEN
);
146 if (eap_sim_prf(xkey
, buf
, sizeof(buf
)) < 0) {
147 wpa_printf(MSG_ERROR
, "EAP-SIM: Failed to derive keys");
151 os_memcpy(msk
, buf
, EAP_SIM_KEYING_DATA_LEN
);
152 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: keying material (MSK)",
153 msk
, EAP_SIM_KEYING_DATA_LEN
);
156 os_memcpy(emsk
, buf
+ EAP_SIM_KEYING_DATA_LEN
, EAP_EMSK_LEN
);
157 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: EMSK", emsk
, EAP_EMSK_LEN
);
159 os_memset(buf
, 0, sizeof(buf
));
165 int eap_sim_verify_mac(const u8
*k_aut
, const struct wpabuf
*req
,
166 const u8
*mac
, const u8
*extra
, size_t extra_len
)
168 unsigned char hmac
[SHA1_MAC_LEN
];
173 if (mac
== NULL
|| wpabuf_len(req
) < EAP_SIM_MAC_LEN
||
174 mac
< wpabuf_head_u8(req
) ||
175 mac
> wpabuf_head_u8(req
) + wpabuf_len(req
) - EAP_SIM_MAC_LEN
)
178 tmp
= os_memdup(wpabuf_head(req
), wpabuf_len(req
));
183 len
[0] = wpabuf_len(req
);
188 os_memset(tmp
+ (mac
- wpabuf_head_u8(req
)), 0, EAP_SIM_MAC_LEN
);
189 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Verify MAC - msg",
190 tmp
, wpabuf_len(req
));
191 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Verify MAC - extra data",
193 wpa_hexdump_key(MSG_MSGDUMP
, "EAP-SIM: Verify MAC - K_aut",
194 k_aut
, EAP_SIM_K_AUT_LEN
);
195 hmac_sha1_vector(k_aut
, EAP_SIM_K_AUT_LEN
, 2, addr
, len
, hmac
);
196 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Verify MAC: MAC",
197 hmac
, EAP_SIM_MAC_LEN
);
200 return (os_memcmp_const(hmac
, mac
, EAP_SIM_MAC_LEN
) == 0) ? 0 : 1;
204 void eap_sim_add_mac(const u8
*k_aut
, const u8
*msg
, size_t msg_len
, u8
*mac
,
205 const u8
*extra
, size_t extra_len
)
207 unsigned char hmac
[SHA1_MAC_LEN
];
217 os_memset(mac
, 0, EAP_SIM_MAC_LEN
);
218 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Add MAC - msg", msg
, msg_len
);
219 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Add MAC - extra data",
221 wpa_hexdump_key(MSG_MSGDUMP
, "EAP-SIM: Add MAC - K_aut",
222 k_aut
, EAP_SIM_K_AUT_LEN
);
223 hmac_sha1_vector(k_aut
, EAP_SIM_K_AUT_LEN
, 2, addr
, len
, hmac
);
224 os_memcpy(mac
, hmac
, EAP_SIM_MAC_LEN
);
225 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Add MAC: MAC",
226 mac
, EAP_SIM_MAC_LEN
);
230 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
231 static void prf_prime(const u8
*k
, const char *seed1
,
232 const u8
*seed2
, size_t seed2_len
,
233 const u8
*seed3
, size_t seed3_len
,
234 u8
*res
, size_t res_len
)
238 u8 hash
[SHA256_MAC_LEN
];
242 * PRF'(K,S) = T1 | T2 | T3 | T4 | ...
243 * T1 = HMAC-SHA-256 (K, S | 0x01)
244 * T2 = HMAC-SHA-256 (K, T1 | S | 0x02)
245 * T3 = HMAC-SHA-256 (K, T2 | S | 0x03)
246 * T4 = HMAC-SHA-256 (K, T3 | S | 0x04)
252 addr
[1] = (const u8
*) seed1
;
253 len
[1] = os_strlen(seed1
);
265 hmac_sha256_vector(k
, 32, 5, addr
, len
, hash
);
266 len
[0] = SHA256_MAC_LEN
;
267 hlen
= res_len
> SHA256_MAC_LEN
? SHA256_MAC_LEN
: res_len
;
268 os_memcpy(res
, hash
, hlen
);
275 void eap_aka_prime_derive_keys(const u8
*identity
, size_t identity_len
,
276 const u8
*ik
, const u8
*ck
, u8
*k_encr
,
277 u8
*k_aut
, u8
*k_re
, u8
*msk
, u8
*emsk
)
279 u8 key
[EAP_AKA_IK_LEN
+ EAP_AKA_CK_LEN
];
280 u8 keys
[EAP_SIM_K_ENCR_LEN
+ EAP_AKA_PRIME_K_AUT_LEN
+
281 EAP_AKA_PRIME_K_RE_LEN
+ EAP_MSK_LEN
+ EAP_EMSK_LEN
];
285 * MK = PRF'(IK'|CK',"EAP-AKA'"|Identity)
286 * K_encr = MK[0..127]
287 * K_aut = MK[128..383]
288 * K_re = MK[384..639]
289 * MSK = MK[640..1151]
290 * EMSK = MK[1152..1663]
293 os_memcpy(key
, ik
, EAP_AKA_IK_LEN
);
294 os_memcpy(key
+ EAP_AKA_IK_LEN
, ck
, EAP_AKA_CK_LEN
);
296 prf_prime(key
, "EAP-AKA'", identity
, identity_len
, NULL
, 0,
300 os_memcpy(k_encr
, pos
, EAP_SIM_K_ENCR_LEN
);
301 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': K_encr",
302 k_encr
, EAP_SIM_K_ENCR_LEN
);
303 pos
+= EAP_SIM_K_ENCR_LEN
;
305 os_memcpy(k_aut
, pos
, EAP_AKA_PRIME_K_AUT_LEN
);
306 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': K_aut",
307 k_aut
, EAP_AKA_PRIME_K_AUT_LEN
);
308 pos
+= EAP_AKA_PRIME_K_AUT_LEN
;
310 os_memcpy(k_re
, pos
, EAP_AKA_PRIME_K_RE_LEN
);
311 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': K_re",
312 k_re
, EAP_AKA_PRIME_K_RE_LEN
);
313 pos
+= EAP_AKA_PRIME_K_RE_LEN
;
315 os_memcpy(msk
, pos
, EAP_MSK_LEN
);
316 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': MSK", msk
, EAP_MSK_LEN
);
319 os_memcpy(emsk
, pos
, EAP_EMSK_LEN
);
320 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': EMSK", emsk
, EAP_EMSK_LEN
);
324 int eap_aka_prime_derive_keys_reauth(const u8
*k_re
, u16 counter
,
325 const u8
*identity
, size_t identity_len
,
326 const u8
*nonce_s
, u8
*msk
, u8
*emsk
)
328 u8 seed3
[2 + EAP_SIM_NONCE_S_LEN
];
329 u8 keys
[EAP_MSK_LEN
+ EAP_EMSK_LEN
];
333 * MK = PRF'(K_re,"EAP-AKA' re-auth"|Identity|counter|NONCE_S)
335 * EMSK = MK[512..1023]
338 WPA_PUT_BE16(seed3
, counter
);
339 os_memcpy(seed3
+ 2, nonce_s
, EAP_SIM_NONCE_S_LEN
);
341 prf_prime(k_re
, "EAP-AKA' re-auth", identity
, identity_len
,
342 seed3
, sizeof(seed3
),
346 os_memcpy(msk
, pos
, EAP_MSK_LEN
);
347 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': MSK", msk
, EAP_MSK_LEN
);
350 os_memcpy(emsk
, pos
, EAP_EMSK_LEN
);
351 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': EMSK", emsk
, EAP_EMSK_LEN
);
353 os_memset(keys
, 0, sizeof(keys
));
359 int eap_sim_verify_mac_sha256(const u8
*k_aut
, const struct wpabuf
*req
,
360 const u8
*mac
, const u8
*extra
, size_t extra_len
)
362 unsigned char hmac
[SHA256_MAC_LEN
];
367 if (mac
== NULL
|| wpabuf_len(req
) < EAP_SIM_MAC_LEN
||
368 mac
< wpabuf_head_u8(req
) ||
369 mac
> wpabuf_head_u8(req
) + wpabuf_len(req
) - EAP_SIM_MAC_LEN
)
372 tmp
= os_memdup(wpabuf_head(req
), wpabuf_len(req
));
377 len
[0] = wpabuf_len(req
);
381 /* HMAC-SHA-256-128 */
382 os_memset(tmp
+ (mac
- wpabuf_head_u8(req
)), 0, EAP_SIM_MAC_LEN
);
383 wpa_hexdump(MSG_MSGDUMP
, "EAP-AKA': Verify MAC - msg",
384 tmp
, wpabuf_len(req
));
385 wpa_hexdump(MSG_MSGDUMP
, "EAP-AKA': Verify MAC - extra data",
387 wpa_hexdump_key(MSG_MSGDUMP
, "EAP-AKA': Verify MAC - K_aut",
388 k_aut
, EAP_AKA_PRIME_K_AUT_LEN
);
389 hmac_sha256_vector(k_aut
, EAP_AKA_PRIME_K_AUT_LEN
, 2, addr
, len
, hmac
);
390 wpa_hexdump(MSG_MSGDUMP
, "EAP-AKA': Verify MAC: MAC",
391 hmac
, EAP_SIM_MAC_LEN
);
394 return (os_memcmp_const(hmac
, mac
, EAP_SIM_MAC_LEN
) == 0) ? 0 : 1;
398 void eap_sim_add_mac_sha256(const u8
*k_aut
, const u8
*msg
, size_t msg_len
,
399 u8
*mac
, const u8
*extra
, size_t extra_len
)
401 unsigned char hmac
[SHA256_MAC_LEN
];
410 /* HMAC-SHA-256-128 */
411 os_memset(mac
, 0, EAP_SIM_MAC_LEN
);
412 wpa_hexdump(MSG_MSGDUMP
, "EAP-AKA': Add MAC - msg", msg
, msg_len
);
413 wpa_hexdump(MSG_MSGDUMP
, "EAP-AKA': Add MAC - extra data",
415 wpa_hexdump_key(MSG_MSGDUMP
, "EAP-AKA': Add MAC - K_aut",
416 k_aut
, EAP_AKA_PRIME_K_AUT_LEN
);
417 hmac_sha256_vector(k_aut
, EAP_AKA_PRIME_K_AUT_LEN
, 2, addr
, len
, hmac
);
418 os_memcpy(mac
, hmac
, EAP_SIM_MAC_LEN
);
419 wpa_hexdump(MSG_MSGDUMP
, "EAP-AKA': Add MAC: MAC",
420 mac
, EAP_SIM_MAC_LEN
);
424 void eap_aka_prime_derive_ck_ik_prime(u8
*ck
, u8
*ik
, const u8
*sqn_ak
,
425 const u8
*network_name
,
426 size_t network_name_len
)
428 u8 key
[EAP_AKA_CK_LEN
+ EAP_AKA_IK_LEN
];
429 u8 hash
[SHA256_MAC_LEN
];
435 /* 3GPP TS 33.402 V8.0.0
436 * (CK', IK') = F(CK, IK, <access network identity>)
438 /* TODO: CK', IK' generation should really be moved into the actual
439 * AKA procedure with network name passed in there and option to use
440 * AMF separation bit = 1 (3GPP TS 33.401). */
442 /* Change Request 33.402 CR 0033 to version 8.1.1 from
443 * 3GPP TSG-SA WG3 Meeting #53 in September 2008:
445 * CK' || IK' = HMAC-SHA-256(Key, S)
446 * S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
449 * P0 = access network identity (3GPP TS 24.302)
450 * L0 = length of acceess network identity (2 octets, big endian)
451 * P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0
457 wpa_printf(MSG_DEBUG
, "EAP-AKA': Derive (CK',IK') from (CK,IK)");
458 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': CK", ck
, EAP_AKA_CK_LEN
);
459 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': IK", ik
, EAP_AKA_IK_LEN
);
460 wpa_printf(MSG_DEBUG
, "EAP-AKA': FC = 0x%x", fc
);
461 wpa_hexdump_ascii(MSG_DEBUG
, "EAP-AKA': P0 = Access network identity",
462 network_name
, network_name_len
);
463 wpa_hexdump(MSG_DEBUG
, "EAP-AKA': P1 = SQN xor AK", sqn_ak
, 6);
465 os_memcpy(key
, ck
, EAP_AKA_CK_LEN
);
466 os_memcpy(key
+ EAP_AKA_CK_LEN
, ik
, EAP_AKA_IK_LEN
);
467 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': Key = CK || IK",
472 addr
[1] = network_name
;
473 len
[1] = network_name_len
;
474 WPA_PUT_BE16(l0
, network_name_len
);
483 hmac_sha256_vector(key
, sizeof(key
), 5, addr
, len
, hash
);
484 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': KDF output (CK' || IK')",
487 os_memcpy(ck
, hash
, EAP_AKA_CK_LEN
);
488 os_memcpy(ik
, hash
+ EAP_AKA_CK_LEN
, EAP_AKA_IK_LEN
);
489 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': CK'", ck
, EAP_AKA_CK_LEN
);
490 wpa_hexdump_key(MSG_DEBUG
, "EAP-AKA': IK'", ik
, EAP_AKA_IK_LEN
);
492 #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
495 int eap_sim_parse_attr(const u8
*start
, const u8
*end
,
496 struct eap_sim_attrs
*attr
, int aka
, int encr
)
498 const u8
*pos
= start
, *apos
;
499 size_t alen
, plen
, i
, list_len
;
501 os_memset(attr
, 0, sizeof(*attr
));
502 attr
->id_req
= NO_ID_REQ
;
503 attr
->notification
= -1;
505 attr
->selected_version
= -1;
506 attr
->client_error_code
= -1;
510 wpa_printf(MSG_INFO
, "EAP-SIM: Attribute overflow(1)");
513 wpa_printf(MSG_MSGDUMP
, "EAP-SIM: Attribute: Type=%d Len=%d",
515 if (pos
+ pos
[1] * 4 > end
) {
516 wpa_printf(MSG_INFO
, "EAP-SIM: Attribute overflow "
517 "(pos=%p len=%d end=%p)",
518 pos
, pos
[1] * 4, end
);
522 wpa_printf(MSG_INFO
, "EAP-SIM: Attribute underflow");
526 alen
= pos
[1] * 4 - 2;
527 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Attribute data",
531 case EAP_SIM_AT_RAND
:
532 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_RAND");
535 if ((!aka
&& (alen
% GSM_RAND_LEN
)) ||
536 (aka
&& alen
!= EAP_AKA_RAND_LEN
)) {
537 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_RAND"
539 (unsigned long) alen
);
543 attr
->num_chal
= alen
/ GSM_RAND_LEN
;
545 case EAP_SIM_AT_AUTN
:
546 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_AUTN");
548 wpa_printf(MSG_DEBUG
, "EAP-SIM: "
549 "Unexpected AT_AUTN");
554 if (alen
!= EAP_AKA_AUTN_LEN
) {
555 wpa_printf(MSG_INFO
, "EAP-AKA: Invalid AT_AUTN"
557 (unsigned long) alen
);
562 case EAP_SIM_AT_PADDING
:
564 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
568 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) AT_PADDING");
569 for (i
= 2; i
< alen
; i
++) {
571 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) "
572 "AT_PADDING used a non-zero"
574 wpa_hexdump(MSG_DEBUG
, "EAP-SIM: "
575 "(encr) padding bytes",
581 case EAP_SIM_AT_NONCE_MT
:
582 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_NONCE_MT");
583 if (alen
!= 2 + EAP_SIM_NONCE_MT_LEN
) {
584 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
585 "AT_NONCE_MT length");
588 attr
->nonce_mt
= apos
+ 2;
590 case EAP_SIM_AT_PERMANENT_ID_REQ
:
591 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_PERMANENT_ID_REQ");
592 attr
->id_req
= PERMANENT_ID
;
595 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_MAC");
596 if (alen
!= 2 + EAP_SIM_MAC_LEN
) {
597 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_MAC "
601 attr
->mac
= apos
+ 2;
603 case EAP_SIM_AT_NOTIFICATION
:
605 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
606 "AT_NOTIFICATION length %lu",
607 (unsigned long) alen
);
610 attr
->notification
= apos
[0] * 256 + apos
[1];
611 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_NOTIFICATION %d",
614 case EAP_SIM_AT_ANY_ID_REQ
:
615 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_ANY_ID_REQ");
616 attr
->id_req
= ANY_ID
;
618 case EAP_SIM_AT_IDENTITY
:
619 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_IDENTITY");
620 plen
= WPA_GET_BE16(apos
);
624 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
625 "AT_IDENTITY (Actual Length %lu, "
626 "remaining length %lu)",
627 (unsigned long) plen
,
628 (unsigned long) alen
);
632 attr
->identity
= apos
;
633 attr
->identity_len
= plen
;
635 case EAP_SIM_AT_VERSION_LIST
:
637 wpa_printf(MSG_DEBUG
, "EAP-AKA: "
638 "Unexpected AT_VERSION_LIST");
641 list_len
= apos
[0] * 256 + apos
[1];
642 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_VERSION_LIST");
643 if (list_len
< 2 || list_len
> alen
- 2) {
644 wpa_printf(MSG_WARNING
, "EAP-SIM: Invalid "
645 "AT_VERSION_LIST (list_len=%lu "
647 (unsigned long) list_len
,
648 (unsigned long) alen
);
651 attr
->version_list
= apos
+ 2;
652 attr
->version_list_len
= list_len
;
654 case EAP_SIM_AT_SELECTED_VERSION
:
655 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_SELECTED_VERSION");
657 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
658 "AT_SELECTED_VERSION length %lu",
659 (unsigned long) alen
);
662 attr
->selected_version
= apos
[0] * 256 + apos
[1];
663 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_SELECTED_VERSION "
664 "%d", attr
->selected_version
);
666 case EAP_SIM_AT_FULLAUTH_ID_REQ
:
667 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_FULLAUTH_ID_REQ");
668 attr
->id_req
= FULLAUTH_ID
;
670 case EAP_SIM_AT_COUNTER
:
672 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
677 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid "
678 "AT_COUNTER (alen=%lu)",
679 (unsigned long) alen
);
682 attr
->counter
= apos
[0] * 256 + apos
[1];
683 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) AT_COUNTER %d",
686 case EAP_SIM_AT_COUNTER_TOO_SMALL
:
688 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
689 "AT_COUNTER_TOO_SMALL");
693 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid "
694 "AT_COUNTER_TOO_SMALL (alen=%lu)",
695 (unsigned long) alen
);
698 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
699 "AT_COUNTER_TOO_SMALL");
700 attr
->counter_too_small
= 1;
702 case EAP_SIM_AT_NONCE_S
:
704 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
708 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
710 if (alen
!= 2 + EAP_SIM_NONCE_S_LEN
) {
711 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid "
712 "AT_NONCE_S (alen=%lu)",
713 (unsigned long) alen
);
716 attr
->nonce_s
= apos
+ 2;
718 case EAP_SIM_AT_CLIENT_ERROR_CODE
:
720 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
721 "AT_CLIENT_ERROR_CODE length %lu",
722 (unsigned long) alen
);
725 attr
->client_error_code
= apos
[0] * 256 + apos
[1];
726 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_CLIENT_ERROR_CODE "
727 "%d", attr
->client_error_code
);
730 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_IV");
731 if (alen
!= 2 + EAP_SIM_MAC_LEN
) {
732 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_IV "
733 "length %lu", (unsigned long) alen
);
738 case EAP_SIM_AT_ENCR_DATA
:
739 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_ENCR_DATA");
740 attr
->encr_data
= apos
+ 2;
741 attr
->encr_data_len
= alen
- 2;
742 if (attr
->encr_data_len
% 16) {
743 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
744 "AT_ENCR_DATA length %lu",
746 attr
->encr_data_len
);
750 case EAP_SIM_AT_NEXT_PSEUDONYM
:
752 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
753 "AT_NEXT_PSEUDONYM");
756 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
757 "AT_NEXT_PSEUDONYM");
758 plen
= apos
[0] * 256 + apos
[1];
759 if (plen
> alen
- 2) {
760 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid"
761 " AT_NEXT_PSEUDONYM (actual"
762 " len %lu, attr len %lu)",
763 (unsigned long) plen
,
764 (unsigned long) alen
);
767 attr
->next_pseudonym
= pos
+ 4;
768 attr
->next_pseudonym_len
= plen
;
770 case EAP_SIM_AT_NEXT_REAUTH_ID
:
772 wpa_printf(MSG_ERROR
, "EAP-SIM: Unencrypted "
773 "AT_NEXT_REAUTH_ID");
776 wpa_printf(MSG_DEBUG
, "EAP-SIM: (encr) "
777 "AT_NEXT_REAUTH_ID");
778 plen
= apos
[0] * 256 + apos
[1];
779 if (plen
> alen
- 2) {
780 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Invalid"
781 " AT_NEXT_REAUTH_ID (actual"
782 " len %lu, attr len %lu)",
783 (unsigned long) plen
,
784 (unsigned long) alen
);
787 attr
->next_reauth_id
= pos
+ 4;
788 attr
->next_reauth_id_len
= plen
;
791 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_RES");
792 attr
->res_len_bits
= WPA_GET_BE16(apos
);
795 if (!aka
|| alen
< EAP_AKA_MIN_RES_LEN
||
796 alen
> EAP_AKA_MAX_RES_LEN
) {
797 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid AT_RES "
799 (unsigned long) alen
);
803 attr
->res_len
= alen
;
805 case EAP_SIM_AT_AUTS
:
806 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_AUTS");
808 wpa_printf(MSG_DEBUG
, "EAP-SIM: "
809 "Unexpected AT_AUTS");
812 if (alen
!= EAP_AKA_AUTS_LEN
) {
813 wpa_printf(MSG_INFO
, "EAP-AKA: Invalid AT_AUTS"
815 (unsigned long) alen
);
820 case EAP_SIM_AT_CHECKCODE
:
821 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_CHECKCODE");
823 wpa_printf(MSG_DEBUG
, "EAP-SIM: "
824 "Unexpected AT_CHECKCODE");
829 if (alen
!= 0 && alen
!= EAP_AKA_CHECKCODE_LEN
&&
830 alen
!= EAP_AKA_PRIME_CHECKCODE_LEN
) {
831 wpa_printf(MSG_INFO
, "EAP-AKA: Invalid "
832 "AT_CHECKCODE (len %lu)",
833 (unsigned long) alen
);
836 attr
->checkcode
= apos
;
837 attr
->checkcode_len
= alen
;
839 case EAP_SIM_AT_RESULT_IND
:
841 wpa_printf(MSG_ERROR
, "EAP-SIM: Encrypted "
846 wpa_printf(MSG_INFO
, "EAP-SIM: Invalid "
847 "AT_RESULT_IND (alen=%lu)",
848 (unsigned long) alen
);
851 wpa_printf(MSG_DEBUG
, "EAP-SIM: AT_RESULT_IND");
852 attr
->result_ind
= 1;
854 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
855 case EAP_SIM_AT_KDF_INPUT
:
857 wpa_printf(MSG_INFO
, "EAP-AKA: Unexpected "
862 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_KDF_INPUT");
863 plen
= WPA_GET_BE16(apos
);
867 wpa_printf(MSG_INFO
, "EAP-AKA': Invalid "
868 "AT_KDF_INPUT (Actual Length %lu, "
869 "remaining length %lu)",
870 (unsigned long) plen
,
871 (unsigned long) alen
);
874 attr
->kdf_input
= apos
;
875 attr
->kdf_input_len
= plen
;
879 wpa_printf(MSG_INFO
, "EAP-AKA: Unexpected "
884 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_KDF");
886 wpa_printf(MSG_INFO
, "EAP-AKA': Invalid "
888 (unsigned long) alen
);
891 if (attr
->kdf_count
== EAP_AKA_PRIME_KDF_MAX
) {
892 wpa_printf(MSG_DEBUG
, "EAP-AKA': Too many "
893 "AT_KDF attributes - ignore this");
896 attr
->kdf
[attr
->kdf_count
] = WPA_GET_BE16(apos
);
899 case EAP_SIM_AT_BIDDING
:
900 wpa_printf(MSG_DEBUG
, "EAP-AKA: AT_BIDDING");
902 wpa_printf(MSG_INFO
, "EAP-AKA: Invalid "
903 "AT_BIDDING (len %lu)",
904 (unsigned long) alen
);
907 attr
->bidding
= apos
;
909 #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
912 wpa_printf(MSG_INFO
, "EAP-SIM: Unrecognized "
913 "non-skippable attribute %d",
918 wpa_printf(MSG_DEBUG
, "EAP-SIM: Unrecognized skippable"
919 " attribute %d ignored", pos
[0]);
926 wpa_printf(MSG_DEBUG
, "EAP-SIM: Attributes parsed successfully "
927 "(aka=%d encr=%d)", aka
, encr
);
933 u8
* eap_sim_parse_encr(const u8
*k_encr
, const u8
*encr_data
,
934 size_t encr_data_len
, const u8
*iv
,
935 struct eap_sim_attrs
*attr
, int aka
)
940 wpa_printf(MSG_INFO
, "EAP-SIM: Encrypted data, but no IV");
944 decrypted
= os_memdup(encr_data
, encr_data_len
);
945 if (decrypted
== NULL
)
948 if (aes_128_cbc_decrypt(k_encr
, iv
, decrypted
, encr_data_len
)) {
952 wpa_hexdump(MSG_MSGDUMP
, "EAP-SIM: Decrypted AT_ENCR_DATA",
953 decrypted
, encr_data_len
);
955 if (eap_sim_parse_attr(decrypted
, decrypted
+ encr_data_len
, attr
,
957 wpa_printf(MSG_INFO
, "EAP-SIM: (encr) Failed to parse "
958 "decrypted AT_ENCR_DATA");
967 #define EAP_SIM_INIT_LEN 128
971 size_t mac
, iv
, encr
; /* index from buf */
975 struct eap_sim_msg
* eap_sim_msg_init(int code
, int id
, int type
, int subtype
)
977 struct eap_sim_msg
*msg
;
981 msg
= os_zalloc(sizeof(*msg
));
985 msg
->buf
= wpabuf_alloc(EAP_SIM_INIT_LEN
);
986 if (msg
->buf
== NULL
) {
990 eap
= wpabuf_put(msg
->buf
, sizeof(*eap
));
992 eap
->identifier
= id
;
994 pos
= wpabuf_put(msg
->buf
, 4);
997 *pos
++ = 0; /* Reserved */
998 *pos
++ = 0; /* Reserved */
1004 struct wpabuf
* eap_sim_msg_finish(struct eap_sim_msg
*msg
, int type
,
1006 const u8
*extra
, size_t extra_len
)
1008 struct eap_hdr
*eap
;
1014 eap
= wpabuf_mhead(msg
->buf
);
1015 eap
->length
= host_to_be16(wpabuf_len(msg
->buf
));
1017 #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME)
1018 if (k_aut
&& msg
->mac
&& type
== EAP_TYPE_AKA_PRIME
) {
1019 eap_sim_add_mac_sha256(k_aut
, (u8
*) wpabuf_head(msg
->buf
),
1020 wpabuf_len(msg
->buf
),
1021 (u8
*) wpabuf_mhead(msg
->buf
) +
1022 msg
->mac
, extra
, extra_len
);
1024 #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */
1025 if (k_aut
&& msg
->mac
) {
1026 eap_sim_add_mac(k_aut
, (u8
*) wpabuf_head(msg
->buf
),
1027 wpabuf_len(msg
->buf
),
1028 (u8
*) wpabuf_mhead(msg
->buf
) + msg
->mac
,
1038 void eap_sim_msg_free(struct eap_sim_msg
*msg
)
1041 wpabuf_free(msg
->buf
);
1047 u8
* eap_sim_msg_add_full(struct eap_sim_msg
*msg
, u8 attr
,
1048 const u8
*data
, size_t len
)
1050 int attr_len
= 2 + len
;
1057 pad_len
= (4 - attr_len
% 4) % 4;
1058 attr_len
+= pad_len
;
1059 if (wpabuf_resize(&msg
->buf
, attr_len
))
1061 start
= wpabuf_put(msg
->buf
, 0);
1062 wpabuf_put_u8(msg
->buf
, attr
);
1063 wpabuf_put_u8(msg
->buf
, attr_len
/ 4);
1064 wpabuf_put_data(msg
->buf
, data
, len
);
1066 os_memset(wpabuf_put(msg
->buf
, pad_len
), 0, pad_len
);
1071 u8
* eap_sim_msg_add(struct eap_sim_msg
*msg
, u8 attr
, u16 value
,
1072 const u8
*data
, size_t len
)
1074 int attr_len
= 4 + len
;
1081 pad_len
= (4 - attr_len
% 4) % 4;
1082 attr_len
+= pad_len
;
1083 if (wpabuf_resize(&msg
->buf
, attr_len
))
1085 start
= wpabuf_put(msg
->buf
, 0);
1086 wpabuf_put_u8(msg
->buf
, attr
);
1087 wpabuf_put_u8(msg
->buf
, attr_len
/ 4);
1088 wpabuf_put_be16(msg
->buf
, value
);
1090 wpabuf_put_data(msg
->buf
, data
, len
);
1092 wpabuf_put(msg
->buf
, len
);
1094 os_memset(wpabuf_put(msg
->buf
, pad_len
), 0, pad_len
);
1099 u8
* eap_sim_msg_add_mac(struct eap_sim_msg
*msg
, u8 attr
)
1101 u8
*pos
= eap_sim_msg_add(msg
, attr
, 0, NULL
, EAP_SIM_MAC_LEN
);
1103 msg
->mac
= (pos
- wpabuf_head_u8(msg
->buf
)) + 4;
1108 int eap_sim_msg_add_encr_start(struct eap_sim_msg
*msg
, u8 attr_iv
,
1111 u8
*pos
= eap_sim_msg_add(msg
, attr_iv
, 0, NULL
, EAP_SIM_IV_LEN
);
1114 msg
->iv
= (pos
- wpabuf_head_u8(msg
->buf
)) + 4;
1115 if (random_get_bytes(wpabuf_mhead_u8(msg
->buf
) + msg
->iv
,
1121 pos
= eap_sim_msg_add(msg
, attr_encr
, 0, NULL
, 0);
1126 msg
->encr
= pos
- wpabuf_head_u8(msg
->buf
);
1132 int eap_sim_msg_add_encr_end(struct eap_sim_msg
*msg
, u8
*k_encr
, int attr_pad
)
1136 if (msg
== NULL
|| k_encr
== NULL
|| msg
->iv
== 0 || msg
->encr
== 0)
1139 encr_len
= wpabuf_len(msg
->buf
) - msg
->encr
- 4;
1140 if (encr_len
% 16) {
1142 int pad_len
= 16 - (encr_len
% 16);
1144 wpa_printf(MSG_WARNING
, "EAP-SIM: "
1145 "eap_sim_msg_add_encr_end - invalid pad_len"
1149 wpa_printf(MSG_DEBUG
, " *AT_PADDING");
1150 pos
= eap_sim_msg_add(msg
, attr_pad
, 0, NULL
, pad_len
- 4);
1153 os_memset(pos
+ 4, 0, pad_len
- 4);
1154 encr_len
+= pad_len
;
1156 wpa_printf(MSG_DEBUG
, " (AT_ENCR_DATA data len %lu)",
1157 (unsigned long) encr_len
);
1158 wpabuf_mhead_u8(msg
->buf
)[msg
->encr
+ 1] = encr_len
/ 4 + 1;
1159 return aes_128_cbc_encrypt(k_encr
, wpabuf_head_u8(msg
->buf
) + msg
->iv
,
1160 wpabuf_mhead_u8(msg
->buf
) + msg
->encr
+ 4,
1165 void eap_sim_report_notification(void *msg_ctx
, int notification
, int aka
)
1167 #ifndef CONFIG_NO_STDOUT_DEBUG
1168 const char *type
= aka
? "AKA" : "SIM";
1169 #endif /* CONFIG_NO_STDOUT_DEBUG */
1171 switch (notification
) {
1172 case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH
:
1173 wpa_printf(MSG_WARNING
, "EAP-%s: General failure "
1174 "notification (after authentication)", type
);
1176 case EAP_SIM_TEMPORARILY_DENIED
:
1177 wpa_printf(MSG_WARNING
, "EAP-%s: Failure notification: "
1178 "User has been temporarily denied access to the "
1179 "requested service", type
);
1181 case EAP_SIM_NOT_SUBSCRIBED
:
1182 wpa_printf(MSG_WARNING
, "EAP-%s: Failure notification: "
1183 "User has not subscribed to the requested service",
1186 case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH
:
1187 wpa_printf(MSG_WARNING
, "EAP-%s: General failure "
1188 "notification (before authentication)", type
);
1190 case EAP_SIM_SUCCESS
:
1191 wpa_printf(MSG_INFO
, "EAP-%s: Successful authentication "
1192 "notification", type
);
1195 if (notification
>= 32768) {
1196 wpa_printf(MSG_INFO
, "EAP-%s: Unrecognized "
1197 "non-failure notification %d",
1198 type
, notification
);
1200 wpa_printf(MSG_WARNING
, "EAP-%s: Unrecognized "
1201 "failure notification %d",
1202 type
, notification
);