summaryrefslogtreecommitdiffstats
path: root/contrib/wpa_supplicant/eap_sim_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa_supplicant/eap_sim_common.c')
-rw-r--r--contrib/wpa_supplicant/eap_sim_common.c316
1 files changed, 181 insertions, 135 deletions
diff --git a/contrib/wpa_supplicant/eap_sim_common.c b/contrib/wpa_supplicant/eap_sim_common.c
index 75947b7..dc8b2f6 100644
--- a/contrib/wpa_supplicant/eap_sim_common.c
+++ b/contrib/wpa_supplicant/eap_sim_common.c
@@ -1,6 +1,6 @@
/*
- * WPA Supplicant / EAP-SIM/AKA shared routines
- * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ * EAP peer: EAP-SIM/AKA shared routines
+ * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -12,9 +12,7 @@
* See README and COPYING for more details.
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "includes.h"
#include "common.h"
#include "eap_i.h"
@@ -24,80 +22,98 @@
#include "eap_sim_common.h"
-static void eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
+static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
{
- u8 xkey[64];
- u32 t[5], _t[5];
- int i, j, m, k;
- u8 *xpos = x;
- u32 carry;
-
- /* FIPS 186-2 + change notice 1 */
-
- memcpy(xkey, key, EAP_SIM_MK_LEN);
- memset(xkey + EAP_SIM_MK_LEN, 0, 64 - EAP_SIM_MK_LEN);
- t[0] = 0x67452301;
- t[1] = 0xEFCDAB89;
- t[2] = 0x98BADCFE;
- t[3] = 0x10325476;
- t[4] = 0xC3D2E1F0;
-
- m = xlen / 40;
- for (j = 0; j < m; j++) {
- /* XSEED_j = 0 */
- for (i = 0; i < 2; i++) {
- /* XVAL = (XKEY + XSEED_j) mod 2^b */
-
- /* w_i = G(t, XVAL) */
- memcpy(_t, t, 20);
- sha1_transform((u8 *) _t, xkey);
- _t[0] = host_to_be32(_t[0]);
- _t[1] = host_to_be32(_t[1]);
- _t[2] = host_to_be32(_t[2]);
- _t[3] = host_to_be32(_t[3]);
- _t[4] = host_to_be32(_t[4]);
- memcpy(xpos, _t, 20);
-
- /* XKEY = (1 + XKEY + w_i) mod 2^b */
- carry = 1;
- for (k = 19; k >= 0; k--) {
- carry += xkey[k] + xpos[k];
- xkey[k] = carry & 0xff;
- carry >>= 8;
- }
+ return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen);
+}
- xpos += SHA1_MAC_LEN;
- }
- /* x_j = w_0|w_1 */
- }
+
+void 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)
+{
+ u8 sel_ver[2];
+ const unsigned char *addr[5];
+ size_t len[5];
+
+ addr[0] = identity;
+ len[0] = identity_len;
+ addr[1] = kc;
+ len[1] = num_chal * EAP_SIM_KC_LEN;
+ addr[2] = nonce_mt;
+ len[2] = EAP_SIM_NONCE_MT_LEN;
+ addr[3] = ver_list;
+ len[3] = ver_list_len;
+ addr[4] = sel_ver;
+ len[4] = 2;
+
+ WPA_PUT_BE16(sel_ver, selected_version);
+
+ /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
+ sha1_vector(5, addr, len, mk);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
+}
+
+
+void eap_aka_derive_mk(const u8 *identity, size_t identity_len,
+ const u8 *ik, const u8 *ck, u8 *mk)
+{
+ const u8 *addr[3];
+ size_t len[3];
+
+ addr[0] = identity;
+ len[0] = identity_len;
+ addr[1] = ik;
+ len[1] = EAP_AKA_IK_LEN;
+ addr[2] = ck;
+ len[2] = EAP_AKA_CK_LEN;
+
+ /* MK = SHA1(Identity|IK|CK) */
+ sha1_vector(3, addr, len, mk);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN);
}
-void eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk)
+int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk, u8 *emsk)
{
- u8 buf[120], *pos;
- eap_sim_prf(mk, buf, 120);
+ u8 buf[EAP_SIM_K_ENCR_LEN + EAP_SIM_K_AUT_LEN +
+ EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN], *pos;
+ if (eap_sim_prf(mk, buf, sizeof(buf)) < 0) {
+ wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
+ return -1;
+ }
pos = buf;
- memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
+ os_memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
pos += EAP_SIM_K_ENCR_LEN;
- memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
+ os_memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
pos += EAP_SIM_K_AUT_LEN;
- memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
+ os_memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
+ pos += EAP_SIM_KEYING_DATA_LEN;
+ os_memcpy(emsk, pos, EAP_EMSK_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
k_encr, EAP_SIM_K_ENCR_LEN);
wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
- k_aut, EAP_SIM_K_ENCR_LEN);
- wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material",
+ k_aut, EAP_SIM_K_AUT_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
msk, EAP_SIM_KEYING_DATA_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
+ os_memset(buf, 0, sizeof(buf));
+
+ return 0;
}
-void eap_sim_derive_keys_reauth(u16 _counter,
- const u8 *identity, size_t identity_len,
- const u8 *nonce_s, const u8 *mk, u8 *msk)
+int 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)
{
u8 xkey[SHA1_MAC_LEN];
+ u8 buf[EAP_SIM_KEYING_DATA_LEN + EAP_EMSK_LEN + 32];
u8 counter[2];
const u8 *addr[4];
size_t len[4];
@@ -125,9 +141,22 @@ void eap_sim_derive_keys_reauth(u16 _counter,
sha1_vector(4, addr, len, xkey);
wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
- eap_sim_prf(xkey, msk, EAP_SIM_KEYING_DATA_LEN);
- wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material",
- msk, EAP_SIM_KEYING_DATA_LEN);
+ if (eap_sim_prf(xkey, buf, sizeof(buf)) < 0) {
+ wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
+ return -1;
+ }
+ if (msk) {
+ os_memcpy(msk, buf, EAP_SIM_KEYING_DATA_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material (MSK)",
+ msk, EAP_SIM_KEYING_DATA_LEN);
+ }
+ if (emsk) {
+ os_memcpy(emsk, buf + EAP_SIM_KEYING_DATA_LEN, EAP_EMSK_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-SIM: EMSK", emsk, EAP_EMSK_LEN);
+ }
+ os_memset(buf, 0, sizeof(buf));
+
+ return 0;
}
@@ -143,7 +172,7 @@ int eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len,
mac > req + req_len - EAP_SIM_MAC_LEN)
return -1;
- tmp = malloc(req_len);
+ tmp = os_malloc(req_len);
if (tmp == NULL)
return -1;
@@ -153,12 +182,19 @@ int eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len,
len[1] = extra_len;
/* HMAC-SHA1-128 */
- memcpy(tmp, req, req_len);
- memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
+ os_memcpy(tmp, req, req_len);
+ os_memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
+ wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", tmp, req_len);
+ wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - extra data",
+ extra, extra_len);
+ wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Verify MAC - K_aut",
+ k_aut, EAP_SIM_K_AUT_LEN);
hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
- free(tmp);
+ wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC: MAC",
+ hmac, EAP_SIM_MAC_LEN);
+ os_free(tmp);
- return (memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
+ return (os_memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
}
@@ -175,9 +211,16 @@ void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac,
len[1] = extra_len;
/* HMAC-SHA1-128 */
- memset(mac, 0, EAP_SIM_MAC_LEN);
+ os_memset(mac, 0, EAP_SIM_MAC_LEN);
+ wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - msg", msg, msg_len);
+ wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC - extra data",
+ extra, extra_len);
+ wpa_hexdump_key(MSG_MSGDUMP, "EAP-SIM: Add MAC - K_aut",
+ k_aut, EAP_SIM_K_AUT_LEN);
hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
- memcpy(mac, hmac, EAP_SIM_MAC_LEN);
+ os_memcpy(mac, hmac, EAP_SIM_MAC_LEN);
+ wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Add MAC: MAC",
+ mac, EAP_SIM_MAC_LEN);
}
@@ -185,10 +228,9 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
struct eap_sim_attrs *attr, int aka, int encr)
{
const u8 *pos = start, *apos;
- size_t alen, plen;
- int list_len, i;
+ size_t alen, plen, i, list_len;
- memset(attr, 0, sizeof(*attr));
+ os_memset(attr, 0, sizeof(*attr));
attr->id_req = NO_ID_REQ;
attr->notification = -1;
attr->counter = -1;
@@ -219,7 +261,7 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
apos += 2;
alen -= 2;
if ((!aka && (alen % GSM_RAND_LEN)) ||
- (aka && alen != AKA_RAND_LEN)) {
+ (aka && alen != EAP_AKA_RAND_LEN)) {
wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
" (len %lu)",
(unsigned long) alen);
@@ -237,7 +279,7 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
}
apos += 2;
alen -= 2;
- if (alen != AKA_AUTN_LEN) {
+ if (alen != EAP_AKA_AUTN_LEN) {
wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
" (len %lu)",
(unsigned long) alen);
@@ -316,8 +358,9 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
if (list_len < 2 || list_len > alen - 2) {
wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
- "AT_VERSION_LIST (list_len=%d "
- "attr_len=%lu)", list_len,
+ "AT_VERSION_LIST (list_len=%lu "
+ "attr_len=%lu)",
+ (unsigned long) list_len,
(unsigned long) alen);
return -1;
}
@@ -356,6 +399,22 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d",
attr->counter);
break;
+ case EAP_SIM_AT_COUNTER_TOO_SMALL:
+ if (!encr) {
+ wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
+ "AT_COUNTER_TOO_SMALL");
+ return -1;
+ }
+ if (alen != 2) {
+ wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid "
+ "AT_COUNTER_TOO_SMALL (alen=%lu)",
+ (unsigned long) alen);
+ return -1;
+ }
+ wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) "
+ "AT_COUNTER_TOO_SMALL");
+ attr->counter_too_small = 1;
+ break;
case EAP_SIM_AT_NONCE_S:
if (!encr) {
wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted "
@@ -444,6 +503,35 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
attr->next_reauth_id = pos + 4;
attr->next_reauth_id_len = plen;
break;
+ case EAP_SIM_AT_RES:
+ wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
+ apos += 2;
+ alen -= 2;
+ if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
+ alen > EAP_AKA_MAX_RES_LEN) {
+ wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES "
+ "(len %lu)",
+ (unsigned long) alen);
+ return -1;
+ }
+ attr->res = apos;
+ attr->res_len = alen;
+ break;
+ case EAP_SIM_AT_AUTS:
+ wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS");
+ if (!aka) {
+ wpa_printf(MSG_DEBUG, "EAP-SIM: "
+ "Unexpected AT_AUTS");
+ return -1;
+ }
+ if (alen != EAP_AKA_AUTS_LEN) {
+ wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS"
+ " (len %lu)",
+ (unsigned long) alen);
+ return -1;
+ }
+ attr->auts = apos;
+ break;
default:
if (pos[0] < 128) {
wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
@@ -478,10 +566,10 @@ u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
return NULL;
}
- decrypted = malloc(encr_data_len);
+ decrypted = os_malloc(encr_data_len);
if (decrypted == NULL)
return NULL;
- memcpy(decrypted, encr_data, encr_data_len);
+ os_memcpy(decrypted, encr_data, encr_data_len);
aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len);
wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
@@ -491,7 +579,7 @@ u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
aka, 1)) {
wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
"decrypted AT_ENCR_DATA");
- free(decrypted);
+ os_free(decrypted);
return NULL;
}
@@ -514,17 +602,15 @@ struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype)
struct eap_hdr *eap;
u8 *pos;
- msg = malloc(sizeof(*msg));
+ msg = os_zalloc(sizeof(*msg));
if (msg == NULL)
return NULL;
- memset(msg, 0, sizeof(*msg));
- msg->buf = malloc(EAP_SIM_INIT_LEN);
+ msg->buf = os_zalloc(EAP_SIM_INIT_LEN);
if (msg->buf == NULL) {
- free(msg);
+ os_free(msg);
return NULL;
}
- memset(msg->buf, 0, EAP_SIM_INIT_LEN);
msg->buf_len = EAP_SIM_INIT_LEN;
eap = (struct eap_hdr *) msg->buf;
eap->code = code;
@@ -561,7 +647,7 @@ u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut,
*len = msg->used;
buf = msg->buf;
- free(msg);
+ os_free(msg);
return buf;
}
@@ -569,8 +655,8 @@ u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut,
void eap_sim_msg_free(struct eap_sim_msg *msg)
{
if (msg) {
- free(msg->buf);
- free(msg);
+ os_free(msg->buf);
+ os_free(msg);
}
}
@@ -578,7 +664,7 @@ void eap_sim_msg_free(struct eap_sim_msg *msg)
static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len)
{
if (msg->used + add_len > msg->buf_len) {
- u8 *nbuf = realloc(msg->buf, msg->used + add_len);
+ u8 *nbuf = os_realloc(msg->buf, msg->used + add_len);
if (nbuf == NULL)
return -1;
msg->buf = nbuf;
@@ -605,10 +691,10 @@ u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr,
start = pos = msg->buf + msg->used;
*pos++ = attr;
*pos++ = attr_len / 4;
- memcpy(pos, data, len);
+ os_memcpy(pos, data, len);
if (pad_len) {
pos += len;
- memset(pos, 0, pad_len);
+ os_memset(pos, 0, pad_len);
}
msg->used += attr_len;
return start;
@@ -635,10 +721,10 @@ u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value,
WPA_PUT_BE16(pos, value);
pos += 2;
if (data)
- memcpy(pos, data, len);
+ os_memcpy(pos, data, len);
if (pad_len) {
pos += len;
- memset(pos, 0, pad_len);
+ os_memset(pos, 0, pad_len);
}
msg->used += attr_len;
return start;
@@ -681,7 +767,7 @@ int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad)
{
size_t encr_len;
- if (k_encr == NULL || msg->iv == 0 || msg->encr == 0)
+ if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0)
return -1;
encr_len = msg->used - msg->encr - 4;
@@ -698,7 +784,7 @@ int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad)
pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4);
if (pos == NULL)
return -1;
- memset(pos + 4, 0, pad_len - 4);
+ os_memset(pos + 4, 0, pad_len - 4);
encr_len += pad_len;
}
wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)",
@@ -752,43 +838,3 @@ void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
}
}
}
-
-
-#ifdef TEST_MAIN_EAP_SIM_COMMON
-static int test_eap_sim_prf(void)
-{
- /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */
- u8 xkey[] = {
- 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
- 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
- 0xeb, 0x5a, 0x38, 0xb6
- };
- u8 w[] = {
- 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
- 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
- 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
- 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
- 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
- };
- u8 buf[40];
-
- printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n");
- eap_sim_prf(xkey, buf, sizeof(buf));
- if (memcmp(w, buf, sizeof(w) != 0)) {
- printf("eap_sim_prf failed\n");
- return 1;
- }
-
- return 0;
-}
-
-
-int main(int argc, char *argv[])
-{
- int errors = 0;
-
- errors += test_eap_sim_prf();
-
- return errors;
-}
-#endif /* TEST_MAIN_EAP_SIM_COMMON */
OpenPOWER on IntegriCloud