1845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/*
2845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * EAP peer: EAP-SIM/AKA shared routines
3845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
5845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This program is free software; you can redistribute it and/or modify
6845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * it under the terms of the GNU General Public License version 2 as
7845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * published by the Free Software Foundation.
8845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
9845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Alternatively, this software may be distributed under the terms of BSD
10845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * license.
11845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *
12845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * See README and COPYING for more details.
13845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */
14845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
15845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "includes.h"
16845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
17845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "common.h"
18845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eap_i.h"
19845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "sha1.h"
20845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "crypto.h"
21845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "aes_wrap.h"
22845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "eap_sim_common.h"
23845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
24845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
25845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
26845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
27845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen);
28845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
29845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
30845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
31845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sim_derive_mk(const u8 *identity, size_t identity_len,
32845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       const u8 *nonce_mt, u16 selected_version,
33845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       const u8 *ver_list, size_t ver_list_len,
34845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       int num_chal, const u8 *kc, u8 *mk)
35845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
36845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 sel_ver[2];
37845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const unsigned char *addr[5];
38845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len[5];
39845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
40845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[0] = identity;
41845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[0] = identity_len;
42845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[1] = kc;
43845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[1] = num_chal * EAP_SIM_KC_LEN;
44845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[2] = nonce_mt;
45845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[2] = EAP_SIM_NONCE_MT_LEN;
46845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[3] = ver_list;
47845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[3] = ver_list_len;
48845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[4] = sel_ver;
49845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[4] = 2;
50845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
51845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(sel_ver, selected_version);
52845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
53845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
54845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sha1_vector(5, addr, len, mk);
55845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
56845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
57845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
58845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
59845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_aka_derive_mk(const u8 *identity, size_t identity_len,
60845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       const u8 *ik, const u8 *ck, u8 *mk)
61845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
62845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *addr[3];
63845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len[3];
64845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
65845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[0] = identity;
66845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[0] = identity_len;
67845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[1] = ik;
68845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[1] = EAP_AKA_IK_LEN;
69845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[2] = ck;
70845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[2] = EAP_AKA_CK_LEN;
71845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
72845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* MK = SHA1(Identity|IK|CK) */
73845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sha1_vector(3, addr, len, mk);
74845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN);
75845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN);
76845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN);
77845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
78845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
79845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
80845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk)
81845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
82845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN +
83845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	       EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos;
84845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) {
85845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
86845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
87845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
88845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = buf;
89845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
90845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += EAP_SIM_K_ENCR_LEN;
91845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
92845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += EAP_SIM_K_AUT_LEN;
93845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
94845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += EAP_SIM_KEYING_DATA_LEN;
95845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(emsk, pos, EAP_EMSK_LEN);
96845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
97845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
98845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			k_encr, EAP_SIM_K_ENCR_LEN);
99845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			k_aut, EAP_SIM_K_AUT_LEN);
101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			msk, EAP_SIM_KEYING_DATA_LEN);
103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(buf, 0, sizeof(buf));
105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sim_derive_keys_reauth(u16 _counter,
111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       const u8 *identity, size_t identity_len,
112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       const u8 *nonce_s, const u8 *mk, u8 *msk,
113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       u8 *emsk)
114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 xkey[SHA1_MAC_LEN];
116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32];
117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 counter[2];
118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *addr[4];
119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len[4];
120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (identity_len > 0 && identity[identity_len - 1] == 0) {
122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null "
123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "character from the end of identity");
124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		identity_len--;
125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[0] = identity;
127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[0] = identity_len;
128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[1] = counter;
129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[1] = 2;
130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[2] = nonce_s;
131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[2] = EAP_SIM_NONCE_S_LEN;
132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[3] = mk;
133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[3] = EAP_SIM_MK_LEN;
134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(counter, _counter);
136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth");
138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  identity, identity_len);
140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2);
141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s,
142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    EAP_SIM_NONCE_S_LEN);
143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */
146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	sha1_vector(4, addr, len, xkey);
147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) {
150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msk) {
154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN);
155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    msk, EAP_SIM_KEYING_DATA_LEN);
157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (emsk) {
159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN);
160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(buf, 0, sizeof(buf));
163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len,
169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       const u8 *mac, const u8 *extra, size_t extra_len)
170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	unsigned char hmac[SHA1_MAC_LEN];
172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *addr[2];
173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len[2];
174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *tmp;
175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (mac == NULL || req_len < EAP_SIM_MAC_LEN || mac < req ||
177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	    mac > req + req_len - EAP_SIM_MAC_LEN)
178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	tmp = os_malloc(req_len);
181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (tmp == NULL)
182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[0] = tmp;
185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[0] = req_len;
186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[1] = extra;
187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[1] = extra_len;
188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* HMAC-SHA1-128 */
190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(tmp, req, req_len);
191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", tmp, req_len);
193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data",
194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    extra, extra_len);
195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut",
196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			k_aut, EAP_SIM_K_AUT_LEN);
197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC",
199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    hmac, EAP_SIM_MAC_LEN);
200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(tmp);
201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac,
207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		     const u8 *extra, size_t extra_len)
208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	unsigned char hmac[SHA1_MAC_LEN];
210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *addr[2];
211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t len[2];
212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[0] = msg;
214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[0] = msg_len;
215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	addr[1] = extra;
216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	len[1] = extra_len;
217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	/* HMAC-SHA1-128 */
219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(mac, 0, EAP_SIM_MAC_LEN);
220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len);
221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data",
222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    extra, extra_len);
223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut",
224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			k_aut, EAP_SIM_K_AUT_LEN);
225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC",
228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    mac, EAP_SIM_MAC_LEN);
229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sim_parse_attr(const u8 *start, const u8 *end,
233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		       struct eap_sim_attrs *attr, int aka, int encr)
234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const u8 *pos = start, *apos;
236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t alen, plen, i, list_len;
237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memset(attr, 0, sizeof(*attr));
239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	attr->id_req = NO_ID_REQ;
240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	attr->notification = -1;
241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	attr->counter = -1;
242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	attr->selected_version = -1;
243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	attr->client_error_code = -1;
244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	while (pos < end) {
246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (pos + 2 > end) {
247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)");
248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return -1;
249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d",
251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   pos[0], pos[1] * 4);
252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (pos + pos[1] * 4 > end) {
253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow "
254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "(pos=%p len=%d end=%p)",
255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   pos, pos[1] * 4, end);
256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return -1;
257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (pos[1] == 0) {
259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow");
260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return -1;
261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		apos = pos + 2;
263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		alen = pos[1] * 4 - 2;
264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data",
265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    apos, alen);
266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		switch (pos[0]) {
268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_RAND:
269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND");
270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			apos += 2;
271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			alen -= 2;
272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if ((!aka && (alen % GSM_RAND_LEN)) ||
273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    (aka && alen != EAP_AKA_RAND_LEN)) {
274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   " (len %lu)",
276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->rand = apos;
280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->num_chal = alen / GSM_RAND_LEN;
281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_AUTN:
283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN");
284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!aka) {
285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_DEBUG, "EAP-SIM: "
286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "Unexpected AT_AUTN");
287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			apos += 2;
290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			alen -= 2;
291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != EAP_AKA_AUTN_LEN) {
292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   " (len %lu)",
294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->autn = apos;
298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_PADDING:
300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!encr) {
301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_PADDING");
303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING");
306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			for (i = 2; i < alen; i++) {
307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				if (apos[i] != 0) {
308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					wpa_printf(MSG_INFO, "EAP-SIM: (encr) "
309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						   "AT_PADDING used a non-zero"
310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						   " padding byte");
311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					wpa_hexdump(MSG_DEBUG, "EAP-SIM: "
312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						    "(encr) padding bytes",
313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project						    apos + 2, alen - 2);
314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					return -1;
315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				}
316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_NONCE_MT:
319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT");
320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2 + EAP_SIM_NONCE_MT_LEN) {
321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_NONCE_MT length");
323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->nonce_mt = apos + 2;
326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_PERMANENT_ID_REQ:
328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ");
329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->id_req = PERMANENT_ID;
330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_MAC:
332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC");
333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2 + EAP_SIM_MAC_LEN) {
334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC "
335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "length");
336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->mac = apos + 2;
339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_NOTIFICATION:
341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2) {
342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_NOTIFICATION length %lu",
344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->notification = apos[0] * 256 + apos[1];
348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d",
349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   attr->notification);
350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_ANY_ID_REQ:
352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ");
353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->id_req = ANY_ID;
354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_IDENTITY:
356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY");
357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->identity = apos + 2;
358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->identity_len = alen - 2;
359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_VERSION_LIST:
361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (aka) {
362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_DEBUG, "EAP-AKA: "
363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "Unexpected AT_VERSION_LIST");
364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			list_len = apos[0] * 256 + apos[1];
367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (list_len < 2 || list_len > alen - 2) {
369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_VERSION_LIST (list_len=%lu "
371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "attr_len=%lu)",
372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) list_len,
373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->version_list = apos + 2;
377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->version_list_len = list_len;
378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_SELECTED_VERSION:
380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION");
381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2) {
382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_SELECTED_VERSION length %lu",
384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->selected_version = apos[0] * 256 + apos[1];
388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION "
389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "%d", attr->selected_version);
390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_FULLAUTH_ID_REQ:
392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ");
393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->id_req = FULLAUTH_ID;
394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_COUNTER:
396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!encr) {
397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_COUNTER");
399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2) {
402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_COUNTER (alen=%lu)",
404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->counter = apos[0] * 256 + apos[1];
408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d",
409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   attr->counter);
410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_COUNTER_TOO_SMALL:
412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!encr) {
413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_COUNTER_TOO_SMALL");
415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2) {
418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_COUNTER_TOO_SMALL (alen=%lu)",
420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "AT_COUNTER_TOO_SMALL");
425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->counter_too_small = 1;
426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_NONCE_S:
428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!encr) {
429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_NONCE_S");
431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "AT_NONCE_S");
435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2 + EAP_SIM_NONCE_S_LEN) {
436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_NONCE_S (alen=%lu)",
438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->nonce_s = apos + 2;
442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_CLIENT_ERROR_CODE:
444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2) {
445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_CLIENT_ERROR_CODE length %lu",
447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->client_error_code = apos[0] * 256 + apos[1];
451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE "
452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "%d", attr->client_error_code);
453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_IV:
455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV");
456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != 2 + EAP_SIM_MAC_LEN) {
457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV "
458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "length %lu", (unsigned long) alen);
459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->iv = apos + 2;
462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_ENCR_DATA:
464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA");
465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->encr_data = apos + 2;
466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->encr_data_len = alen - 2;
467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (attr->encr_data_len % 16) {
468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_ENCR_DATA length %lu",
470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long)
471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   attr->encr_data_len);
472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_NEXT_PSEUDONYM:
476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!encr) {
477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_NEXT_PSEUDONYM");
479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "AT_NEXT_PSEUDONYM");
483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			plen = apos[0] * 256 + apos[1];
484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (plen > alen - 2) {
485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   " AT_NEXT_PSEUDONYM (actual"
487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   " len %lu, attr len %lu)",
488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) plen,
489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->next_pseudonym = pos + 4;
493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->next_pseudonym_len = plen;
494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_NEXT_REAUTH_ID:
496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!encr) {
497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "AT_NEXT_REAUTH_ID");
499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "AT_NEXT_REAUTH_ID");
503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			plen = apos[0] * 256 + apos[1];
504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (plen > alen - 2) {
505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   " AT_NEXT_REAUTH_ID (actual"
507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   " len %lu, attr len %lu)",
508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) plen,
509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->next_reauth_id = pos + 4;
513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->next_reauth_id_len = plen;
514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_RES:
516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			apos += 2;
518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			alen -= 2;
519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    alen > EAP_AKA_MAX_RES_LEN) {
521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES "
522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "(len %lu)",
523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->res = apos;
527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->res_len = alen;
528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		case EAP_SIM_AT_AUTS:
530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS");
531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (!aka) {
532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_DEBUG, "EAP-SIM: "
533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "Unexpected AT_AUTS");
534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (alen != EAP_AKA_AUTS_LEN) {
537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS"
538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   " (len %lu)",
539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   (unsigned long) alen);
540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			attr->auts = apos;
543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		default:
545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			if (pos[0] < 128) {
546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   "non-skippable attribute %d",
548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project					   pos[0]);
549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				return -1;
550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			}
551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable"
553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   " attribute %d ignored", pos[0]);
554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			break;
555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos += pos[1] * 4;
558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully "
561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   "(aka=%d encr=%d)", aka, encr);
562845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
563845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
564845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
565845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
566845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
567845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
568845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			size_t encr_data_len, const u8 *iv,
569845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			struct eap_sim_attrs *attr, int aka)
570845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
571845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *decrypted;
572845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
573845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (!iv) {
574845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV");
575845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
576845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
577845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
578845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	decrypted = os_malloc(encr_data_len);
579845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (decrypted == NULL)
580845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
581845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(decrypted, encr_data, encr_data_len);
582845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
583845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len);
584845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
585845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		    decrypted, encr_data_len);
586845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
587845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr,
588845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       aka, 1)) {
589845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
590845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "decrypted AT_ENCR_DATA");
591845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(decrypted);
592845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
593845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
594845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
595845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return decrypted;
596845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
597845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
598845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
599845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#define EAP_SIM_INIT_LEN 128
600845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
601845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct eap_sim_msg {
602845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *buf;
603845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t buf_len, used;
604845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t mac, iv, encr; /* index from buf */
605845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project};
606845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
607845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
608845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype)
609845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
610845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_sim_msg *msg;
611845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *eap;
612845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos;
613845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
614845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg = os_zalloc(sizeof(*msg));
615845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg == NULL)
616845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
617845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
618845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->buf = os_zalloc(EAP_SIM_INIT_LEN);
619845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg->buf == NULL) {
620845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(msg);
621845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
622845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
623845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->buf_len = EAP_SIM_INIT_LEN;
624845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap = (struct eap_hdr *) msg->buf;
625845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->code = code;
626845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->identifier = id;
627845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->used = sizeof(*eap);
628845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
629845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = (u8 *) (eap + 1);
630845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = type;
631845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = subtype;
632845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = 0; /* Reserved */
633845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = 0; /* Reserved */
634845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->used += 4;
635845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
636845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return msg;
637845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
638845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
639845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
640845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut,
641845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			const u8 *extra, size_t extra_len)
642845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
643845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	struct eap_hdr *eap;
644845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *buf;
645845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
646845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg == NULL)
647845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
648845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
649845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap = (struct eap_hdr *) msg->buf;
650845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	eap->length = host_to_be16(msg->used);
651845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
652845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (k_aut && msg->mac) {
653845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		eap_sim_add_mac(k_aut, msg->buf, msg->used,
654845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				msg->buf + msg->mac, extra, extra_len);
655845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
656845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
657845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*len = msg->used;
658845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	buf = msg->buf;
659845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_free(msg);
660845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return buf;
661845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
662845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
663845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
664845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sim_msg_free(struct eap_sim_msg *msg)
665845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
666845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg) {
667845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(msg->buf);
668845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_free(msg);
669845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
670845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
671845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
672845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
673845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len)
674845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
675845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg->used + add_len > msg->buf_len) {
676845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		u8 *nbuf = os_realloc(msg->buf, msg->used + add_len);
677845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (nbuf == NULL)
678845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return -1;
679845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		msg->buf = nbuf;
680845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		msg->buf_len = msg->used + add_len;
681845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
682845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
683845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
684845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
685845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
686845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr,
687845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			  const u8 *data, size_t len)
688845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
689845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int attr_len = 2 + len;
690845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int pad_len;
691845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *start, *pos;
692845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
693845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg == NULL)
694845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
695845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
696845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pad_len = (4 - attr_len % 4) % 4;
697845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	attr_len += pad_len;
698845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_sim_msg_resize(msg, attr_len))
699845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
700845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	start = pos = msg->buf + msg->used;
701845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = attr;
702845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = attr_len / 4;
703845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	os_memcpy(pos, data, len);
704845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pad_len) {
705845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos += len;
706845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memset(pos, 0, pad_len);
707845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
708845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->used += attr_len;
709845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return start;
710845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
711845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
712845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
713845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value,
714845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		     const u8 *data, size_t len)
715845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
716845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int attr_len = 4 + len;
717845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	int pad_len;
718845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *start, *pos;
719845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
720845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg == NULL)
721845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
722845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
723845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pad_len = (4 - attr_len % 4) % 4;
724845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	attr_len += pad_len;
725845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (eap_sim_msg_resize(msg, attr_len))
726845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return NULL;
727845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	start = pos = msg->buf + msg->used;
728845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = attr;
729845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	*pos++ = attr_len / 4;
730845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	WPA_PUT_BE16(pos, value);
731845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos += 2;
732845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (data)
733845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memcpy(pos, data, len);
734845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pad_len) {
735845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos += len;
736845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memset(pos, 0, pad_len);
737845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
738845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->used += attr_len;
739845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return start;
740845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
741845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
742845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
743845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectu8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr)
744845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
745845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN);
746845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos)
747845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		msg->mac = (pos - msg->buf) + 4;
748845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return pos;
749845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
750845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
751845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
752845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv,
753845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			       u8 attr_encr)
754845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
755845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN);
756845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL)
757845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
758845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->iv = (pos - msg->buf) + 4;
759845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (hostapd_get_rand(msg->buf + msg->iv, EAP_SIM_IV_LEN)) {
760845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		msg->iv = 0;
761845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
762845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
763845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
764845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0);
765845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (pos == NULL) {
766845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		msg->iv = 0;
767845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
768845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
769845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->encr = pos - msg->buf;
770845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
771845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
772845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
773845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
774845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
775845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad)
776845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
777845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	size_t encr_len;
778845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
779845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0)
780845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		return -1;
781845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
782845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	encr_len = msg->used - msg->encr - 4;
783845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	if (encr_len % 16) {
784845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		u8 *pos;
785845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		int pad_len = 16 - (encr_len % 16);
786845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (pad_len < 4) {
787845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_WARNING, "EAP-SIM: "
788845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "eap_sim_msg_add_encr_end - invalid pad_len"
789845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   " %d", pad_len);
790845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return -1;
791845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
792845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_DEBUG, "   *AT_PADDING");
793845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4);
794845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (pos == NULL)
795845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			return -1;
796845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		os_memset(pos + 4, 0, pad_len - 4);
797845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		encr_len += pad_len;
798845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
799845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	wpa_printf(MSG_DEBUG, "   (AT_ENCR_DATA data len %lu)",
800845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		   (unsigned long) encr_len);
801845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	msg->buf[msg->encr + 1] = encr_len / 4 + 1;
802845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	aes_128_cbc_encrypt(k_encr, msg->buf + msg->iv,
803845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			    msg->buf + msg->encr + 4, encr_len);
804845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
805845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	return 0;
806845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
807845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
808845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
809845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid eap_sim_report_notification(void *msg_ctx, int notification, int aka)
810845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{
811845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#ifndef CONFIG_NO_STDOUT_DEBUG
812845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	const char *type = aka ? "AKA" : "SIM";
813845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_NO_STDOUT_DEBUG */
814845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project
815845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	switch (notification) {
816845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH:
817845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "EAP-%s: General failure "
818845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "notification (after authentication)", type);
819845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
820845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SIM_TEMPORARILY_DENIED:
821845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
822845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "User has been temporarily denied access to the "
823845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "requested service", type);
824845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
825845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SIM_NOT_SUBSCRIBED:
826845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
827845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "User has not subscribed to the requested service",
828845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   type);
829845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
830845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH:
831845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_WARNING, "EAP-%s: General failure "
832845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "notification (before authentication)", type);
833845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
834845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	case EAP_SIM_SUCCESS:
835845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		wpa_printf(MSG_INFO, "EAP-%s: Successful authentication "
836845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			   "notification", type);
837845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		break;
838845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	default:
839845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		if (notification >= 32768) {
840845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_INFO, "EAP-%s: Unrecognized "
841845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "non-failure notification %d",
842845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   type, notification);
843845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		} else {
844845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project			wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized "
845845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   "failure notification %d",
846845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project				   type, notification);
847845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project		}
848845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project	}
849845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project}
850