PHY ids for Broadcom 5755/5787
[dragonfly/vkernel-mp.git] / contrib / hostapd-0.4.9 / eap_sim_common.c
blob75947b7995a0d34fab219b4fc40aa47b5f2fe901
1 /*
2 * WPA Supplicant / EAP-SIM/AKA shared routines
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
19 #include "common.h"
20 #include "eap_i.h"
21 #include "sha1.h"
22 #include "crypto.h"
23 #include "aes_wrap.h"
24 #include "eap_sim_common.h"
27 static void eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
29 u8 xkey[64];
30 u32 t[5], _t[5];
31 int i, j, m, k;
32 u8 *xpos = x;
33 u32 carry;
35 /* FIPS 186-2 + change notice 1 */
37 memcpy(xkey, key, EAP_SIM_MK_LEN);
38 memset(xkey + EAP_SIM_MK_LEN, 0, 64 - EAP_SIM_MK_LEN);
39 t[0] = 0x67452301;
40 t[1] = 0xEFCDAB89;
41 t[2] = 0x98BADCFE;
42 t[3] = 0x10325476;
43 t[4] = 0xC3D2E1F0;
45 m = xlen / 40;
46 for (j = 0; j < m; j++) {
47 /* XSEED_j = 0 */
48 for (i = 0; i < 2; i++) {
49 /* XVAL = (XKEY + XSEED_j) mod 2^b */
51 /* w_i = G(t, XVAL) */
52 memcpy(_t, t, 20);
53 sha1_transform((u8 *) _t, xkey);
54 _t[0] = host_to_be32(_t[0]);
55 _t[1] = host_to_be32(_t[1]);
56 _t[2] = host_to_be32(_t[2]);
57 _t[3] = host_to_be32(_t[3]);
58 _t[4] = host_to_be32(_t[4]);
59 memcpy(xpos, _t, 20);
61 /* XKEY = (1 + XKEY + w_i) mod 2^b */
62 carry = 1;
63 for (k = 19; k >= 0; k--) {
64 carry += xkey[k] + xpos[k];
65 xkey[k] = carry & 0xff;
66 carry >>= 8;
69 xpos += SHA1_MAC_LEN;
71 /* x_j = w_0|w_1 */
76 void eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk)
78 u8 buf[120], *pos;
79 eap_sim_prf(mk, buf, 120);
80 pos = buf;
81 memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
82 pos += EAP_SIM_K_ENCR_LEN;
83 memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
84 pos += EAP_SIM_K_AUT_LEN;
85 memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
87 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
88 k_encr, EAP_SIM_K_ENCR_LEN);
89 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
90 k_aut, EAP_SIM_K_ENCR_LEN);
91 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material",
92 msk, EAP_SIM_KEYING_DATA_LEN);
96 void eap_sim_derive_keys_reauth(u16 _counter,
97 const u8 *identity, size_t identity_len,
98 const u8 *nonce_s, const u8 *mk, u8 *msk)
100 u8 xkey[SHA1_MAC_LEN];
101 u8 counter[2];
102 const u8 *addr[4];
103 size_t len[4];
105 addr[0] = identity;
106 len[0] = identity_len;
107 addr[1] = counter;
108 len[1] = 2;
109 addr[2] = nonce_s;
110 len[2] = EAP_SIM_NONCE_S_LEN;
111 addr[3] = mk;
112 len[3] = EAP_SIM_MK_LEN;
114 WPA_PUT_BE16(counter, _counter);
116 wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth");
117 wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
118 identity, identity_len);
119 wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2);
120 wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s,
121 EAP_SIM_NONCE_S_LEN);
122 wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
124 /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */
125 sha1_vector(4, addr, len, xkey);
126 wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
128 eap_sim_prf(xkey, msk, EAP_SIM_KEYING_DATA_LEN);
129 wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material",
130 msk, EAP_SIM_KEYING_DATA_LEN);
134 int eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len,
135 const u8 *mac, const u8 *extra, size_t extra_len)
137 unsigned char hmac[SHA1_MAC_LEN];
138 const u8 *addr[2];
139 size_t len[2];
140 u8 *tmp;
142 if (mac == NULL || req_len < EAP_SIM_MAC_LEN || mac < req ||
143 mac > req + req_len - EAP_SIM_MAC_LEN)
144 return -1;
146 tmp = malloc(req_len);
147 if (tmp == NULL)
148 return -1;
150 addr[0] = tmp;
151 len[0] = req_len;
152 addr[1] = extra;
153 len[1] = extra_len;
155 /* HMAC-SHA1-128 */
156 memcpy(tmp, req, req_len);
157 memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
158 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
159 free(tmp);
161 return (memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
165 void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac,
166 const u8 *extra, size_t extra_len)
168 unsigned char hmac[SHA1_MAC_LEN];
169 const u8 *addr[2];
170 size_t len[2];
172 addr[0] = msg;
173 len[0] = msg_len;
174 addr[1] = extra;
175 len[1] = extra_len;
177 /* HMAC-SHA1-128 */
178 memset(mac, 0, EAP_SIM_MAC_LEN);
179 hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
180 memcpy(mac, hmac, EAP_SIM_MAC_LEN);
184 int eap_sim_parse_attr(const u8 *start, const u8 *end,
185 struct eap_sim_attrs *attr, int aka, int encr)
187 const u8 *pos = start, *apos;
188 size_t alen, plen;
189 int list_len, i;
191 memset(attr, 0, sizeof(*attr));
192 attr->id_req = NO_ID_REQ;
193 attr->notification = -1;
194 attr->counter = -1;
195 attr->selected_version = -1;
196 attr->client_error_code = -1;
198 while (pos < end) {
199 if (pos + 2 > end) {
200 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)");
201 return -1;
203 wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d",
204 pos[0], pos[1] * 4);
205 if (pos + pos[1] * 4 > end) {
206 wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow "
207 "(pos=%p len=%d end=%p)",
208 pos, pos[1] * 4, end);
209 return -1;
211 apos = pos + 2;
212 alen = pos[1] * 4 - 2;
213 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data",
214 apos, alen);
216 switch (pos[0]) {
217 case EAP_SIM_AT_RAND:
218 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND");
219 apos += 2;
220 alen -= 2;
221 if ((!aka && (alen % GSM_RAND_LEN)) ||
222 (aka && alen != AKA_RAND_LEN)) {
223 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
224 " (len %lu)",
225 (unsigned long) alen);
226 return -1;
228 attr->rand = apos;
229 attr->num_chal = alen / GSM_RAND_LEN;
230 break;
231 case EAP_SIM_AT_AUTN:
232 wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN");
233 if (!aka) {
234 wpa_printf(MSG_DEBUG, "EAP-SIM: "
235 "Unexpected AT_AUTN");
236 return -1;
238 apos += 2;
239 alen -= 2;
240 if (alen != AKA_AUTN_LEN) {
241 wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
242 " (len %lu)",
243 (unsigned long) alen);
244 return -1;
246 attr->autn = apos;
247 break;
248 case EAP_SIM_AT_PADDING:
249 if (!encr) {
250 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
251 "AT_PADDING");
252 return -1;
254 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING");
255 for (i = 2; i < alen; i++) {
256 if (apos[i] != 0) {
257 wpa_printf(MSG_INFO, "EAP-SIM: (encr) "
258 "AT_PADDING used a non-zero"
259 " padding byte");
260 wpa_hexdump(MSG_DEBUG, "EAP-SIM: "
261 "(encr) padding bytes",
262 apos + 2, alen - 2);
263 return -1;
266 break;
267 case EAP_SIM_AT_NONCE_MT:
268 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT");
269 if (alen != 2 + EAP_SIM_NONCE_MT_LEN) {
270 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
271 "AT_NONCE_MT length");
272 return -1;
274 attr->nonce_mt = apos + 2;
275 break;
276 case EAP_SIM_AT_PERMANENT_ID_REQ:
277 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ");
278 attr->id_req = PERMANENT_ID;
279 break;
280 case EAP_SIM_AT_MAC:
281 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC");
282 if (alen != 2 + EAP_SIM_MAC_LEN) {
283 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC "
284 "length");
285 return -1;
287 attr->mac = apos + 2;
288 break;
289 case EAP_SIM_AT_NOTIFICATION:
290 if (alen != 2) {
291 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
292 "AT_NOTIFICATION length %lu",
293 (unsigned long) alen);
294 return -1;
296 attr->notification = apos[0] * 256 + apos[1];
297 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d",
298 attr->notification);
299 break;
300 case EAP_SIM_AT_ANY_ID_REQ:
301 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ");
302 attr->id_req = ANY_ID;
303 break;
304 case EAP_SIM_AT_IDENTITY:
305 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY");
306 attr->identity = apos + 2;
307 attr->identity_len = alen - 2;
308 break;
309 case EAP_SIM_AT_VERSION_LIST:
310 if (aka) {
311 wpa_printf(MSG_DEBUG, "EAP-AKA: "
312 "Unexpected AT_VERSION_LIST");
313 return -1;
315 list_len = apos[0] * 256 + apos[1];
316 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
317 if (list_len < 2 || list_len > alen - 2) {
318 wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
319 "AT_VERSION_LIST (list_len=%d "
320 "attr_len=%lu)", list_len,
321 (unsigned long) alen);
322 return -1;
324 attr->version_list = apos + 2;
325 attr->version_list_len = list_len;
326 break;
327 case EAP_SIM_AT_SELECTED_VERSION:
328 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION");
329 if (alen != 2) {
330 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
331 "AT_SELECTED_VERSION length %lu",
332 (unsigned long) alen);
333 return -1;
335 attr->selected_version = apos[0] * 256 + apos[1];
336 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION "
337 "%d", attr->selected_version);
338 break;
339 case EAP_SIM_AT_FULLAUTH_ID_REQ:
340 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ");
341 attr->id_req = FULLAUTH_ID;
342 break;
343 case EAP_SIM_AT_COUNTER:
344 if (!encr) {
345 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
346 "AT_COUNTER");
347 return -1;
349 if (alen != 2) {
350 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
351 "AT_COUNTER (alen=%lu)",
352 (unsigned long) alen);
353 return -1;
355 attr->counter = apos[0] * 256 + apos[1];
356 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d",
357 attr->counter);
358 break;
359 case EAP_SIM_AT_NONCE_S:
360 if (!encr) {
361 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
362 "AT_NONCE_S");
363 return -1;
365 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
366 "AT_NONCE_S");
367 if (alen != 2 + EAP_SIM_NONCE_S_LEN) {
368 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
369 "AT_NONCE_S (alen=%lu)",
370 (unsigned long) alen);
371 return -1;
373 attr->nonce_s = apos + 2;
374 break;
375 case EAP_SIM_AT_CLIENT_ERROR_CODE:
376 if (alen != 2) {
377 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
378 "AT_CLIENT_ERROR_CODE length %lu",
379 (unsigned long) alen);
380 return -1;
382 attr->client_error_code = apos[0] * 256 + apos[1];
383 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE "
384 "%d", attr->client_error_code);
385 break;
386 case EAP_SIM_AT_IV:
387 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV");
388 if (alen != 2 + EAP_SIM_MAC_LEN) {
389 wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV "
390 "length %lu", (unsigned long) alen);
391 return -1;
393 attr->iv = apos + 2;
394 break;
395 case EAP_SIM_AT_ENCR_DATA:
396 wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA");
397 attr->encr_data = apos + 2;
398 attr->encr_data_len = alen - 2;
399 if (attr->encr_data_len % 16) {
400 wpa_printf(MSG_INFO, "EAP-SIM: Invalid "
401 "AT_ENCR_DATA length %lu",
402 (unsigned long)
403 attr->encr_data_len);
404 return -1;
406 break;
407 case EAP_SIM_AT_NEXT_PSEUDONYM:
408 if (!encr) {
409 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
410 "AT_NEXT_PSEUDONYM");
411 return -1;
413 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
414 "AT_NEXT_PSEUDONYM");
415 plen = apos[0] * 256 + apos[1];
416 if (plen > alen - 2) {
417 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
418 " AT_NEXT_PSEUDONYM (actual"
419 " len %lu, attr len %lu)",
420 (unsigned long) plen,
421 (unsigned long) alen);
422 return -1;
424 attr->next_pseudonym = pos + 4;
425 attr->next_pseudonym_len = plen;
426 break;
427 case EAP_SIM_AT_NEXT_REAUTH_ID:
428 if (!encr) {
429 wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
430 "AT_NEXT_REAUTH_ID");
431 return -1;
433 wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
434 "AT_NEXT_REAUTH_ID");
435 plen = apos[0] * 256 + apos[1];
436 if (plen > alen - 2) {
437 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid"
438 " AT_NEXT_REAUTH_ID (actual"
439 " len %lu, attr len %lu)",
440 (unsigned long) plen,
441 (unsigned long) alen);
442 return -1;
444 attr->next_reauth_id = pos + 4;
445 attr->next_reauth_id_len = plen;
446 break;
447 default:
448 if (pos[0] < 128) {
449 wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
450 "non-skippable attribute %d",
451 pos[0]);
452 return -1;
455 wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable"
456 " attribute %d ignored", pos[0]);
457 break;
460 pos += pos[1] * 4;
463 wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully "
464 "(aka=%d encr=%d)", aka, encr);
466 return 0;
470 u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
471 size_t encr_data_len, const u8 *iv,
472 struct eap_sim_attrs *attr, int aka)
474 u8 *decrypted;
476 if (!iv) {
477 wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV");
478 return NULL;
481 decrypted = malloc(encr_data_len);
482 if (decrypted == NULL)
483 return NULL;
484 memcpy(decrypted, encr_data, encr_data_len);
486 aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len);
487 wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
488 decrypted, encr_data_len);
490 if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr,
491 aka, 1)) {
492 wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
493 "decrypted AT_ENCR_DATA");
494 free(decrypted);
495 return NULL;
498 return decrypted;
502 #define EAP_SIM_INIT_LEN 128
504 struct eap_sim_msg {
505 u8 *buf;
506 size_t buf_len, used;
507 size_t mac, iv, encr; /* index from buf */
511 struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype)
513 struct eap_sim_msg *msg;
514 struct eap_hdr *eap;
515 u8 *pos;
517 msg = malloc(sizeof(*msg));
518 if (msg == NULL)
519 return NULL;
520 memset(msg, 0, sizeof(*msg));
522 msg->buf = malloc(EAP_SIM_INIT_LEN);
523 if (msg->buf == NULL) {
524 free(msg);
525 return NULL;
527 memset(msg->buf, 0, EAP_SIM_INIT_LEN);
528 msg->buf_len = EAP_SIM_INIT_LEN;
529 eap = (struct eap_hdr *) msg->buf;
530 eap->code = code;
531 eap->identifier = id;
532 msg->used = sizeof(*eap);
534 pos = (u8 *) (eap + 1);
535 *pos++ = type;
536 *pos++ = subtype;
537 *pos++ = 0; /* Reserved */
538 *pos++ = 0; /* Reserved */
539 msg->used += 4;
541 return msg;
545 u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut,
546 const u8 *extra, size_t extra_len)
548 struct eap_hdr *eap;
549 u8 *buf;
551 if (msg == NULL)
552 return NULL;
554 eap = (struct eap_hdr *) msg->buf;
555 eap->length = host_to_be16(msg->used);
557 if (k_aut && msg->mac) {
558 eap_sim_add_mac(k_aut, msg->buf, msg->used,
559 msg->buf + msg->mac, extra, extra_len);
562 *len = msg->used;
563 buf = msg->buf;
564 free(msg);
565 return buf;
569 void eap_sim_msg_free(struct eap_sim_msg *msg)
571 if (msg) {
572 free(msg->buf);
573 free(msg);
578 static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len)
580 if (msg->used + add_len > msg->buf_len) {
581 u8 *nbuf = realloc(msg->buf, msg->used + add_len);
582 if (nbuf == NULL)
583 return -1;
584 msg->buf = nbuf;
585 msg->buf_len = msg->used + add_len;
587 return 0;
591 u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr,
592 const u8 *data, size_t len)
594 int attr_len = 2 + len;
595 int pad_len;
596 u8 *start, *pos;
598 if (msg == NULL)
599 return NULL;
601 pad_len = (4 - attr_len % 4) % 4;
602 attr_len += pad_len;
603 if (eap_sim_msg_resize(msg, attr_len))
604 return NULL;
605 start = pos = msg->buf + msg->used;
606 *pos++ = attr;
607 *pos++ = attr_len / 4;
608 memcpy(pos, data, len);
609 if (pad_len) {
610 pos += len;
611 memset(pos, 0, pad_len);
613 msg->used += attr_len;
614 return start;
618 u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value,
619 const u8 *data, size_t len)
621 int attr_len = 4 + len;
622 int pad_len;
623 u8 *start, *pos;
625 if (msg == NULL)
626 return NULL;
628 pad_len = (4 - attr_len % 4) % 4;
629 attr_len += pad_len;
630 if (eap_sim_msg_resize(msg, attr_len))
631 return NULL;
632 start = pos = msg->buf + msg->used;
633 *pos++ = attr;
634 *pos++ = attr_len / 4;
635 WPA_PUT_BE16(pos, value);
636 pos += 2;
637 if (data)
638 memcpy(pos, data, len);
639 if (pad_len) {
640 pos += len;
641 memset(pos, 0, pad_len);
643 msg->used += attr_len;
644 return start;
648 u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr)
650 u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN);
651 if (pos)
652 msg->mac = (pos - msg->buf) + 4;
653 return pos;
657 int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv,
658 u8 attr_encr)
660 u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN);
661 if (pos == NULL)
662 return -1;
663 msg->iv = (pos - msg->buf) + 4;
664 if (hostapd_get_rand(msg->buf + msg->iv, EAP_SIM_IV_LEN)) {
665 msg->iv = 0;
666 return -1;
669 pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0);
670 if (pos == NULL) {
671 msg->iv = 0;
672 return -1;
674 msg->encr = pos - msg->buf;
676 return 0;
680 int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad)
682 size_t encr_len;
684 if (k_encr == NULL || msg->iv == 0 || msg->encr == 0)
685 return -1;
687 encr_len = msg->used - msg->encr - 4;
688 if (encr_len % 16) {
689 u8 *pos;
690 int pad_len = 16 - (encr_len % 16);
691 if (pad_len < 4) {
692 wpa_printf(MSG_WARNING, "EAP-SIM: "
693 "eap_sim_msg_add_encr_end - invalid pad_len"
694 " %d", pad_len);
695 return -1;
697 wpa_printf(MSG_DEBUG, " *AT_PADDING");
698 pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4);
699 if (pos == NULL)
700 return -1;
701 memset(pos + 4, 0, pad_len - 4);
702 encr_len += pad_len;
704 wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)",
705 (unsigned long) encr_len);
706 msg->buf[msg->encr + 1] = encr_len / 4 + 1;
707 aes_128_cbc_encrypt(k_encr, msg->buf + msg->iv,
708 msg->buf + msg->encr + 4, encr_len);
710 return 0;
714 void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
716 #ifndef CONFIG_NO_STDOUT_DEBUG
717 const char *type = aka ? "AKA" : "SIM";
718 #endif /* CONFIG_NO_STDOUT_DEBUG */
720 switch (notification) {
721 case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH:
722 wpa_printf(MSG_WARNING, "EAP-%s: General failure "
723 "notification (after authentication)", type);
724 break;
725 case EAP_SIM_TEMPORARILY_DENIED:
726 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
727 "User has been temporarily denied access to the "
728 "requested service", type);
729 break;
730 case EAP_SIM_NOT_SUBSCRIBED:
731 wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: "
732 "User has not subscribed to the requested service",
733 type);
734 break;
735 case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH:
736 wpa_printf(MSG_WARNING, "EAP-%s: General failure "
737 "notification (before authentication)", type);
738 break;
739 case EAP_SIM_SUCCESS:
740 wpa_printf(MSG_INFO, "EAP-%s: Successful authentication "
741 "notification", type);
742 break;
743 default:
744 if (notification >= 32768) {
745 wpa_printf(MSG_INFO, "EAP-%s: Unrecognized "
746 "non-failure notification %d",
747 type, notification);
748 } else {
749 wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized "
750 "failure notification %d",
751 type, notification);
757 #ifdef TEST_MAIN_EAP_SIM_COMMON
758 static int test_eap_sim_prf(void)
760 /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */
761 u8 xkey[] = {
762 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
763 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
764 0xeb, 0x5a, 0x38, 0xb6
766 u8 w[] = {
767 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
768 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
769 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
770 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
771 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
773 u8 buf[40];
775 printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n");
776 eap_sim_prf(xkey, buf, sizeof(buf));
777 if (memcmp(w, buf, sizeof(w) != 0)) {
778 printf("eap_sim_prf failed\n");
779 return 1;
782 return 0;
786 int main(int argc, char *argv[])
788 int errors = 0;
790 errors += test_eap_sim_prf();
792 return errors;
794 #endif /* TEST_MAIN_EAP_SIM_COMMON */