wpa_supplicant(HIDL): EAP Imsi Encryption support

The unncrypted identity is saved to eap.imsi_identity.
The encrypted identity is saved to eap.identity.
Bug: 30988281
Signed-off-by: Ecco Park <eccopark@google.com>

Change-Id: I0bbc8390e39e65d7701df217da9010892a5fa94c
diff --git a/wpa_supplicant/hidl/1.1/sta_network.cpp b/wpa_supplicant/hidl/1.1/sta_network.cpp
index 17991e7..e50927f 100644
--- a/wpa_supplicant/hidl/1.1/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.1/sta_network.cpp
@@ -989,7 +989,13 @@
 	if (setByteArrayFieldAndResetState(
 		identity.data(), identity.size(), &(wpa_ssid->eap.identity),
 		&(wpa_ssid->eap.identity_len), "eap identity")) {
-		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+		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, ""};
 }
@@ -997,7 +1003,14 @@
 SupplicantStatus StaNetwork::setEapEncryptedImsiIdentityInternal(
     const std::vector<uint8_t> &identity)
 {
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	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, ""};
 }
 
 SupplicantStatus StaNetwork::setEapAnonymousIdentityInternal(
@@ -1667,7 +1680,23 @@
 SupplicantStatus StaNetwork::sendNetworkEapIdentityResponseInternal_1_1(
     const std::vector<uint8_t> &identity, const std::vector<uint8_t> &encrypted_imsi_identity)
 {
-	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	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, ""};
 }
 
 /**
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;