wifi: remove certificates for network factory reset

When a user does network factory reset, wifi certificate should
also be cleared as these certificates are also personal credentials.

Bug: 231985227
Test: atest FrameworksWifiTests
Merged-In: I0334064347080e43096d01f00cf516804812d0c0
Change-Id: I0334064347080e43096d01f00cf516804812d0c0
(cherry picked from commit dbf6810cd00ae78802997077633f5bd441fa1f20)
Merged-In: I0334064347080e43096d01f00cf516804812d0c0
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index c0cb899..a8bfc82 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -1388,7 +1388,7 @@
         // will remove the enterprise keys when provider is uninstalled. Suggestion enterprise
         // networks will remove the enterprise keys when suggestion is removed.
         if (!config.fromWifiNetworkSuggestion && !config.isPasspoint() && config.isEnterprise()) {
-            mWifiKeyStore.removeKeys(config.enterpriseConfig);
+            mWifiKeyStore.removeKeys(config.enterpriseConfig, false);
         }
 
         removeConnectChoiceFromAllNetworks(config.getKey());
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 5531c4e..385b2dc 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -847,4 +847,9 @@
     public DeviceConfigFacade getDeviceConfigFacade() {
         return mDeviceConfigFacade;
     }
+
+    @NonNull
+    public WifiKeyStore getWifiKeyStore() {
+        return mWifiKeyStore;
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiKeyStore.java b/service/java/com/android/server/wifi/WifiKeyStore.java
index 70daa0d..08a101f 100644
--- a/service/java/com/android/server/wifi/WifiKeyStore.java
+++ b/service/java/com/android/server/wifi/WifiKeyStore.java
@@ -200,11 +200,12 @@
      * Remove enterprise keys from the network config.
      *
      * @param config Config corresponding to the network.
+     * @param forceRemove remove keys regardless of the key installer.
      */
-    public void removeKeys(WifiEnterpriseConfig config) {
+    public void removeKeys(WifiEnterpriseConfig config, boolean forceRemove) {
         Preconditions.checkNotNull(mKeyStore);
         // Do not remove keys that were manually installed by the user
-        if (config.isAppInstalledDeviceKeyAndCert()) {
+        if (forceRemove || config.isAppInstalledDeviceKeyAndCert()) {
             String client = config.getClientCertificateAlias();
             // a valid client certificate is configured
             if (!TextUtils.isEmpty(client)) {
@@ -218,7 +219,7 @@
         }
 
         // Do not remove CA certs that were manually installed by the user
-        if (config.isAppInstalledCaCert()) {
+        if (forceRemove || config.isAppInstalledCaCert()) {
             String[] aliases = config.getCaCertificateAliases();
             if (aliases == null || aliases.length == 0) {
                 return;
diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
index 2632835..1904b2b 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java
@@ -1095,7 +1095,7 @@
                 removeFromPassPointInfoMap(ewns);
             } else {
                 if (ewns.wns.wifiConfiguration.isEnterprise()) {
-                    mWifiKeyStore.removeKeys(ewns.wns.wifiConfiguration.enterpriseConfig);
+                    mWifiKeyStore.removeKeys(ewns.wns.wifiConfiguration.enterpriseConfig, false);
                 }
                 removeFromScanResultMatchInfoMapAndRemoveRelatedScoreCard(ewns);
             }
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 20e82d8..4b57036 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -103,6 +103,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.MutableBoolean;
 
@@ -3443,7 +3444,14 @@
         List<WifiConfiguration> networks = mWifiThreadRunner.call(
                 () -> mWifiConfigManager.getSavedNetworks(Process.WIFI_UID),
                 Collections.emptyList());
+        EventLog.writeEvent(0x534e4554, "231985227", -1,
+                "Remove certs for factory reset");
         for (WifiConfiguration network : networks) {
+            if (network.isEnterprise()) {
+                mWifiThreadRunner.run(() ->
+                        mWifiInjector.getWifiKeyStore()
+                                .removeKeys(network.enterpriseConfig, true));
+            }
             removeNetwork(network.networkId, packageName);
         }
         // Delete all Passpoint configurations
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index 9d96116..84c9a73 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -900,7 +900,7 @@
         assertEquals(suggestionNetwork.networkId, wifiConfigCaptor.getValue().networkId);
         assertTrue(mWifiConfigManager
                 .removeNetwork(suggestionNetwork.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME));
-        verify(mWifiKeyStore, never()).removeKeys(any());
+        verify(mWifiKeyStore, never()).removeKeys(any(), eq(false));
     }
 
     /**
@@ -1158,7 +1158,7 @@
                 passpointNetwork.networkId, Process.WIFI_UID, null));
 
         // Verify keys are not being removed.
-        verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class));
+        verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class), eq(false));
         verifyNetworkRemoveBroadcast();
         // Ensure that the write was not invoked for Passpoint network remove.
         mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
@@ -5212,7 +5212,7 @@
                 configuration.networkId, TEST_CREATOR_UID, TEST_CREATOR_NAME));
 
         // Verify keys are not being removed.
-        verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class));
+        verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class), eq(false));
         verifyNetworkRemoveBroadcast();
         // Ensure that the write was not invoked for Passpoint network remove.
         mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
index 8eef7e7..c7d0d0c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
@@ -93,7 +93,7 @@
     public void testRemoveKeysForAppInstalledCerts() throws Exception {
         when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(true);
         when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(true);
-        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig, false);
 
         // Method calls the KeyStore#delete method 4 times, user key, user cert, and 2 CA cert
         verify(mKeyStore).deleteEntry(USER_CERT_ALIAS);
@@ -108,7 +108,7 @@
     public void testRemoveKeysForMixedInstalledCerts1() throws Exception {
         when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(true);
         when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(false);
-        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig, false);
 
         // Method calls the KeyStore#deleteEntry method: user key and user cert
         verify(mKeyStore).deleteEntry(USER_CERT_ALIAS);
@@ -123,7 +123,7 @@
     public void testRemoveKeysForMixedInstalledCerts2() throws Exception {
         when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(false);
         when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(true);
-        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig, false);
 
         // Method calls the KeyStore#delete method 2 times: 2 CA certs
         verify(mKeyStore).deleteEntry(USER_CA_CERT_ALIASES[0]);
@@ -138,7 +138,24 @@
     public void testRemoveKeysForUserInstalledCerts() {
         when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(false);
         when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(false);
-        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig);
+        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig, false);
+        verifyNoMoreInteractions(mKeyStore);
+    }
+
+    /**
+     * Verifies that keys and certs are removed when they were not installed by the user
+     * when forceRemove is true.
+     */
+    @Test
+    public void testForceRemoveKeysForUserInstalledCerts() throws Exception {
+        when(mWifiEnterpriseConfig.isAppInstalledDeviceKeyAndCert()).thenReturn(false);
+        when(mWifiEnterpriseConfig.isAppInstalledCaCert()).thenReturn(false);
+        mWifiKeyStore.removeKeys(mWifiEnterpriseConfig, true);
+
+        // KeyStore#deleteEntry() is called three time for user cert, and 2 CA cert.
+        verify(mKeyStore).deleteEntry(USER_CERT_ALIAS);
+        verify(mKeyStore).deleteEntry(USER_CA_CERT_ALIASES[0]);
+        verify(mKeyStore).deleteEntry(USER_CA_CERT_ALIASES[1]);
         verifyNoMoreInteractions(mKeyStore);
     }
 
@@ -212,8 +229,8 @@
         WifiConfiguration suggestionNetwork = new WifiConfiguration(savedNetwork);
         suggestionNetwork.fromWifiNetworkSuggestion = true;
         suggestionNetwork.creatorName = TEST_PACKAGE_NAME;
-        mWifiKeyStore.removeKeys(savedNetwork.enterpriseConfig);
-        mWifiKeyStore.removeKeys(suggestionNetwork.enterpriseConfig);
+        mWifiKeyStore.removeKeys(savedNetwork.enterpriseConfig, false);
+        mWifiKeyStore.removeKeys(suggestionNetwork.enterpriseConfig, false);
         verify(mKeyStore, never()).deleteEntry(any());
     }
 
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
index fd27dcc..97d4f37 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSuggestionsManagerTest.java
@@ -428,7 +428,8 @@
                         new ArrayList<WifiNetworkSuggestion>() {{ add(removingSuggestion); }},
                         TEST_UID_1, TEST_PACKAGE_1));
         // Make sure remove the keyStore with the internal config
-        verify(mWifiKeyStore).removeKeys(networkSuggestion1.wifiConfiguration.enterpriseConfig);
+        verify(mWifiKeyStore).removeKeys(networkSuggestion1.wifiConfiguration.enterpriseConfig,
+                false);
         verify(mLruConnectionTracker).removeNetwork(any());
     }
 
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 55f35e3..87e09ac 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -316,6 +316,7 @@
     @Mock WifiSettingsConfigStore mWifiSettingsConfigStore;
     @Mock WifiScanAlwaysAvailableSettingsCompatibility mScanAlwaysAvailableSettingsCompatibility;
     @Mock PackageInfo mPackageInfo;
+    @Mock WifiKeyStore mWifiKeyStore;
 
     WifiLog mLog = new LogcatLog(TAG);
 
@@ -409,6 +410,7 @@
         when(mScanRequestProxy.startScan(anyInt(), anyString())).thenReturn(true);
         when(mLohsCallback.asBinder()).thenReturn(mock(IBinder.class));
         when(mWifiSettingsConfigStore.get(eq(WIFI_VERBOSE_LOGGING_ENABLED))).thenReturn(true);
+        when(mWifiInjector.getWifiKeyStore()).thenReturn(mWifiKeyStore);
 
         mWifiServiceImpl = makeWifiServiceImpl();
         mDppCallback = new IDppCallback() {
@@ -4189,7 +4191,11 @@
                 anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
         when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
         final String fqdn = "example.com";
-        WifiConfiguration network = WifiConfigurationTestUtil.createOpenNetwork();
+        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.networkId = TEST_NETWORK_ID;
+        WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork(
+                WifiEnterpriseConfig.Eap.TLS, WifiEnterpriseConfig.Phase2.NONE);
+        eapNetwork.networkId = TEST_NETWORK_ID + 1;
         PasspointConfiguration config = new PasspointConfiguration();
         HomeSp homeSp = new HomeSp();
         homeSp.setFqdn(fqdn);
@@ -4200,7 +4206,7 @@
 
         mWifiServiceImpl.mClientModeImplChannel = mAsyncChannel;
         when(mWifiConfigManager.getSavedNetworks(anyInt()))
-                .thenReturn(Arrays.asList(network));
+                .thenReturn(Arrays.asList(openNetwork, eapNetwork));
         when(mPasspointManager.getProviderConfigs(anyInt(), anyBoolean()))
                 .thenReturn(Arrays.asList(config));
 
@@ -4212,7 +4218,10 @@
         mLooper.dispatchAll();
 
         verify(mWifiConfigManager).removeNetwork(
-                network.networkId, Binder.getCallingUid(), TEST_PACKAGE_NAME);
+                openNetwork.networkId, Binder.getCallingUid(), TEST_PACKAGE_NAME);
+        verify(mWifiConfigManager).removeNetwork(
+                eapNetwork.networkId, Binder.getCallingUid(), TEST_PACKAGE_NAME);
+        verify(mWifiKeyStore).removeKeys(eapNetwork.enterpriseConfig, true);
         verify(mPasspointManager).removeProvider(anyInt(), anyBoolean(), eq(config.getUniqueId()),
                 isNull());
         verify(mPasspointManager).clearAnqpRequestsAndFlushCache();