1 /*
2 * EAP peer: EAP-SIM/AKA shared routines
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eap_i.h"
19 #include "sha1.h"
20 #include "crypto.h"
21 #include "aes_wrap.h"
22 #include "eap_sim_common.h"
23
24
eap_sim_prf(const u8 * key,u8 * x,size_t xlen)25 static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
26 {
27 return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen);
28 }
29
30
eap_sim_derive_mk(const u8 * identity,size_t identity_len,const u8 * nonce_mt,u16 selected_version,const u8 * ver_list,size_t ver_list_len,int num_chal,const u8 * kc,u8 * mk)31 void eap_sim_derive_mk(const u8 *identity, size_t identity_len,
32 const u8 *nonce_mt, u16 selected_version,
33 const u8 *ver_list, size_t ver_list_len,
34 int num_chal, const u8 *kc, u8 *mk)
35 {
36 u8 sel_ver[2];
37 const unsigned char *addr[5];
38 size_t len[5];
39
40 addr[0] = identity;
41 len[0] = identity_len;
42 addr[1] = kc;
43 len[1] = num_chal * EAP_SIM_KC_LEN;
44 addr[2] = nonce_mt;
45 len[2] = EAP_SIM_NONCE_MT_LEN;
46 addr[3] = ver_list;
47 len[3] = ver_list_len;
48 addr[4] = sel_ver;
49 len[4] = 2;
50
51 WPA_PUT_BE16(sel_ver, selected_version);
52
53 /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
54 sha1_vector(5, addr, len, mk);
55 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
56 }
57
58
eap_aka_derive_mk(const u8 * identity,size_t identity_len,const u8 * ik,const u8 * ck,u8 * mk)59 void eap_aka_derive_mk(const u8 *identity, size_t identity_len,
60 const u8 *ik, const u8 *ck, u8 *mk)
61 {
62 const u8 *addr[3];
63 size_t len[3];
64
65 addr[0] = identity;
66 len[0] = identity_len;
67 addr[1] = ik;
68 len[1] = EAP_AKA_IK_LEN;
69 addr[2] = ck;
70 len[2] = EAP_AKA_CK_LEN;
71
72 /* MK = SHA1(Identity|IK|CK) */
73 sha1_vector(3, addr, len, mk);
74 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN);
75 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN);
76 wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN);
77 }
78
79
eap_sim_derive_keys(const u8 * mk,u8 * k_encr,u8 * k_aut,u8 * msk,u8 * emsk)80 int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk)
81 {
82 u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN +
83 EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos;
84 if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) {
85 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
86 return -1;
87 }
88 pos = buf;
89 os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
90 pos += EAP_SIM_K_ENCR_LEN;
91 os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
92 pos += EAP_SIM_K_AUT_LEN;
93 os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
94 pos += EAP_SIM_KEYING_DATA_LEN;
95 os_memcpy(emsk, pos, EAP_EMSK_LEN);
96
97 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
98 k_encr, EAP_SIM_K_ENCR_LEN);
99 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
100 k_aut, EAP_SIM_K_AUT_LEN);
101 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
102 msk, EAP_SIM_KEYING_DATA_LEN);
103 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
104 os_memset(buf, 0, sizeof(buf));
105
106 return 0;
107 }
108
109
eap_sim_derive_keys_reauth(u16 _counter,const u8 * identity,size_t identity_len,const u8 * nonce_s,const u8 * mk,u8 * msk,u8 * emsk)110 int eap_sim_derive_keys_reauth(u16 _counter,
111 const u8 *identity, size_t identity_len,
112 const u8 *nonce_s, const u8 *mk, u8 *msk,
113 u8 *emsk)
114 {
115 u8 xkey[SHA1_MAC_LEN];
116 u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32];
117 u8 counter[2];
118 const u8 *addr[4];
119 size_t len[4];
120
121 while (identity_len > 0 && identity[identity_len - 1] == 0) {
122 wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null "
123 "character from the end of identity");
124 identity_len--;
125 }
126 addr[0] = identity;
127 len[0] = identity_len;
128 addr[1] = counter;
129 len[1] = 2;
130 addr[2] = nonce_s;
131 len[2] = EAP_SIM_NONCE_S_LEN;
132 addr[3] = mk;
133 len[3] = EAP_SIM_MK_LEN;
134
135 WPA_PUT_BE16(counter, _counter);
136
137 wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth");
138 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
139 identity, identity_len);
140 wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2);
141 wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s,
142 EAP_SIM_NONCE_S_LEN);
143 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
144
145 /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */
146 sha1_vector(4, addr, len, xkey);
147 wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
148
149 if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) {
150 wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
151 return -1;
152 }
153 if (msk) {
154 os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN);
155 wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
156 msk, EAP_SIM_KEYING_DATA_LEN);
157 }
158 if (emsk) {
159 os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN);
160 wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
161 }
162 os_memset(buf, 0, sizeof(buf));
163
164 return 0;
165 }
166
167
eap_sim_verify_mac(const u8 * k_aut,const u8 * req,size_t req_len,const u8 * mac,const u8 * extra,size_t extra_len)168 int eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len,
169 const u8 *mac, const u8 *extra, size_t extra_len)
170 {
171 unsigned char hmac[SHA1_MAC_LEN];
172 const u8 *addr[2];
173 size_t len[2];
174 u8 *tmp;
175
176 if (mac == NULL || req_len < EAP_SIM_MAC_LEN || mac < req ||
177 mac > req + req_len - EAP_SIM_MAC_LEN)
178 return -1;
179
180 tmp = os_malloc(req_len);
181 if (tmp == NULL)
182 return -1;
183
184 addr[0] = tmp;
185 len[0] = req_len;
186 addr[1] = extra;
187 len[1] = extra_len;
188
189 /* HMAC-SHA1-128 */
190 os_memcpy(tmp, req, req_len);
191 os_memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
192 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", tmp, req_len);
193 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data",
194 extra, extra_len);
195 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut",
196 k_aut, EAP_SIM_K_AUT_LEN);
197 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
198 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC",
199 hmac, EAP_SIM_MAC_LEN);
200 os_free(tmp);
201
202 return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
203 }
204
205
eap_sim_add_mac(const u8 * k_aut,u8 * msg,size_t msg_len,u8 * mac,const u8 * extra,size_t extra_len)206 void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac,
207 const u8 *extra, size_t extra_len)
208 {
209 unsigned char hmac[SHA1_MAC_LEN];
210 const u8 *addr[2];
211 size_t len[2];
212
213 addr[0] = msg;
214 len[0] = msg_len;
215 addr[1] = extra;
216 len[1] = extra_len;
217
218 /* HMAC-SHA1-128 */
219 os_memset(mac, 0, EAP_SIM_MAC_LEN);
220 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len);
221 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data",
222 extra, extra_len);
223 wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut",
224 k_aut, EAP_SIM_K_AUT_LEN);
225 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
226 os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
227 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC",
228 mac, EAP_SIM_MAC_LEN);
229 }
230
231
eap_sim_parse_attr(const u8 * start,const u8 * end,struct eap_sim_attrs * attr,int aka,int encr)232 int eap_sim_parse_attr(const u8 *start, const u8 *end,
233 struct eap_sim_attrs *attr, int aka, int encr)
234 {
235 const u8 *pos = start, *apos;
236 size_t alen, plen, i, list_len;
237
238 os_memset(attr, 0, sizeof(*attr));
239 attr->id_req = NO_ID_REQ;
240 attr->notification = -1;
241 attr->counter = -1;
242 attr->selected_version = -1;
243 attr->client_error_code = -1;
244
245 while (pos < end) {
246 if (pos + 2 > end) {
247 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)");
248 return -1;
249 }
250 wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d",
251 pos[0], pos[1] * 4);
252 if (pos + pos[1] * 4 > end) {
253 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow "
254 "(pos=%p len=%d end=%p)",
255 pos, pos[1] * 4, end);
256 return -1;
257 }
258 if (pos[1] == 0) {
259 wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow");
260 return -1;
261 }
262 apos = pos + 2;
263 alen = pos[1] * 4 - 2;
264 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data",
265 apos, alen);
266
267 switch (pos[0]) {
268 case EAP_SIM_AT_RAND:
269 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND");
270 apos += 2;
271 alen -= 2;
272 if ((!aka && (alen % GSM_RAND_LEN)) ||
273 (aka && alen != EAP_AKA_RAND_LEN)) {
274 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
275 " (len %lu)",
276 (unsigned long) alen);
277 return -1;
278 }
279 attr->rand = apos;
280 attr->num_chal = alen / GSM_RAND_LEN;
281 break;
282 case EAP_SIM_AT_AUTN:
283 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN");
284 if (!aka) {
285 wpa_printf(MSG_DEBUG, "EAP-SIM: "
286 "Unexpected AT_AUTN");
287 return -1;
288 }
289 apos += 2;
290 alen -= 2;
291 if (alen != EAP_AKA_AUTN_LEN) {
292 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
293 " (len %lu)",
294 (unsigned long) alen);
295 return -1;
296 }
297 attr->autn = apos;
298 break;
299 case EAP_SIM_AT_PADDING:
300 if (!encr) {
301 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
302 "AT_PADDING");
303 return -1;
304 }
305 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING");
306 for (i = 2; i < alen; i++) {
307 if (apos[i] != 0) {
308 wpa_printf(MSG_INFO, "EAP-SIM: (encr) "
309 "AT_PADDING used a non-zero"
310 " padding byte");
311 wpa_hexdump(MSG_DEBUG, "EAP-SIM: "
312 "(encr) padding bytes",
313 apos + 2, alen - 2);
314 return -1;
315 }
316 }
317 break;
318 case EAP_SIM_AT_NONCE_MT:
319 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT");
320 if (alen != 2 + EAP_SIM_NONCE_MT_LEN) {
321 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
322 "AT_NONCE_MT length");
323 return -1;
324 }
325 attr->nonce_mt = apos + 2;
326 break;
327 case EAP_SIM_AT_PERMANENT_ID_REQ:
328 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ");
329 attr->id_req = PERMANENT_ID;
330 break;
331 case EAP_SIM_AT_MAC:
332 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC");
333 if (alen != 2 + EAP_SIM_MAC_LEN) {
334 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC "
335 "length");
336 return -1;
337 }
338 attr->mac = apos + 2;
339 break;
340 case EAP_SIM_AT_NOTIFICATION:
341 if (alen != 2) {
342 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
343 "AT_NOTIFICATION length %lu",
344 (unsigned long) alen);
345 return -1;
346 }
347 attr->notification = apos[0] * 256 + apos[1];
348 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d",
349 attr->notification);
350 break;
351 case EAP_SIM_AT_ANY_ID_REQ:
352 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ");
353 attr->id_req = ANY_ID;
354 break;
355 case EAP_SIM_AT_IDENTITY:
356 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY");
357 attr->identity = apos + 2;
358 attr->identity_len = alen - 2;
359 break;
360 case EAP_SIM_AT_VERSION_LIST:
361 if (aka) {
362 wpa_printf(MSG_DEBUG, "EAP-AKA: "
363 "Unexpected AT_VERSION_LIST");
364 return -1;
365 }
366 list_len = apos[0] * 256 + apos[1];
367 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
368 if (list_len < 2 || list_len > alen - 2) {
369 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
370 "AT_VERSION_LIST (list_len=%lu "
371 "attr_len=%lu)",
372 (unsigned long) list_len,
373 (unsigned long) alen);
374 return -1;
375 }
376 attr->version_list = apos + 2;
377 attr->version_list_len = list_len;
378 break;
379 case EAP_SIM_AT_SELECTED_VERSION:
380 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION");
381 if (alen != 2) {
382 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
383 "AT_SELECTED_VERSION length %lu",
384 (unsigned long) alen);
385 return -1;
386 }
387 attr->selected_version = apos[0] * 256 + apos[1];
388 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION "
389 "%d", attr->selected_version);
390 break;
391 case EAP_SIM_AT_FULLAUTH_ID_REQ:
392 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ");
393 attr->id_req = FULLAUTH_ID;
394 break;
395 case EAP_SIM_AT_COUNTER:
396 if (!encr) {
397 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
398 "AT_COUNTER");
399 return -1;
400 }
401 if (alen != 2) {
402 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
403 "AT_COUNTER (alen=%lu)",
404 (unsigned long) alen);
405 return -1;
406 }
407 attr->counter = apos[0] * 256 + apos[1];
408 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d",
409 attr->counter);
410 break;
411 case EAP_SIM_AT_COUNTER_TOO_SMALL:
412 if (!encr) {
413 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
414 "AT_COUNTER_TOO_SMALL");
415 return -1;
416 }
417 if (alen != 2) {
418 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
419 "AT_COUNTER_TOO_SMALL (alen=%lu)",
420 (unsigned long) alen);
421 return -1;
422 }
423 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
424 "AT_COUNTER_TOO_SMALL");
425 attr->counter_too_small = 1;
426 break;
427 case EAP_SIM_AT_NONCE_S:
428 if (!encr) {
429 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
430 "AT_NONCE_S");
431 return -1;
432 }
433 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
434 "AT_NONCE_S");
435 if (alen != 2 + EAP_SIM_NONCE_S_LEN) {
436 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
437 "AT_NONCE_S (alen=%lu)",
438 (unsigned long) alen);
439 return -1;
440 }
441 attr->nonce_s = apos + 2;
442 break;
443 case EAP_SIM_AT_CLIENT_ERROR_CODE:
444 if (alen != 2) {
445 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
446 "AT_CLIENT_ERROR_CODE length %lu",
447 (unsigned long) alen);
448 return -1;
449 }
450 attr->client_error_code = apos[0] * 256 + apos[1];
451 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE "
452 "%d", attr->client_error_code);
453 break;
454 case EAP_SIM_AT_IV:
455 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV");
456 if (alen != 2 + EAP_SIM_MAC_LEN) {
457 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV "
458 "length %lu", (unsigned long) alen);
459 return -1;
460 }
461 attr->iv = apos + 2;
462 break;
463 case EAP_SIM_AT_ENCR_DATA:
464 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA");
465 attr->encr_data = apos + 2;
466 attr->encr_data_len = alen - 2;
467 if (attr->encr_data_len % 16) {
468 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
469 "AT_ENCR_DATA length %lu",
470 (unsigned long)
471 attr->encr_data_len);
472 return -1;
473 }
474 break;
475 case EAP_SIM_AT_NEXT_PSEUDONYM:
476 if (!encr) {
477 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
478 "AT_NEXT_PSEUDONYM");
479 return -1;
480 }
481 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
482 "AT_NEXT_PSEUDONYM");
483 plen = apos[0] * 256 + apos[1];
484 if (plen > alen - 2) {
485 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
486 " AT_NEXT_PSEUDONYM (actual"
487 " len %lu, attr len %lu)",
488 (unsigned long) plen,
489 (unsigned long) alen);
490 return -1;
491 }
492 attr->next_pseudonym = pos + 4;
493 attr->next_pseudonym_len = plen;
494 break;
495 case EAP_SIM_AT_NEXT_REAUTH_ID:
496 if (!encr) {
497 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
498 "AT_NEXT_REAUTH_ID");
499 return -1;
500 }
501 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
502 "AT_NEXT_REAUTH_ID");
503 plen = apos[0] * 256 + apos[1];
504 if (plen > alen - 2) {
505 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
506 " AT_NEXT_REAUTH_ID (actual"
507 " len %lu, attr len %lu)",
508 (unsigned long) plen,
509 (unsigned long) alen);
510 return -1;
511 }
512 attr->next_reauth_id = pos + 4;
513 attr->next_reauth_id_len = plen;
514 break;
515 case EAP_SIM_AT_RES:
516 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
517 apos += 2;
518 alen -= 2;
519 if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
520 alen > EAP_AKA_MAX_RES_LEN) {
521 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES "
522 "(len %lu)",
523 (unsigned long) alen);
524 return -1;
525 }
526 attr->res = apos;
527 attr->res_len = alen;
528 break;
529 case EAP_SIM_AT_AUTS:
530 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS");
531 if (!aka) {
532 wpa_printf(MSG_DEBUG, "EAP-SIM: "
533 "Unexpected AT_AUTS");
534 return -1;
535 }
536 if (alen != EAP_AKA_AUTS_LEN) {
537 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS"
538 " (len %lu)",
539 (unsigned long) alen);
540 return -1;
541 }
542 attr->auts = apos;
543 break;
544 default:
545 if (pos[0] < 128) {
546 wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
547 "non-skippable attribute %d",
548 pos[0]);
549 return -1;
550 }
551
552 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable"
553 " attribute %d ignored", pos[0]);
554 break;
555 }
556
557 pos += pos[1] * 4;
558 }
559
560 wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully "
561 "(aka=%d encr=%d)", aka, encr);
562
563 return 0;
564 }
565
566
eap_sim_parse_encr(const u8 * k_encr,const u8 * encr_data,size_t encr_data_len,const u8 * iv,struct eap_sim_attrs * attr,int aka)567 u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
568 size_t encr_data_len, const u8 *iv,
569 struct eap_sim_attrs *attr, int aka)
570 {
571 u8 *decrypted;
572
573 if (!iv) {
574 wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV");
575 return NULL;
576 }
577
578 decrypted = os_malloc(encr_data_len);
579 if (decrypted == NULL)
580 return NULL;
581 os_memcpy(decrypted, encr_data, encr_data_len);
582
583 aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len);
584 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
585 decrypted, encr_data_len);
586
587 if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr,
588 aka, 1)) {
589 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
590 "decrypted AT_ENCR_DATA");
591 os_free(decrypted);
592 return NULL;
593 }
594
595 return decrypted;
596 }
597
598
599 #define EAP_SIM_INIT_LEN 128
600
601 struct eap_sim_msg {
602 u8 *buf;
603 size_t buf_len, used;
604 size_t mac, iv, encr; /* index from buf */
605 };
606
607
eap_sim_msg_init(int code,int id,int type,int subtype)608 struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype)
609 {
610 struct eap_sim_msg *msg;
611 struct eap_hdr *eap;
612 u8 *pos;
613
614 msg = os_zalloc(sizeof(*msg));
615 if (msg == NULL)
616 return NULL;
617
618 msg->buf = os_zalloc(EAP_SIM_INIT_LEN);
619 if (msg->buf == NULL) {
620 os_free(msg);
621 return NULL;
622 }
623 msg->buf_len = EAP_SIM_INIT_LEN;
624 eap = (struct eap_hdr *) msg->buf;
625 eap->code = code;
626 eap->identifier = id;
627 msg->used = sizeof(*eap);
628
629 pos = (u8 *) (eap + 1);
630 *pos++ = type;
631 *pos++ = subtype;
632 *pos++ = 0; /* Reserved */
633 *pos++ = 0; /* Reserved */
634 msg->used += 4;
635
636 return msg;
637 }
638
639
eap_sim_msg_finish(struct eap_sim_msg * msg,size_t * len,const u8 * k_aut,const u8 * extra,size_t extra_len)640 u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut,
641 const u8 *extra, size_t extra_len)
642 {
643 struct eap_hdr *eap;
644 u8 *buf;
645
646 if (msg == NULL)
647 return NULL;
648
649 eap = (struct eap_hdr *) msg->buf;
650 eap->length = host_to_be16(msg->used);
651
652 if (k_aut && msg->mac) {
653 eap_sim_add_mac(k_aut, msg->buf, msg->used,
654 msg->buf + msg->mac, extra, extra_len);
655 }
656
657 *len = msg->used;
658 buf = msg->buf;
659 os_free(msg);
660 return buf;
661 }
662
663
eap_sim_msg_free(struct eap_sim_msg * msg)664 void eap_sim_msg_free(struct eap_sim_msg *msg)
665 {
666 if (msg) {
667 os_free(msg->buf);
668 os_free(msg);
669 }
670 }
671
672
eap_sim_msg_resize(struct eap_sim_msg * msg,size_t add_len)673 static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len)
674 {
675 if (msg->used + add_len > msg->buf_len) {
676 u8 *nbuf = os_realloc(msg->buf, msg->used + add_len);
677 if (nbuf == NULL)
678 return -1;
679 msg->buf = nbuf;
680 msg->buf_len = msg->used + add_len;
681 }
682 return 0;
683 }
684
685
eap_sim_msg_add_full(struct eap_sim_msg * msg,u8 attr,const u8 * data,size_t len)686 u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr,
687 const u8 *data, size_t len)
688 {
689 int attr_len = 2 + len;
690 int pad_len;
691 u8 *start, *pos;
692
693 if (msg == NULL)
694 return NULL;
695
696 pad_len = (4 - attr_len % 4) % 4;
697 attr_len += pad_len;
698 if (eap_sim_msg_resize(msg, attr_len))
699 return NULL;
700 start = pos = msg->buf + msg->used;
701 *pos++ = attr;
702 *pos++ = attr_len / 4;
703 os_memcpy(pos, data, len);
704 if (pad_len) {
705 pos += len;
706 os_memset(pos, 0, pad_len);
707 }
708 msg->used += attr_len;
709 return start;
710 }
711
712
eap_sim_msg_add(struct eap_sim_msg * msg,u8 attr,u16 value,const u8 * data,size_t len)713 u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value,
714 const u8 *data, size_t len)
715 {
716 int attr_len = 4 + len;
717 int pad_len;
718 u8 *start, *pos;
719
720 if (msg == NULL)
721 return NULL;
722
723 pad_len = (4 - attr_len % 4) % 4;
724 attr_len += pad_len;
725 if (eap_sim_msg_resize(msg, attr_len))
726 return NULL;
727 start = pos = msg->buf + msg->used;
728 *pos++ = attr;
729 *pos++ = attr_len / 4;
730 WPA_PUT_BE16(pos, value);
731 pos += 2;
732 if (data)
733 os_memcpy(pos, data, len);
734 if (pad_len) {
735 pos += len;
736 os_memset(pos, 0, pad_len);
737 }
738 msg->used += attr_len;
739 return start;
740 }
741
742
eap_sim_msg_add_mac(struct eap_sim_msg * msg,u8 attr)743 u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr)
744 {
745 u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN);
746 if (pos)
747 msg->mac = (pos - msg->buf) + 4;
748 return pos;
749 }
750
751
eap_sim_msg_add_encr_start(struct eap_sim_msg * msg,u8 attr_iv,u8 attr_encr)752 int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv,
753 u8 attr_encr)
754 {
755 u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN);
756 if (pos == NULL)
757 return -1;
758 msg->iv = (pos - msg->buf) + 4;
759 if (hostapd_get_rand(msg->buf + msg->iv, EAP_SIM_IV_LEN)) {
760 msg->iv = 0;
761 return -1;
762 }
763
764 pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0);
765 if (pos == NULL) {
766 msg->iv = 0;
767 return -1;
768 }
769 msg->encr = pos - msg->buf;
770
771 return 0;
772 }
773
774
eap_sim_msg_add_encr_end(struct eap_sim_msg * msg,u8 * k_encr,int attr_pad)775 int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad)
776 {
777 size_t encr_len;
778
779 if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0)
780 return -1;
781
782 encr_len = msg->used - msg->encr - 4;
783 if (encr_len % 16) {
784 u8 *pos;
785 int pad_len = 16 - (encr_len % 16);
786 if (pad_len < 4) {
787 wpa_printf(MSG_WARNING, "EAP-SIM: "
788 "eap_sim_msg_add_encr_end - invalid pad_len"
789 " %d", pad_len);
790 return -1;
791 }
792 wpa_printf(MSG_DEBUG, " *AT_PADDING");
793 pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4);
794 if (pos == NULL)
795 return -1;
796 os_memset(pos + 4, 0, pad_len - 4);
797 encr_len += pad_len;
798 }
799 wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)",
800 (unsigned long) encr_len);
801 msg->buf[msg->encr + 1] = encr_len / 4 + 1;
802 aes_128_cbc_encrypt(k_encr, msg->buf + msg->iv,
803 msg->buf + msg->encr + 4, encr_len);
804
805 return 0;
806 }
807
808
eap_sim_report_notification(void * msg_ctx,int notification,int aka)809 void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
810 {
811 #ifndef CONFIG_NO_STDOUT_DEBUG
812 const char *type = aka ? "AKA" : "SIM";
813 #endif /* CONFIG_NO_STDOUT_DEBUG */
814
815 switch (notification) {
816 case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH:
817 wpa_printf(MSG_WARNING, "EAP-%s: General failure "
818 "notification (after authentication)", type);
819 break;
820 case EAP_SIM_TEMPORARILY_DENIED:
821 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
822 "User has been temporarily denied access to the "
823 "requested service", type);
824 break;
825 case EAP_SIM_NOT_SUBSCRIBED:
826 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
827 "User has not subscribed to the requested service",
828 type);
829 break;
830 case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH:
831 wpa_printf(MSG_WARNING, "EAP-%s: General failure "
832 "notification (before authentication)", type);
833 break;
834 case EAP_SIM_SUCCESS:
835 wpa_printf(MSG_INFO, "EAP-%s: Successful authentication "
836 "notification", type);
837 break;
838 default:
839 if (notification >= 32768) {
840 wpa_printf(MSG_INFO, "EAP-%s: Unrecognized "
841 "non-failure notification %d",
842 type, notification);
843 } else {
844 wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized "
845 "failure notification %d",
846 type, notification);
847 }
848 }
849 }
850