diff options
10 files changed, 211 insertions, 52 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. diff --git a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java index 22e66823d..d0cdf2e83 100644 --- a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java +++ b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkConfigTest.java @@ -110,7 +110,7 @@ public class CarrierNetworkConfigTest { when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID)) .thenReturn(generateTestConfig(TEST_SSID, TEST_STANDARD_EAP_TYPE, CarrierNetworkConfig.ENCODING_METHOD_RFC_2045, - CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI)); + CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0)); when(mSubscriptionManager.getActiveSubscriptionInfoList()) .thenReturn(Arrays.asList(new SubscriptionInfo[] {TEST_SUBSCRIPTION_INFO})); when(mTelephonyManager.getCarrierInfoForImsiEncryption(TelephonyManager.KEY_TYPE_WLAN)) @@ -143,7 +143,7 @@ public class CarrierNetworkConfigTest { assertEquals(TEST_INTERNAL_EAP_TYPE, mCarrierNetworkConfig.getNetworkEapType(TEST_SSID)); assertEquals(TEST_CARRIER_NAME, mCarrierNetworkConfig.getCarrierName(TEST_SSID)); assertEquals(Base64.DEFAULT, mCarrierNetworkConfig.getBase64EncodingFlag()); - assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI, + assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0, mCarrierNetworkConfig.getEapIdentitySequence()); } @@ -210,7 +210,7 @@ public class CarrierNetworkConfigTest { when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID)) .thenReturn(generateTestConfig(updatedSsid, updatedStandardEapType, CarrierNetworkConfig.ENCODING_METHOD_RFC_2045, - CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI)); + CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0)); mBroadcastReceiver.onReceive(mContext, new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); @@ -219,7 +219,7 @@ public class CarrierNetworkConfigTest { assertEquals(-1, mCarrierNetworkConfig.getNetworkEapType(TEST_SSID)); assertEquals(null, mCarrierNetworkConfig.getCarrierName(TEST_SSID)); assertEquals(Base64.DEFAULT, mCarrierNetworkConfig.getBase64EncodingFlag()); - assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI, + assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0, mCarrierNetworkConfig.getEapIdentitySequence()); // Verify that updated SSID is associated with a carrier network. @@ -227,7 +227,7 @@ public class CarrierNetworkConfigTest { assertEquals(updatedInternalEapType, mCarrierNetworkConfig.getNetworkEapType(updatedSsid)); assertEquals(updatedCarrierName, mCarrierNetworkConfig.getCarrierName(updatedSsid)); assertEquals(Base64.DEFAULT, mCarrierNetworkConfig.getBase64EncodingFlag()); - assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI, + assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0, mCarrierNetworkConfig.getEapIdentitySequence()); } @@ -270,7 +270,7 @@ public class CarrierNetworkConfigTest { when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID)) .thenReturn(generateTestConfig(TEST_SSID, TEST_STANDARD_EAP_TYPE, CarrierNetworkConfig.ENCODING_METHOD_RFC_4648, - CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI)); + CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0)); mBroadcastReceiver.onReceive(mContext, new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); assertEquals(Base64.NO_WRAP, mCarrierNetworkConfig.getBase64EncodingFlag()); @@ -285,7 +285,7 @@ public class CarrierNetworkConfigTest { String ssid = "invalid carrier AP"; when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID)) .thenReturn(generateTestConfig(ssid, TEST_STANDARD_EAP_TYPE, 123, - CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI)); + CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0)); mBroadcastReceiver.onReceive(mContext, new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); @@ -304,11 +304,11 @@ public class CarrierNetworkConfigTest { when(mCarrierConfigManager.getConfigForSubId(TEST_SUBSCRIPTION_ID)) .thenReturn(generateTestConfig(TEST_SSID, TEST_STANDARD_EAP_TYPE, CarrierNetworkConfig.ENCODING_METHOD_RFC_2045, - CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI)); + CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_0)); mBroadcastReceiver.onReceive(mContext, new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)); - assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI, + assertEquals(CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_0, mCarrierNetworkConfig.getEapIdentitySequence()); } } diff --git a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java index ce4882f55..4c9d82df1 100644 --- a/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/CarrierNetworkEvaluatorTest.java @@ -159,7 +159,7 @@ public class CarrierNetworkEvaluatorTest { when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true); when(mCarrierNetworkConfig.getEapIdentitySequence()).thenReturn( - CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI); + CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0); when(mCarrierNetworkConfig.isCarrierNetwork(eq(CARRIER1_SSID.replace("\"", "")))) .thenReturn(true); @@ -396,8 +396,7 @@ public class CarrierNetworkEvaluatorTest { int[] levels = {10}; String expectedAnonymousIdentity = "anonymous@wlan.mnc456.mcc123.3gppnetwork.org"; when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true); - when(mCarrierNetworkConfig.getEapIdentitySequence()).thenReturn( - CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI); + when(mCarrierNetworkConfig.isSupportAnonymousIdentity()).thenReturn(true); List<ScanDetail> scanDetails = WifiNetworkSelectorTestUtil.buildScanDetails(ssids, bssids, freqs, caps, levels, mClock); WifiConfiguration carrierConfig = configureNewSsid(CARRIER1_NET_ID, scanDetails.get(0), diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java index 718c82fdd..452dfa399 100644 --- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java +++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java @@ -1024,8 +1024,7 @@ public class ClientModeImplTest { triggerConnect(); when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true); - when(mCarrierNetworkConfig.getEapIdentitySequence()).thenReturn( - CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI); + when(mCarrierNetworkConfig.isSupportAnonymousIdentity()).thenReturn(true); when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID)) .thenReturn(mScanDetailCache); diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java index 591db7d09..a396d4d93 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointNetworkEvaluatorTest.java @@ -413,8 +413,7 @@ public class PasspointNetworkEvaluatorTest { when(testProvider.isSimCredential()).thenReturn(true); when(mWifiConfigManager.isSimPresent()).thenReturn(true); when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true); - when(mCarrierNetworkConfig.getEapIdentitySequence()).thenReturn( - CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI); + when(mCarrierNetworkConfig.isSupportAnonymousIdentity()).thenReturn(true); when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) .thenReturn(new NetworkUpdateResult(TEST_NETWORK_ID)); when(mWifiConfigManager.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(config); diff --git a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java index 0d9cd59e1..0c0b76fa3 100644 --- a/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java +++ b/tests/wifitests/src/com/android/server/wifi/util/TelephonyUtilTest.java @@ -16,6 +16,8 @@ package com.android.server.wifi.util; +import static com.android.server.wifi.CarrierNetworkConfig.IDENTITY_SEQUENCE_IMSI_V1_0; + import static org.junit.Assert.*; import static org.mockito.Mockito.*; @@ -42,6 +44,7 @@ import org.mockito.MockitoSession; import java.security.PublicKey; +import javax.crypto.BadPaddingException; import javax.crypto.Cipher; /** @@ -58,8 +61,11 @@ public class TelephonyUtilTest { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); when(mCarrierNetworkConfig.getBase64EncodingFlag()).thenReturn(Base64.DEFAULT); + when(mCarrierNetworkConfig.getEapIdentitySequence()).thenReturn( + IDENTITY_SEQUENCE_IMSI_V1_0); mTelephonyUtil = new TelephonyUtil(); } + @Test public void getSimIdentityEapSim() { TelephonyManager tm = mock(TelephonyManager.class); @@ -119,11 +125,11 @@ public class TelephonyUtilTest { } /** - * Verify that an expected identity is returned when using the encrypted IMSI encoded by - * RFC4648. + * Verify that an expected identity is returned when using the encrypted identity for V1.0 + * encoded by RFC4648. */ @Test - public void getEncryptedIdentityImsiWithRfc4648() throws Exception { + public void getEncryptedIdentity_V_1_0_WithRfc4648() throws Exception { TelephonyManager tm = mock(TelephonyManager.class); Cipher cipher = mock(Cipher.class); PublicKey key = null; @@ -159,6 +165,49 @@ public class TelephonyUtilTest { } /** + * Verify that an expected identity is returned when using the encrypted identity for V1.6 + * encoded by RFC4648. + */ + @Test + public void getEncryptedIdentity_V_1_6_WithRfc4648() throws Exception { + TelephonyManager tm = mock(TelephonyManager.class); + Cipher cipher = mock(Cipher.class); + PublicKey key = null; + int flag = Base64.NO_WRAP; + String imsi = "3214561234567890"; + String permanentIdentity = "03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org"; + String encryptedImsi = Base64.encodeToString(permanentIdentity.getBytes(), 0, + permanentIdentity.getBytes().length, flag); + String encryptedIdentity = "\0" + encryptedImsi; + final Pair<String, String> expectedIdentity = Pair.create(permanentIdentity, + encryptedIdentity); + + // static mocking + MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( + Cipher.class).startMocking(); + try { + when(Cipher.getInstance(anyString())).thenReturn(cipher); + when(cipher.doFinal(any(byte[].class))).thenReturn(permanentIdentity.getBytes()); + when(tm.getSubscriberId()).thenReturn(imsi); + when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); + when(tm.getSimOperator()).thenReturn("321456"); + ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456", + TelephonyManager.KEY_TYPE_WLAN, null, key, null); + when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN))) + .thenReturn(info); + when(mCarrierNetworkConfig.getBase64EncodingFlag()).thenReturn(flag); + when(mCarrierNetworkConfig.getEapIdentitySequence()).thenReturn( + CarrierNetworkConfig.IDENTITY_SEQUENCE_ANONYMOUS_THEN_IMSI_V1_6); + + assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil, + WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA, + WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig)); + } finally { + session.finishMocking(); + } + } + + /** * Verify that an expected identity is returned when using the encrypted IMSI encoded by RFC2045 * with key identifier. */ @@ -201,24 +250,58 @@ public class TelephonyUtilTest { } /** - * Verify that a null identity will be returned when IMSI encryption failed. + * Verify that {@code null} will be returned when IMSI encryption failed. * * @throws Exception */ @Test public void getEncryptedIdentityFailed() throws Exception { TelephonyManager tm = mock(TelephonyManager.class); + Cipher cipher = mock(Cipher.class); + String keyIdentifier = "key=testKey"; String imsi = "3214561234567890"; + // static mocking + MockitoSession session = ExtendedMockito.mockitoSession().mockStatic( + Cipher.class).startMocking(); + try { + when(Cipher.getInstance(anyString())).thenReturn(cipher); + when(cipher.doFinal(any(byte[].class))).thenThrow(BadPaddingException.class); + when(tm.getSubscriberId()).thenReturn(imsi); + when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); + when(tm.getSimOperator()).thenReturn("321456"); + ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456", + TelephonyManager.KEY_TYPE_WLAN, keyIdentifier, (PublicKey) null, null); + when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN))) + .thenReturn(info); + + assertNull(TelephonyUtil.getSimIdentity(tm, mTelephonyUtil, + WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA, + WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig)); + } finally { + session.finishMocking(); + } + } + + /** + * Verify that {@code null} will be returned when IMSI encryption failed because + * the sequence of EAP identity is not valid. + */ + @Test + public void getEncryptedIdentityFailedWithInvalidEapIdentitySequence() throws Exception { + TelephonyManager tm = mock(TelephonyManager.class); final Pair<String, String> expectedIdentity = Pair.create( "03214561234567890@wlan.mnc456.mcc321.3gppnetwork.org", ""); when(tm.getSubscriberId()).thenReturn("3214561234567890"); when(tm.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); when(tm.getSimOperator()).thenReturn("321456"); + ImsiEncryptionInfo info = new ImsiEncryptionInfo("321", "456", + TelephonyManager.KEY_TYPE_WLAN, null, (PublicKey) null, null); when(tm.getCarrierInfoForImsiEncryption(eq(TelephonyManager.KEY_TYPE_WLAN))) - .thenReturn(null); + .thenReturn(info); + when(mCarrierNetworkConfig.getEapIdentitySequence()).thenReturn(-1); - assertEquals(expectedIdentity, TelephonyUtil.getSimIdentity(tm, mTelephonyUtil, + assertNull(TelephonyUtil.getSimIdentity(tm, mTelephonyUtil, WifiConfigurationTestUtil.createEapNetwork(WifiEnterpriseConfig.Eap.AKA, WifiEnterpriseConfig.Phase2.NONE), mCarrierNetworkConfig)); } |