summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoshan Pius <rpius@google.com>2019-10-22 16:38:36 -0700
committerRoshan Pius <rpius@google.com>2019-11-14 12:12:55 -0800
commit09621a42f86690346814c48cf1cdb1f123402e12 (patch)
tree52a587e81b7b78424e1c5797bdc80cc6072046ae
parent6237115f3c6ae723eb3927640c843714793fbe59 (diff)
WifiConfigStore: Encrypt credentials for networks (3/4)
Encrypt/Decrypt preSharedKey & enterprise config's password fields. When deserializing, handle migration from older config store version file. Any encryption failure are silently ignored. Decryption failures are however non-recoverable. Bug: 140485110 Test: atest com.android.server.wifi Test: Manual verification - Store a PSK network config on older build - Upgrade to build with this CL - Ensured that the psk was read correctly on upgrade - Ensured that the psk was encrypted when stored on disk after upgrade Change-Id: Ic7673cb375c9e5447ff4074ed78321152573e1c3 Merged-In: Ic7673cb375c9e5447ff4074ed78321152573e1c3
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java6
-rw-r--r--service/java/com/android/server/wifi/util/EncryptedData.java27
-rw-r--r--service/java/com/android/server/wifi/util/XmlUtil.java563
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java8
-rw-r--r--tests/wifitests/src/com/android/server/wifi/util/XmlUtilTest.java67
5 files changed, 429 insertions, 242 deletions
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index dee52a795..350e8b52f 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -170,12 +170,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
*/
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/XmlUtil.java b/service/java/com/android/server/wifi/util/XmlUtil.java
index 292c7929a..6128b0b4c 100644
--- a/service/java/com/android/server/wifi/util/XmlUtil.java
+++ b/service/java/com/android/server/wifi/util/XmlUtil.java
@@ -30,6 +30,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;
@@ -379,12 +380,42 @@ 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 configuration WifiConfiguration object to be serialized.
- * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}.
+ * @param encryptionUtil Instance of {@link EncryptedDataXmlUtil}. Backup/restore stores
+ * keys unencrypted.
*/
public static void writeCommonElementsToXml(
XmlSerializer out, WifiConfiguration configuration,
@@ -393,7 +424,7 @@ public class XmlUtil {
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);
@@ -517,13 +548,13 @@ public class XmlUtil {
*
* @param in XmlPullParser instance pointing to the XML stream.
* @param outerTagDepth depth of the outer tag in the XML document.
- * @param areCredentialsEncrypted Whether credentials are encrypted or not.
+ * @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, boolean areCredentialsEncrypted,
+ XmlPullParser in, int outerTagDepth, boolean shouldExpectEncryptedCredentials,
@NonNull WifiConfigStoreEncryptionUtil encryptionUtil)
throws XmlPullParserException, IOException {
WifiConfiguration configuration = new WifiConfiguration();
@@ -532,147 +563,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) {
+ 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) {
@@ -1028,6 +1087,35 @@ 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,
+ @NonNull 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.
*
@@ -1042,8 +1130,9 @@ public class XmlUtil {
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,
@@ -1073,87 +1162,123 @@ public class XmlUtil {
*
* @param in XmlPullParser instance pointing to the XML stream.
* @param outerTagDepth depth of the outer tag in the XML document.
- * @param areCredentialsEncrypted Whether credentials are encrypted or not.
+ * @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,
- boolean areCredentialsEncrypted,
+ boolean shouldExpectEncryptedCredentials,
@NonNull WifiConfigStoreEncryptionUtil encryptionUtil)
throws XmlPullParserException, IOException {
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
// 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_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);
- 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]);
+ 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) {
+ 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;
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
index 9c16b1257..efa2d4336 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
@@ -16,8 +16,6 @@
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.*;
@@ -189,7 +187,7 @@ public class WifiConfigStoreTest {
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME);
when(mEncryptionUtil.encrypt(any(byte[].class)))
- .thenReturn(ZEROED_ENCRYPTED_DATA);
+ .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);
@@ -820,8 +818,8 @@ public class WifiConfigStoreTest {
*/
@Test
public void testReadVersion2StoreFile() throws Exception {
- byte[] encryptedData = new byte[EncryptedData.ENCRYPTED_DATA_LENGTH];
- byte[] iv = new byte[EncryptedData.IV_LENGTH];
+ byte[] encryptedData = new byte[0];
+ byte[] iv = new byte[0];
Random random = new Random();
random.nextBytes(encryptedData);
random.nextBytes(iv);
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 126a80d3c..66534d247 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,11 @@ 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.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -73,6 +77,13 @@ public class XmlUtilTest {
private static final int TEST_PHASE2_METHOD = WifiEnterpriseConfig.Phase2.MSCHAPV2;
private final String mXmlDocHeader = "XmlUtilTest";
+ @Mock private WifiConfigStoreEncryptionUtil mWifiConfigStoreEncryptionUtil;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
/**
* Verify that a open WifiConfiguration is serialized & deserialized correctly.
*/
@@ -101,6 +112,21 @@ public class XmlUtilTest {
}
/**
+ * Verify that a psk WifiConfiguration is serialized & deserialized correctly.
+ */
+ @Test
+ public void testPskWifiConfigurationSerializeDeserializeWithEncryption()
+ throws IOException, XmlPullParserException {
+ 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 +408,36 @@ 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);
+
+ 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.
*
@@ -474,7 +530,7 @@ public class XmlUtilTest {
out.setOutput(outputStream, StandardCharsets.UTF_8.name());
XmlUtil.writeDocumentStart(out, mXmlDocHeader);
WifiConfigurationXmlUtil.writeToXmlForConfigStore(
- out, configuration, mock(WifiConfigStoreEncryptionUtil.class));
+ out, configuration, mWifiConfigStoreEncryptionUtil);
XmlUtil.writeDocumentEnd(out, mXmlDocHeader);
return outputStream.toByteArray();
}
@@ -487,7 +543,9 @@ public class XmlUtilTest {
in.setInput(inputStream, StandardCharsets.UTF_8.name());
XmlUtil.gotoDocumentStart(in, mXmlDocHeader);
return WifiConfigurationXmlUtil.parseFromXml(
- in, in.getDepth(), false, mock(WifiConfigStoreEncryptionUtil.class));
+ in, in.getDepth(),
+ mWifiConfigStoreEncryptionUtil != null,
+ mWifiConfigStoreEncryptionUtil);
}
/**
@@ -596,7 +654,7 @@ public class XmlUtilTest {
out.setOutput(outputStream, StandardCharsets.UTF_8.name());
XmlUtil.writeDocumentStart(out, mXmlDocHeader);
WifiEnterpriseConfigXmlUtil.writeToXml(
- out, config, mock(WifiConfigStoreEncryptionUtil.class));
+ out, config, mWifiConfigStoreEncryptionUtil);
XmlUtil.writeDocumentEnd(out, mXmlDocHeader);
return outputStream.toByteArray();
}
@@ -608,7 +666,8 @@ public class XmlUtilTest {
in.setInput(inputStream, StandardCharsets.UTF_8.name());
XmlUtil.gotoDocumentStart(in, mXmlDocHeader);
return WifiEnterpriseConfigXmlUtil.parseFromXml(
- in, in.getDepth(), false, mock(WifiConfigStoreEncryptionUtil.class));
+ in, in.getDepth(), mWifiConfigStoreEncryptionUtil != null,
+ mWifiConfigStoreEncryptionUtil);
}
private void serializeDeserializeWifiEnterpriseConfig(WifiEnterpriseConfig config)