Snap for 4571561 from 00a7b21c7b2af9b19a0b6173e0de92197d537fec to pi-release

Change-Id: I14f2bf2dee0c39f2429eba0bb42ed5a968005c8f
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index f7e3cd6..7a6bfc9 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -1025,8 +1025,17 @@
 	} else if (data->pseudonym) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
-	} else
-		identity = eap_get_config_identity(sm, &identity_len);
+	} else {
+		struct eap_peer_config *config;
+
+		config = eap_get_config(sm);
+		if (config && config->imsi_identity) {
+			identity = config->imsi_identity;
+			identity_len = config->imsi_identity_len;
+		} else {
+			identity = eap_get_config_identity(sm, &identity_len);
+		}
+	}
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK "
 			  "derivation", identity, identity_len);
 	if (data->eap_method == EAP_TYPE_AKA_PRIME) {
diff --git a/src/eap_peer/eap_config.h b/src/eap_peer/eap_config.h
index 16521c3..d416afd 100644
--- a/src/eap_peer/eap_config.h
+++ b/src/eap_peer/eap_config.h
@@ -46,6 +46,9 @@
 	 */
 	size_t anonymous_identity_len;
 
+	u8 *imsi_identity;
+	size_t imsi_identity_len;
+
 	/**
 	 * password - Password string for EAP
 	 *
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index 25f592c..cd687cb 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -767,8 +767,17 @@
 	} else if (data->pseudonym) {
 		identity = data->pseudonym;
 		identity_len = data->pseudonym_len;
-	} else
-		identity = eap_get_config_identity(sm, &identity_len);
+	} else {
+		struct eap_peer_config *config;
+
+		config = eap_get_config(sm);
+		if (config && config->imsi_identity) {
+			identity = config->imsi_identity;
+			identity_len = config->imsi_identity_len;
+		} else {
+			identity = eap_get_config_identity(sm, &identity_len);
+		}
+	}
 	wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK "
 			  "derivation", identity, identity_len);
 	eap_sim_derive_mk(identity, identity_len, data->nonce_mt,
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a0d480e..a22434c 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2154,6 +2154,7 @@
 	{ FUNC(eap) },
 	{ STR_LENe(identity) },
 	{ STR_LENe(anonymous_identity) },
+	{ STR_LENe(imsi_identity) },
 	{ FUNC_KEY(password) },
 	{ STRe(ca_cert) },
 	{ STRe(ca_path) },
@@ -2411,6 +2412,7 @@
 	os_free(eap->eap_methods);
 	bin_clear_free(eap->identity, eap->identity_len);
 	os_free(eap->anonymous_identity);
+	os_free(eap->imsi_identity);
 	bin_clear_free(eap->password, eap->password_len);
 	os_free(eap->ca_cert);
 	os_free(eap->ca_path);
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 6b7abe2..058b366 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -760,6 +760,7 @@
 	write_eap(f, ssid);
 	STR(identity);
 	STR(anonymous_identity);
+	STR(imsi_identity);
 	STR(password);
 	STR(ca_cert);
 	STR(ca_path);
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 24f496b..0ba1aa5 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -880,6 +880,7 @@
 	write_eap(netw, ssid);
 	STR(identity);
 	STR(anonymous_identity);
+	STR(imsi_identity);
 	STR(password);
 	STR(ca_cert);
 	STR(ca_path);
diff --git a/wpa_supplicant/hidl/1.1/sta_network.cpp b/wpa_supplicant/hidl/1.1/sta_network.cpp
index 7af8f08..e50927f 100644
--- a/wpa_supplicant/hidl/1.1/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.1/sta_network.cpp
@@ -249,6 +249,14 @@
 	    &StaNetwork::setEapIdentityInternal, _hidl_cb, identity);
 }
 
+Return<void> StaNetwork::setEapEncryptedImsiIdentity(
+    const EapSimEncryptedIdentity &identity, setEapEncryptedImsiIdentity_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::setEapEncryptedImsiIdentityInternal, _hidl_cb, identity);
+}
+
 Return<void> StaNetwork::setEapAnonymousIdentity(
     const hidl_vec<uint8_t> &identity, setEapAnonymousIdentity_cb _hidl_cb)
 {
@@ -645,6 +653,17 @@
 	    identity);
 }
 
+Return<void> StaNetwork::sendNetworkEapIdentityResponse_1_1(
+    const EapSimIdentity &identity,
+    const EapSimEncryptedIdentity &encrypted_imsi_identity,
+    sendNetworkEapIdentityResponse_1_1_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::sendNetworkEapIdentityResponseInternal_1_1, _hidl_cb,
+	    identity, encrypted_imsi_identity);
+}
+
 std::pair<SupplicantStatus, uint32_t> StaNetwork::getIdInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
@@ -970,6 +989,25 @@
 	if (setByteArrayFieldAndResetState(
 		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
 		&(wpa_ssid->eap.identity_len), "eap identity")) {
+		return { SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	// plain IMSI identity
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(), &(wpa_ssid->eap.imsi_identity),
+		&(wpa_ssid->eap.imsi_identity_len), "eap imsi identity")) {
+		return { SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+SupplicantStatus StaNetwork::setEapEncryptedImsiIdentityInternal(
+    const std::vector<uint8_t> &identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// encrypted IMSI identity
+	if (setByteArrayFieldAndResetState(
+		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
+		&(wpa_ssid->eap.identity_len), "eap encrypted imsi identity")) {
 		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	return {SupplicantStatusCode::SUCCESS, ""};
@@ -1639,6 +1677,28 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal_1_1(
+    const std::vector<uint8_t> &identity, const std::vector<uint8_t> &encrypted_imsi_identity)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	// format: plain identity + ":" + encrypted identity(encrypted_imsi_identity)
+	std::string ctrl_rsp_param =
+		std::string(identity.begin(), identity.end()) + ":" +
+		std::string(encrypted_imsi_identity.begin(), encrypted_imsi_identity.end());
+	enum wpa_ctrl_req_type rtype = WPA_CTRL_REQ_EAP_IDENTITY;
+	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
+	if (wpa_supplicant_ctrl_rsp_handle(
+		wpa_s, wpa_ssid, rtype, ctrl_rsp_param.c_str(),
+		ctrl_rsp_param.size())) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	eapol_sm_notify_ctrl_response(wpa_s->eapol);
+	wpa_hexdump_ascii_key(
+	    MSG_DEBUG, "network identity response param",
+	    (const u8 *)ctrl_rsp_param.c_str(), ctrl_rsp_param.size());
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_ssid| struct pointer for
  * this network.
diff --git a/wpa_supplicant/hidl/1.1/sta_network.h b/wpa_supplicant/hidl/1.1/sta_network.h
index c856163..b647773 100644
--- a/wpa_supplicant/hidl/1.1/sta_network.h
+++ b/wpa_supplicant/hidl/1.1/sta_network.h
@@ -15,7 +15,7 @@
 
 #include <android-base/macros.h>
 
-#include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetwork.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaNetwork.h>
 #include <android/hardware/wifi/supplicant/1.0/ISupplicantStaNetworkCallback.h>
 
 extern "C" {
@@ -42,7 +42,7 @@
  * object is used for control operations on a specific network
  * controlled by wpa_supplicant.
  */
-class StaNetwork : public ISupplicantStaNetwork
+class StaNetwork : public V1_1::ISupplicantStaNetwork
 {
 public:
 	StaNetwork(
@@ -109,6 +109,9 @@
 	    const hidl_string& path, setEapClientCert_cb _hidl_cb) override;
 	Return<void> setEapPrivateKeyId(
 	    const hidl_string& id, setEapPrivateKeyId_cb _hidl_cb) override;
+        Return<void> setEapEncryptedImsiIdentity(
+            const EapSimEncryptedIdentity& identity,
+            setEapEncryptedImsiIdentity_cb _hidl_cb) override;
 	Return<void> setEapSubjectMatch(
 	    const hidl_string& match, setEapSubjectMatch_cb _hidl_cb) override;
 	Return<void> setEapAltSubjectMatch(
@@ -186,6 +189,10 @@
 	Return<void> sendNetworkEapIdentityResponse(
 	    const hidl_vec<uint8_t>& identity,
 	    sendNetworkEapIdentityResponse_cb _hidl_cb) override;
+	Return<void> sendNetworkEapIdentityResponse_1_1(
+	    const EapSimIdentity& identity,
+	    const EapSimEncryptedIdentity& imsiIdentity,
+	    sendNetworkEapIdentityResponse_1_1_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -215,6 +222,8 @@
 	    ISupplicantStaNetwork::EapPhase2Method method);
 	SupplicantStatus setEapIdentityInternal(
 	    const std::vector<uint8_t>& identity);
+        SupplicantStatus setEapEncryptedImsiIdentityInternal(
+	    const std::vector<uint8_t>& identity);
 	SupplicantStatus setEapAnonymousIdentityInternal(
 	    const std::vector<uint8_t>& identity);
 	SupplicantStatus setEapPasswordInternal(
@@ -287,6 +296,9 @@
 	SupplicantStatus sendNetworkEapSimUmtsAuthFailureInternal();
 	SupplicantStatus sendNetworkEapIdentityResponseInternal(
 	    const std::vector<uint8_t>& identity);
+	SupplicantStatus sendNetworkEapIdentityResponseInternal_1_1(
+	    const std::vector<uint8_t>& identity,
+	    const std::vector<uint8_t>& imsi_identity);
 
 	struct wpa_ssid* retrieveNetworkPtr();
 	struct wpa_supplicant* retrieveIfacePtr();
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 498967b..ee5710f 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -6367,12 +6367,31 @@
 {
 #ifdef IEEE8021X_EAPOL
 	struct eap_peer_config *eap = &ssid->eap;
+	char *identity, *imsi_identity;
 
 	switch (rtype) {
 	case WPA_CTRL_REQ_EAP_IDENTITY:
 		os_free(eap->identity);
-		eap->identity = (u8 *) dup_binstr(value, value_len);
-		eap->identity_len = value_len;
+		os_free(eap->imsi_identity);
+		if (value == NULL)
+			return -1;
+		identity = os_strchr(value, ':');
+		if (identity == NULL) {
+			/* plain identity */
+			eap->identity = (u8 *)os_strdup(value);
+			eap->identity_len = os_strlen(value);
+		} else {
+			/* have both plain identity and encrypted identity */
+			imsi_identity = value;
+			*identity++ = '\0';
+			/* plain identity */
+			eap->imsi_identity = (u8 *)dup_binstr(imsi_identity, strlen(imsi_identity));
+			eap->imsi_identity_len = strlen(imsi_identity);
+			/* encrypted identity */
+			eap->identity = (u8 *)dup_binstr(identity,
+							 value_len - strlen(imsi_identity) - 1);
+			eap->identity_len = value_len - strlen(imsi_identity) - 1;
+		}
 		eap->pending_req_identity = 0;
 		if (ssid == wpa_s->current_ssid)
 			wpa_s->reassociate = 1;