summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorEcco Park <eccopark@google.com>2019-04-15 14:49:19 -0700
committerEcco Park <eccopark@google.com>2019-04-17 13:31:20 -0700
commit1a859e8e16d693e245edabd95411888e9157a585 (patch)
treeb64864fceaad2cd7fb5fb4e7504e6fa89cc3f830 /service
parent43c1e848f2b848a02738f3ccce7440c331e9262b (diff)
carrier-wifi: support encrypted identity for V1.6
Encrypted identity for V1.6 requires to encrypt permanent_identity@NAIRealm while the encrypted identity for V1.0 requires to encrypt permanent_identity only. Define additional sequence flag to specify the sequence that it sends anonymous identity and then permanent identity for v1.6 Bug: 130569681 Test: unit test Change-Id: Ia0d263ed2704fe2c83fe1501092a5ffe454ec0c3 Signed-off-by: Ecco Park <eccopark@google.com>
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/server/wifi/CarrierNetworkConfig.java34
-rw-r--r--service/java/com/android/server/wifi/CarrierNetworkEvaluator.java3
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java7
-rw-r--r--service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java3
-rw-r--r--service/java/com/android/server/wifi/util/TelephonyUtil.java92
5 files changed, 109 insertions, 30 deletions
diff --git a/service/java/com/android/server/wifi/CarrierNetworkConfig.java b/service/java/com/android/server/wifi/CarrierNetworkConfig.java
index 56e7c261b..1814eecf4 100644
--- a/service/java/com/android/server/wifi/CarrierNetworkConfig.java
+++ b/service/java/com/android/server/wifi/CarrierNetworkConfig.java
@@ -61,7 +61,7 @@ public class CarrierNetworkConfig {
private final Map<String, NetworkInfo> mCarrierNetworkMap;
private boolean mIsCarrierImsiEncryptionInfoAvailable = false;
private int mBase64EncodingMethod = Base64.DEFAULT;
- private int mEapIdentitySequence = IDENTITY_SEQUENCE_IMSI;
+ private int mEapIdentitySequence = IDENTITY_SEQUENCE_IMSI_V1_0;
private ImsiEncryptionInfo mLastImsiEncryptionInfo = null; // used for dumpsys only
// RFC2045: adds Line Feed at each 76 chars and encode it.
@@ -70,8 +70,20 @@ public class CarrierNetworkConfig {
// RFC4648: encodes whole data into one string.
public static final int ENCODING_METHOD_RFC_4648 = 4648;
- public static final int IDENTITY_SEQUENCE_IMSI = 1;
- public static final int IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI = 2;
+ // Send encrypted IMSI with the format of V1.0
+ // V1.0 format: "\0"|<encrypted IMSI>|@NAIRealm
+ // <encrypted IMSI>: Base64{RSA Public Key Encryption{<permanent ID>}}
+ // <permanent ID>: One char ("0" for AKA, "1" for SIM, "6" for AKA')|IMSI
+ public static final int IDENTITY_SEQUENCE_IMSI_V1_0 = 1;
+
+ // Send anonymous identity and encrypted IMSI identity with the format of V1.0
+ public static final int IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_0 = 2;
+
+ // Send anonymous identity and encrypted IMSI identity with the format of V1.6
+ // V1.6 format: "\0"|<encrypted identity>
+ // <encrypted identity>: Base64{RSA Public Key Encryption{<permanent ID>}}.
+ // <permanent ID>: One char ("0" for AKA, "1" for SIM, "6" for AKA')|IMSI|@NAIRealm
+ public static final int IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_6 = 3;
/**
* Enable/disable verbose logging.
@@ -144,6 +156,15 @@ public class CarrierNetworkConfig {
}
/**
+ * @return {@code true} if current carrier wifi network supports anonymous identity, {@code
+ * false} otherwise.
+ */
+ public boolean isSupportAnonymousIdentity() {
+ return mEapIdentitySequence == IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_0
+ || mEapIdentitySequence == IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_6;
+ }
+
+ /**
* @return True if carrier IMSI encryption info is available, False otherwise.
*/
public boolean isCarrierEncryptionInfoAvailable() {
@@ -268,9 +289,10 @@ public class CarrierNetworkConfig {
}
int sequence = carrierConfig.getInt(CarrierConfigManager.KEY_EAP_IDENTITY_SEQUENCE_INT,
- IDENTITY_SEQUENCE_IMSI);
- if (sequence != IDENTITY_SEQUENCE_IMSI
- && sequence != IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI) {
+ IDENTITY_SEQUENCE_IMSI_V1_0);
+ if (sequence != IDENTITY_SEQUENCE_IMSI_V1_0
+ && sequence != IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_0
+ && sequence != IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_6) {
Log.e(TAG, "Invalid eap identity sequence: " + sequence);
return;
}
diff --git a/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java b/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java
index fd143529b..3b19eaff8 100644
--- a/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/CarrierNetworkEvaluator.java
@@ -161,8 +161,7 @@ public class CarrierNetworkEvaluator implements NetworkEvaluator {
// In case of a carrier supporting anonymous identity, we need
// to send anonymous@realm as EAP-IDENTITY response.
- if (mCarrierNetworkConfig.getEapIdentitySequence()
- == CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI) {
+ if (mCarrierNetworkConfig.isSupportAnonymousIdentity()) {
config.enterpriseConfig.setAnonymousIdentity(
TelephonyUtil.getAnonymousIdentityWith3GppRealm(getTelephonyManager()));
}
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 0bdd37b1a..2ae6b4ed5 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -23,8 +23,6 @@ import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
-import static com.android.server.wifi.CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -4434,9 +4432,8 @@ public class ClientModeImpl extends StateMachine {
} else {
CarrierNetworkConfig carrierNetworkConfig =
mWifiInjector.getCarrierNetworkConfig();
- if (carrierNetworkConfig.isCarrierEncryptionInfoAvailable() && (
- carrierNetworkConfig.getEapIdentitySequence()
- == IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI)) {
+ if (carrierNetworkConfig.isCarrierEncryptionInfoAvailable()
+ && carrierNetworkConfig.isSupportAnonymousIdentity()) {
// In case of a carrier supporting encrypted IMSI and
// anonymous identity, we need to send anonymous@realm as
// EAP-IDENTITY response.
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
index 9f76a2782..58c51486d 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointNetworkEvaluator.java
@@ -188,8 +188,7 @@ public class PasspointNetworkEvaluator implements WifiNetworkSelector.NetworkEva
WifiConfiguration config = networkInfo.mProvider.getWifiConfig();
if (TelephonyUtil.isSimEapMethod(config.enterpriseConfig.getEapMethod())
&& mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()
- && (mCarrierNetworkConfig.getEapIdentitySequence()
- == CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI)) {
+ && mCarrierNetworkConfig.isSupportAnonymousIdentity()) {
// In case of a carrier supporting encrypted IMSI and anonymous identity, we need
// to send anonymous@realm as EAP-IDENTITY response.
config.enterpriseConfig.setAnonymousIdentity(
diff --git a/service/java/com/android/server/wifi/util/TelephonyUtil.java b/service/java/com/android/server/wifi/util/TelephonyUtil.java
index 873fda528..80cadc0af 100644
--- a/service/java/com/android/server/wifi/util/TelephonyUtil.java
+++ b/service/java/com/android/server/wifi/util/TelephonyUtil.java
@@ -16,6 +16,10 @@
package com.android.server.wifi.util;
+import static com.android.server.wifi.CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_0;
+import static com.android.server.wifi.CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_6;
+import static com.android.server.wifi.CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0;
+
import android.annotation.NonNull;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
@@ -102,6 +106,12 @@ public class TelephonyUtil {
mccMnc = tm.getSimOperator();
}
+ String identity = buildIdentity(getSimMethodForConfig(config), imsi, mccMnc, false);
+ if (identity == null) {
+ Log.e(TAG, "Failed to build the identity");
+ return null;
+ }
+
ImsiEncryptionInfo imsiEncryptionInfo;
try {
imsiEncryptionInfo = tm.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN);
@@ -109,21 +119,30 @@ public class TelephonyUtil {
Log.e(TAG, "Failed to get imsi encryption info: " + e.getMessage());
return null;
}
-
- String identity = buildIdentity(getSimMethodForConfig(config), imsi, mccMnc, false);
- if (identity == null) {
- Log.e(TAG, "Failed to build the identity");
- return null;
+ if (imsiEncryptionInfo == null) {
+ // Does not support encrypted identity.
+ return Pair.create(identity, "");
}
int base64EncodingFlag = carrierNetworkConfig.getBase64EncodingFlag();
- String encryptedIdentity = buildEncryptedIdentity(telephonyUtil,
- getSimMethodForConfig(config), imsi, mccMnc, imsiEncryptionInfo,
- base64EncodingFlag);
-
- // In case of failure for encryption, set empty string
- if (encryptedIdentity == null) encryptedIdentity = "";
+ String encryptedIdentity = null;
+ int eapSequence = carrierNetworkConfig.getEapIdentitySequence();
+ if (eapSequence == IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_6) {
+ encryptedIdentity = buildEncryptedIdentityV1_6(telephonyUtil, identity,
+ imsiEncryptionInfo, base64EncodingFlag);
+ } else if (eapSequence == IDENTITY_SEQUENCE_IMSI_V1_0
+ || eapSequence == IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_0) {
+ encryptedIdentity = buildEncryptedIdentityV1_0(telephonyUtil,
+ getSimMethodForConfig(config), imsi, mccMnc, imsiEncryptionInfo,
+ base64EncodingFlag);
+ }
+
+ // In case of failure for encryption, abort current EAP authentication.
+ if (encryptedIdentity == null) {
+ Log.e(TAG, "failed to encrypt the identity, eapIdentitySequence: " + eapSequence);
+ return null;
+ }
return Pair.create(identity, encryptedIdentity);
}
@@ -179,19 +198,21 @@ public class TelephonyUtil {
}
/**
- * Create the encrypted IMSI.
- * Prefix value:
+ * Create the encrypted identity for V1.0.
+ *
+ * Prefix value:
* "0" - EAP-AKA Identity
* "1" - EAP-SIM Identity
* "6" - EAP-AKA' Identity
- *
+ * Encrypted Identity format for V1.0: prefix|IMSI
* @param eapMethod EAP authentication method: EAP-SIM, EAP-AKA, EAP-AKA'
* @param imsi The IMSI retrieved from the SIM
* @param mccMnc The MCC MNC identifier retrieved from the SIM
* @param imsiEncryptionInfo The IMSI encryption info retrieved from the SIM
* @param base64EncodingFlag base64 encoding flag
+ * @return "\0" + encryptedIdentity@<NAIRealm> + "{, Key Identifier AVP}"
*/
- private static String buildEncryptedIdentity(TelephonyUtil telephonyUtil, int eapMethod,
+ private static String buildEncryptedIdentityV1_0(TelephonyUtil telephonyUtil, int eapMethod,
String imsi, String mccMnc,
ImsiEncryptionInfo imsiEncryptionInfo, int base64EncodingFlag) {
if (imsiEncryptionInfo == null) {
@@ -220,6 +241,47 @@ public class TelephonyUtil {
}
/**
+ * Create the encrypted identity for V1.6.
+ *
+ * Prefix value:
+ * "0" - EAP-AKA Identity
+ * "1" - EAP-SIM Identity
+ * "6" - EAP-AKA' Identity
+ * Encrypted identity format for V1.6: prefix|IMSI@<NAIRealm>
+ * @param telephonyUtil TelephonyUtil instance
+ * @param identity permanent identity with format based on section 4.1.1.6 of RFC 4187
+ * and 4.2.1.6 of RFC 4186.
+ * @param imsiEncryptionInfo The IMSI encryption info retrieved from the SIM
+ * @param base64EncodingFlag base64 encoding flag
+ * @return "\0" + encryptedIdentity + "{, Key Identifier AVP}"
+ */
+ private static String buildEncryptedIdentityV1_6(TelephonyUtil telephonyUtil, String identity,
+ ImsiEncryptionInfo imsiEncryptionInfo, int base64EncodingFlag) {
+ if (imsiEncryptionInfo == null) {
+ Log.e(TAG, "imsiEncryptionInfo is not valid");
+ return null;
+ }
+ if (identity == null) {
+ Log.e(TAG, "identity is not valid");
+ return null;
+ }
+
+ // Build and return the encrypted identity.
+ String encryptedIdentity = telephonyUtil.encryptDataUsingPublicKey(
+ imsiEncryptionInfo.getPublicKey(), identity.getBytes(), base64EncodingFlag);
+ if (encryptedIdentity == null) {
+ Log.e(TAG, "Failed to encrypt IMSI");
+ return null;
+ }
+ encryptedIdentity = DEFAULT_EAP_PREFIX + encryptedIdentity;
+ if (imsiEncryptionInfo.getKeyIdentifier() != null) {
+ // Include key identifier AVP (Attribute Value Pair).
+ encryptedIdentity = encryptedIdentity + "," + imsiEncryptionInfo.getKeyIdentifier();
+ }
+ return encryptedIdentity;
+ }
+
+ /**
* Create an identity used for SIM-based EAP authentication. The identity will be based on
* the info retrieved from the SIM card, such as IMSI and IMSI encryption info. The IMSI
* contained in the identity will be encrypted if IMSI encryption info is provided.