diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-11-17 00:10:45 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-11-17 00:10:45 +0000 |
commit | d5f40d3862d639684672bdba709ca598c9d0e248 (patch) | |
tree | 8bb3ec31fbb2e671d51aef48afdc9a1ed6b3fe8a | |
parent | 7ebfe807c4ef8c41ea13fca1cb844c0f3b6e8fb4 (diff) | |
parent | a9ebe48227eb5befd221451a013cbd0a76eac999 (diff) | |
download | android_frameworks_opt_net_wifi-d5f40d3862d639684672bdba709ca598c9d0e248.tar.gz android_frameworks_opt_net_wifi-d5f40d3862d639684672bdba709ca598c9d0e248.tar.bz2 android_frameworks_opt_net_wifi-d5f40d3862d639684672bdba709ca598c9d0e248.zip |
Snap for 6013205 from a9ebe48227eb5befd221451a013cbd0a76eac999 to qt-qpr2-release
Change-Id: I16793ede4d0cdb517d5c7a546476eb36c10da8e3
31 files changed, 877 insertions, 896 deletions
diff --git a/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java b/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java index 0c064884c..b71d5a023 100644 --- a/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java +++ b/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java @@ -16,6 +16,9 @@ package com.android.server.wifi; +import android.annotation.Nullable; + +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; @@ -44,7 +47,8 @@ public class DeletedEphemeralSsidsStoreData implements WifiConfigStore.StoreData } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { if (mSsidToTimeMap != null) { XmlUtil.writeNextValue(out, XML_TAG_SSID_LIST, mSsidToTimeMap); @@ -52,7 +56,9 @@ public class DeletedEphemeralSsidsStoreData implements WifiConfigStore.StoreData } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { diff --git a/service/java/com/android/server/wifi/FrameworkFacade.java b/service/java/com/android/server/wifi/FrameworkFacade.java index f3c5d4b3d..4fbe31867 100644 --- a/service/java/com/android/server/wifi/FrameworkFacade.java +++ b/service/java/com/android/server/wifi/FrameworkFacade.java @@ -45,6 +45,11 @@ import com.android.server.wifi.util.WifiAsyncChannel; */ public class FrameworkFacade { public static final String TAG = "FrameworkFacade"; + /** + * NIAP global settings flag. + * Note: This should be added to {@link android.provider.Settings.Global}. + */ + private static final String NIAP_MODE_SETTINGS_NAME = "niap_mode"; private ActivityManagerInternal mActivityManagerInternal; @@ -83,6 +88,13 @@ public class FrameworkFacade { } /** + * Returns whether the device is in NIAP mode or not. + */ + public boolean isNiapModeOn(Context context) { + return getIntegerSetting(context, NIAP_MODE_SETTINGS_NAME, 0) == 1; + } + + /** * Helper method for classes to register a ContentObserver * {@see ContentResolver#registerContentObserver(Uri,boolean,ContentObserver)}. * diff --git a/service/java/com/android/server/wifi/NetworkListStoreData.java b/service/java/com/android/server/wifi/NetworkListStoreData.java index 696647185..52e655b1e 100644 --- a/service/java/com/android/server/wifi/NetworkListStoreData.java +++ b/service/java/com/android/server/wifi/NetworkListStoreData.java @@ -16,6 +16,9 @@ package com.android.server.wifi; +import static com.android.server.wifi.WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION; + +import android.annotation.Nullable; import android.content.Context; import android.net.IpConfiguration; import android.net.wifi.WifiConfiguration; @@ -25,6 +28,7 @@ import android.os.Process; import android.util.Log; import android.util.Pair; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil; import com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil; @@ -66,19 +70,22 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { - serializeNetworkList(out, mConfigurations); + serializeNetworkList(out, mConfigurations, encryptionUtil); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { return; } - mConfigurations = parseNetworkList(in, outerTagDepth); + mConfigurations = parseNetworkList(in, outerTagDepth, version, encryptionUtil); } @Override @@ -118,33 +125,38 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData * * @param out The output stream to serialize the data to * @param networkList The network list to serialize + * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} * @throws XmlPullParserException * @throws IOException */ - private void serializeNetworkList(XmlSerializer out, List<WifiConfiguration> networkList) + private void serializeNetworkList(XmlSerializer out, List<WifiConfiguration> networkList, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { if (networkList == null) { return; } for (WifiConfiguration network : networkList) { - serializeNetwork(out, network); + serializeNetwork(out, network, encryptionUtil); } } /** * Serialize a {@link WifiConfiguration} to an output stream in XML format. - * @param out - * @param config + * + * @param out The output stream to serialize the data to + * @param config The network config to serialize + * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} * @throws XmlPullParserException * @throws IOException */ - private void serializeNetwork(XmlSerializer out, WifiConfiguration config) + private void serializeNetwork(XmlSerializer out, WifiConfiguration config, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK); // Serialize WifiConfiguration. XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, config); + WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, config, encryptionUtil); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); // Serialize network selection status. @@ -162,7 +174,7 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) { XmlUtil.writeNextSectionStart( out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); - WifiEnterpriseConfigXmlUtil.writeToXml(out, config.enterpriseConfig); + WifiEnterpriseConfigXmlUtil.writeToXml(out, config.enterpriseConfig, encryptionUtil); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); } @@ -174,11 +186,15 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData * * @param in The input stream to read from * @param outerTagDepth The XML tag depth of the outer XML block + * @param version Version of config store file. + * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} * @return List of {@link WifiConfiguration} * @throws XmlPullParserException * @throws IOException */ - private List<WifiConfiguration> parseNetworkList(XmlPullParser in, int outerTagDepth) + private List<WifiConfiguration> parseNetworkList(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { List<WifiConfiguration> networkList = new ArrayList<>(); while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_NETWORK, @@ -186,7 +202,8 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are // fatal and should abort the entire loading process. try { - WifiConfiguration config = parseNetwork(in, outerTagDepth + 1); + WifiConfiguration config = + parseNetwork(in, outerTagDepth + 1, version, encryptionUtil); networkList.add(config); } catch (RuntimeException e) { // Failed to parse this network, skip it. @@ -201,11 +218,15 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData * * @param in The input stream to read from * @param outerTagDepth The XML tag depth of the outer XML block + * @param version Version of config store file. + * @param encryptionUtil Instance of {@link WifiConfigStoreEncryptionUtil} * @return {@link WifiConfiguration} * @throws XmlPullParserException * @throws IOException */ - private WifiConfiguration parseNetwork(XmlPullParser in, int outerTagDepth) + private WifiConfiguration parseNetwork(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { Pair<String, WifiConfiguration> parsedConfig = null; NetworkSelectionStatus status = null; @@ -220,7 +241,9 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData throw new XmlPullParserException("Detected duplicate tag for: " + XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); } - parsedConfig = WifiConfigurationXmlUtil.parseFromXml(in, outerTagDepth + 1); + parsedConfig = WifiConfigurationXmlUtil.parseFromXml(in, outerTagDepth + 1, + version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + encryptionUtil); break; case XML_TAG_SECTION_HEADER_NETWORK_STATUS: if (status != null) { @@ -242,7 +265,9 @@ public abstract class NetworkListStoreData implements WifiConfigStore.StoreData + XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); } enterpriseConfig = - WifiEnterpriseConfigXmlUtil.parseFromXml(in, outerTagDepth + 1); + WifiEnterpriseConfigXmlUtil.parseFromXml(in, outerTagDepth + 1, + version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + encryptionUtil); break; default: throw new XmlPullParserException("Unknown tag under " diff --git a/service/java/com/android/server/wifi/NetworkRequestStoreData.java b/service/java/com/android/server/wifi/NetworkRequestStoreData.java index 8d1244f05..7457079ae 100644 --- a/service/java/com/android/server/wifi/NetworkRequestStoreData.java +++ b/service/java/com/android/server/wifi/NetworkRequestStoreData.java @@ -16,10 +16,12 @@ package com.android.server.wifi; +import android.annotation.Nullable; import android.net.MacAddress; import android.util.Log; import com.android.server.wifi.WifiNetworkFactory.AccessPoint; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; @@ -87,13 +89,16 @@ public class NetworkRequestStoreData implements WifiConfigStore.StoreData { } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { serializeApprovedAccessPointsMap(out, mDataSource.toSerialize()); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { diff --git a/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java b/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java index 9627a9daa..e973bdbe2 100644 --- a/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java +++ b/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java @@ -16,6 +16,9 @@ package com.android.server.wifi; +import static com.android.server.wifi.WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION; + +import android.annotation.Nullable; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiNetworkSuggestion; @@ -26,6 +29,7 @@ import android.util.Pair; import com.android.internal.util.XmlUtils; import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; @@ -98,19 +102,23 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { - serializeNetworkSuggestionsMap(out, mDataSource.toSerialize()); + serializeNetworkSuggestionsMap(out, mDataSource.toSerialize(), encryptionUtil); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { return; } - mDataSource.fromDeserialized(parseNetworkSuggestionsMap(in, outerTagDepth)); + mDataSource.fromDeserialized( + parseNetworkSuggestionsMap(in, outerTagDepth, version, encryptionUtil)); } @Override @@ -140,7 +148,8 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { * @throws IOException */ private void serializeNetworkSuggestionsMap( - XmlSerializer out, final Map<String, PerAppInfo> networkSuggestionsMap) + XmlSerializer out, final Map<String, PerAppInfo> networkSuggestionsMap, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { if (networkSuggestionsMap == null) { return; @@ -155,7 +164,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_PACKAGE_NAME, packageName); XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_HAS_USER_APPROVED, hasUserApproved); XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_MAX_SIZE, maxSize); - serializeExtNetworkSuggestions(out, networkSuggestions); + serializeExtNetworkSuggestions(out, networkSuggestions, encryptionUtil); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP); } } @@ -167,10 +176,11 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { * @throws IOException */ private void serializeExtNetworkSuggestions( - XmlSerializer out, final Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions) + XmlSerializer out, final Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { for (ExtendedWifiNetworkSuggestion extNetworkSuggestion : extNetworkSuggestions) { - serializeNetworkSuggestion(out, extNetworkSuggestion.wns); + serializeNetworkSuggestion(out, extNetworkSuggestion.wns, encryptionUtil); } } @@ -181,13 +191,15 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { * @throws IOException */ private void serializeNetworkSuggestion(XmlSerializer out, - final WifiNetworkSuggestion suggestion) + final WifiNetworkSuggestion suggestion, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION); // Serialize WifiConfiguration. XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); - WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, suggestion.wifiConfiguration); + WifiConfigurationXmlUtil.writeToXmlForConfigStore( + out, suggestion.wifiConfiguration, encryptionUtil); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); // Serialize enterprise configuration for enterprise networks. if (suggestion.wifiConfiguration.enterpriseConfig != null @@ -196,7 +208,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { XmlUtil.writeNextSectionStart( out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); XmlUtil.WifiEnterpriseConfigXmlUtil.writeToXml( - out, suggestion.wifiConfiguration.enterpriseConfig); + out, suggestion.wifiConfiguration.enterpriseConfig, encryptionUtil); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); } @@ -218,7 +230,9 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { * @throws XmlPullParserException * @throws IOException */ - private Map<String, PerAppInfo> parseNetworkSuggestionsMap(XmlPullParser in, int outerTagDepth) + private Map<String, PerAppInfo> parseNetworkSuggestionsMap(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { Map<String, PerAppInfo> networkSuggestionsMap = new HashMap<>(); while (XmlUtil.gotoNextSectionWithNameOrEnd( @@ -233,7 +247,8 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { int maxSize = (int) XmlUtil.readNextValueWithName(in, XML_TAG_SUGGESTOR_MAX_SIZE); PerAppInfo perAppInfo = new PerAppInfo(packageName); Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = - parseExtNetworkSuggestions(in, outerTagDepth + 1, perAppInfo); + parseExtNetworkSuggestions( + in, outerTagDepth + 1, version, encryptionUtil, perAppInfo); perAppInfo.hasUserApproved = hasUserApproved; perAppInfo.maxSize = maxSize; perAppInfo.extNetworkSuggestions.addAll(extNetworkSuggestions); @@ -253,7 +268,8 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { * @throws IOException */ private Set<ExtendedWifiNetworkSuggestion> parseExtNetworkSuggestions( - XmlPullParser in, int outerTagDepth, PerAppInfo perAppInfo) + XmlPullParser in, int outerTagDepth, @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, PerAppInfo perAppInfo) throws XmlPullParserException, IOException { Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = new HashSet<>(); while (XmlUtil.gotoNextSectionWithNameOrEnd( @@ -262,7 +278,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { // fatal and should abort the entire loading process. try { WifiNetworkSuggestion networkSuggestion = - parseNetworkSuggestion(in, outerTagDepth + 1); + parseNetworkSuggestion(in, outerTagDepth + 1, version, encryptionUtil); extNetworkSuggestions.add(ExtendedWifiNetworkSuggestion.fromWns( networkSuggestion, perAppInfo)); } catch (RuntimeException e) { @@ -279,7 +295,9 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { * @throws XmlPullParserException * @throws IOException */ - private WifiNetworkSuggestion parseNetworkSuggestion(XmlPullParser in, int outerTagDepth) + private WifiNetworkSuggestion parseNetworkSuggestion(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { Pair<String, WifiConfiguration> parsedConfig = null; WifiEnterpriseConfig enterpriseConfig = null; @@ -324,7 +342,9 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { + XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION); } parsedConfig = WifiConfigurationXmlUtil.parseFromXml( - in, outerTagDepth + 1); + in, outerTagDepth + 1, + version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + encryptionUtil); break; case XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION: if (enterpriseConfig != null) { @@ -332,7 +352,9 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { + XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION); } enterpriseConfig = XmlUtil.WifiEnterpriseConfigXmlUtil.parseFromXml( - in, outerTagDepth + 1); + in, outerTagDepth + 1, + version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + encryptionUtil); break; default: throw new XmlPullParserException("Unknown tag under " diff --git a/service/java/com/android/server/wifi/RandomizedMacStoreData.java b/service/java/com/android/server/wifi/RandomizedMacStoreData.java index 1e4d972ef..ecbd7177f 100644 --- a/service/java/com/android/server/wifi/RandomizedMacStoreData.java +++ b/service/java/com/android/server/wifi/RandomizedMacStoreData.java @@ -16,6 +16,9 @@ package com.android.server.wifi; +import android.annotation.Nullable; + +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; @@ -40,7 +43,8 @@ public class RandomizedMacStoreData implements WifiConfigStore.StoreData { RandomizedMacStoreData() {} @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { if (mMacMapping != null) { XmlUtil.writeNextValue(out, XML_TAG_MAC_MAP, mMacMapping); @@ -48,7 +52,9 @@ public class RandomizedMacStoreData implements WifiConfigStore.StoreData { } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { diff --git a/service/java/com/android/server/wifi/SsidSetStoreData.java b/service/java/com/android/server/wifi/SsidSetStoreData.java index 7d1b99340..36b547cd2 100644 --- a/service/java/com/android/server/wifi/SsidSetStoreData.java +++ b/service/java/com/android/server/wifi/SsidSetStoreData.java @@ -16,8 +16,10 @@ package com.android.server.wifi; +import android.annotation.Nullable; import android.text.TextUtils; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; @@ -74,7 +76,8 @@ public class SsidSetStoreData implements WifiConfigStore.StoreData { } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { Set<String> ssidSet = mDataSource.getSsids(); if (ssidSet != null && !ssidSet.isEmpty()) { @@ -83,7 +86,9 @@ public class SsidSetStoreData implements WifiConfigStore.StoreData { } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { diff --git a/service/java/com/android/server/wifi/WakeupConfigStoreData.java b/service/java/com/android/server/wifi/WakeupConfigStoreData.java index d191ee3d6..847d8fbbc 100644 --- a/service/java/com/android/server/wifi/WakeupConfigStoreData.java +++ b/service/java/com/android/server/wifi/WakeupConfigStoreData.java @@ -16,10 +16,12 @@ package com.android.server.wifi; +import android.annotation.Nullable; import android.util.ArraySet; import android.util.Log; import com.android.server.wifi.WifiConfigStore.StoreData; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; @@ -94,7 +96,8 @@ public class WakeupConfigStoreData implements StoreData { } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { writeFeatureState(out); @@ -141,7 +144,9 @@ public class WakeupConfigStoreData implements StoreData { } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { if (!mHasBeenRead) { Log.d(TAG, "WifiWake user data has been read"); diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index d1734d445..533155d0c 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -3131,7 +3131,8 @@ public class WifiConfigManager { if (mDeferredUserUnlockRead) { Log.i(TAG, "Handling user unlock before loading from store."); List<WifiConfigStore.StoreFile> userStoreFiles = - WifiConfigStore.createUserFiles(mCurrentUserId); + WifiConfigStore.createUserFiles( + mCurrentUserId, mFrameworkFacade.isNiapModeOn(mContext)); if (userStoreFiles == null) { Log.wtf(TAG, "Failed to create user store files"); return false; @@ -3170,7 +3171,8 @@ public class WifiConfigManager { private boolean loadFromUserStoreAfterUnlockOrSwitch(int userId) { try { List<WifiConfigStore.StoreFile> userStoreFiles = - WifiConfigStore.createUserFiles(userId); + WifiConfigStore.createUserFiles( + userId, mFrameworkFacade.isNiapModeOn(mContext)); if (userStoreFiles == null) { Log.e(TAG, "Failed to create user store files"); return false; @@ -3180,8 +3182,8 @@ public class WifiConfigManager { Log.wtf(TAG, "Reading from new store failed. All saved private networks are lost!", e); return false; } catch (XmlPullParserException e) { - Log.wtf(TAG, "XML deserialization of store failed. All saved private networks are" + - "lost!", e); + Log.wtf(TAG, "XML deserialization of store failed. All saved private networks are " + + "lost!", e); return false; } loadInternalDataFromUserStore(mNetworkListUserStoreData.getConfigurations(), diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java index e189d00e1..42d9f82cb 100644 --- a/service/java/com/android/server/wifi/WifiConfigStore.java +++ b/service/java/com/android/server/wifi/WifiConfigStore.java @@ -35,8 +35,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.AtomicFile; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.Preconditions; -import com.android.server.wifi.util.DataIntegrityChecker; import com.android.server.wifi.util.EncryptedData; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; @@ -53,7 +53,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -62,6 +61,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * This class provides a mechanism to save data to persistent store files {@link StoreFile}. @@ -101,22 +101,36 @@ public class WifiConfigStore { private static final String XML_TAG_DOCUMENT_HEADER = "WifiConfigStoreData"; private static final String XML_TAG_VERSION = "Version"; private static final String XML_TAG_HEADER_INTEGRITY = "Integrity"; - private static final String XML_TAG_INTEGRITY_ENCRYPTED_DATA = "EncryptedData"; - private static final String XML_TAG_INTEGRITY_IV = "IV"; /** * Current config store data version. This will be incremented for any additions. */ - private static final int CURRENT_CONFIG_STORE_DATA_VERSION = 2; + private static final int CURRENT_CONFIG_STORE_DATA_VERSION = 3; /** This list of older versions will be used to restore data from older config store. */ /** * First version of the config store data format. */ - private static final int INITIAL_CONFIG_STORE_DATA_VERSION = 1; + public static final int INITIAL_CONFIG_STORE_DATA_VERSION = 1; /** * Second version of the config store data format, introduced: * - Integrity info. */ - private static final int INTEGRITY_CONFIG_STORE_DATA_VERSION = 2; + public static final int INTEGRITY_CONFIG_STORE_DATA_VERSION = 2; + /** + * Third version of the config store data format, + * introduced: + * - Encryption of credentials + * removed: + * - Integrity info. + */ + public static final int ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION = 3; + + @IntDef(suffix = { "_VERSION" }, value = { + INITIAL_CONFIG_STORE_DATA_VERSION, + INTEGRITY_CONFIG_STORE_DATA_VERSION, + ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Version { } /** * Alarm tag to use for starting alarms for buffering file writes. @@ -157,12 +171,6 @@ public class WifiConfigStore { put(STORE_FILE_USER_GENERAL, STORE_FILE_NAME_USER_GENERAL); put(STORE_FILE_USER_NETWORK_SUGGESTIONS, STORE_FILE_NAME_USER_NETWORK_SUGGESTIONS); }}; - - @VisibleForTesting - public static final EncryptedData ZEROED_ENCRYPTED_DATA = - new EncryptedData( - new byte[EncryptedData.ENCRYPTED_DATA_LENGTH], - new byte[EncryptedData.IV_LENGTH]); /** * Handler instance to post alarm timeouts to */ @@ -280,9 +288,11 @@ public class WifiConfigStore { * @param storeBaseDir Base directory under which the store file is to be stored. The store file * will be at <storeBaseDir>/wifi/WifiConfigStore.xml. * @param fileId Identifier for the file. See {@link StoreFileId}. + * @param shouldEncryptCredentials Whether to encrypt credentials or not. * @return new instance of the store file or null if the directory cannot be created. */ - private static @Nullable StoreFile createFile(File storeBaseDir, @StoreFileId int fileId) { + private static @Nullable StoreFile createFile(File storeBaseDir, @StoreFileId int fileId, + boolean shouldEncryptCredentials) { File storeDir = new File(storeBaseDir, STORE_DIRECTORY_NAME); if (!storeDir.exists()) { if (!storeDir.mkdir()) { @@ -291,17 +301,22 @@ public class WifiConfigStore { } } File file = new File(storeDir, STORE_ID_TO_FILE_NAME.get(fileId)); - DataIntegrityChecker dataIntegrityChecker = new DataIntegrityChecker(file.getName()); - return new StoreFile(file, fileId, dataIntegrityChecker); + WifiConfigStoreEncryptionUtil encryptionUtil = null; + if (shouldEncryptCredentials) { + encryptionUtil = new WifiConfigStoreEncryptionUtil(file.getName()); + } + return new StoreFile(file, fileId, encryptionUtil); } /** * Create a new instance of the shared store file. * + * @param shouldEncryptCredentials Whether to encrypt credentials or not. * @return new instance of the store file or null if the directory cannot be created. */ - public static @Nullable StoreFile createSharedFile() { - return createFile(Environment.getDataMiscDirectory(), STORE_FILE_SHARED_GENERAL); + public static @Nullable StoreFile createSharedFile(boolean shouldEncryptCredentials) { + return createFile(Environment.getDataMiscDirectory(), STORE_FILE_SHARED_GENERAL, + shouldEncryptCredentials); } /** @@ -309,14 +324,18 @@ public class WifiConfigStore { * The user store file is inside the user's encrypted data directory. * * @param userId userId corresponding to the currently logged-in user. + * @param shouldEncryptCredentials Whether to encrypt credentials or not. * @return List of new instances of the store files created or null if the directory cannot be * created. */ - public static @Nullable List<StoreFile> createUserFiles(int userId) { + public static @Nullable List<StoreFile> createUserFiles(int userId, + boolean shouldEncryptCredentials) { List<StoreFile> storeFiles = new ArrayList<>(); for (int fileId : Arrays.asList( STORE_FILE_USER_GENERAL, STORE_FILE_USER_NETWORK_SUGGESTIONS)) { - StoreFile storeFile = createFile(Environment.getDataMiscCeDirectory(userId), fileId); + StoreFile storeFile = + createFile(Environment.getDataMiscCeDirectory(userId), fileId, + shouldEncryptCredentials); if (storeFile == null) { return null; } @@ -427,88 +446,18 @@ public class WifiConfigStore { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - // To compute integrity, write zeroes in the integrity fields. Once the integrity is - // computed, go back and modfiy the XML fields in place with the computed values. - writeDocumentMetadata(out, ZEROED_ENCRYPTED_DATA); + // First XML header. + XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER); + // Next version. + XmlUtil.writeNextValue(out, XML_TAG_VERSION, CURRENT_CONFIG_STORE_DATA_VERSION); for (StoreData storeData : storeDataList) { String tag = storeData.getName(); XmlUtil.writeNextSectionStart(out, tag); - storeData.serializeData(out); + storeData.serializeData(out, storeFile.getEncryptionUtil()); XmlUtil.writeNextSectionEnd(out, tag); } XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER); - - byte[] outBytes = outputStream.toByteArray(); - EncryptedData encryptedData = storeFile.computeIntegrity(outBytes); - if (encryptedData == null) { - // should never happen, this is a fatal failure. Abort file write. - Log.wtf(TAG, "Failed to compute integrity, failing write"); - return null; - } - return rewriteDocumentMetadataRawBytes(outBytes, encryptedData); - } - - /** - * Helper method to write the metadata at the start of every config store file. - * The metadata consists of: - * a) Version - * b) Integrity data computed on the data contents. - */ - private void writeDocumentMetadata(XmlSerializer out, EncryptedData encryptedData) - throws XmlPullParserException, IOException { - // First XML header. - XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER); - // Next version. - XmlUtil.writeNextValue(out, XML_TAG_VERSION, CURRENT_CONFIG_STORE_DATA_VERSION); - - // Next integrity data. - XmlUtil.writeNextSectionStart(out, XML_TAG_HEADER_INTEGRITY); - XmlUtil.writeNextValue(out, XML_TAG_INTEGRITY_ENCRYPTED_DATA, - encryptedData.getEncryptedData()); - XmlUtil.writeNextValue(out, XML_TAG_INTEGRITY_IV, encryptedData.getIv()); - XmlUtil.writeNextSectionEnd(out, XML_TAG_HEADER_INTEGRITY); - } - - /** - * Helper method to generate the raw bytes containing the the metadata at the start of every - * config store file. - * - * NOTE: This does not create a fully formed XML document (the start tag is not closed for - * example). This only creates the top portion of the XML which contains the modified - * integrity data & version along with the XML prolog (metadata): - * <?xml version='1.0' encoding='utf-8' standalone='yes' ?> - * <WifiConfigStoreData> - * <int name="Version" value="2" /> - * <Integrity> - * <byte-array name="EncryptedData" num="48">!EncryptedData!</byte-array> - * <byte-array name="IV" num="12">!IV!</byte-array> - * </Integrity> - */ - private byte[] generateDocumentMetadataRawBytes(EncryptedData encryptedData) - throws XmlPullParserException, IOException { - final XmlSerializer outXml = new FastXmlSerializer(); - final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - outXml.setOutput(outStream, StandardCharsets.UTF_8.name()); - writeDocumentMetadata(outXml, encryptedData); - outXml.endDocument(); - return outStream.toByteArray(); - } - - /** - * Helper method to rewrite the existing document metadata in the incoming raw bytes in - * |inBytes| with the new document metadata created with the provided |encryptedData|. - * - * NOTE: This assumes that the metadata in existing XML inside |inBytes| aligns exactly - * with the new metadata created. So, a simple in place rewrite of the first few bytes ( - * corresponding to metadata section of the document) from |inBytes| will preserve the overall - * document structure. - */ - private byte[] rewriteDocumentMetadataRawBytes(byte[] inBytes, EncryptedData encryptedData) - throws XmlPullParserException, IOException { - byte[] replaceMetadataBytes = generateDocumentMetadataRawBytes(encryptedData); - ByteBuffer outByteBuffer = ByteBuffer.wrap(inBytes); - outByteBuffer.put(replaceMetadataBytes); - return outByteBuffer.array(); + return outputStream.toByteArray(); } /** @@ -629,10 +578,11 @@ public class WifiConfigStore { } // Inform all the provided store data clients that there is nothing in the store for them. - private void indicateNoDataForStoreDatas(Collection<StoreData> storeDataSet) + private void indicateNoDataForStoreDatas(Collection<StoreData> storeDataSet, + @Version int version, @NonNull WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { for (StoreData storeData : storeDataSet) { - storeData.deserializeData(null, 0); + storeData.deserializeData(null, 0, version, encryptionUtil); } } @@ -654,7 +604,8 @@ public class WifiConfigStore { throws XmlPullParserException, IOException { List<StoreData> storeDataList = retrieveStoreDataListForStoreFile(storeFile); if (dataBytes == null) { - indicateNoDataForStoreDatas(storeDataList); + indicateNoDataForStoreDatas(storeDataList, -1 /* unknown */, + storeFile.getEncryptionUtil()); return; } final XmlPullParser in = Xml.newPullParser(); @@ -665,21 +616,10 @@ public class WifiConfigStore { int rootTagDepth = in.getDepth() + 1; XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER); - int version = parseVersionFromXml(in); - // Version 2 onwards contains integrity data, so check the integrity of the file. - if (version >= INTEGRITY_CONFIG_STORE_DATA_VERSION) { - EncryptedData integrityData = parseIntegrityDataFromXml(in, rootTagDepth); - // To compute integrity, write zeroes in the integrity fields. - dataBytes = rewriteDocumentMetadataRawBytes(dataBytes, ZEROED_ENCRYPTED_DATA); - if (!storeFile.checkIntegrity(dataBytes, integrityData)) { - Log.wtf(TAG, "Integrity mismatch, discarding data from " + storeFile.mFileName); - return; - } - } else { - // When integrity checking is introduced. The existing data will have no related - // integrity file for validation. Thus, we will assume the existing data is correct. - // Integrity will be computed for the next write. - Log.d(TAG, "No integrity data to check; thus vacously true"); + @Version int version = parseVersionFromXml(in); + // Version 2 contains the now unused integrity data, parse & then discard the information. + if (version == INTEGRITY_CONFIG_STORE_DATA_VERSION) { + parseAndDiscardIntegrityDataFromXml(in, rootTagDepth); } String[] headerName = new String[1]; @@ -695,14 +635,15 @@ public class WifiConfigStore { throw new XmlPullParserException("Unknown store data: " + headerName[0] + ". List of store data: " + storeDataList); } - storeData.deserializeData(in, rootTagDepth + 1); + storeData.deserializeData(in, rootTagDepth + 1, version, + storeFile.getEncryptionUtil()); storeDatasInvoked.add(storeData); } // Inform all the other registered store data clients that there is nothing in the store // for them. Set<StoreData> storeDatasNotInvoked = new HashSet<>(storeDataList); storeDatasNotInvoked.removeAll(storeDatasInvoked); - indicateNoDataForStoreDatas(storeDatasNotInvoked); + indicateNoDataForStoreDatas(storeDatasNotInvoked, version, storeFile.getEncryptionUtil()); } /** @@ -712,7 +653,7 @@ public class WifiConfigStore { * @param in XmlPullParser instance pointing to the XML stream. * @return version number retrieved from the Xml stream. */ - private static int parseVersionFromXml(XmlPullParser in) + private static @Version int parseVersionFromXml(XmlPullParser in) throws XmlPullParserException, IOException { int version = (int) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION); if (version < INITIAL_CONFIG_STORE_DATA_VERSION @@ -723,22 +664,15 @@ public class WifiConfigStore { } /** - * Parse the integrity data structure from the XML stream. - * This is used for both the shared and user config store data. + * Parse the integrity data structure from the XML stream and discard it. * * @param in XmlPullParser instance pointing to the XML stream. * @param outerTagDepth Outer tag depth. - * @return Instance of {@link EncryptedData} retrieved from the Xml stream. */ - private static @NonNull EncryptedData parseIntegrityDataFromXml( - XmlPullParser in, int outerTagDepth) + private static void parseAndDiscardIntegrityDataFromXml(XmlPullParser in, int outerTagDepth) throws XmlPullParserException, IOException { XmlUtil.gotoNextSectionWithName(in, XML_TAG_HEADER_INTEGRITY, outerTagDepth); - byte[] encryptedData = - (byte[]) XmlUtil.readNextValueWithName(in, XML_TAG_INTEGRITY_ENCRYPTED_DATA); - byte[] iv = - (byte[]) XmlUtil.readNextValueWithName(in, XML_TAG_INTEGRITY_IV); - return new EncryptedData(encryptedData, iv); + XmlUtil.EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); } /** @@ -746,6 +680,13 @@ public class WifiConfigStore { */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Dump of WifiConfigStore"); + pw.println("WifiConfigStore - Store File Begin ----"); + Stream.of(Arrays.asList(mSharedStore), mUserStores) + .flatMap(List::stream) + .forEach((storeFile) -> { + pw.print("Name: " + storeFile.mFileName); + pw.println(", Credentials encrypted: " + storeFile.getEncryptionUtil() != null); + }); pw.println("WifiConfigStore - Store Data Begin ----"); for (StoreData storeData : mStoreDataList) { pw.print("StoreData =>"); @@ -790,14 +731,14 @@ public class WifiConfigStore { /** * Integrity checking for the store file. */ - private final DataIntegrityChecker mDataIntegrityChecker; + private final WifiConfigStoreEncryptionUtil mEncryptionUtil; public StoreFile(File file, @StoreFileId int fileId, - @NonNull DataIntegrityChecker dataIntegrityChecker) { + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) { mAtomicFile = new AtomicFile(file); mFileName = file.getAbsolutePath(); mFileId = fileId; - mDataIntegrityChecker = dataIntegrityChecker; + mEncryptionUtil = encryptionUtil; } /** @@ -810,6 +751,13 @@ public class WifiConfigStore { } /** + * @return Returns the encryption util used for this store file. + */ + public @Nullable WifiConfigStoreEncryptionUtil getEncryptionUtil() { + return mEncryptionUtil; + } + + /** * Read the entire raw data from the store file and return in a byte array. * * @return raw data read from the file or null if the file is not found or the data has @@ -862,33 +810,6 @@ public class WifiConfigStore { // Reset the pending write data after write. mWriteData = null; } - - /** - * Compute integrity of |dataWithZeroedIntegrityFields| to be written to the file. - * - * @param dataWithZeroedIntegrityFields raw data to be written to the file with the - * integrity fields zeroed out for integrity - * calculation. - * @return Instance of {@link EncryptedData} holding the encrypted integrity data for the - * raw data to be written to the file. - */ - public EncryptedData computeIntegrity(byte[] dataWithZeroedIntegrityFields) { - return mDataIntegrityChecker.compute(dataWithZeroedIntegrityFields); - } - - /** - * Check integrity of |dataWithZeroedIntegrityFields| read from the file with the integrity - * data parsed from the file. - * @param dataWithZeroedIntegrityFields raw data read from the file with the integrity - * fields zeroed out for integrity calculation. - * @param parsedEncryptedData Instance of {@link EncryptedData} parsed from the integrity - * fields in the raw data. - * @return true if the integrity matches, false otherwise. - */ - public boolean checkIntegrity(byte[] dataWithZeroedIntegrityFields, - EncryptedData parsedEncryptedData) { - return mDataIntegrityChecker.isOk(dataWithZeroedIntegrityFields, parsedEncryptedData); - } } /** @@ -908,8 +829,10 @@ public class WifiConfigStore { * Serialize a XML data block to the output stream. * * @param out The output stream to serialize the data to + * @param encryptionUtil Utility to help encrypt any credential data. */ - void serializeData(XmlSerializer out) + void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException; /** @@ -918,10 +841,14 @@ public class WifiConfigStore { * @param in The input stream to read the data from. This could be null if there is * nothing in the store. * @param outerTagDepth The depth of the outer tag in the XML document + * @param version Version of config store file. + * @param encryptionUtil Utility to help decrypt any credential data. + * * Note: This will be invoked every time a store file is read, even if there is nothing * in the store for them. */ - void deserializeData(@Nullable XmlPullParser in, int outerTagDepth) + void deserializeData(@Nullable XmlPullParser in, int outerTagDepth, @Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException; /** diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index fe9ebea17..f7212ddfc 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -241,7 +241,7 @@ public class WifiInjector { mWifiKeyStore = new WifiKeyStore(mKeyStore); mWifiConfigStore = new WifiConfigStore( mContext, clientModeImplLooper, mClock, mWifiMetrics, - WifiConfigStore.createSharedFile()); + WifiConfigStore.createSharedFile(mFrameworkFacade.isNiapModeOn(mContext))); SubscriptionManager subscriptionManager = mContext.getSystemService(SubscriptionManager.class); // Config Manager diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java index 419ea7993..7f5a6b408 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreData.java @@ -16,7 +16,10 @@ package com.android.server.wifi.hotspot2; +import android.annotation.Nullable; + import com.android.server.wifi.WifiConfigStore; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; @@ -72,13 +75,16 @@ public class PasspointConfigSharedStoreData implements WifiConfigStore.StoreData } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { serializeShareData(out); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java b/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java index 0114cfb21..123cf8982 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointConfigUserStoreData.java @@ -16,6 +16,7 @@ package com.android.server.wifi.hotspot2; +import android.annotation.Nullable; import android.net.wifi.hotspot2.PasspointConfiguration; import android.text.TextUtils; @@ -23,6 +24,7 @@ import com.android.internal.util.XmlUtils; import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiConfigStore; import com.android.server.wifi.WifiKeyStore; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import org.xmlpull.v1.XmlPullParser; @@ -103,13 +105,16 @@ public class PasspointConfigUserStoreData implements WifiConfigStore.StoreData { } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { serializeUserData(out); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, + @WifiConfigStore.Version int version, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { // Ignore empty reads. if (in == null) { diff --git a/service/java/com/android/server/wifi/util/EncryptedData.java b/service/java/com/android/server/wifi/util/EncryptedData.java index 91342d335..baec20426 100644 --- a/service/java/com/android/server/wifi/util/EncryptedData.java +++ b/service/java/com/android/server/wifi/util/EncryptedData.java @@ -18,21 +18,19 @@ package com.android.server.wifi.util; import com.android.internal.util.Preconditions; +import java.util.Arrays; +import java.util.Objects; + /** - * A class to store data created by {@link DataIntegrityChecker}. + * A class to store data created by {@link WifiConfigStoreEncryptionUtil}. */ public class EncryptedData { - public static final int ENCRYPTED_DATA_LENGTH = 48; - public static final int IV_LENGTH = 12; - private final byte[] mEncryptedData; private final byte[] mIv; public EncryptedData(byte[] encryptedData, byte[] iv) { - Preconditions.checkNotNull(encryptedData, iv); - Preconditions.checkState(encryptedData.length == ENCRYPTED_DATA_LENGTH, - "encryptedData.length=" + encryptedData.length); - Preconditions.checkState(iv.length == IV_LENGTH, "iv.length=" + iv.length); + Preconditions.checkNotNull(encryptedData); + Preconditions.checkNotNull(iv); mEncryptedData = encryptedData; mIv = iv; } @@ -44,4 +42,17 @@ public class EncryptedData { public byte[] getIv() { return mIv; } + + @Override + public boolean equals(Object other) { + if (!(other instanceof EncryptedData)) return false; + EncryptedData otherEncryptedData = (EncryptedData) other; + return Arrays.equals(this.mEncryptedData, otherEncryptedData.mEncryptedData) + && Arrays.equals(this.mIv, otherEncryptedData.mIv); + } + + @Override + public int hashCode() { + return Objects.hash(Arrays.hashCode(mEncryptedData), Arrays.hashCode(mIv)); + } } diff --git a/service/java/com/android/server/wifi/util/DataIntegrityChecker.java b/service/java/com/android/server/wifi/util/WifiConfigStoreEncryptionUtil.java index 6f03a4861..2f9b08f2b 100644 --- a/service/java/com/android/server/wifi/util/DataIntegrityChecker.java +++ b/service/java/com/android/server/wifi/util/WifiConfigStoreEncryptionUtil.java @@ -17,22 +17,22 @@ package com.android.server.wifi.util; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Process; import android.os.SystemProperties; +import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; import android.text.TextUtils; import android.util.Log; -import java.io.IOException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.UnrecoverableEntryException; -import java.security.cert.CertificateException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; @@ -43,34 +43,26 @@ import javax.crypto.SecretKey; import javax.crypto.spec.GCMParameterSpec; /** - * Tools to provide integrity checking of byte arrays based on NIAP Common Criteria Protection - * Profile <a href="https://www.niap-ccevs.org/MMO/PP/-417-/#FCS_STG_EXT.3.1">FCS_STG_EXT.3.1</a>. + * Tools to help encrypt/decrypt */ -public class DataIntegrityChecker { - private static final String TAG = "DataIntegrityChecker"; +public class WifiConfigStoreEncryptionUtil { + private static final String TAG = "WifiConfigStoreEncryptionUtil"; - private static final String ALIAS_SUFFIX = ".data-integrity-checker-key"; + private static final String ALIAS_SUFFIX = ".data-encryption-key"; private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; - private static final String DIGEST_ALGORITHM = "SHA-256"; private static final int GCM_TAG_LENGTH = 128; private static final String KEY_STORE = "AndroidKeyStore"; - /** - * When KEYSTORE_FAILURE_RETURN_VALUE is true, all cryptographic operation failures will not - * enforce security and {@link #isOk(byte[], EncryptedData)} always return true. - */ - private static final boolean KEYSTORE_FAILURE_RETURN_VALUE = true; - private final String mDataFileName; /** - * Construct a new integrity checker to update and check if/when a data file was altered - * outside expected conditions. + * Construct a new util to help {@link com.android.server.wifi.WifiConfigStore.StoreData} + * modules to encrypt/decrypt credential data written/read from this config store file. * - * @param dataFileName The full path of the data file for which integrity check is performed. + * @param dataFileName The full path of the data file. * @throws NullPointerException When data file is empty string. */ - public DataIntegrityChecker(@NonNull String dataFileName) { + public WifiConfigStoreEncryptionUtil(@NonNull String dataFileName) { if (TextUtils.isEmpty(dataFileName)) { throw new NullPointerException("dataFileName must not be null or the empty " + "string"); @@ -83,80 +75,16 @@ public class DataIntegrityChecker { } /** - * Computes a digest of a byte array, encrypt it, and store the result - * - * Call this method immediately before storing the byte array - * - * @param data The data desired to ensure integrity - * @return Instance of {@link EncryptedData} containing the encrypted integrity data. - */ - public EncryptedData compute(byte[] data) { - if (data == null || data.length < 1) { - reportException(new Exception("No data to compute"), "No data to compute."); - return null; - } - byte[] digest = getDigest(data); - if (digest == null || digest.length < 1) { - reportException(new Exception("digest null in compute"), - "digest null in compute"); - return null; - } - EncryptedData integrityData = encrypt(digest, getKeyAlias()); - if (integrityData == null) { - reportException(new Exception("integrityData null in compute"), - "integrityData null in compute"); - } - return integrityData; - } - - - /** - * Check the integrity of a given byte array - * - * Call this method immediately before trusting the byte array. This method will return false - * when the integrity data calculated on the byte array does not match the encrypted integrity - * data provided to compare or if there is an underlying issue with the cryptographic functions - * or the key store. + * Encrypt the provided data blob. * - * @param data The data to check if its been altered. - * @param integrityData Encrypted integrity data to be used for comparison. - * @return true if the integrity data computed on |data| matches the provided |integrityData|. + * @param data Data blob to be encrypted. + * @return Instance of {@link EncryptedData} containing the encrypted info. */ - public boolean isOk(@NonNull byte[] data, @NonNull EncryptedData integrityData) { - if (data == null || data.length < 1) { - return KEYSTORE_FAILURE_RETURN_VALUE; - } - byte[] currentDigest = getDigest(data); - if (currentDigest == null || currentDigest.length < 1) { - reportException(new Exception("current digest null"), "current digest null"); - return KEYSTORE_FAILURE_RETURN_VALUE; - } - if (integrityData == null) { - reportException(new Exception("integrityData null in isOk"), - "integrityData null in isOk"); - return KEYSTORE_FAILURE_RETURN_VALUE; - } - byte[] storedDigest = decrypt(integrityData, getKeyAlias()); - if (storedDigest == null) { - return KEYSTORE_FAILURE_RETURN_VALUE; - } - return constantTimeEquals(storedDigest, currentDigest); - } - - private byte[] getDigest(byte[] data) { - try { - return MessageDigest.getInstance(DIGEST_ALGORITHM).digest(data); - } catch (NoSuchAlgorithmException e) { - reportException(e, "getDigest could not find algorithm: " + DIGEST_ALGORITHM); - return null; - } - } - - private EncryptedData encrypt(byte[] data, String keyAlias) { + public @Nullable EncryptedData encrypt(byte[] data) { EncryptedData encryptedData = null; try { Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - SecretKey secretKeyReference = getOrCreateSecretKey(keyAlias); + SecretKey secretKeyReference = getOrCreateSecretKey(getKeyAlias()); if (secretKeyReference != null) { cipher.init(Cipher.ENCRYPT_MODE, secretKeyReference); encryptedData = new EncryptedData(cipher.doFinal(data), cipher.getIV()); @@ -178,12 +106,18 @@ public class DataIntegrityChecker { return encryptedData; } - private byte[] decrypt(EncryptedData encryptedData, String keyAlias) { + /** + * Decrypt the original data blob from the provided {@link EncryptedData}. + * + * @param encryptedData Instance of {@link EncryptedData} containing the encrypted info. + * @return Original data blob that was encrypted. + */ + public @Nullable byte[] decrypt(@NonNull EncryptedData encryptedData) { byte[] decryptedData = null; try { Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH, encryptedData.getIv()); - SecretKey secretKeyReference = getOrCreateSecretKey(keyAlias); + SecretKey secretKeyReference = getOrCreateSecretKey(getKeyAlias()); if (secretKeyReference != null) { cipher.init(Cipher.DECRYPT_MODE, secretKeyReference, spec); decryptedData = cipher.doFinal(encryptedData.getEncryptedData()); @@ -207,8 +141,7 @@ public class DataIntegrityChecker { private SecretKey getOrCreateSecretKey(String keyAlias) { SecretKey secretKey = null; try { - KeyStore keyStore = KeyStore.getInstance(KEY_STORE); - keyStore.load(null); + KeyStore keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(Process.WIFI_UID); if (keyStore.containsAlias(keyAlias)) { // The key exists in key store. Get the key. KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore .getEntry(keyAlias, null); @@ -227,17 +160,14 @@ public class DataIntegrityChecker { KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .setUid(Process.WIFI_UID) .build(); keyGenerator.init(keyGenParameterSpec); secretKey = keyGenerator.generateKey(); } - } catch (CertificateException e) { - reportException(e, "getOrCreateSecretKey had a certificate exception."); } catch (InvalidAlgorithmParameterException e) { reportException(e, "getOrCreateSecretKey had an invalid algorithm parameter"); - } catch (IOException e) { - reportException(e, "getOrCreateSecretKey had an IO exception."); } catch (KeyStoreException e) { reportException(e, "getOrCreateSecretKey cannot find the keystore: " + KEY_STORE); } catch (NoSuchAlgorithmException e) { @@ -250,22 +180,6 @@ public class DataIntegrityChecker { return secretKey; } - private boolean constantTimeEquals(byte[] a, byte[] b) { - if (a == null && b == null) { - return true; - } - - if (a == null || b == null || a.length != b.length) { - return false; - } - - byte differenceAccumulator = 0; - for (int i = 0; i < a.length; ++i) { - differenceAccumulator |= a[i] ^ b[i]; - } - return (differenceAccumulator == 0); - } - /* TODO(b/128526030): Remove this error reporting code upon resolving the bug. */ private static final boolean REQUEST_BUG_REPORT = false; private void reportException(Exception exception, String error) { @@ -275,4 +189,5 @@ public class DataIntegrityChecker { SystemProperties.set("ctl.start", "bugreport"); } } + } diff --git a/service/java/com/android/server/wifi/util/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java index 188d3b5c7..db0f4289b 100644 --- a/service/java/com/android/server/wifi/util/XmlUtil.java +++ b/service/java/com/android/server/wifi/util/XmlUtil.java @@ -16,6 +16,7 @@ package com.android.server.wifi.util; +import android.annotation.Nullable; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -28,6 +29,7 @@ import android.net.StaticIpConfiguration; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; import android.net.wifi.WifiEnterpriseConfig; +import android.text.TextUtils; import android.util.Log; import android.util.Pair; @@ -377,19 +379,51 @@ public class XmlUtil { } /** + * Write preshared key to the XML stream. + * + * If encryptionUtil is null or if encryption fails for some reason, the pre-shared + * key is stored in plaintext, else the encrypted psk is stored. + */ + private static void writePreSharedKeyToXml( + XmlSerializer out, String preSharedKey, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) + throws XmlPullParserException, IOException { + EncryptedData encryptedData = null; + if (encryptionUtil != null) { + if (preSharedKey != null) { + encryptedData = encryptionUtil.encrypt(preSharedKey.getBytes()); + if (encryptedData == null) { + // We silently fail encryption failures! + Log.wtf(TAG, "Encryption of preSharedKey failed"); + } + } + } + if (encryptedData != null) { + XmlUtil.writeNextSectionStart(out, XML_TAG_PRE_SHARED_KEY); + EncryptedDataXmlUtil.writeToXml(out, encryptedData); + XmlUtil.writeNextSectionEnd(out, XML_TAG_PRE_SHARED_KEY); + } else { + XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, preSharedKey); + } + } + + /** * Write the Configuration data elements that are common for backup & config store to the * XML stream. * - * @param out XmlSerializer instance pointing to the XML stream. + * @param out XmlSerializer instance pointing to the XML stream. * @param configuration WifiConfiguration object to be serialized. + * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. Backup/restore stores + * keys unencrypted. */ public static void writeCommonElementsToXml( - XmlSerializer out, WifiConfiguration configuration) + XmlSerializer out, WifiConfiguration configuration, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.configKey()); XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID); XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID); - XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, configuration.preSharedKey); + writePreSharedKeyToXml(out, configuration.preSharedKey, encryptionUtil); writeWepKeysToXml(out, configuration.wepKeys); XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID); @@ -428,7 +462,7 @@ public class XmlUtil { */ public static void writeToXmlForBackup(XmlSerializer out, WifiConfiguration configuration) throws XmlPullParserException, IOException { - writeCommonElementsToXml(out, configuration); + writeCommonElementsToXml(out, configuration, null); XmlUtil.writeNextValue(out, XML_TAG_METERED_OVERRIDE, configuration.meteredOverride); } @@ -436,13 +470,15 @@ public class XmlUtil { * Write the Configuration data elements for config store from the provided Configuration * to the XML stream. * - * @param out XmlSerializer instance pointing to the XML stream. + * @param out XmlSerializer instance pointing to the XML stream. * @param configuration WifiConfiguration object to be serialized. + * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. */ public static void writeToXmlForConfigStore( - XmlSerializer out, WifiConfiguration configuration) + XmlSerializer out, WifiConfiguration configuration, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { - writeCommonElementsToXml(out, configuration); + writeCommonElementsToXml(out, configuration, encryptionUtil); XmlUtil.writeNextValue(out, XML_TAG_STATUS, configuration.status); XmlUtil.writeNextValue(out, XML_TAG_FQDN, configuration.FQDN); XmlUtil.writeNextValue( @@ -509,13 +545,16 @@ public class XmlUtil { * Note: This is used for parsing both backup data and config store data. Looping through * the tags make it easy to add or remove elements in the future versions if needed. * - * @param in XmlPullParser instance pointing to the XML stream. + * @param in XmlPullParser instance pointing to the XML stream. * @param outerTagDepth depth of the outer tag in the XML document. + * @param shouldExpectEncryptedCredentials Whether to expect encrypted credentials or not. + * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. * @return Pair<Config key, WifiConfiguration object> if parsing is successful, * null otherwise. */ public static Pair<String, WifiConfiguration> parseFromXml( - XmlPullParser in, int outerTagDepth) + XmlPullParser in, int outerTagDepth, boolean shouldExpectEncryptedCredentials, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { WifiConfiguration configuration = new WifiConfiguration(); String configKeyInData = null; @@ -523,147 +562,175 @@ public class XmlUtil { // Loop through and parse out all the elements from the stream within this section. while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { - String[] valueName = new String[1]; - Object value = XmlUtil.readCurrentValue(in, valueName); - if (valueName[0] == null) { - throw new XmlPullParserException("Missing value name"); - } - switch (valueName[0]) { - case XML_TAG_CONFIG_KEY: - configKeyInData = (String) value; - break; - case XML_TAG_SSID: - configuration.SSID = (String) value; - break; - case XML_TAG_BSSID: - configuration.BSSID = (String) value; - break; - case XML_TAG_PRE_SHARED_KEY: - configuration.preSharedKey = (String) value; - break; - case XML_TAG_WEP_KEYS: - populateWepKeysFromXmlValue(value, configuration.wepKeys); - break; - case XML_TAG_WEP_TX_KEY_INDEX: - configuration.wepTxKeyIndex = (int) value; - break; - case XML_TAG_HIDDEN_SSID: - configuration.hiddenSSID = (boolean) value; - break; - case XML_TAG_REQUIRE_PMF: - configuration.requirePMF = (boolean) value; - break; - case XML_TAG_ALLOWED_KEY_MGMT: - byte[] allowedKeyMgmt = (byte[]) value; - configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); - break; - case XML_TAG_ALLOWED_PROTOCOLS: - byte[] allowedProtocols = (byte[]) value; - configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); - break; - case XML_TAG_ALLOWED_AUTH_ALGOS: - byte[] allowedAuthAlgorithms = (byte[]) value; - configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); - break; - case XML_TAG_ALLOWED_GROUP_CIPHERS: - byte[] allowedGroupCiphers = (byte[]) value; - configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers); - break; - case XML_TAG_ALLOWED_PAIRWISE_CIPHERS: - byte[] allowedPairwiseCiphers = (byte[]) value; - configuration.allowedPairwiseCiphers = - BitSet.valueOf(allowedPairwiseCiphers); - break; - case XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS: - byte[] allowedGroupMgmtCiphers = (byte[]) value; - configuration.allowedGroupManagementCiphers = - BitSet.valueOf(allowedGroupMgmtCiphers); - break; - case XML_TAG_ALLOWED_SUITE_B_CIPHERS: - byte[] allowedSuiteBCiphers = (byte[]) value; - configuration.allowedSuiteBCiphers = - BitSet.valueOf(allowedSuiteBCiphers); - break; - case XML_TAG_SHARED: - configuration.shared = (boolean) value; - break; - case XML_TAG_STATUS: - int status = (int) value; - // Any network which was CURRENT before reboot needs - // to be restored to ENABLED. - if (status == WifiConfiguration.Status.CURRENT) { - status = WifiConfiguration.Status.ENABLED; - } - configuration.status = status; - break; - case XML_TAG_FQDN: - configuration.FQDN = (String) value; - break; - case XML_TAG_PROVIDER_FRIENDLY_NAME: - configuration.providerFriendlyName = (String) value; - break; - case XML_TAG_LINKED_NETWORKS_LIST: - configuration.linkedConfigurations = (HashMap<String, Integer>) value; - break; - case XML_TAG_DEFAULT_GW_MAC_ADDRESS: - configuration.defaultGwMacAddress = (String) value; - break; - case XML_TAG_VALIDATED_INTERNET_ACCESS: - configuration.validatedInternetAccess = (boolean) value; - break; - case XML_TAG_NO_INTERNET_ACCESS_EXPECTED: - configuration.noInternetAccessExpected = (boolean) value; - break; - case XML_TAG_USER_APPROVED: - configuration.userApproved = (int) value; - break; - case XML_TAG_METERED_HINT: - configuration.meteredHint = (boolean) value; - break; - case XML_TAG_METERED_OVERRIDE: - configuration.meteredOverride = (int) value; - break; - case XML_TAG_USE_EXTERNAL_SCORES: - configuration.useExternalScores = (boolean) value; - break; - case XML_TAG_NUM_ASSOCIATION: - configuration.numAssociation = (int) value; - break; - case XML_TAG_CREATOR_UID: - configuration.creatorUid = (int) value; - break; - case XML_TAG_CREATOR_NAME: - configuration.creatorName = (String) value; - break; - case XML_TAG_CREATION_TIME: - configuration.creationTime = (String) value; - break; - case XML_TAG_LAST_UPDATE_UID: - configuration.lastUpdateUid = (int) value; - break; - case XML_TAG_LAST_UPDATE_NAME: - configuration.lastUpdateName = (String) value; - break; - case XML_TAG_LAST_CONNECT_UID: - configuration.lastConnectUid = (int) value; - break; - case XML_TAG_IS_LEGACY_PASSPOINT_CONFIG: - configuration.isLegacyPasspointConfig = (boolean) value; - break; - case XML_TAG_ROAMING_CONSORTIUM_OIS: - configuration.roamingConsortiumIds = (long[]) value; - break; - case XML_TAG_RANDOMIZED_MAC_ADDRESS: - configuration.setRandomizedMacAddress( - MacAddress.fromString((String) value)); - break; - case XML_TAG_MAC_RANDOMIZATION_SETTING: - configuration.macRandomizationSetting = (int) value; - macRandomizationSettingExists = true; - break; - default: - throw new XmlPullParserException( - "Unknown value name found: " + valueName[0]); + if (in.getAttributeValue(null, "name") != null) { + // Value elements. + String[] valueName = new String[1]; + Object value = XmlUtil.readCurrentValue(in, valueName); + if (valueName[0] == null) { + throw new XmlPullParserException("Missing value name"); + } + switch (valueName[0]) { + case XML_TAG_CONFIG_KEY: + configKeyInData = (String) value; + break; + case XML_TAG_SSID: + configuration.SSID = (String) value; + break; + case XML_TAG_BSSID: + configuration.BSSID = (String) value; + break; + case XML_TAG_PRE_SHARED_KEY: + configuration.preSharedKey = (String) value; + break; + case XML_TAG_WEP_KEYS: + populateWepKeysFromXmlValue(value, configuration.wepKeys); + break; + case XML_TAG_WEP_TX_KEY_INDEX: + configuration.wepTxKeyIndex = (int) value; + break; + case XML_TAG_HIDDEN_SSID: + configuration.hiddenSSID = (boolean) value; + break; + case XML_TAG_REQUIRE_PMF: + configuration.requirePMF = (boolean) value; + break; + case XML_TAG_ALLOWED_KEY_MGMT: + byte[] allowedKeyMgmt = (byte[]) value; + configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); + break; + case XML_TAG_ALLOWED_PROTOCOLS: + byte[] allowedProtocols = (byte[]) value; + configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); + break; + case XML_TAG_ALLOWED_AUTH_ALGOS: + byte[] allowedAuthAlgorithms = (byte[]) value; + configuration.allowedAuthAlgorithms = BitSet.valueOf( + allowedAuthAlgorithms); + break; + case XML_TAG_ALLOWED_GROUP_CIPHERS: + byte[] allowedGroupCiphers = (byte[]) value; + configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers); + break; + case XML_TAG_ALLOWED_PAIRWISE_CIPHERS: + byte[] allowedPairwiseCiphers = (byte[]) value; + configuration.allowedPairwiseCiphers = + BitSet.valueOf(allowedPairwiseCiphers); + break; + case XML_TAG_ALLOWED_GROUP_MGMT_CIPHERS: + byte[] allowedGroupMgmtCiphers = (byte[]) value; + configuration.allowedGroupManagementCiphers = + BitSet.valueOf(allowedGroupMgmtCiphers); + break; + case XML_TAG_ALLOWED_SUITE_B_CIPHERS: + byte[] allowedSuiteBCiphers = (byte[]) value; + configuration.allowedSuiteBCiphers = + BitSet.valueOf(allowedSuiteBCiphers); + break; + case XML_TAG_SHARED: + configuration.shared = (boolean) value; + break; + case XML_TAG_STATUS: + int status = (int) value; + // Any network which was CURRENT before reboot needs + // to be restored to ENABLED. + if (status == WifiConfiguration.Status.CURRENT) { + status = WifiConfiguration.Status.ENABLED; + } + configuration.status = status; + break; + case XML_TAG_FQDN: + configuration.FQDN = (String) value; + break; + case XML_TAG_PROVIDER_FRIENDLY_NAME: + configuration.providerFriendlyName = (String) value; + break; + case XML_TAG_LINKED_NETWORKS_LIST: + configuration.linkedConfigurations = (HashMap<String, Integer>) value; + break; + case XML_TAG_DEFAULT_GW_MAC_ADDRESS: + configuration.defaultGwMacAddress = (String) value; + break; + case XML_TAG_VALIDATED_INTERNET_ACCESS: + configuration.validatedInternetAccess = (boolean) value; + break; + case XML_TAG_NO_INTERNET_ACCESS_EXPECTED: + configuration.noInternetAccessExpected = (boolean) value; + break; + case XML_TAG_USER_APPROVED: + configuration.userApproved = (int) value; + break; + case XML_TAG_METERED_HINT: + configuration.meteredHint = (boolean) value; + break; + case XML_TAG_METERED_OVERRIDE: + configuration.meteredOverride = (int) value; + break; + case XML_TAG_USE_EXTERNAL_SCORES: + configuration.useExternalScores = (boolean) value; + break; + case XML_TAG_NUM_ASSOCIATION: + configuration.numAssociation = (int) value; + break; + case XML_TAG_CREATOR_UID: + configuration.creatorUid = (int) value; + break; + case XML_TAG_CREATOR_NAME: + configuration.creatorName = (String) value; + break; + case XML_TAG_CREATION_TIME: + configuration.creationTime = (String) value; + break; + case XML_TAG_LAST_UPDATE_UID: + configuration.lastUpdateUid = (int) value; + break; + case XML_TAG_LAST_UPDATE_NAME: + configuration.lastUpdateName = (String) value; + break; + case XML_TAG_LAST_CONNECT_UID: + configuration.lastConnectUid = (int) value; + break; + case XML_TAG_IS_LEGACY_PASSPOINT_CONFIG: + configuration.isLegacyPasspointConfig = (boolean) value; + break; + case XML_TAG_ROAMING_CONSORTIUM_OIS: + configuration.roamingConsortiumIds = (long[]) value; + break; + case XML_TAG_RANDOMIZED_MAC_ADDRESS: + configuration.setRandomizedMacAddress( + MacAddress.fromString((String) value)); + break; + case XML_TAG_MAC_RANDOMIZATION_SETTING: + configuration.macRandomizationSetting = (int) value; + macRandomizationSettingExists = true; + break; + default: + throw new XmlPullParserException( + "Unknown value name found: " + valueName[0]); + } + } else { + String tagName = in.getName(); + if (tagName == null) { + throw new XmlPullParserException("Unexpected null tag found"); + } + switch (tagName) { + case XML_TAG_PRE_SHARED_KEY: + if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { + throw new XmlPullParserException( + "Encrypted preSharedKey section not expected"); + } + EncryptedData encryptedData = + EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); + byte[] preSharedKeyBytes = encryptionUtil.decrypt(encryptedData); + if (preSharedKeyBytes == null) { + Log.wtf(TAG, "Decryption of preSharedKey failed"); + } else { + configuration.preSharedKey = new String(preSharedKeyBytes); + } + break; + default: + throw new XmlPullParserException( + "Unknown tag name found: " + tagName); + } } } if (!macRandomizationSettingExists) { @@ -1019,20 +1086,52 @@ public class XmlUtil { public static final String XML_TAG_REALM = "Realm"; /** + * Write password key to the XML stream. + * + * If encryptionUtil is null or if encryption fails for some reason, the password is stored + * in plaintext, else the encrypted psk is stored. + */ + private static void writePasswordToXml( + XmlSerializer out, String password, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) + throws XmlPullParserException, IOException { + EncryptedData encryptedData = null; + if (encryptionUtil != null) { + if (password != null) { + encryptedData = encryptionUtil.encrypt(password.getBytes()); + if (encryptedData == null) { + // We silently fail encryption failures! + Log.wtf(TAG, "Encryption of password failed"); + } + } + } + if (encryptedData != null) { + XmlUtil.writeNextSectionStart(out, XML_TAG_PASSWORD); + EncryptedDataXmlUtil.writeToXml(out, encryptedData); + XmlUtil.writeNextSectionEnd(out, XML_TAG_PASSWORD); + } else { + XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, password); + } + } + + /** * Write the WifiEnterpriseConfig data elements from the provided config to the XML * stream. * - * @param out XmlSerializer instance pointing to the XML stream. + * @param out XmlSerializer instance pointing to the XML stream. * @param enterpriseConfig WifiEnterpriseConfig object to be serialized. + * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. */ - public static void writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig) + public static void writeToXml(XmlSerializer out, WifiEnterpriseConfig enterpriseConfig, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { XmlUtil.writeNextValue(out, XML_TAG_IDENTITY, enterpriseConfig.getFieldValue(WifiEnterpriseConfig.IDENTITY_KEY)); XmlUtil.writeNextValue(out, XML_TAG_ANON_IDENTITY, enterpriseConfig.getFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY)); - XmlUtil.writeNextValue(out, XML_TAG_PASSWORD, - enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY)); + writePasswordToXml( + out, enterpriseConfig.getFieldValue(WifiEnterpriseConfig.PASSWORD_KEY), + encryptionUtil); XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CERT, enterpriseConfig.getFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY)); XmlUtil.writeNextValue(out, XML_TAG_CA_CERT, @@ -1060,15 +1159,170 @@ public class XmlUtil { /** * Parses the data elements from the provided XML stream to a WifiEnterpriseConfig object. * - * @param in XmlPullParser instance pointing to the XML stream. + * @param in XmlPullParser instance pointing to the XML stream. * @param outerTagDepth depth of the outer tag in the XML document. + * @param shouldExpectEncryptedCredentials Whether to expect encrypted credentials or not. + * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. * @return WifiEnterpriseConfig object if parsing is successful, null otherwise. */ - public static WifiEnterpriseConfig parseFromXml(XmlPullParser in, int outerTagDepth) + public static WifiEnterpriseConfig parseFromXml(XmlPullParser in, int outerTagDepth, + boolean shouldExpectEncryptedCredentials, + @Nullable WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); // Loop through and parse out all the elements from the stream within this section. + while (XmlUtils.nextElementWithin(in, outerTagDepth)) { + if (in.getAttributeValue(null, "name") != null) { + // Value elements. + String[] valueName = new String[1]; + Object value = XmlUtil.readCurrentValue(in, valueName); + if (valueName[0] == null) { + throw new XmlPullParserException("Missing value name"); + } + switch (valueName[0]) { + case XML_TAG_IDENTITY: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.IDENTITY_KEY, (String) value); + break; + case XML_TAG_ANON_IDENTITY: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.ANON_IDENTITY_KEY, (String) value); + break; + case XML_TAG_PASSWORD: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.PASSWORD_KEY, (String) value); + if (shouldExpectEncryptedCredentials + && !TextUtils.isEmpty(enterpriseConfig.getFieldValue( + WifiEnterpriseConfig.PASSWORD_KEY))) { + // Indicates that encryption of password failed when it was last + // written. + Log.e(TAG, "password value not expected"); + } + break; + case XML_TAG_CLIENT_CERT: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.CLIENT_CERT_KEY, (String) value); + break; + case XML_TAG_CA_CERT: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.CA_CERT_KEY, (String) value); + break; + case XML_TAG_SUBJECT_MATCH: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.SUBJECT_MATCH_KEY, (String) value); + break; + case XML_TAG_ENGINE: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.ENGINE_KEY, (String) value); + break; + case XML_TAG_ENGINE_ID: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.ENGINE_ID_KEY, (String) value); + break; + case XML_TAG_PRIVATE_KEY_ID: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, (String) value); + break; + case XML_TAG_ALT_SUBJECT_MATCH: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, (String) value); + break; + case XML_TAG_DOM_SUFFIX_MATCH: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, (String) value); + break; + case XML_TAG_CA_PATH: + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.CA_PATH_KEY, (String) value); + break; + case XML_TAG_EAP_METHOD: + enterpriseConfig.setEapMethod((int) value); + break; + case XML_TAG_PHASE2_METHOD: + enterpriseConfig.setPhase2Method((int) value); + break; + case XML_TAG_PLMN: + enterpriseConfig.setPlmn((String) value); + break; + case XML_TAG_REALM: + enterpriseConfig.setRealm((String) value); + break; + default: + throw new XmlPullParserException( + "Unknown value name found: " + valueName[0]); + } + } else { + String tagName = in.getName(); + if (tagName == null) { + throw new XmlPullParserException("Unexpected null tag found"); + } + switch (tagName) { + case XML_TAG_PASSWORD: + if (!shouldExpectEncryptedCredentials || encryptionUtil == null) { + throw new XmlPullParserException( + "encrypted password section not expected"); + } + EncryptedData encryptedData = + EncryptedDataXmlUtil.parseFromXml(in, outerTagDepth + 1); + byte[] passwordBytes = encryptionUtil.decrypt(encryptedData); + if (passwordBytes == null) { + Log.wtf(TAG, "Decryption of password failed"); + } else { + enterpriseConfig.setFieldValue( + WifiEnterpriseConfig.PASSWORD_KEY, + new String(passwordBytes)); + } + break; + default: + throw new XmlPullParserException( + "Unknown tag name found: " + tagName); + } + } + } + return enterpriseConfig; + } + } + + /** + * Utility class to serialize and deseriaize {@link EncryptedData} object to XML & + * vice versa. This is used by {@link com.android.server.wifi.WifiConfigStore} module. + */ + public static class EncryptedDataXmlUtil { + /** + * List of XML tags corresponding to EncryptedData object elements. + */ + private static final String XML_TAG_ENCRYPTED_DATA = "EncryptedData"; + private static final String XML_TAG_IV = "IV"; + + /** + * Write the NetworkSelectionStatus data elements from the provided status to the XML + * stream. + * + * @param out XmlSerializer instance pointing to the XML stream. + * @param encryptedData EncryptedData object to be serialized. + */ + public static void writeToXml(XmlSerializer out, EncryptedData encryptedData) + throws XmlPullParserException, IOException { + XmlUtil.writeNextValue( + out, XML_TAG_ENCRYPTED_DATA, encryptedData.getEncryptedData()); + XmlUtil.writeNextValue(out, XML_TAG_IV, encryptedData.getIv()); + } + + /** + * Parses the EncryptedData data elements from the provided XML stream to a + * EncryptedData object. + * + * @param in XmlPullParser instance pointing to the XML stream. + * @param outerTagDepth depth of the outer tag in the XML document. + * @return EncryptedData object if parsing is successful, null otherwise. + */ + public static EncryptedData parseFromXml(XmlPullParser in, int outerTagDepth) + throws XmlPullParserException, IOException { + byte[] encryptedData = null; + byte[] iv = null; + + // Loop through and parse out all the elements from the stream within this section. while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { String[] valueName = new String[1]; Object value = XmlUtil.readCurrentValue(in, valueName); @@ -1076,72 +1330,18 @@ public class XmlUtil { throw new XmlPullParserException("Missing value name"); } switch (valueName[0]) { - case XML_TAG_IDENTITY: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.IDENTITY_KEY, (String) value); - break; - case XML_TAG_ANON_IDENTITY: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ANON_IDENTITY_KEY, (String) value); + case XML_TAG_ENCRYPTED_DATA: + encryptedData = (byte[]) value; break; - case XML_TAG_PASSWORD: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.PASSWORD_KEY, (String) value); - break; - case XML_TAG_CLIENT_CERT: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.CLIENT_CERT_KEY, (String) value); - break; - case XML_TAG_CA_CERT: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.CA_CERT_KEY, (String) value); - break; - case XML_TAG_SUBJECT_MATCH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.SUBJECT_MATCH_KEY, (String) value); - break; - case XML_TAG_ENGINE: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ENGINE_KEY, (String) value); - break; - case XML_TAG_ENGINE_ID: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ENGINE_ID_KEY, (String) value); - break; - case XML_TAG_PRIVATE_KEY_ID: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, (String) value); - break; - case XML_TAG_ALT_SUBJECT_MATCH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, (String) value); - break; - case XML_TAG_DOM_SUFFIX_MATCH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, (String) value); - break; - case XML_TAG_CA_PATH: - enterpriseConfig.setFieldValue( - WifiEnterpriseConfig.CA_PATH_KEY, (String) value); - break; - case XML_TAG_EAP_METHOD: - enterpriseConfig.setEapMethod((int) value); - break; - case XML_TAG_PHASE2_METHOD: - enterpriseConfig.setPhase2Method((int) value); - break; - case XML_TAG_PLMN: - enterpriseConfig.setPlmn((String) value); - break; - case XML_TAG_REALM: - enterpriseConfig.setRealm((String) value); + case XML_TAG_IV: + iv = (byte[]) value; break; default: throw new XmlPullParserException( "Unknown value name found: " + valueName[0]); } } - return enterpriseConfig; + return new EncryptedData(encryptedData, iv); } } } diff --git a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java index 702aa99df..17b9d1c2e 100644 --- a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java @@ -24,6 +24,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -78,7 +79,8 @@ public class DeletedEphemeralSsidsStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mDeletedEphemeralSsidsStoreData.serializeData(out); + mDeletedEphemeralSsidsStoreData.serializeData( + out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -94,7 +96,9 @@ public class DeletedEphemeralSsidsStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mDeletedEphemeralSsidsStoreData.deserializeData(in, in.getDepth()); + mDeletedEphemeralSsidsStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); return mDeletedEphemeralSsidsStoreData.getSsidToTimeMap(); } diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java index 7336c4119..20b6c4f76 100644 --- a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java @@ -31,6 +31,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtilTest; import org.junit.Before; @@ -213,7 +214,7 @@ public class NetworkListStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkListSharedStoreData.serializeData(out); + mNetworkListSharedStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -229,7 +230,9 @@ public class NetworkListStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkListSharedStoreData.deserializeData(in, in.getDepth()); + mNetworkListSharedStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); return mNetworkListSharedStoreData.getConfigurations(); } diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java index f40f71bcf..c0f03505e 100644 --- a/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/NetworkRequestStoreDataTest.java @@ -27,6 +27,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiNetworkFactory.AccessPoint; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -80,7 +81,7 @@ public class NetworkRequestStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.serializeData(out); + mNetworkRequestStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -92,7 +93,9 @@ public class NetworkRequestStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.deserializeData(in, in.getDepth()); + mNetworkRequestStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java index 5c1dcb459..a35c510fc 100644 --- a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionStoreDataTest.java @@ -28,6 +28,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion; import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -119,7 +120,7 @@ public class NetworkSuggestionStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkSuggestionStoreData.serializeData(out); + mNetworkSuggestionStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -131,7 +132,9 @@ public class NetworkSuggestionStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkSuggestionStoreData.deserializeData(in, in.getDepth()); + mNetworkSuggestionStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java index 4df560fd2..cdd4e6c84 100644 --- a/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/RandomizedMacStoreDataTest.java @@ -24,6 +24,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -62,7 +63,7 @@ public class RandomizedMacStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mRandomizedMacStoreData.serializeData(out); + mRandomizedMacStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -78,7 +79,9 @@ public class RandomizedMacStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mRandomizedMacStoreData.deserializeData(in, in.getDepth()); + mRandomizedMacStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); return mRandomizedMacStoreData.getMacMapping(); } diff --git a/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java index ac6ae21a2..feedc0d2a 100644 --- a/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/SsidSetStoreDataTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,6 +30,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -80,7 +82,7 @@ public class SsidSetStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mSsidSetStoreData.serializeData(out); + mSsidSetStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -95,7 +97,9 @@ public class SsidSetStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mSsidSetStoreData.deserializeData(in, in.getDepth()); + mSsidSetStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java index c814aef1a..df93eb4fb 100644 --- a/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WakeupConfigStoreDataTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -28,6 +29,7 @@ import android.util.Xml; import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.google.android.collect.Sets; @@ -74,7 +76,7 @@ public class WakeupConfigStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mWakeupConfigData.serializeData(out); + mWakeupConfigData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -88,7 +90,9 @@ public class WakeupConfigStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mWakeupConfigData.deserializeData(in, in.getDepth()); + mWakeupConfigData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** @@ -177,7 +181,9 @@ public class WakeupConfigStoreDataTest { */ @Test public void hasBeenReadIsTrueWhenUserStoreIsLoaded() throws Exception { - mWakeupConfigData.deserializeData(null /* in */, 0 /* outerTagDepth */); + mWakeupConfigData.deserializeData(null /* in */, 0 /* outerTagDepth */, + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); assertTrue(mWakeupConfigData.hasBeenRead()); } diff --git a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java index 009429b3f..a004995b9 100644 --- a/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WakeupControllerTest.java @@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -38,6 +39,7 @@ import android.provider.Settings; import androidx.test.filters.SmallTest; import com.android.server.wifi.util.ScanResultUtil; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -149,7 +151,9 @@ public class WakeupControllerTest { private void readUserStore() { try { - mWakeupConfigStoreData.deserializeData(null, 0); + mWakeupConfigStoreData.deserializeData(null, 0, + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } catch (XmlPullParserException | IOException e) { // unreachable } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 0badc6fbd..c4cbc6e50 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -234,7 +234,7 @@ public class WifiConfigManagerTest { .spyStatic(WifiConfigurationUtil.class) .strictness(Strictness.LENIENT) .startMocking(); - when(WifiConfigStore.createUserFiles(anyInt())).thenReturn(mock(List.class)); + when(WifiConfigStore.createUserFiles(anyInt(), anyBoolean())).thenReturn(mock(List.class)); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mDataTelephonyManager); when(WifiConfigurationUtil.calculatePersistentMacForConfiguration(any(), any())) .thenReturn(TEST_RANDOMIZED_MAC); diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java index b59e367dd..efa2d4336 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java @@ -16,12 +16,9 @@ package com.android.server.wifi; -import static com.android.server.wifi.WifiConfigStore.ZEROED_ENCRYPTED_DATA; - import static org.junit.Assert.*; import static org.mockito.Mockito.*; -import android.app.test.MockAnswerUtil.AnswerWithArguments; import android.app.test.TestAlarmManager; import android.content.Context; import android.content.pm.PackageManager; @@ -34,8 +31,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.ArrayUtils; import com.android.server.wifi.WifiConfigStore.StoreData; import com.android.server.wifi.WifiConfigStore.StoreFile; -import com.android.server.wifi.util.DataIntegrityChecker; import com.android.server.wifi.util.EncryptedData; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.XmlUtil; import libcore.util.HexEncoding; @@ -43,7 +40,6 @@ import libcore.util.HexEncoding; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.xmlpull.v1.XmlPullParser; @@ -73,13 +69,7 @@ public class WifiConfigStoreTest { private static final String TEST_DATA_XML_STRING_FORMAT = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" + "<WifiConfigStoreData>\n" - + "<int name=\"Version\" value=\"2\" />\n" - + "<Integrity>\n" - + "<byte-array name=\"EncryptedData\" num=\"48\">000000000000000000000000000000" - + "000000000000000000000000000000000000000000000000000000000000000000" - + "</byte-array>\n" - + "<byte-array name=\"IV\" num=\"12\">000000000000000000000000</byte-array>\n" - + "</Integrity>\n" + + "<int name=\"Version\" value=\"3\" />\n" + "<NetworkList>\n" + "<Network>\n" + "<WifiConfiguration>\n" @@ -172,7 +162,7 @@ public class WifiConfigStoreTest { private TestLooper mLooper; @Mock private Clock mClock; @Mock private WifiMetrics mWifiMetrics; - @Mock private DataIntegrityChecker mDataIntegrityChecker; + @Mock private WifiConfigStoreEncryptionUtil mEncryptionUtil; private MockStoreFile mSharedStore; private MockStoreFile mUserStore; private MockStoreFile mUserNetworkSuggestionsStore; @@ -196,10 +186,10 @@ public class WifiConfigStoreTest { .thenReturn(mAlarmManager.getAlarmManager()); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME); - when(mDataIntegrityChecker.compute(any(byte[].class))) - .thenReturn(ZEROED_ENCRYPTED_DATA); - when(mDataIntegrityChecker.isOk(any(byte[].class), any(EncryptedData.class))) - .thenReturn(true); + when(mEncryptionUtil.encrypt(any(byte[].class))) + .thenReturn(new EncryptedData(new byte[0], new byte[0])); + when(mEncryptionUtil.decrypt(any(EncryptedData.class))) + .thenReturn(new byte[0]); mSharedStore = new MockStoreFile(WifiConfigStore.STORE_FILE_SHARED_GENERAL); mUserStore = new MockStoreFile(WifiConfigStore.STORE_FILE_USER_GENERAL); mUserNetworkSuggestionsStore = @@ -432,9 +422,9 @@ public class WifiConfigStoreTest { // Ensure that we got the call to deserialize empty shared data, but no user data. verify(sharedStoreData).resetData(); - verify(sharedStoreData).deserializeData(eq(null), anyInt()); + verify(sharedStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); verify(userStoreData, never()).resetData(); - verify(userStoreData, never()).deserializeData(any(), anyInt()); + verify(userStoreData, never()).deserializeData(any(), anyInt(), anyInt(), any()); } /** @@ -462,9 +452,9 @@ public class WifiConfigStoreTest { // Ensure that we got the call to deserialize empty shared & user data. verify(userStoreData).resetData(); - verify(userStoreData).deserializeData(eq(null), anyInt()); + verify(userStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); verify(sharedStoreData).resetData(); - verify(sharedStoreData).deserializeData(eq(null), anyInt()); + verify(sharedStoreData).deserializeData(eq(null), anyInt(), anyInt(), any()); } /** @@ -639,9 +629,9 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(null); mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt()); - verify(storeData1, never()).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); // Scenario 2: StoreData2 in user store file. @@ -655,9 +645,9 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes()); mWifiConfigStore.read(); - verify(storeData1).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(notNull(), anyInt()); - verify(storeData2, never()).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); // Scenario 3: StoreData1 in shared store file & StoreData2 in user store file. @@ -671,10 +661,10 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(fileContentsXmlStringWithOnlyStoreData2.getBytes()); mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt()); - verify(storeData1, never()).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(notNull(), anyInt()); - verify(storeData2, never()).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); // Scenario 4: StoreData1 & StoreData2 in shared store file. @@ -689,10 +679,10 @@ public class WifiConfigStoreTest { mUserStore.storeRawDataToWrite(null); mWifiConfigStore.read(); - verify(storeData1).deserializeData(notNull(), anyInt()); - verify(storeData1, never()).deserializeData(eq(null), anyInt()); - verify(storeData2).deserializeData(notNull(), anyInt()); - verify(storeData2, never()).deserializeData(eq(null), anyInt()); + verify(storeData1).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData1, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); + verify(storeData2).deserializeData(notNull(), anyInt(), anyInt(), any()); + verify(storeData2, never()).deserializeData(eq(null), anyInt(), anyInt(), any()); reset(storeData1, storeData2); } @@ -739,9 +729,9 @@ public class WifiConfigStoreTest { verify(userStoreNetworkSuggestionsData).hasNewDataToSerialize(); // Verify that we serialized data from the first 2 data source, but not from the last one. - verify(sharedStoreData).serializeData(any()); - verify(userStoreData).serializeData(any()); - verify(userStoreNetworkSuggestionsData, never()).serializeData(any()); + verify(sharedStoreData).serializeData(any(), any()); + verify(userStoreData).serializeData(any(), any()); + verify(userStoreNetworkSuggestionsData, never()).serializeData(any(), any()); } /** @@ -815,190 +805,21 @@ public class WifiConfigStoreTest { // Read and verify the data content in the store file (metadata stripped out) has been sent // to the corresponding store data when integrity check passes. mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - - // We shouldn't perform any data integrity checks on version 1 file. - verifyZeroInteractions(mDataIntegrityChecker); - } - - /** - * Tests the read API behaviour when integrity check fails. - * Expected behaviour: The read should return an empty store data. - */ - @Test - public void testReadWhenIntegrityCheckFails() throws Exception { - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Now store some content in the shared and user data files. - mUserStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_USER_DATA).getBytes()); - mSharedStore.storeRawDataToWrite( - String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_SHARE_DATA).getBytes()); - - // Read and verify the data content in the store file (metadata stripped out) has been sent - // to the corresponding store data when integrity check passes. - mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - - // Read and verify the data content in the store file (metadata stripped out) has not been - // sent to the corresponding store data when integrity check fails. - when(mDataIntegrityChecker.isOk(any(byte[].class), any(EncryptedData.class))) - .thenReturn(false); - mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); + verify(sharedStoreData, times(1)).deserializeData( + any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION), any()); + verify(userStoreData, times(1)).deserializeData( + any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION), any()); } /** - * Tests the write API behaviour when integrity check fails. - * Expected behaviour: The read should return an empty store data. + * Tests the read API behaviour to ensure that the integrity data is parsed from the file. */ @Test - public void testWriteWhenIntegrityComputeFails() throws Exception { - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - when(sharedStoreData.hasNewDataToSerialize()).thenReturn(true); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - when(userStoreData.hasNewDataToSerialize()).thenReturn(true); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Reset store file contents & ensure that the user and store data files are empty. - mUserStore.storeRawDataToWrite(null); - mSharedStore.storeRawDataToWrite(null); - assertNull(mUserStore.getStoreBytes()); - assertNull(mSharedStore.getStoreBytes()); - - // Write and verify that the data is written to the config store file when integrity - // computation passes. - mWifiConfigStore.write(true); - assertNotNull(mUserStore.getStoreBytes()); - assertNotNull(mSharedStore.getStoreBytes()); - assertTrue(new String(mUserStore.getStoreBytes()).contains(TEST_USER_DATA)); - assertTrue(new String(mSharedStore.getStoreBytes()).contains(TEST_SHARE_DATA)); - - // Reset store file contents & ensure that the user and store data files are empty. - mUserStore.storeRawDataToWrite(null); - mSharedStore.storeRawDataToWrite(null); - assertNull(mUserStore.getStoreBytes()); - assertNull(mSharedStore.getStoreBytes()); - - // Write and verify that the data is not written to the config store file when integrity - // computation fails. - when(mDataIntegrityChecker.compute(any(byte[].class))).thenReturn(null); - mWifiConfigStore.write(true); - assertNull(mUserStore.getStoreBytes()); - assertNull(mSharedStore.getStoreBytes()); - } - - /** - * Tests the write API behaviour to ensure that the integrity data is written to the file. - */ - @Test - public void testWriteContainsIntegrityData() throws Exception { - byte[] encryptedData = new byte[EncryptedData.ENCRYPTED_DATA_LENGTH]; - byte[] iv = new byte[EncryptedData.IV_LENGTH]; - Random random = new Random(); - random.nextBytes(encryptedData); - random.nextBytes(iv); - final EncryptedData testEncryptedData = new EncryptedData(encryptedData, iv); - - doAnswer(new AnswerWithArguments() { - public EncryptedData answer(byte[] data) { - String storeXmlString = new String(data); - // Verify that we fill in zeros to the data when we compute integrity. - if (storeXmlString.contains(TEST_SHARE_DATA)) { - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_SHARE_DATA), storeXmlString); - } else if (storeXmlString.contains(TEST_USER_DATA)) { - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_USER_DATA), storeXmlString); - } - return testEncryptedData; - } - }).when(mDataIntegrityChecker).compute(any(byte[].class)); - - // Register data container. - StoreData sharedStoreData = mock(StoreData.class); - when(sharedStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_SHARED_GENERAL); - when(sharedStoreData.getName()).thenReturn(TEST_SHARE_DATA); - when(sharedStoreData.hasNewDataToSerialize()).thenReturn(true); - StoreData userStoreData = mock(StoreData.class); - when(userStoreData.getStoreFileId()) - .thenReturn(WifiConfigStore.STORE_FILE_USER_GENERAL); - when(userStoreData.getName()).thenReturn(TEST_USER_DATA); - when(userStoreData.hasNewDataToSerialize()).thenReturn(true); - mWifiConfigStore.registerStoreData(sharedStoreData); - mWifiConfigStore.registerStoreData(userStoreData); - - // Read both share and user config store. - mWifiConfigStore.setUserStores(mUserStores); - - // Write and verify that the data is written to the config store file when integrity - // computation passes. - mWifiConfigStore.write(true); - - // Verify that we fill in zeros to the data when we computed integrity. - verify(mDataIntegrityChecker, times(2)).compute(any(byte[].class)); - - // Verify the parsed integrity data - assertNotNull(mUserStore.getStoreBytes()); - assertNotNull(mSharedStore.getStoreBytes()); - String userStoreXmlString = new String(mUserStore.getStoreBytes()); - String sharedStoreXmlString = new String(mSharedStore.getStoreBytes()); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(encryptedData).toLowerCase(), - HexEncoding.encodeToString(iv).toLowerCase(), - TEST_USER_DATA), userStoreXmlString); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(encryptedData).toLowerCase(), - HexEncoding.encodeToString(iv).toLowerCase(), - TEST_SHARE_DATA), sharedStoreXmlString); - } - - /** - * Tests the read API behaviour to ensure that the integrity data is parsed from the file and - * used for checking integrity of the file. - */ - @Test - public void testReadParsesIntegrityData() throws Exception { - byte[] encryptedData = new byte[EncryptedData.ENCRYPTED_DATA_LENGTH]; - byte[] iv = new byte[EncryptedData.IV_LENGTH]; + public void testReadVersion2StoreFile() throws Exception { + byte[] encryptedData = new byte[0]; + byte[] iv = new byte[0]; Random random = new Random(); random.nextBytes(encryptedData); random.nextBytes(iv); @@ -1033,40 +854,14 @@ public class WifiConfigStoreTest { TEST_SHARE_DATA).getBytes()); // Read and verify the data content in the store file (metadata stripped out) has been sent - // to the corresponding store data when integrity check passes. + // to the corresponding store data. mWifiConfigStore.read(); - verify(sharedStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - verify(userStoreData, times(1)).deserializeData(any(XmlPullParser.class), anyInt()); - - // Verify that we parsed the integrity data and used it for checking integrity of the file. - ArgumentCaptor<EncryptedData> integrityCaptor = - ArgumentCaptor.forClass(EncryptedData.class); - ArgumentCaptor<byte[]> dataCaptor = ArgumentCaptor.forClass(byte[].class); - // Will be invoked twice for each file - shared & user store file. - verify(mDataIntegrityChecker, times(2)).isOk( - dataCaptor.capture(), integrityCaptor.capture()); - // Verify the parsed integrity data - assertEquals(2, integrityCaptor.getAllValues().size()); - EncryptedData parsedEncryptedData1 = integrityCaptor.getAllValues().get(0); - assertArrayEquals(encryptedData, parsedEncryptedData1.getEncryptedData()); - assertArrayEquals(iv, parsedEncryptedData1.getIv()); - EncryptedData parsedEncryptedData2 = integrityCaptor.getAllValues().get(1); - assertArrayEquals(encryptedData, parsedEncryptedData2.getEncryptedData()); - assertArrayEquals(iv, parsedEncryptedData2.getIv()); - - // Verify that we fill in zeros to the data when we performed integrity checked. - assertEquals(2, dataCaptor.getAllValues().size()); - String sharedStoreXmlStringWithZeroedIntegrity = - new String(dataCaptor.getAllValues().get(0)); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_SHARE_DATA), sharedStoreXmlStringWithZeroedIntegrity); - String userStoreXmlStringWithZeroedIntegrity = new String(dataCaptor.getAllValues().get(1)); - assertEquals(String.format(TEST_DATA_XML_STRING_FORMAT_V2_WITH_ONE_DATA_SOURCE, - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getEncryptedData()), - HexEncoding.encodeToString(ZEROED_ENCRYPTED_DATA.getIv()), - TEST_USER_DATA), userStoreXmlStringWithZeroedIntegrity); + verify(sharedStoreData, times(1)) + .deserializeData(any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INTEGRITY_CONFIG_STORE_DATA_VERSION), any()); + verify(userStoreData, times(1)) + .deserializeData(any(XmlPullParser.class), anyInt(), + eq(WifiConfigStore.INTEGRITY_CONFIG_STORE_DATA_VERSION), any()); } /** @@ -1078,7 +873,7 @@ public class WifiConfigStoreTest { private boolean mStoreWritten; MockStoreFile(@WifiConfigStore.StoreFileId int fileId) { - super(new File("MockStoreFile"), fileId, mDataIntegrityChecker); + super(new File("MockStoreFile"), fileId, mEncryptionUtil); } @Override @@ -1129,13 +924,14 @@ public class WifiConfigStoreTest { } @Override - public void serializeData(XmlSerializer out) + public void serializeData(XmlSerializer out, WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mData); } @Override - public void deserializeData(XmlPullParser in, int outerTagDepth) + public void deserializeData(XmlPullParser in, int outerTagDepth, int version, + WifiConfigStoreEncryptionUtil encryptionUtil) throws XmlPullParserException, IOException { if (in == null) { return; diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java index 222c4953a..d20c99c4f 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -68,6 +68,7 @@ import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiNetworkFactory.AccessPoint; import com.android.server.wifi.nano.WifiMetricsProto; import com.android.server.wifi.util.ScanResultUtil; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import com.android.server.wifi.util.WifiPermissionsUtil; import org.junit.After; @@ -2932,7 +2933,7 @@ public class WifiNetworkFactoryTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.serializeData(out); + mNetworkRequestStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -2947,6 +2948,8 @@ public class WifiNetworkFactoryTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mNetworkRequestStoreData.deserializeData(in, in.getDepth()); + mNetworkRequestStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } } diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java index c76e2c878..7a815001c 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigSharedStoreDataTest.java @@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.WifiConfigStore; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -62,7 +63,7 @@ public class PasspointConfigSharedStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.serializeData(out); + mConfigStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -77,7 +78,9 @@ public class PasspointConfigSharedStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.deserializeData(in, in.getDepth()); + mConfigStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java index 82cdb5a90..5278e1933 100644 --- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointConfigUserStoreDataTest.java @@ -32,6 +32,7 @@ import com.android.internal.util.FastXmlSerializer; import com.android.server.wifi.SIMAccessor; import com.android.server.wifi.WifiConfigStore; import com.android.server.wifi.WifiKeyStore; +import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil; import org.junit.Before; import org.junit.Test; @@ -213,7 +214,7 @@ public class PasspointConfigUserStoreDataTest { final XmlSerializer out = new FastXmlSerializer(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.serializeData(out); + mConfigStoreData.serializeData(out, mock(WifiConfigStoreEncryptionUtil.class)); out.flush(); return outputStream.toByteArray(); } @@ -228,7 +229,9 @@ public class PasspointConfigUserStoreDataTest { final XmlPullParser in = Xml.newPullParser(); final ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); - mConfigStoreData.deserializeData(in, in.getDepth()); + mConfigStoreData.deserializeData(in, in.getDepth(), + WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, + mock(WifiConfigStoreEncryptionUtil.class)); } /** diff --git a/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java b/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java deleted file mode 100644 index c281b6440..000000000 --- a/tests/wifitests/src/com/android/server/wifi/util/DataIntegrityCheckerTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2018 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.server.wifi.util; - -import static org.junit.Assert.*; - -import org.junit.Ignore; -import org.junit.Test; - -import java.io.File; - -/** - * Unit tests for {@link com.android.server.wifi.util.DataIntegrityChecker}. - */ -public class DataIntegrityCheckerTest { - private static byte[] sGoodData = {1, 2, 3, 4}; - private static byte[] sBadData = {5, 6, 7, 8}; - - /** - * Verify that updating the integrity token with known data and alias will - * pass the integrity test. This test ensure the expected outcome for - * unedited data succeeds. - * - * @throws Exception - */ - @Test - @Ignore - public void testIntegrityWithKnownDataAndKnownAlias() throws Exception { - File integrityFile = File.createTempFile("testIntegrityWithKnownDataAndKnownAlias", - ".tmp"); - DataIntegrityChecker dataIntegrityChecker = new DataIntegrityChecker( - integrityFile.getParent()); - EncryptedData encryptedData = dataIntegrityChecker.compute(sGoodData); - assertTrue(dataIntegrityChecker.isOk(sGoodData, encryptedData)); - } - - /** - * Verify that checking the integrity of unknown data and a known alias - * will fail the integrity test. This test ensure the expected failure for - * altered data, in fact, fails. - * - * - * @throws Exception - */ - @Test - @Ignore - public void testIntegrityWithUnknownDataAndKnownAlias() throws Exception { - File integrityFile = File.createTempFile("testIntegrityWithUnknownDataAndKnownAlias", - ".tmp"); - DataIntegrityChecker dataIntegrityChecker = new DataIntegrityChecker( - integrityFile.getParent()); - EncryptedData encryptedData = dataIntegrityChecker.compute(sGoodData); - assertFalse(dataIntegrityChecker.isOk(sBadData, encryptedData)); - } -} diff --git a/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java index 85b4a9370..8f96bc106 100644 --- a/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java +++ b/tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java @@ -35,7 +35,9 @@ import com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil; import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil; import com.android.server.wifi.util.XmlUtil.WifiEnterpriseConfigXmlUtil; +import org.junit.Before; import org.junit.Test; +import org.mockito.MockitoAnnotations; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -73,6 +75,13 @@ public class XmlUtilTest { private static final int TEST_PHASE2_METHOD = WifiEnterpriseConfig.Phase2.MSCHAPV2; private final String mXmlDocHeader = "XmlUtilTest"; + private WifiConfigStoreEncryptionUtil mWifiConfigStoreEncryptionUtil = null; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + /** * Verify that a open WifiConfiguration is serialized & deserialized correctly. */ @@ -101,6 +110,22 @@ public class XmlUtilTest { } /** + * Verify that a psk WifiConfiguration is serialized & deserialized correctly. + */ + @Test + public void testPskWifiConfigurationSerializeDeserializeWithEncryption() + throws IOException, XmlPullParserException { + mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class); + WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork(); + EncryptedData encryptedData = new EncryptedData(new byte[0], new byte[0]); + when(mWifiConfigStoreEncryptionUtil.encrypt(pskNetwork.preSharedKey.getBytes())) + .thenReturn(encryptedData); + when(mWifiConfigStoreEncryptionUtil.decrypt(encryptedData)) + .thenReturn(pskNetwork.preSharedKey.getBytes()); + serializeDeserializeWifiConfiguration(pskNetwork); + } + + /** * Verify that a psk hidden WifiConfiguration is serialized & deserialized correctly. */ @Test @@ -382,6 +407,37 @@ public class XmlUtilTest { } /** + * Verify that a WifiEnterpriseConfig object is serialized & deserialized correctly. + */ + @Test + public void testWifiEnterpriseConfigSerializeDeserializeWithEncryption() + throws IOException, XmlPullParserException { + WifiEnterpriseConfig config = new WifiEnterpriseConfig(); + config.setFieldValue(WifiEnterpriseConfig.IDENTITY_KEY, TEST_IDENTITY); + config.setFieldValue(WifiEnterpriseConfig.ANON_IDENTITY_KEY, TEST_ANON_IDENTITY); + config.setFieldValue(WifiEnterpriseConfig.PASSWORD_KEY, TEST_PASSWORD); + config.setFieldValue(WifiEnterpriseConfig.CLIENT_CERT_KEY, TEST_CLIENT_CERT); + config.setFieldValue(WifiEnterpriseConfig.CA_CERT_KEY, TEST_CA_CERT); + config.setFieldValue(WifiEnterpriseConfig.SUBJECT_MATCH_KEY, TEST_SUBJECT_MATCH); + config.setFieldValue(WifiEnterpriseConfig.ENGINE_KEY, TEST_ENGINE); + config.setFieldValue(WifiEnterpriseConfig.ENGINE_ID_KEY, TEST_ENGINE_ID); + config.setFieldValue(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY, TEST_PRIVATE_KEY_ID); + config.setFieldValue(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY, TEST_ALTSUBJECT_MATCH); + config.setFieldValue(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY, TEST_DOM_SUFFIX_MATCH); + config.setFieldValue(WifiEnterpriseConfig.CA_PATH_KEY, TEST_CA_PATH); + config.setEapMethod(TEST_EAP_METHOD); + config.setPhase2Method(TEST_PHASE2_METHOD); + + mWifiConfigStoreEncryptionUtil = mock(WifiConfigStoreEncryptionUtil.class); + EncryptedData encryptedData = new EncryptedData(new byte[0], new byte[0]); + when(mWifiConfigStoreEncryptionUtil.encrypt(TEST_PASSWORD.getBytes())) + .thenReturn(encryptedData); + when(mWifiConfigStoreEncryptionUtil.decrypt(encryptedData)) + .thenReturn(TEST_PASSWORD.getBytes()); + serializeDeserializeWifiEnterpriseConfig(config); + } + + /** * Verify that an illegal argument exception is thrown when trying to parse out a corrupted * WifiEnterpriseConfig. * @@ -473,7 +529,8 @@ public class XmlUtilTest { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); XmlUtil.writeDocumentStart(out, mXmlDocHeader); - WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, configuration); + WifiConfigurationXmlUtil.writeToXmlForConfigStore( + out, configuration, mWifiConfigStoreEncryptionUtil); XmlUtil.writeDocumentEnd(out, mXmlDocHeader); return outputStream.toByteArray(); } @@ -485,7 +542,10 @@ public class XmlUtilTest { ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - return WifiConfigurationXmlUtil.parseFromXml(in, in.getDepth()); + return WifiConfigurationXmlUtil.parseFromXml( + in, in.getDepth(), + mWifiConfigStoreEncryptionUtil != null, + mWifiConfigStoreEncryptionUtil); } /** @@ -593,7 +653,8 @@ public class XmlUtilTest { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); out.setOutput(outputStream, StandardCharsets.UTF_8.name()); XmlUtil.writeDocumentStart(out, mXmlDocHeader); - WifiEnterpriseConfigXmlUtil.writeToXml(out, config); + WifiEnterpriseConfigXmlUtil.writeToXml( + out, config, mWifiConfigStoreEncryptionUtil); XmlUtil.writeDocumentEnd(out, mXmlDocHeader); return outputStream.toByteArray(); } @@ -604,7 +665,9 @@ public class XmlUtilTest { ByteArrayInputStream inputStream = new ByteArrayInputStream(data); in.setInput(inputStream, StandardCharsets.UTF_8.name()); XmlUtil.gotoDocumentStart(in, mXmlDocHeader); - return WifiEnterpriseConfigXmlUtil.parseFromXml(in, in.getDepth()); + return WifiEnterpriseConfigXmlUtil.parseFromXml( + in, in.getDepth(), mWifiConfigStoreEncryptionUtil != null, + mWifiConfigStoreEncryptionUtil); } private void serializeDeserializeWifiEnterpriseConfig(WifiEnterpriseConfig config) |