Accumulative patch from commit b618a469c42120e984ab1c85ed6058504d1fca78
Author: Jouni Malinen <jouni@qca.qualcomm.com>
Date: Sat Feb 16 19:54:09 2013 +0200
Interworking: Select highest priority cred if multiple matches
Interworking: Select highest priority cred if multiple matches
GAS server: Fix a regression in GAS server callback
hostapd: Fix Max SP Length derivation from QoS Info
nl80211: Configure STA Capabilities and Extended Capabilities
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Fix build without CONFIG_WPS_NFC
WPS: Add support for NFC handover select generation with wpa_supplicant
WPS: Update NFC connection handover documentation
WPS: Add support for config token generation with wpa_supplicant
WPS: Allow password token to be written with nfcpy
WPS: Use pre-configured NFC password token instead of overriding it
TDLS: Pass peer's Capability and Ext Capability info during sta_add
TDLS: Pass peer's HT Capability and QOS information during sta_add
nl80211: Add debug prints for STA add/set operations
TDLS: Fix add/set STA operation
Synchronize with wireless-testing.git include/uapi/linux/nl80211.h
WPS: Allow Device Password to be changed from M1 to M2
WPS: Fix wps_reg nfc-pw option
TDLS: Tear down peers when disconnecting from the AP
P2P: Do not use old scan result data for peer discovery
Use more accurate timestamps for scan results
P2P: Postpone P2P-DEVICE-FOUND if config_methods not known
P2P: Do not allow peer update to clear config_methods
WPS: Report NFC connection handover completion differently
P2P: Avoid concurrent scans during all steps of group formation
P2P: Cancel group formation timeout on group removal (on client)
WPS: Change listen time to match nfcpy default (250 ms)
WPS: Report only the carrier record from NFC to wpa_supplicant
WPS: Fetch only the carrier record from wpa_supplicant for NFC
WPS: Update nfcpy script to support AP mode NFC connection handover
WPS: Add command for fetching carrier record for NFC handover
WPS: Clean up debug prints with nfcpy
WPS: Remove 0.5 sec extra wait from NFC handover with nfcpy
WPS: Use alternating poll/listen for NFC peer discovery with nfcpy
WPS: Configure logging to show nfcpy log message
WPS: Add an example python script for NFC operations with hostapd
hostapd: Do not change HT40 capability due to OBSS scan
dbus: Add missing signal description for WPS (7)
EAP peer: Add Session-Id derivation to more EAP methods
EAP peer: Add Session-Id derivation
EAP-IKEV2 server: Fix invalid memory freeing operation
eap_proxy: Add a dummy implementation for compilation testing
eap_proxy: Add mechanism for allowing EAP methods to be offloaded
Android: Allow setgroups to be overridden from build configuration
P2P: Send p2p_stop_find event on failure to start pending p2p_find
P2P: Fix GO Probe Response IEs when Wi-Fi Display is enabled
Capability matching for 60 GHz band
nl80211: Add ctrl_iface message for AP mode connection rejection
P2P: Allow local configuration to use 5 GHz band 40 MHz channels
Fix BSS RANGE command for no exact id match cases
Change-Id: Iac9284bba31db40911aecc3adf2843c9b1576db1
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c
index 85c242a..4df8853 100644
--- a/src/eap_peer/eap.c
+++ b/src/eap_peer/eap.c
@@ -161,6 +161,8 @@
eapol_set_bool(sm, EAPOL_eapFail, FALSE);
os_free(sm->eapKeyData);
sm->eapKeyData = NULL;
+ os_free(sm->eapSessionId);
+ sm->eapSessionId = NULL;
sm->eapKeyAvailable = FALSE;
eapol_set_bool(sm, EAPOL_eapRestart, FALSE);
sm->lastId = -1; /* new session - make sure this does not match with
@@ -403,6 +405,13 @@
os_free(sm->eapKeyData);
sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv,
&sm->eapKeyDataLen);
+ os_free(sm->eapSessionId);
+ sm->eapSessionId = sm->m->getSessionId(sm, sm->eap_method_priv,
+ &sm->eapSessionIdLen);
+ if (sm->eapSessionId) {
+ wpa_hexdump(MSG_DEBUG, "EAP: Session-Id",
+ sm->eapSessionId, sm->eapSessionIdLen);
+ }
}
}
@@ -1462,6 +1471,8 @@
sm->eapRespData = NULL;
os_free(sm->eapKeyData);
sm->eapKeyData = NULL;
+ os_free(sm->eapSessionId);
+ sm->eapSessionId = NULL;
/* This is not clearly specified in the EAP statemachines draft, but
* it seems necessary to make sure that some of the EAPOL variables get
@@ -2159,6 +2170,28 @@
/**
+ * eap_get_eapSessionId - Get Session-Id from EAP state machine
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @len: Pointer to variable that will be set to number of bytes in the session
+ * Returns: Pointer to the EAP Session-Id or %NULL on failure
+ *
+ * Fetch EAP Session-Id from the EAP state machine. The Session-Id is available
+ * only after a successful authentication. EAP state machine continues to manage
+ * the Session-Id and the caller must not change or free the returned data.
+ */
+const u8 * eap_get_eapSessionId(struct eap_sm *sm, size_t *len)
+{
+ if (sm == NULL || sm->eapSessionId == NULL) {
+ *len = 0;
+ return NULL;
+ }
+
+ *len = sm->eapSessionIdLen;
+ return sm->eapSessionId;
+}
+
+
+/**
* eap_get_eapKeyData - Get master session key (MSK) from EAP state machine
* @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
* @len: Pointer to variable that will be set to number of bytes in the key
diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h
index 8bccef1..f87f9b3 100644
--- a/src/eap_peer/eap.h
+++ b/src/eap_peer/eap.h
@@ -306,6 +306,7 @@
int eap_key_available(struct eap_sm *sm);
void eap_notify_success(struct eap_sm *sm);
void eap_notify_lower_layer_success(struct eap_sm *sm);
+const u8 * eap_get_eapSessionId(struct eap_sm *sm, size_t *len);
const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len);
struct wpabuf * eap_get_eapRespData(struct eap_sm *sm);
void eap_register_scard_ctx(struct eap_sm *sm, void *ctx);
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index 59861cb..dc424d7 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -1340,6 +1340,28 @@
}
+static u8 * eap_aka_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_aka_data *data = priv;
+ u8 *id;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ *len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
+ id = os_malloc(*len);
+ if (id == NULL)
+ return NULL;
+
+ id[0] = data->eap_method;
+ os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
+ os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn, EAP_AKA_AUTN_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len);
+
+ return id;
+}
+
+
static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_aka_data *data = priv;
@@ -1374,6 +1396,7 @@
eap->process = eap_aka_process;
eap->isKeyAvailable = eap_aka_isKeyAvailable;
eap->getKey = eap_aka_getKey;
+ eap->getSessionId = eap_aka_get_session_id;
eap->has_reauth_data = eap_aka_has_reauth_data;
eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
eap->init_for_reauth = eap_aka_init_for_reauth;
@@ -1404,6 +1427,7 @@
eap->process = eap_aka_process;
eap->isKeyAvailable = eap_aka_isKeyAvailable;
eap->getKey = eap_aka_getKey;
+ eap->getSessionId = eap_aka_get_session_id;
eap->has_reauth_data = eap_aka_has_reauth_data;
eap->deinit_for_reauth = eap_aka_deinit_for_reauth;
eap->init_for_reauth = eap_aka_init_for_reauth;
diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c
index 7ca5288..3b8d803 100644
--- a/src/eap_peer/eap_fast.c
+++ b/src/eap_peer/eap_fast.c
@@ -53,6 +53,8 @@
int session_ticket_used;
u8 key_data[EAP_FAST_KEY_LEN];
+ u8 *session_id;
+ size_t id_len;
u8 emsk[EAP_EMSK_LEN];
int success;
@@ -238,6 +240,7 @@
pac = pac->next;
eap_fast_free_pac(prev);
}
+ os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
os_free(data);
}
@@ -785,6 +788,21 @@
return NULL;
}
+ if (!data->anon_provisioning && data->phase2_success) {
+ os_free(data->session_id);
+ data->session_id = eap_peer_tls_derive_session_id(
+ sm, &data->ssl, EAP_TYPE_FAST, &data->id_len);
+ if (data->session_id) {
+ wpa_hexdump(MSG_DEBUG, "EAP-FAST: Derived Session-Id",
+ data->session_id, data->id_len);
+ } else {
+ wpa_printf(MSG_ERROR, "EAP-FAST: Failed to derive "
+ "Session-Id");
+ wpabuf_free(resp);
+ return NULL;
+ }
+ }
+
pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv));
eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *)
pos, _bind, cmk);
@@ -1604,6 +1622,8 @@
os_free(data);
return NULL;
}
+ os_free(data->session_id);
+ data->session_id = NULL;
if (data->phase2_priv && data->phase2_method &&
data->phase2_method->init_for_reauth)
data->phase2_method->init_for_reauth(sm, data->phase2_priv);
@@ -1662,6 +1682,25 @@
}
+static u8 * eap_fast_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_fast_data *data = priv;
+ u8 *id;
+
+ if (!data->success)
+ return NULL;
+
+ id = os_malloc(data->id_len);
+ if (id == NULL)
+ return NULL;
+
+ *len = data->id_len;
+ os_memcpy(id, data->session_id, data->id_len);
+
+ return id;
+}
+
+
static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_fast_data *data = priv;
@@ -1696,6 +1735,7 @@
eap->process = eap_fast_process;
eap->isKeyAvailable = eap_fast_isKeyAvailable;
eap->getKey = eap_fast_getKey;
+ eap->getSessionId = eap_fast_get_session_id;
eap->get_status = eap_fast_get_status;
#if 0
eap->has_reauth_data = eap_fast_has_reauth_data;
diff --git a/src/eap_peer/eap_gpsk.c b/src/eap_peer/eap_gpsk.c
index 2bd0d48..8a0644d 100644
--- a/src/eap_peer/eap_gpsk.c
+++ b/src/eap_peer/eap_gpsk.c
@@ -23,8 +23,8 @@
size_t sk_len;
u8 pk[EAP_GPSK_MAX_PK_LEN];
size_t pk_len;
- u8 session_id;
- int session_id_set;
+ u8 session_id[128];
+ size_t id_len;
u8 *id_peer;
size_t id_peer_len;
u8 *id_server;
@@ -354,6 +354,21 @@
return NULL;
}
+ if (eap_gpsk_derive_session_id(data->psk, data->psk_len,
+ data->vendor, data->specifier,
+ data->rand_peer, data->rand_server,
+ data->id_peer, data->id_peer_len,
+ data->id_server, data->id_server_len,
+ EAP_TYPE_GPSK,
+ data->session_id, &data->id_len) < 0) {
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id");
+ eap_gpsk_state(data, FAILURE);
+ wpabuf_free(resp);
+ return NULL;
+ }
+ wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id",
+ data->session_id, data->id_len);
+
/* No PD_Payload_1 */
wpabuf_put_be16(resp, 0);
@@ -708,6 +723,24 @@
}
+static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_gpsk_data *data = priv;
+ u8 *sid;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ sid = os_malloc(data->id_len);
+ if (sid == NULL)
+ return NULL;
+ os_memcpy(sid, data->session_id, data->id_len);
+ *len = data->id_len;
+
+ return sid;
+}
+
+
int eap_peer_gpsk_register(void)
{
struct eap_method *eap;
@@ -724,6 +757,7 @@
eap->isKeyAvailable = eap_gpsk_isKeyAvailable;
eap->getKey = eap_gpsk_getKey;
eap->get_emsk = eap_gpsk_get_emsk;
+ eap->getSessionId = eap_gpsk_get_session_id;
ret = eap_peer_method_register(eap);
if (ret)
diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h
index dd94317..62c867c 100644
--- a/src/eap_peer/eap_i.h
+++ b/src/eap_peer/eap_i.h
@@ -261,6 +261,19 @@
* private data or this function may derive the key.
*/
u8 * (*get_emsk)(struct eap_sm *sm, void *priv, size_t *len);
+
+ /**
+ * getSessionId - Get EAP method specific Session-Id
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @priv: Pointer to private EAP method data from eap_method::init()
+ * @len: Pointer to a variable to store Session-Id length
+ * Returns: Session-Id or %NULL if not available
+ *
+ * This function can be used to get the Session-Id from the EAP method.
+ * The Session-Id may already be stored in the method-specific private
+ * data or this function may derive the Session-Id.
+ */
+ u8 * (*getSessionId)(struct eap_sm *sm, void *priv, size_t *len);
};
@@ -298,6 +311,8 @@
Boolean eapKeyAvailable; /* peer to lower layer */
u8 *eapKeyData; /* peer to lower layer */
size_t eapKeyDataLen; /* peer to lower layer */
+ u8 *eapSessionId; /* peer to lower layer */
+ size_t eapSessionIdLen; /* peer to lower layer */
const struct eap_method *m; /* selected EAP method */
/* not defined in RFC 4137 */
Boolean changed;
diff --git a/src/eap_peer/eap_ikev2.c b/src/eap_peer/eap_ikev2.c
index a227f8b..09a655e 100644
--- a/src/eap_peer/eap_ikev2.c
+++ b/src/eap_peer/eap_ikev2.c
@@ -475,6 +475,36 @@
}
+static u8 * eap_ikev2_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_ikev2_data *data = priv;
+ u8 *sid;
+ size_t sid_len;
+ size_t offset;
+
+ if (data->state != DONE || !data->keymat_ok)
+ return NULL;
+
+ sid_len = 1 + data->ikev2.i_nonce_len + data->ikev2.r_nonce_len;
+ sid = os_malloc(sid_len);
+ if (sid) {
+ offset = 0;
+ sid[offset] = EAP_TYPE_IKEV2;
+ offset++;
+ os_memcpy(sid + offset, data->ikev2.i_nonce,
+ data->ikev2.i_nonce_len);
+ offset += data->ikev2.i_nonce_len;
+ os_memcpy(sid + offset, data->ikev2.r_nonce,
+ data->ikev2.r_nonce_len);
+ *len = sid_len;
+ wpa_hexdump(MSG_DEBUG, "EAP-IKEV2: Derived Session-Id",
+ sid, sid_len);
+ }
+
+ return sid;
+}
+
+
int eap_peer_ikev2_register(void)
{
struct eap_method *eap;
@@ -492,6 +522,7 @@
eap->isKeyAvailable = eap_ikev2_isKeyAvailable;
eap->getKey = eap_ikev2_getKey;
eap->get_emsk = eap_ikev2_get_emsk;
+ eap->getSessionId = eap_ikev2_get_session_id;
ret = eap_peer_method_register(eap);
if (ret)
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 7fff145..3b93209 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -56,6 +56,8 @@
int resuming; /* starting a resumed session */
int reauth; /* reauthentication */
u8 *key_data;
+ u8 *session_id;
+ size_t id_len;
struct wpabuf *pending_phase2_req;
enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
@@ -179,6 +181,7 @@
os_free(data->phase2_types);
eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
+ os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
os_free(data);
}
@@ -1107,6 +1110,20 @@
"derive key");
}
+ os_free(data->session_id);
+ data->session_id =
+ eap_peer_tls_derive_session_id(sm, &data->ssl,
+ EAP_TYPE_PEAP,
+ &data->id_len);
+ if (data->session_id) {
+ wpa_hexdump(MSG_DEBUG,
+ "EAP-PEAP: Derived Session-Id",
+ data->session_id, data->id_len);
+ } else {
+ wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to "
+ "derive Session-Id");
+ }
+
if (sm->workaround && data->resuming) {
/*
* At least few RADIUS servers (Aegis v1.1.6;
@@ -1178,6 +1195,8 @@
struct eap_peap_data *data = priv;
os_free(data->key_data);
data->key_data = NULL;
+ os_free(data->session_id);
+ data->session_id = NULL;
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
os_free(data);
return NULL;
@@ -1260,6 +1279,25 @@
}
+static u8 * eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_peap_data *data = priv;
+ u8 *id;
+
+ if (data->session_id == NULL || !data->phase2_success)
+ return NULL;
+
+ id = os_malloc(data->id_len);
+ if (id == NULL)
+ return NULL;
+
+ *len = data->id_len;
+ os_memcpy(id, data->session_id, data->id_len);
+
+ return id;
+}
+
+
int eap_peer_peap_register(void)
{
struct eap_method *eap;
@@ -1279,6 +1317,7 @@
eap->has_reauth_data = eap_peap_has_reauth_data;
eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
eap->init_for_reauth = eap_peap_init_for_reauth;
+ eap->getSessionId = eap_peap_get_session_id;
ret = eap_peer_method_register(eap);
if (ret)
diff --git a/src/eap_peer/eap_proxy.h b/src/eap_peer/eap_proxy.h
new file mode 100644
index 0000000..3b4dcef
--- /dev/null
+++ b/src/eap_peer/eap_proxy.h
@@ -0,0 +1,48 @@
+/*
+ * EAP proxy definitions
+ * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef EAP_PROXY_H
+#define EAP_PROXY_H
+
+struct eap_proxy_sm;
+struct eapol_callbacks;
+struct eap_sm;
+struct eap_peer_config;
+
+enum eap_proxy_status {
+ EAP_PROXY_FAILURE = 0x00,
+ EAP_PROXY_SUCCESS
+};
+
+struct eap_proxy_sm *
+eap_proxy_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
+ void *msg_ctx);
+
+void eap_proxy_deinit(struct eap_proxy_sm *eap_proxy);
+
+int eap_proxy_key_available(struct eap_proxy_sm *sm);
+
+const u8 * eap_proxy_get_eapKeyData(struct eap_proxy_sm *sm, size_t *len);
+
+struct wpabuf * eap_proxy_get_eapRespData(struct eap_proxy_sm *sm);
+
+int eap_proxy_sm_step(struct eap_proxy_sm *sm, struct eap_sm *eap_sm);
+
+enum eap_proxy_status
+eap_proxy_packet_update(struct eap_proxy_sm *eap_proxy, u8 *eapReqData,
+ int eapReqDataLen);
+
+int eap_proxy_sm_get_status(struct eap_proxy_sm *sm, char *buf, size_t buflen,
+ int verbose);
+
+int eap_proxy_get_imsi(char *imsi_buf, size_t *imsi_len);
+
+int eap_proxy_notify_config(struct eap_proxy_sm *sm,
+ struct eap_peer_config *config);
+
+#endif /* EAP_PROXY_H */
diff --git a/src/eap_peer/eap_proxy_dummy.c b/src/eap_peer/eap_proxy_dummy.c
new file mode 100644
index 0000000..cd97fb6
--- /dev/null
+++ b/src/eap_peer/eap_proxy_dummy.c
@@ -0,0 +1,76 @@
+/*
+ * EAP proxy - dummy implementation for build testing
+ * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "eap_proxy.h"
+
+struct eap_proxy_sm *
+eap_proxy_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb,
+ void *msg_ctx)
+{
+ return NULL;
+}
+
+
+void eap_proxy_deinit(struct eap_proxy_sm *eap_proxy)
+{
+}
+
+
+int eap_proxy_key_available(struct eap_proxy_sm *sm)
+{
+ return 0;
+}
+
+
+const u8 * eap_proxy_get_eapKeyData(struct eap_proxy_sm *sm, size_t *len)
+{
+ return NULL;
+}
+
+
+struct wpabuf * eap_proxy_get_eapRespData(struct eap_proxy_sm *sm)
+{
+ return NULL;
+}
+
+
+int eap_proxy_sm_step(struct eap_proxy_sm *sm, struct eap_sm *eap_sm)
+{
+ return 0;
+}
+
+
+enum eap_proxy_status
+eap_proxy_packet_update(struct eap_proxy_sm *eap_proxy, u8 *eapReqData,
+ int eapReqDataLen)
+{
+ return EAP_PROXY_FAILURE;
+}
+
+
+int eap_proxy_sm_get_status(struct eap_proxy_sm *sm, char *buf, size_t buflen,
+ int verbose)
+{
+ return 0;
+}
+
+
+int eap_proxy_get_imsi(char *imsi_buf, size_t *imsi_len)
+{
+ return -1;
+}
+
+
+int eap_proxy_notify_config(struct eap_proxy_sm *sm,
+ struct eap_peer_config *config)
+{
+ return -1;
+}
diff --git a/src/eap_peer/eap_psk.c b/src/eap_peer/eap_psk.c
index d618fcf..cd0e3f9 100644
--- a/src/eap_peer/eap_psk.c
+++ b/src/eap_peer/eap_psk.c
@@ -21,6 +21,7 @@
struct eap_psk_data {
enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state;
u8 rand_p[EAP_PSK_RAND_LEN];
+ u8 rand_s[EAP_PSK_RAND_LEN];
u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
u8 *id_s, *id_p;
size_t id_s_len, id_p_len;
@@ -112,6 +113,7 @@
}
wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s,
EAP_PSK_RAND_LEN);
+ os_memcpy(data->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
os_free(data->id_s);
data->id_s_len = len - sizeof(*hdr1);
data->id_s = os_malloc(data->id_s_len);
@@ -434,6 +436,28 @@
}
+static u8 * eap_psk_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_psk_data *data = priv;
+ u8 *id;
+
+ if (data->state != PSK_DONE)
+ return NULL;
+
+ *len = 1 + 2 * EAP_PSK_RAND_LEN;
+ id = os_malloc(*len);
+ if (id == NULL)
+ return NULL;
+
+ id[0] = EAP_TYPE_PSK;
+ os_memcpy(id + 1, data->rand_p, EAP_PSK_RAND_LEN);
+ os_memcpy(id + 1 + EAP_PSK_RAND_LEN, data->rand_s, EAP_PSK_RAND_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-PSK: Derived Session-Id", id, *len);
+
+ return id;
+}
+
+
static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_psk_data *data = priv;
@@ -468,6 +492,7 @@
eap->process = eap_psk_process;
eap->isKeyAvailable = eap_psk_isKeyAvailable;
eap->getKey = eap_psk_getKey;
+ eap->getSessionId = eap_psk_get_session_id;
eap->get_emsk = eap_psk_get_emsk;
ret = eap_peer_method_register(eap);
diff --git a/src/eap_peer/eap_sake.c b/src/eap_peer/eap_sake.c
index e072f46..431519c 100644
--- a/src/eap_peer/eap_sake.c
+++ b/src/eap_peer/eap_sake.c
@@ -452,6 +452,28 @@
}
+static u8 * eap_sake_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_sake_data *data = priv;
+ u8 *id;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ *len = 1 + 2 * EAP_SAKE_RAND_LEN;
+ id = os_malloc(*len);
+ if (id == NULL)
+ return NULL;
+
+ id[0] = EAP_TYPE_SAKE;
+ os_memcpy(id + 1, data->rand_s, EAP_SAKE_RAND_LEN);
+ os_memcpy(id + 1 + EAP_SAKE_RAND_LEN, data->rand_s, EAP_SAKE_RAND_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-SAKE: Derived Session-Id", id, *len);
+
+ return id;
+}
+
+
static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_sake_data *data = priv;
@@ -485,6 +507,7 @@
eap->process = eap_sake_process;
eap->isKeyAvailable = eap_sake_isKeyAvailable;
eap->getKey = eap_sake_getKey;
+ eap->getSessionId = eap_sake_get_session_id;
eap->get_emsk = eap_sake_get_emsk;
ret = eap_peer_method_register(eap);
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index c936a44..82ea18d 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -1084,6 +1084,29 @@
}
+static u8 * eap_sim_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_sim_data *data = priv;
+ u8 *id;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ *len = 1 + data->num_chal * GSM_RAND_LEN + EAP_SIM_NONCE_MT_LEN;
+ id = os_malloc(*len);
+ if (id == NULL)
+ return NULL;
+
+ id[0] = EAP_TYPE_SIM;
+ os_memcpy(id + 1, data->rand, data->num_chal * GSM_RAND_LEN);
+ os_memcpy(id + 1 + data->num_chal * GSM_RAND_LEN, data->nonce_mt,
+ EAP_SIM_NONCE_MT_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-SIM: Derived Session-Id", id, *len);
+
+ return id;
+}
+
+
static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_sim_data *data = priv;
@@ -1118,6 +1141,7 @@
eap->process = eap_sim_process;
eap->isKeyAvailable = eap_sim_isKeyAvailable;
eap->getKey = eap_sim_getKey;
+ eap->getSessionId = eap_sim_get_session_id;
eap->has_reauth_data = eap_sim_has_reauth_data;
eap->deinit_for_reauth = eap_sim_deinit_for_reauth;
eap->init_for_reauth = eap_sim_init_for_reauth;
diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c
index 061a72b..d2066cd 100644
--- a/src/eap_peer/eap_tls.c
+++ b/src/eap_peer/eap_tls.c
@@ -21,6 +21,8 @@
struct eap_tls_data {
struct eap_ssl_data ssl;
u8 *key_data;
+ u8 *session_id;
+ size_t id_len;
void *ssl_ctx;
u8 eap_type;
};
@@ -103,6 +105,7 @@
return;
eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
+ os_free(data->session_id);
os_free(data);
}
@@ -165,6 +168,17 @@
} else {
wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key");
}
+
+ os_free(data->session_id);
+ data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl,
+ EAP_TYPE_TLS,
+ &data->id_len);
+ if (data->session_id) {
+ wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id",
+ data->session_id, data->id_len);
+ } else {
+ wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id");
+ }
}
@@ -228,6 +242,8 @@
struct eap_tls_data *data = priv;
os_free(data->key_data);
data->key_data = NULL;
+ os_free(data->session_id);
+ data->session_id = NULL;
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
os_free(data);
return NULL;
@@ -289,6 +305,25 @@
}
+static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_tls_data *data = priv;
+ u8 *id;
+
+ if (data->session_id == NULL)
+ return NULL;
+
+ id = os_malloc(data->id_len);
+ if (id == NULL)
+ return NULL;
+
+ *len = data->id_len;
+ os_memcpy(id, data->session_id, data->id_len);
+
+ return id;
+}
+
+
int eap_peer_tls_register(void)
{
struct eap_method *eap;
@@ -304,6 +339,7 @@
eap->process = eap_tls_process;
eap->isKeyAvailable = eap_tls_isKeyAvailable;
eap->getKey = eap_tls_getKey;
+ eap->getSessionId = eap_tls_get_session_id;
eap->get_status = eap_tls_get_status;
eap->has_reauth_data = eap_tls_has_reauth_data;
eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index aedd85a..a777bb0 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -340,6 +340,52 @@
/**
+ * eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data
+ * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
+ * @data: Data for TLS processing
+ * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST)
+ * @len: Pointer to length of the session ID generated
+ * Returns: Pointer to allocated Session-Id on success or %NULL on failure
+ *
+ * This function derive the Session-Id based on the TLS session data
+ * (client/server random and method type).
+ *
+ * The caller is responsible for freeing the returned buffer.
+ */
+u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
+ struct eap_ssl_data *data, u8 eap_type,
+ size_t *len)
+{
+ struct tls_keys keys;
+ u8 *out;
+
+ /*
+ * TLS library did not support session ID generation,
+ * so get the needed TLS session parameters
+ */
+ if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
+ return NULL;
+
+ if (keys.client_random == NULL || keys.server_random == NULL ||
+ keys.master_key == NULL)
+ return NULL;
+
+ *len = 1 + keys.client_random_len + keys.server_random_len;
+ out = os_malloc(*len);
+ if (out == NULL)
+ return NULL;
+
+ /* Session-Id = EAP type || client.random || server.random */
+ out[0] = eap_type;
+ os_memcpy(out + 1, keys.client_random, keys.client_random_len);
+ os_memcpy(out + 1 + keys.client_random_len, keys.server_random,
+ keys.server_random_len);
+
+ return out;
+}
+
+
+/**
* eap_peer_tls_reassemble_fragment - Reassemble a received fragment
* @data: Data for TLS processing
* @in_data: Next incoming TLS segment
diff --git a/src/eap_peer/eap_tls_common.h b/src/eap_peer/eap_tls_common.h
index 91d3a25..1a5e0f8 100644
--- a/src/eap_peer/eap_tls_common.h
+++ b/src/eap_peer/eap_tls_common.h
@@ -94,6 +94,9 @@
void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
const char *label, size_t len);
+u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
+ struct eap_ssl_data *data, u8 eap_type,
+ size_t *len);
int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
EapType eap_type, int peap_version,
u8 id, const u8 *in_data, size_t in_len,
diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c
index 9360a42..5091bf0 100644
--- a/src/eap_peer/eap_ttls.c
+++ b/src/eap_peer/eap_ttls.c
@@ -54,6 +54,8 @@
int resuming; /* starting a resumed session */
int reauth; /* reauthentication */
u8 *key_data;
+ u8 *session_id;
+ size_t id_len;
struct wpabuf *pending_phase2_req;
@@ -140,6 +142,7 @@
os_free(data->phase2_eap_types);
eap_peer_tls_ssl_deinit(sm, &data->ssl);
os_free(data->key_data);
+ os_free(data->session_id);
wpabuf_free(data->pending_phase2_req);
os_free(data);
}
@@ -222,6 +225,17 @@
wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
data->key_data, EAP_TLS_KEY_LEN);
+ os_free(data->session_id);
+ data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl,
+ EAP_TYPE_TTLS,
+ &data->id_len);
+ if (data->session_id) {
+ wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Derived Session-Id",
+ data->session_id, data->id_len);
+ } else {
+ wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive Session-Id");
+ }
+
return 0;
}
@@ -1528,6 +1542,8 @@
struct eap_ttls_data *data = priv;
os_free(data->key_data);
data->key_data = NULL;
+ os_free(data->session_id);
+ data->session_id = NULL;
if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
os_free(data);
return NULL;
@@ -1612,6 +1628,25 @@
}
+static u8 * eap_ttls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_ttls_data *data = priv;
+ u8 *id;
+
+ if (data->session_id == NULL || !data->phase2_success)
+ return NULL;
+
+ id = os_malloc(data->id_len);
+ if (id == NULL)
+ return NULL;
+
+ *len = data->id_len;
+ os_memcpy(id, data->session_id, data->id_len);
+
+ return id;
+}
+
+
int eap_peer_ttls_register(void)
{
struct eap_method *eap;
@@ -1627,6 +1662,7 @@
eap->process = eap_ttls_process;
eap->isKeyAvailable = eap_ttls_isKeyAvailable;
eap->getKey = eap_ttls_getKey;
+ eap->getSessionId = eap_ttls_get_session_id;
eap->get_status = eap_ttls_get_status;
eap->has_reauth_data = eap_ttls_has_reauth_data;
eap->deinit_for_reauth = eap_ttls_deinit_for_reauth;
diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
index d007a57..f358156 100644
--- a/src/eap_peer/eap_wsc.c
+++ b/src/eap_peer/eap_wsc.c
@@ -194,7 +194,8 @@
cfg.pin = dev_pw;
cfg.pin_len /= 2;
}
- if (cfg.pin_len == 6 && os_strncmp(pos, "nfc-pw", 6) == 0) {
+ if (cfg.pin_len == 6 &&
+ os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) {
cfg.pin = NULL;
cfg.pin_len = 0;
nfc = 1;