Loading src/com/android/settings/utils/AndroidKeystoreAliasLoader.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.utils; import android.os.Process; import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyProperties; import android.security.keystore2.AndroidKeyStoreLoadStoreParameter; import android.util.Log; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.UnrecoverableKeyException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; /** * This class provides a portable and unified way to load the content of AndroidKeyStore through * public API. * @hide */ public class AndroidKeystoreAliasLoader { private static final String TAG = "SettingsKeystoreUtils"; private final Collection<String> mKeyCertAliases; private final Collection<String> mCaCertAliases; /** * This Constructor loads all aliases of asymmetric key pairs and certificates in the * AndroidKeyStore within the given namespace. * Viable namespaces are {@link KeyProperties#NAMESPACE_WIFI}, * {@link KeyProperties#NAMESPACE_APPLICATION}, or null. The latter two are equivalent in * that they will load the keystore content of the app's own namespace. In case of settings, * this is the namespace of the AID_SYSTEM. * * @param namespace {@link KeyProperties#NAMESPACE_WIFI}, * {@link KeyProperties#NAMESPACE_APPLICATION}, or null * @hide */ public AndroidKeystoreAliasLoader(Integer namespace) { mKeyCertAliases = new ArrayList<>(); mCaCertAliases = new ArrayList<>(); KeyStore keyStore = null; final Enumeration<String> aliases; try { if (namespace != null && namespace != KeyProperties.NAMESPACE_APPLICATION) { if (AndroidKeyStoreProvider.isKeystore2Enabled()) { keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(new AndroidKeyStoreLoadStoreParameter(namespace)); } else { // In the legacy case we pass in the WIFI UID because that is the only // possible special namespace that existed as of this writing, // and new namespaces must only be added using the new mechanism. keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(Process.WIFI_UID); } } else { keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); } aliases = keyStore.aliases(); } catch (Exception e) { Log.e(TAG, "Failed to open Android Keystore.", e); // Will return empty lists. return; } while (aliases.hasMoreElements()) { final String alias = aliases.nextElement(); try { final Key key = keyStore.getKey(alias, null); if (key != null) { if (key instanceof PrivateKey) { mKeyCertAliases.add(alias); } } else { if (keyStore.getCertificate(alias) != null) { mCaCertAliases.add(alias); } } } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) { Log.e(TAG, "Failed to load alias: " + alias + " from Android Keystore. Ignoring.", e); } } } /** * Returns the aliases of the key pairs and certificates stored in the Android KeyStore at the * time the constructor was called. * @return Collection of keystore aliases. * @hide */ public Collection<String> getKeyCertAliases() { return mKeyCertAliases; } /** * Returns the aliases of the trusted certificates stored in the Android KeyStore at the * time the constructor was called. * @return Collection of keystore aliases. * @hide */ public Collection<String> getCaCertAliases() { return mCaCertAliases; } } src/com/android/settings/wifi/WifiConfigController.java +16 −17 Original line number Diff line number Diff line Loading @@ -35,8 +35,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; import android.security.Credentials; import android.security.KeyStore; import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; Loading Loading @@ -73,6 +72,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; Loading @@ -83,7 +83,7 @@ import com.android.settingslib.wifi.AccessPoint; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; Loading Loading @@ -1051,15 +1051,17 @@ public class WifiConfigController implements TextWatcher, if (refreshCertificates) { loadSims(); final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY, androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -1142,10 +1144,13 @@ public class WifiConfigController implements TextWatcher, } else if (caCerts.length == 1) { setSelection(mEapCaCertSpinner, caCerts[0]); } else { final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); // Reload the cert spinner with an extra "multiple certificates added" item. loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); Loading Loading @@ -1464,8 +1469,8 @@ public class WifiConfigController implements TextWatcher, } @VisibleForTesting KeyStore getKeyStore() { return KeyStore.getInstance(); AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting Loading Loading @@ -1509,7 +1514,7 @@ public class WifiConfigController implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, String prefix, Collection<String> choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { Loading @@ -1524,14 +1529,8 @@ public class WifiConfigController implements TextWatcher, certs.add(mUseSystemCertsString); } String[] certificateNames = null; try { certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); } catch (Exception e) { Log.e(TAG, "can't get the certificate list from KeyStore"); } if (certificateNames != null && certificateNames.length != 0) { certs.addAll(Arrays.stream(certificateNames) if (choices != null && choices.size() != 0) { certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { Loading src/com/android/settings/wifi/WifiConfigController2.java +15 −17 Original line number Diff line number Diff line Loading @@ -33,8 +33,7 @@ import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; import android.security.Credentials; import android.security.KeyStore; import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; Loading Loading @@ -71,6 +70,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; Loading @@ -83,7 +83,7 @@ import com.android.wifitrackerlib.WifiEntry.ConnectedInfo; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; Loading Loading @@ -1034,15 +1034,17 @@ public class WifiConfigController2 implements TextWatcher, if (refreshCertificates) { loadSims(); final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY, androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -1127,9 +1129,11 @@ public class WifiConfigController2 implements TextWatcher, setSelection(mEapCaCertSpinner, caCerts[0]); } else { // Reload the cert spinner with an extra "multiple certificates added" item. final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); Loading Loading @@ -1448,8 +1452,8 @@ public class WifiConfigController2 implements TextWatcher, } @VisibleForTesting KeyStore getKeyStore() { return KeyStore.getInstance(); AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting Loading Loading @@ -1493,7 +1497,7 @@ public class WifiConfigController2 implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, String prefix, Collection<String> choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { Loading @@ -1508,14 +1512,8 @@ public class WifiConfigController2 implements TextWatcher, certs.add(mUseSystemCertsString); } String[] certificateNames = null; try { certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); } catch (Exception e) { Log.e(TAG, "can't get the certificate list from KeyStore"); } if (certificateNames != null && certificateNames.length != 0) { certs.addAll(Arrays.stream(certificateNames) if (choices != null && choices.size() != 0) { certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { Loading tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java +12 −30 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; Loading @@ -33,9 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.ServiceSpecificException; import android.security.Credentials; import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; Loading @@ -50,9 +44,12 @@ import android.widget.TextView; import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowConnectivityManager; import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.wifitrackerlib.WifiEntry; import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -78,7 +75,7 @@ public class WifiConfigController2Test { @Mock private WifiEntry mWifiEntry; @Mock private KeyStore mKeyStore; private AndroidKeystoreAliasLoader mAndroidKeystoreAliasLoader; private View mView; private Spinner mHiddenSettingsSpinner; private Spinner mEapCaCertSpinner; Loading Loading @@ -284,28 +281,12 @@ public class WifiConfigController2Test { assertThat(mController.getSignalString()).isNull(); } @Test public void loadCertificates_keyStoreListFail_shouldNotCrash() { // Set up when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); when(mKeyStore.list(anyString())) .thenThrow(new ServiceSpecificException(-1, "permission error")); mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, WifiConfigUiBase2.MODE_CONNECT); // Verify that the EAP method menu is visible. assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); // No Crash } @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, "prefix", Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -436,8 +417,8 @@ public class WifiConfigController2Test { } @Override KeyStore getKeyStore() { return mKeyStore; AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { return mAndroidKeystoreAliasLoader; } } Loading Loading @@ -883,6 +864,7 @@ public class WifiConfigController2Test { String savedUserCertificate) { final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class); final WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class); mockWifiConfig.enterpriseConfig = mockWifiEnterpriseConfig; when(mWifiEntry.isSaved()).thenReturn(true); when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); Loading @@ -893,15 +875,15 @@ public class WifiConfigController2Test { String[] savedCaCertificates = new String[]{savedCaCertificate}; when(mockWifiEnterpriseConfig.getCaCertificateAliases()) .thenReturn(savedCaCertificates); when(mKeyStore.list(eq(Credentials.CA_CERTIFICATE), anyInt())) .thenReturn(savedCaCertificates); when(mAndroidKeystoreAliasLoader.getCaCertAliases()) .thenReturn(ImmutableList.of(savedCaCertificate)); } if (savedUserCertificate != null) { String[] savedUserCertificates = new String[]{savedUserCertificate}; when(mockWifiEnterpriseConfig.getClientCertificateAlias()) .thenReturn(savedUserCertificate); when(mKeyStore.list(eq(Credentials.USER_PRIVATE_KEY), anyInt())) .thenReturn(savedUserCertificates); when(mAndroidKeystoreAliasLoader.getKeyCertAliases()) .thenReturn(ImmutableList.of(savedUserCertificate)); } mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, Loading tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java +1 −25 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; Loading @@ -31,8 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.ServiceSpecificException; import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; Loading Loading @@ -74,8 +71,6 @@ public class WifiConfigControllerTest { private Context mContext; @Mock private AccessPoint mAccessPoint; @Mock private KeyStore mKeyStore; private View mView; private Spinner mHiddenSettingsSpinner; private ShadowSubscriptionManager mShadowSubscriptionManager; Loading Loading @@ -263,28 +258,12 @@ public class WifiConfigControllerTest { assertThat(mController.getSignalString()).isNull(); } @Test public void loadCertificates_keyStoreListFail_shouldNotCrash() { // Set up when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_EAP); when(mKeyStore.list(anyString())) .thenThrow(new ServiceSpecificException(-1, "permission error")); mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, WifiConfigUiBase.MODE_CONNECT); // Verify that the EAP method menu is visible. assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); // No Crash } @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, "prefix", Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -413,9 +392,6 @@ public class WifiConfigControllerTest { boolean isSplitSystemUser() { return false; } @Override KeyStore getKeyStore() { return mKeyStore; } } @Test Loading Loading
src/com/android/settings/utils/AndroidKeystoreAliasLoader.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.utils; import android.os.Process; import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyProperties; import android.security.keystore2.AndroidKeyStoreLoadStoreParameter; import android.util.Log; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.UnrecoverableKeyException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; /** * This class provides a portable and unified way to load the content of AndroidKeyStore through * public API. * @hide */ public class AndroidKeystoreAliasLoader { private static final String TAG = "SettingsKeystoreUtils"; private final Collection<String> mKeyCertAliases; private final Collection<String> mCaCertAliases; /** * This Constructor loads all aliases of asymmetric key pairs and certificates in the * AndroidKeyStore within the given namespace. * Viable namespaces are {@link KeyProperties#NAMESPACE_WIFI}, * {@link KeyProperties#NAMESPACE_APPLICATION}, or null. The latter two are equivalent in * that they will load the keystore content of the app's own namespace. In case of settings, * this is the namespace of the AID_SYSTEM. * * @param namespace {@link KeyProperties#NAMESPACE_WIFI}, * {@link KeyProperties#NAMESPACE_APPLICATION}, or null * @hide */ public AndroidKeystoreAliasLoader(Integer namespace) { mKeyCertAliases = new ArrayList<>(); mCaCertAliases = new ArrayList<>(); KeyStore keyStore = null; final Enumeration<String> aliases; try { if (namespace != null && namespace != KeyProperties.NAMESPACE_APPLICATION) { if (AndroidKeyStoreProvider.isKeystore2Enabled()) { keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(new AndroidKeyStoreLoadStoreParameter(namespace)); } else { // In the legacy case we pass in the WIFI UID because that is the only // possible special namespace that existed as of this writing, // and new namespaces must only be added using the new mechanism. keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(Process.WIFI_UID); } } else { keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); } aliases = keyStore.aliases(); } catch (Exception e) { Log.e(TAG, "Failed to open Android Keystore.", e); // Will return empty lists. return; } while (aliases.hasMoreElements()) { final String alias = aliases.nextElement(); try { final Key key = keyStore.getKey(alias, null); if (key != null) { if (key instanceof PrivateKey) { mKeyCertAliases.add(alias); } } else { if (keyStore.getCertificate(alias) != null) { mCaCertAliases.add(alias); } } } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) { Log.e(TAG, "Failed to load alias: " + alias + " from Android Keystore. Ignoring.", e); } } } /** * Returns the aliases of the key pairs and certificates stored in the Android KeyStore at the * time the constructor was called. * @return Collection of keystore aliases. * @hide */ public Collection<String> getKeyCertAliases() { return mKeyCertAliases; } /** * Returns the aliases of the trusted certificates stored in the Android KeyStore at the * time the constructor was called. * @return Collection of keystore aliases. * @hide */ public Collection<String> getCaCertAliases() { return mCaCertAliases; } }
src/com/android/settings/wifi/WifiConfigController.java +16 −17 Original line number Diff line number Diff line Loading @@ -35,8 +35,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; import android.security.Credentials; import android.security.KeyStore; import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; Loading Loading @@ -73,6 +72,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; Loading @@ -83,7 +83,7 @@ import com.android.settingslib.wifi.AccessPoint; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; Loading Loading @@ -1051,15 +1051,17 @@ public class WifiConfigController implements TextWatcher, if (refreshCertificates) { loadSims(); final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY, androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -1142,10 +1144,13 @@ public class WifiConfigController implements TextWatcher, } else if (caCerts.length == 1) { setSelection(mEapCaCertSpinner, caCerts[0]); } else { final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); // Reload the cert spinner with an extra "multiple certificates added" item. loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); Loading Loading @@ -1464,8 +1469,8 @@ public class WifiConfigController implements TextWatcher, } @VisibleForTesting KeyStore getKeyStore() { return KeyStore.getInstance(); AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting Loading Loading @@ -1509,7 +1514,7 @@ public class WifiConfigController implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, String prefix, Collection<String> choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { Loading @@ -1524,14 +1529,8 @@ public class WifiConfigController implements TextWatcher, certs.add(mUseSystemCertsString); } String[] certificateNames = null; try { certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); } catch (Exception e) { Log.e(TAG, "can't get the certificate list from KeyStore"); } if (certificateNames != null && certificateNames.length != 0) { certs.addAll(Arrays.stream(certificateNames) if (choices != null && choices.size() != 0) { certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { Loading
src/com/android/settings/wifi/WifiConfigController2.java +15 −17 Original line number Diff line number Diff line Loading @@ -33,8 +33,7 @@ import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.IBinder; import android.os.UserManager; import android.security.Credentials; import android.security.KeyStore; import android.security.keystore.KeyProperties; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.text.Editable; Loading Loading @@ -71,6 +70,7 @@ import com.android.net.module.util.NetUtils; import com.android.net.module.util.ProxyUtils; import com.android.settings.ProxySelector; import com.android.settings.R; import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.settings.wifi.details2.WifiPrivacyPreferenceController2; import com.android.settings.wifi.dpp.WifiDppUtils; Loading @@ -83,7 +83,7 @@ import com.android.wifitrackerlib.WifiEntry.ConnectedInfo; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; Loading Loading @@ -1034,15 +1034,17 @@ public class WifiConfigController2 implements TextWatcher, if (refreshCertificates) { loadSims(); final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, false /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); loadCertificates( mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY, androidKeystoreAliasLoader.getKeyCertAliases(), mDoNotProvideEapUserCertString, false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -1127,9 +1129,11 @@ public class WifiConfigController2 implements TextWatcher, setSelection(mEapCaCertSpinner, caCerts[0]); } else { // Reload the cert spinner with an extra "multiple certificates added" item. final AndroidKeystoreAliasLoader androidKeystoreAliasLoader = getAndroidKeystoreAliasLoader(); loadCertificates( mEapCaCertSpinner, Credentials.CA_CERTIFICATE, androidKeystoreAliasLoader.getCaCertAliases(), null /* noCertificateString */, true /* showMultipleCerts */, true /* showUsePreinstalledCertOption */); Loading Loading @@ -1448,8 +1452,8 @@ public class WifiConfigController2 implements TextWatcher, } @VisibleForTesting KeyStore getKeyStore() { return KeyStore.getInstance(); AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { return new AndroidKeystoreAliasLoader(KeyProperties.NAMESPACE_WIFI); } @VisibleForTesting Loading Loading @@ -1493,7 +1497,7 @@ public class WifiConfigController2 implements TextWatcher, @VisibleForTesting void loadCertificates( Spinner spinner, String prefix, Collection<String> choices, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption) { Loading @@ -1508,14 +1512,8 @@ public class WifiConfigController2 implements TextWatcher, certs.add(mUseSystemCertsString); } String[] certificateNames = null; try { certificateNames = getKeyStore().list(prefix, android.os.Process.WIFI_UID); } catch (Exception e) { Log.e(TAG, "can't get the certificate list from KeyStore"); } if (certificateNames != null && certificateNames.length != 0) { certs.addAll(Arrays.stream(certificateNames) if (choices != null && choices.size() != 0) { certs.addAll(choices.stream() .filter(certificateName -> { for (String undesired : UNDESIRED_CERTIFICATES) { if (certificateName.startsWith(undesired)) { Loading
tests/robotests/src/com/android/settings/wifi/WifiConfigController2Test.java +12 −30 Original line number Diff line number Diff line Loading @@ -18,9 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; Loading @@ -33,9 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.ServiceSpecificException; import android.security.Credentials; import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; Loading @@ -50,9 +44,12 @@ import android.widget.TextView; import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowConnectivityManager; import com.android.settings.utils.AndroidKeystoreAliasLoader; import com.android.settings.wifi.details.WifiPrivacyPreferenceController; import com.android.wifitrackerlib.WifiEntry; import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -78,7 +75,7 @@ public class WifiConfigController2Test { @Mock private WifiEntry mWifiEntry; @Mock private KeyStore mKeyStore; private AndroidKeystoreAliasLoader mAndroidKeystoreAliasLoader; private View mView; private Spinner mHiddenSettingsSpinner; private Spinner mEapCaCertSpinner; Loading Loading @@ -284,28 +281,12 @@ public class WifiConfigController2Test { assertThat(mController.getSignalString()).isNull(); } @Test public void loadCertificates_keyStoreListFail_shouldNotCrash() { // Set up when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); when(mKeyStore.list(anyString())) .thenThrow(new ServiceSpecificException(-1, "permission error")); mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, WifiConfigUiBase2.MODE_CONNECT); // Verify that the EAP method menu is visible. assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); // No Crash } @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, "prefix", Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -436,8 +417,8 @@ public class WifiConfigController2Test { } @Override KeyStore getKeyStore() { return mKeyStore; AndroidKeystoreAliasLoader getAndroidKeystoreAliasLoader() { return mAndroidKeystoreAliasLoader; } } Loading Loading @@ -883,6 +864,7 @@ public class WifiConfigController2Test { String savedUserCertificate) { final WifiConfiguration mockWifiConfig = mock(WifiConfiguration.class); final WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class); mockWifiConfig.enterpriseConfig = mockWifiEnterpriseConfig; when(mWifiEntry.isSaved()).thenReturn(true); when(mWifiEntry.getSecurity()).thenReturn(WifiEntry.SECURITY_EAP); Loading @@ -893,15 +875,15 @@ public class WifiConfigController2Test { String[] savedCaCertificates = new String[]{savedCaCertificate}; when(mockWifiEnterpriseConfig.getCaCertificateAliases()) .thenReturn(savedCaCertificates); when(mKeyStore.list(eq(Credentials.CA_CERTIFICATE), anyInt())) .thenReturn(savedCaCertificates); when(mAndroidKeystoreAliasLoader.getCaCertAliases()) .thenReturn(ImmutableList.of(savedCaCertificate)); } if (savedUserCertificate != null) { String[] savedUserCertificates = new String[]{savedUserCertificate}; when(mockWifiEnterpriseConfig.getClientCertificateAlias()) .thenReturn(savedUserCertificate); when(mKeyStore.list(eq(Credentials.USER_PRIVATE_KEY), anyInt())) .thenReturn(savedUserCertificates); when(mAndroidKeystoreAliasLoader.getKeyCertAliases()) .thenReturn(ImmutableList.of(savedUserCertificate)); } mController = new TestWifiConfigController2(mConfigUiBase, mView, mWifiEntry, Loading
tests/robotests/src/com/android/settings/wifi/WifiConfigControllerTest.java +1 −25 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.settings.wifi; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; Loading @@ -31,8 +30,6 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; import android.net.wifi.WifiManager; import android.os.ServiceSpecificException; import android.security.KeyStore; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; Loading Loading @@ -74,8 +71,6 @@ public class WifiConfigControllerTest { private Context mContext; @Mock private AccessPoint mAccessPoint; @Mock private KeyStore mKeyStore; private View mView; private Spinner mHiddenSettingsSpinner; private ShadowSubscriptionManager mShadowSubscriptionManager; Loading Loading @@ -263,28 +258,12 @@ public class WifiConfigControllerTest { assertThat(mController.getSignalString()).isNull(); } @Test public void loadCertificates_keyStoreListFail_shouldNotCrash() { // Set up when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_EAP); when(mKeyStore.list(anyString())) .thenThrow(new ServiceSpecificException(-1, "permission error")); mController = new TestWifiConfigController(mConfigUiBase, mView, mAccessPoint, WifiConfigUiBase.MODE_CONNECT); // Verify that the EAP method menu is visible. assertThat(mView.findViewById(R.id.eap).getVisibility()).isEqualTo(View.VISIBLE); // No Crash } @Test public void loadCertificates_undesiredCertificates_shouldNotLoadUndesiredCertificates() { final Spinner spinner = new Spinner(mContext); when(mKeyStore.list(anyString())).thenReturn(WifiConfigController.UNDESIRED_CERTIFICATES); mController.loadCertificates(spinner, "prefix", Arrays.asList(WifiConfigController.UNDESIRED_CERTIFICATES), "doNotProvideEapUserCertString", false /* showMultipleCerts */, false /* showUsePreinstalledCertOption */); Loading Loading @@ -413,9 +392,6 @@ public class WifiConfigControllerTest { boolean isSplitSystemUser() { return false; } @Override KeyStore getKeyStore() { return mKeyStore; } } @Test Loading