diff --git a/wifi/java/android/net/wifi/SecurityParams.java b/wifi/java/android/net/wifi/SecurityParams.java new file mode 100644 index 0000000000000..157d1c5748d07 --- /dev/null +++ b/wifi/java/android/net/wifi/SecurityParams.java @@ -0,0 +1,794 @@ +/* + * Copyright (C) 2020 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 android.net.wifi; + +import android.annotation.NonNull; +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.net.wifi.WifiConfiguration.GroupCipher; +import android.net.wifi.WifiConfiguration.GroupMgmtCipher; +import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; +import android.net.wifi.WifiConfiguration.SecurityType; +import android.net.wifi.WifiConfiguration.SuiteBCipher; +import android.os.Parcel; + +import java.util.BitSet; +import java.util.Objects; + +/** + * A class representing a security configuration. + * @hide + */ +public class SecurityParams { + private static final String TAG = "SecurityParams"; + + private @SecurityType int mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + + /** + * This indicates that this security type is enabled or disabled. + * Ex. While receiving Transition Disable Indication, older + * security should be disabled. + */ + private boolean mEnabled = true; + + /** + * The set of key management protocols supported by this configuration. + * See {@link KeyMgmt} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedKeyManagement = new BitSet(); + + /** + * The set of security protocols supported by this configuration. + * See {@link Protocol} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedProtocols = new BitSet(); + + /** + * The set of authentication protocols supported by this configuration. + * See {@link AuthAlgorithm} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedAuthAlgorithms = new BitSet(); + + /** + * The set of pairwise ciphers for WPA supported by this configuration. + * See {@link PairwiseCipher} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedPairwiseCiphers = new BitSet(); + + /** + * The set of group ciphers supported by this configuration. + * See {@link GroupCipher} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedGroupCiphers = new BitSet(); + + /** + * The set of group management ciphers supported by this configuration. + * See {@link GroupMgmtCipher} for descriptions of the values. + */ + private BitSet mAllowedGroupManagementCiphers = new BitSet(); + + /** + * The set of SuiteB ciphers supported by this configuration. + * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the + * certificate type that is used in this configuration. + */ + private BitSet mAllowedSuiteBCiphers = new BitSet(); + + /** + * True if the network requires Protected Management Frames (PMF), false otherwise. + */ + private boolean mRequirePmf = false; + + /** Indicate that this SAE security type only accepts H2E (Hash-to-Element) mode. */ + private boolean mIsSaeH2eOnlyMode = false; + + /** Indicate that this SAE security type only accepts PK (Public Key) mode. */ + private boolean mIsSaePkOnlyMode = false; + + /** Indicate whether this is added by auto-upgrade or not. */ + private boolean mIsAddedByAutoUpgrade = false; + + /** Constructor */ + private SecurityParams() { + } + + /** Copy constructor */ + public SecurityParams(@NonNull SecurityParams source) { + this.mSecurityType = source.mSecurityType; + this.mEnabled = source.mEnabled; + this.mAllowedKeyManagement = (BitSet) source.mAllowedKeyManagement.clone(); + this.mAllowedProtocols = (BitSet) source.mAllowedProtocols.clone(); + this.mAllowedAuthAlgorithms = (BitSet) source.mAllowedAuthAlgorithms.clone(); + this.mAllowedPairwiseCiphers = (BitSet) source.mAllowedPairwiseCiphers.clone(); + this.mAllowedGroupCiphers = (BitSet) source.mAllowedGroupCiphers.clone(); + this.mAllowedGroupManagementCiphers = + (BitSet) source.mAllowedGroupManagementCiphers.clone(); + this.mAllowedSuiteBCiphers = + (BitSet) source.mAllowedSuiteBCiphers.clone(); + this.mRequirePmf = source.mRequirePmf; + this.mIsSaeH2eOnlyMode = source.mIsSaeH2eOnlyMode; + this.mIsSaePkOnlyMode = source.mIsSaePkOnlyMode; + this.mIsAddedByAutoUpgrade = source.mIsAddedByAutoUpgrade; + } + + @Override + public boolean equals(Object thatObject) { + if (this == thatObject) { + return true; + } + if (!(thatObject instanceof SecurityParams)) { + return false; + } + SecurityParams that = (SecurityParams) thatObject; + + if (this.mSecurityType != that.mSecurityType) return false; + if (this.mEnabled != that.mEnabled) return false; + if (!this.mAllowedKeyManagement.equals(that.mAllowedKeyManagement)) return false; + if (!this.mAllowedProtocols.equals(that.mAllowedProtocols)) return false; + if (!this.mAllowedAuthAlgorithms.equals(that.mAllowedAuthAlgorithms)) return false; + if (!this.mAllowedPairwiseCiphers.equals(that.mAllowedPairwiseCiphers)) return false; + if (!this.mAllowedGroupCiphers.equals(that.mAllowedGroupCiphers)) return false; + if (!this.mAllowedGroupManagementCiphers.equals(that.mAllowedGroupManagementCiphers)) { + return false; + } + if (!this.mAllowedSuiteBCiphers.equals(that.mAllowedSuiteBCiphers)) return false; + if (this.mRequirePmf != that.mRequirePmf) return false; + if (this.mIsSaeH2eOnlyMode != that.mIsSaeH2eOnlyMode) return false; + if (this.mIsSaePkOnlyMode != that.mIsSaePkOnlyMode) return false; + if (this.mIsAddedByAutoUpgrade != that.mIsAddedByAutoUpgrade) return false; + + return true; + } + + @Override + public int hashCode() { + return Objects.hash(mSecurityType, mEnabled, + mAllowedKeyManagement, mAllowedProtocols, mAllowedAuthAlgorithms, + mAllowedPairwiseCiphers, mAllowedGroupCiphers, mAllowedGroupManagementCiphers, + mAllowedSuiteBCiphers, mRequirePmf, + mIsSaeH2eOnlyMode, mIsSaePkOnlyMode, mIsAddedByAutoUpgrade); + } + + /** + * Check the security type of this params. + * + * @param type the testing security type. + * @return true if this is for the corresponiding type. + */ + public boolean isSecurityType(@SecurityType int type) { + return type == mSecurityType; + } + + /** + * Check whether the security of given params is the same as this one. + * + * @param params the testing security params. + * @return true if their security types are the same. + */ + public boolean isSameSecurityType(SecurityParams params) { + return params.mSecurityType == mSecurityType; + } + + /** + * Update security params to legacy WifiConfiguration object. + * + * @param config the target configuration. + */ + public void updateLegacyWifiConfiguration(WifiConfiguration config) { + config.allowedKeyManagement = (BitSet) mAllowedKeyManagement.clone(); + config.allowedProtocols = (BitSet) mAllowedProtocols.clone(); + config.allowedAuthAlgorithms = (BitSet) mAllowedAuthAlgorithms.clone(); + config.allowedPairwiseCiphers = (BitSet) mAllowedPairwiseCiphers.clone(); + config.allowedGroupCiphers = (BitSet) mAllowedGroupCiphers.clone(); + config.allowedGroupManagementCiphers = (BitSet) mAllowedGroupManagementCiphers.clone(); + config.allowedSuiteBCiphers = (BitSet) mAllowedSuiteBCiphers.clone(); + config.requirePmf = mRequirePmf; + } + + /** + * Set this params enabled. + * + * @param enable enable a specific security type. + */ + public void setEnabled(boolean enable) { + mEnabled = enable; + } + + /** + * Indicate this params is enabled or not. + */ + public boolean isEnabled() { + return mEnabled; + } + + /** + * Set the supporting Fast Initial Link Set-up (FILS) key management. + * + * FILS can be applied to all security types. + * @param enableFilsSha256 Enable FILS SHA256. + * @param enableFilsSha384 Enable FILS SHA256. + */ + public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) { + if (enableFilsSha256) { + mAllowedKeyManagement.set(KeyMgmt.FILS_SHA256); + } + + if (enableFilsSha384) { + mAllowedKeyManagement.set(KeyMgmt.FILS_SHA384); + } + } + + /** + * Get the copy of allowed key management. + */ + public BitSet getAllowedKeyManagement() { + return (BitSet) mAllowedKeyManagement.clone(); + } + + /** + * Get the copy of allowed protocols. + */ + public BitSet getAllowedProtocols() { + return (BitSet) mAllowedProtocols.clone(); + } + + /** + * Get the copy of allowed auth algorithms. + */ + public BitSet getAllowedAuthAlgorithms() { + return (BitSet) mAllowedAuthAlgorithms.clone(); + } + + /** + * Get the copy of allowed pairwise ciphers. + */ + public BitSet getAllowedPairwiseCiphers() { + return (BitSet) mAllowedPairwiseCiphers.clone(); + } + + /** + * Get the copy of allowed group ciphers. + */ + public BitSet getAllowedGroupCiphers() { + return (BitSet) mAllowedGroupCiphers.clone(); + } + + /** + * Get the copy of allowed group management ciphers. + */ + public BitSet getAllowedGroupManagementCiphers() { + return (BitSet) mAllowedGroupManagementCiphers.clone(); + } + + /** + * Enable Suite-B ciphers. + * + * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support. + * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support. + */ + public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) { + if (enableEcdheEcdsa) { + mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_ECDSA); + } else { + mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_ECDSA); + } + + if (enableEcdheRsa) { + mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_RSA); + } else { + mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_RSA); + } + } + + /** + * Get the copy of allowed suite-b ciphers. + */ + public BitSet getAllowedSuiteBCiphers() { + return (BitSet) mAllowedSuiteBCiphers.clone(); + } + + /** + * Indicate PMF is required or not. + */ + public boolean isRequirePmf() { + return mRequirePmf; + } + + /** + * Indicate that this is open security type. + */ + public boolean isOpenSecurityType() { + return isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN) + || isSecurityType(WifiConfiguration.SECURITY_TYPE_OWE); + } + + /** + * Indicate that this is enterprise security type. + */ + public boolean isEnterpriseSecurityType() { + return mAllowedKeyManagement.get(KeyMgmt.WPA_EAP) + || mAllowedKeyManagement.get(KeyMgmt.IEEE8021X) + || mAllowedKeyManagement.get(KeyMgmt.SUITE_B_192) + || mAllowedKeyManagement.get(KeyMgmt.WAPI_CERT); + } + + /** + * Enable Hash-to-Element only mode. + * + * @param enable set H2E only mode enabled or not. + */ + public void enableSaeH2eOnlyMode(boolean enable) { + mIsSaeH2eOnlyMode = enable; + } + + /** + * Indicate whether this params is H2E only mode. + * + * @return true if this is H2E only mode params. + */ + public boolean isSaeH2eOnlyMode() { + return mIsSaeH2eOnlyMode; + } + /** + * Enable Pubilc-Key only mode. + * + * @param enable set PK only mode enabled or not. + */ + public void enableSaePkOnlyMode(boolean enable) { + mIsSaePkOnlyMode = enable; + } + + /** + * Indicate whether this params is PK only mode. + * + * @return true if this is PK only mode params. + */ + public boolean isSaePkOnlyMode() { + return mIsSaePkOnlyMode; + } + + /** + * Set whether this is added by auto-upgrade. + * + * @param addedByAutoUpgrade true if added by auto-upgrade. + */ + public void setIsAddedByAutoUpgrade(boolean addedByAutoUpgrade) { + mIsAddedByAutoUpgrade = addedByAutoUpgrade; + } + + /** + * Indicate whether this is added by auto-upgrade or not. + * + * @return true if added by auto-upgrade; otherwise, false. + */ + public boolean isAddedByAutoUpgrade() { + return mIsAddedByAutoUpgrade; + } + + @Override + public String toString() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("Security Parameters:\n"); + sbuf.append(" Type: ").append(mSecurityType).append("\n"); + sbuf.append(" Enabled: ").append(mEnabled).append("\n"); + sbuf.append(" KeyMgmt:"); + for (int k = 0; k < mAllowedKeyManagement.size(); k++) { + if (mAllowedKeyManagement.get(k)) { + sbuf.append(" "); + if (k < KeyMgmt.strings.length) { + sbuf.append(KeyMgmt.strings[k]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" Protocols:"); + for (int p = 0; p < mAllowedProtocols.size(); p++) { + if (mAllowedProtocols.get(p)) { + sbuf.append(" "); + if (p < Protocol.strings.length) { + sbuf.append(Protocol.strings[p]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" AuthAlgorithms:"); + for (int a = 0; a < mAllowedAuthAlgorithms.size(); a++) { + if (mAllowedAuthAlgorithms.get(a)) { + sbuf.append(" "); + if (a < AuthAlgorithm.strings.length) { + sbuf.append(AuthAlgorithm.strings[a]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" PairwiseCiphers:"); + for (int pc = 0; pc < mAllowedPairwiseCiphers.size(); pc++) { + if (mAllowedPairwiseCiphers.get(pc)) { + sbuf.append(" "); + if (pc < PairwiseCipher.strings.length) { + sbuf.append(PairwiseCipher.strings[pc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" GroupCiphers:"); + for (int gc = 0; gc < mAllowedGroupCiphers.size(); gc++) { + if (mAllowedGroupCiphers.get(gc)) { + sbuf.append(" "); + if (gc < GroupCipher.strings.length) { + sbuf.append(GroupCipher.strings[gc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" GroupMgmtCiphers:"); + for (int gmc = 0; gmc < mAllowedGroupManagementCiphers.size(); gmc++) { + if (mAllowedGroupManagementCiphers.get(gmc)) { + sbuf.append(" "); + if (gmc < GroupMgmtCipher.strings.length) { + sbuf.append(GroupMgmtCipher.strings[gmc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" SuiteBCiphers:"); + for (int sbc = 0; sbc < mAllowedSuiteBCiphers.size(); sbc++) { + if (mAllowedSuiteBCiphers.get(sbc)) { + sbuf.append(" "); + if (sbc < SuiteBCipher.strings.length) { + sbuf.append(SuiteBCipher.strings[sbc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" RequirePmf: ").append(mRequirePmf).append('\n'); + sbuf.append(" IsAddedByAutoUpgrade: ").append(mIsAddedByAutoUpgrade).append("\n"); + sbuf.append(" IsSaeH2eOnlyMode: ").append(mIsSaeH2eOnlyMode).append("\n"); + sbuf.append(" IsSaePkOnlyMode: ").append(mIsSaePkOnlyMode).append("\n"); + return sbuf.toString(); + } + + private static BitSet readBitSet(Parcel src) { + int cardinality = src.readInt(); + + BitSet set = new BitSet(); + for (int i = 0; i < cardinality; i++) { + set.set(src.readInt()); + } + + return set; + } + + private static void writeBitSet(Parcel dest, BitSet set) { + int nextSetBit = -1; + + dest.writeInt(set.cardinality()); + + while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { + dest.writeInt(nextSetBit); + } + } + + /** Write this object to the parcel. */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mSecurityType); + dest.writeBoolean(mEnabled); + writeBitSet(dest, mAllowedKeyManagement); + writeBitSet(dest, mAllowedProtocols); + writeBitSet(dest, mAllowedAuthAlgorithms); + writeBitSet(dest, mAllowedPairwiseCiphers); + writeBitSet(dest, mAllowedGroupCiphers); + writeBitSet(dest, mAllowedGroupManagementCiphers); + writeBitSet(dest, mAllowedSuiteBCiphers); + dest.writeBoolean(mRequirePmf); + dest.writeBoolean(mIsAddedByAutoUpgrade); + dest.writeBoolean(mIsSaeH2eOnlyMode); + dest.writeBoolean(mIsSaePkOnlyMode); + + } + + /** Create a SecurityParams object from the parcel. */ + public static final @NonNull SecurityParams createFromParcel(Parcel in) { + SecurityParams params = new SecurityParams(); + params.mSecurityType = in.readInt(); + params.mEnabled = in.readBoolean(); + params.mAllowedKeyManagement = readBitSet(in); + params.mAllowedProtocols = readBitSet(in); + params.mAllowedAuthAlgorithms = readBitSet(in); + params.mAllowedPairwiseCiphers = readBitSet(in); + params.mAllowedGroupCiphers = readBitSet(in); + params.mAllowedGroupManagementCiphers = readBitSet(in); + params.mAllowedSuiteBCiphers = readBitSet(in); + params.mRequirePmf = in.readBoolean(); + params.mIsAddedByAutoUpgrade = in.readBoolean(); + params.mIsSaeH2eOnlyMode = in.readBoolean(); + params.mIsSaePkOnlyMode = in.readBoolean(); + return params; + } + + /** + * Create EAP security params. + */ + public static @NonNull SecurityParams createWpaWpa2EnterpriseParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + return params; + } + + /** + * Create EAP security params for Passpoint. + */ + public static @NonNull SecurityParams createPasspointParams(boolean requirePmf) { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + + params.mRequirePmf = requirePmf; + return params; + } + + /** + * Create Enhanced Open params. + */ + public static @NonNull SecurityParams createEnhancedOpenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OWE; + + params.mAllowedKeyManagement.set(KeyMgmt.OWE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create Open params. + */ + public static @NonNull SecurityParams createOpenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN; + + params.mAllowedKeyManagement.set(KeyMgmt.NONE); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + return params; + } + + /** + * Create OSEN params. + */ + public static @NonNull SecurityParams createOsenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN; + + params.mAllowedKeyManagement.set(KeyMgmt.OSEN); + + params.mAllowedProtocols.set(Protocol.OSEN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + return params; + } + + /** + * Create WAPI-CERT params. + */ + public static @NonNull SecurityParams createWapiCertParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT; + + params.mAllowedKeyManagement.set(KeyMgmt.WAPI_CERT); + + params.mAllowedProtocols.set(Protocol.WAPI); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4); + + params.mAllowedGroupCiphers.set(GroupCipher.SMS4); + return params; + } + + /** + * Create WAPI-PSK params. + */ + public static @NonNull SecurityParams createWapiPskParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK; + + params.mAllowedKeyManagement.set(KeyMgmt.WAPI_PSK); + + params.mAllowedProtocols.set(Protocol.WAPI); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4); + + params.mAllowedGroupCiphers.set(GroupCipher.SMS4); + return params; + } + + /** + * Create WEP params. + */ + public static @NonNull SecurityParams createWepParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WEP; + + params.mAllowedKeyManagement.set(KeyMgmt.NONE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedAuthAlgorithms.set(AuthAlgorithm.OPEN); + params.mAllowedAuthAlgorithms.set(AuthAlgorithm.SHARED); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + params.mAllowedGroupCiphers.set(GroupCipher.WEP40); + params.mAllowedGroupCiphers.set(GroupCipher.WEP104); + return params; + } + + /** + * Create WPA3 Enterprise 192-bit params. + */ + public static @NonNull SecurityParams createWpa3Enterprise192BitParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + params.mAllowedKeyManagement.set(KeyMgmt.SUITE_B_192); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mAllowedGroupManagementCiphers.set(GroupMgmtCipher.BIP_GMAC_256); + + // Note: allowedSuiteBCiphers bitset will be set by the service once the + // certificates are attached to this profile + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA3 Enterprise params. + */ + public static @NonNull SecurityParams createWpa3EnterpriseParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA3 Personal params. + */ + public static @NonNull SecurityParams createWpa3PersonalParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_SAE; + + params.mAllowedKeyManagement.set(KeyMgmt.SAE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA/WPA2 Personal params. + */ + public static @NonNull SecurityParams createWpaWpa2PersonalParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_PSK); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + params.mAllowedGroupCiphers.set(GroupCipher.WEP40); + params.mAllowedGroupCiphers.set(GroupCipher.WEP104); + return params; + } +} diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 85b3170d59bde..a78cb04fb0b4c 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -19,6 +19,7 @@ package android.net.wifi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.PackageManager; @@ -46,10 +47,13 @@ import com.android.net.module.util.MacAddressUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Calendar; +import java.util.Collections; import java.util.HashMap; +import java.util.List; /** * A class representing a configured Wi-Fi network, including the @@ -250,6 +254,11 @@ public class WifiConfiguration implements Parcelable { */ public static final int WAPI = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {WPA, RSN, OSEN, WAPI}) + public @interface ProtocolScheme {}; + public static final String varName = "proto"; public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" }; @@ -274,6 +283,11 @@ public class WifiConfiguration implements Parcelable { /** SAE (Used only for WPA3-Personal) */ public static final int SAE = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {OPEN, SHARED, LEAP, SAE}) + public @interface AuthAlgorithmScheme {}; + public static final String varName = "auth_alg"; public static final String[] strings = { "OPEN", "SHARED", "LEAP", "SAE" }; @@ -308,6 +322,10 @@ public class WifiConfiguration implements Parcelable { */ public static final int GCMP_128 = 5; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {NONE, TKIP, CCMP, GCMP_256, SMS4, GCMP_128}) + public @interface PairwiseCipherScheme {}; public static final String varName = "pairwise"; @@ -359,6 +377,11 @@ public class WifiConfiguration implements Parcelable { */ public static final int GCMP_128 = 7; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {WEP40, WEP104, TKIP, CCMP, GTK_NOT_USED, GCMP_256, SMS4, GCMP_128}) + public @interface GroupCipherScheme {}; + public static final String varName = "group"; public static final String[] strings = @@ -387,9 +410,16 @@ public class WifiConfiguration implements Parcelable { /** GMAC-256 = Galois Message Authentication Code */ public static final int BIP_GMAC_256 = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {BIP_CMAC_256, BIP_GMAC_128, BIP_GMAC_256}) + public @interface GroupMgmtCipherScheme {}; + private static final String varName = "groupMgmt"; - private static final String[] strings = { "BIP_CMAC_256", + /** @hide */ + @SuppressLint("AllUpper") + public static final @NonNull String[] strings = { "BIP_CMAC_256", "BIP_GMAC_128", "BIP_GMAC_256"}; } @@ -410,9 +440,16 @@ public class WifiConfiguration implements Parcelable { /** Diffie-Hellman with_RSA signature */ public static final int ECDHE_RSA = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {ECDHE_ECDSA, ECDHE_RSA}) + public @interface SuiteBCipherScheme {}; + private static final String varName = "SuiteB"; - private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; + /** @hide */ + @SuppressLint("AllUpper") + public static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; } /** Possible status of a network configuration. */ @@ -460,6 +497,11 @@ public class WifiConfiguration implements Parcelable { public static final int SECURITY_TYPE_WAPI_CERT = 8; /** Security type for a WPA3-Enterprise network. */ public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9; + /** + * Security type for an OSEN network. + * @hide + */ + public static final int SECURITY_TYPE_OSEN = 10; /** * Security types we support. @@ -481,9 +523,52 @@ public class WifiConfiguration implements Parcelable { }) public @interface SecurityType {} + private List mSecurityParamsList = new ArrayList<>(); + + private void updateLegacySecurityParams() { + if (mSecurityParamsList.isEmpty()) return; + mSecurityParamsList.get(0).updateLegacyWifiConfiguration(this); + } + /** * Set the various security params to correspond to the provided security type. * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + *
+ * This API would clear existing security types and add a default one. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} + */ + public void setSecurityParams(@SecurityType int securityType) { + // Clear existing data. + mSecurityParamsList = new ArrayList<>(); + addSecurityParams(securityType); + } + + /** + * Add the various security params. + *
+ * This API would clear existing security types and add a default one. + * @hide + */ + public void setSecurityParams(SecurityParams params) { + // Clear existing data. + mSecurityParamsList = new ArrayList<>(); + addSecurityParams(params); + } + + /** + * Add the various security params to correspond to the provided security type. + * This is accomplished by setting the various BitSets exposed in WifiConfiguration. * * @param securityType One of the following security types: * {@link #SECURITY_TYPE_OPEN}, @@ -491,103 +576,318 @@ public class WifiConfiguration implements Parcelable { * {@link #SECURITY_TYPE_PSK}, * {@link #SECURITY_TYPE_EAP}, * {@link #SECURITY_TYPE_SAE}, - * {@link #SECURITY_TYPE_EAP_SUITE_B}, * {@link #SECURITY_TYPE_OWE}, * {@link #SECURITY_TYPE_WAPI_PSK}, * {@link #SECURITY_TYPE_WAPI_CERT}, * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} + * + * @hide */ - public void setSecurityParams(@SecurityType int securityType) { - // Clear all the bitsets. - allowedKeyManagement.clear(); - allowedProtocols.clear(); - allowedAuthAlgorithms.clear(); - allowedPairwiseCiphers.clear(); - allowedGroupCiphers.clear(); - allowedGroupManagementCiphers.clear(); - allowedSuiteBCiphers.clear(); - + public void addSecurityParams(@SecurityType int securityType) { + // This ensures that there won't be duplicate security types. + if (mSecurityParamsList.stream().anyMatch(params -> params.isSecurityType(securityType))) { + throw new IllegalArgumentException("duplicate security type " + securityType); + } + SecurityParams params = null; switch (securityType) { case SECURITY_TYPE_OPEN: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + params = SecurityParams.createOpenParams(); break; case SECURITY_TYPE_WEP: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); + params = SecurityParams.createWepParams(); break; case SECURITY_TYPE_PSK: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + params = SecurityParams.createWpaWpa2PersonalParams(); break; case SECURITY_TYPE_EAP: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); + params = SecurityParams.createWpaWpa2EnterpriseParams(); break; case SECURITY_TYPE_SAE: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createWpa3PersonalParams(); break; // The value of {@link SECURITY_TYPE_EAP_SUITE_B} is the same as - // {@link SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it to avoid + // {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it to avoid // duplicate case label errors. case SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); - // Note: allowedSuiteBCiphers bitset will be set by the service once the - // certificates are attached to this profile - requirePmf = true; + params = SecurityParams.createWpa3Enterprise192BitParams(); break; case SECURITY_TYPE_OWE: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createEnhancedOpenParams(); break; case SECURITY_TYPE_WAPI_PSK: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK); - allowedProtocols.set(WifiConfiguration.Protocol.WAPI); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); + params = SecurityParams.createWapiPskParams(); break; case SECURITY_TYPE_WAPI_CERT: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT); - allowedProtocols.set(WifiConfiguration.Protocol.WAPI); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); + params = SecurityParams.createWapiCertParams(); break; case SECURITY_TYPE_EAP_WPA3_ENTERPRISE: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createWpa3EnterpriseParams(); + break; + case SECURITY_TYPE_OSEN: + params = SecurityParams.createOsenParams(); break; default: throw new IllegalArgumentException("unknown security type " + securityType); } + + addSecurityParams(params); + } + + /** @hide */ + public void addSecurityParams(@NonNull SecurityParams newParams) { + if (mSecurityParamsList.stream().anyMatch(params -> params.isSameSecurityType(newParams))) { + throw new IllegalArgumentException("duplicate security params " + newParams); + } + if (!mSecurityParamsList.isEmpty()) { + if (newParams.isEnterpriseSecurityType() && !isEnterprise()) { + throw new IllegalArgumentException( + "An enterprise security type cannot be added to a personal configuation."); + } + if (!newParams.isEnterpriseSecurityType() && isEnterprise()) { + throw new IllegalArgumentException( + "A personal security type cannot be added to an enterprise configuation."); + } + if (newParams.isOpenSecurityType() && !isOpenNetwork()) { + throw new IllegalArgumentException( + "An open security type cannot be added to a non-open configuation."); + } + if (!newParams.isOpenSecurityType() && isOpenNetwork()) { + throw new IllegalArgumentException( + "A non-open security type cannot be added to an open configuation."); + } + if (newParams.isSecurityType(SECURITY_TYPE_OSEN)) { + throw new IllegalArgumentException( + "An OSEN security type must be the only one type."); + } + } + mSecurityParamsList.add(new SecurityParams(newParams)); + updateLegacySecurityParams(); + } + + /** + * If there is no security params, generate one according to legacy fields. + * @hide + */ + public void convertLegacyFieldsToSecurityParamsIfNeeded() { + if (!mSecurityParamsList.isEmpty()) return; + + if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { + setSecurityParams(SECURITY_TYPE_WAPI_CERT); + } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) { + setSecurityParams(SECURITY_TYPE_WAPI_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { + setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); + } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { + setSecurityParams(SECURITY_TYPE_OWE); + } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { + setSecurityParams(SECURITY_TYPE_SAE); + } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) { + setSecurityParams(SECURITY_TYPE_OSEN); + } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { + setSecurityParams(SECURITY_TYPE_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { + if (requirePmf) { + setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE); + } else { + setSecurityParams(SECURITY_TYPE_EAP); + } + } else if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { + setSecurityParams(SECURITY_TYPE_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.NONE)) { + if (hasWepKeys()) { + setSecurityParams(SECURITY_TYPE_WEP); + } else { + setSecurityParams(SECURITY_TYPE_OPEN); + } + } else { + setSecurityParams(SECURITY_TYPE_OPEN); + } + } + + /** + * Disable the various security params to correspond to the provided security type. + * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} + * + * @hide + */ + public void setSecurityParamsEnabled(@SecurityType int securityType, boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(securityType)) + .findAny() + .ifPresent(params -> params.setEnabled(enable)); + } + + /** + * Get the specific security param. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} + * + * @return the copy of specific security params if found; otherwise null. + * @hide + */ + public @Nullable SecurityParams getSecurityParams(@SecurityType int securityType) { + SecurityParams p = mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(securityType)) + .findAny() + .orElse(null); + return (p != null) ? new SecurityParams(p) : null; + } + + /** + * Indicate whether this configuration is the specific security type. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} + * + * @return true if there is a security params matches the type. + * @hide + */ + public boolean isSecurityType(@SecurityType int securityType) { + return mSecurityParamsList.stream() + .anyMatch(params -> params.isSecurityType(securityType)); + } + + /** + * Get the security params list of this configuration. + * + * The returning list is a priority list, the first is the lowest priority and default one. + * + * @return this list of security params. + * @hide + */ + public List getSecurityParamsList() { + return Collections.unmodifiableList(mSecurityParamsList); + } + + /** + * Enable the support of Fast Initial Link Set-up (FILS). + * + * FILS can be applied to all security types. + * @param enableFilsSha256 Enable FILS SHA256. + * @param enableFilsSha384 Enable FILS SHA256. + * @hide + */ + public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) { + mSecurityParamsList.stream() + .forEach(params -> params.enableFils(enableFilsSha256, enableFilsSha384)); + updateLegacySecurityParams(); + } + + /** + * Indicate FILS SHA256 is enabled. + * + * @return true if FILS SHA256 is enabled. + * @hide + */ + public boolean isFilsSha256Enabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA256)); + } + + /** + * Indicate FILS SHA384 is enabled. + * + * @return true if FILS SHA384 is enabled. + * @hide + */ + public boolean isFilsSha384Enabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA384)); + } + + /** + * Enable Suite-B ciphers. + * + * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support. + * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support. + * @hide + */ + public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT)) + .findAny() + .ifPresent(params -> params.enableSuiteBCiphers(enableEcdheEcdsa, enableEcdheRsa)); + updateLegacySecurityParams(); + } + + /** + * Indicate ECDHE_ECDSA is enabled. + * + * @return true if enabled. + * @hide + */ + public boolean isSuiteBCipherEcdheEcdsaEnabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_ECDSA)); + } + + /** + * Indicate ECDHE_RSA is enabled. + * + * @return true if enabled. + * @hide + */ + public boolean isSuiteBCipherEcdheRsaEnabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_RSA)); + } + + /** + * Set SAE Hash-toElement only mode enabled. + * + * @param enable true if enabled; false otherwise. + * @hide + */ + public void enableSaeH2eOnlyMode(boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE)) + .findAny() + .ifPresent(params -> params.enableSaeH2eOnlyMode(enable)); + } + + /** + * Set SAE Public-Key only mode enabled. + * + * @param enable true if enabled; false otherwise. + * @hide + */ + public void enableSaePkOnlyMode(boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE)) + .findAny() + .ifPresent(params -> params.enableSaePkOnlyMode(enable)); } /** @hide */ @@ -1161,27 +1461,25 @@ public class WifiConfiguration implements Parcelable { return metered; } - /** - * @hide - * Returns true if this WiFi config is for an open network. - */ - public boolean isOpenNetwork() { - final int cardinality = allowedKeyManagement.cardinality(); - final boolean hasNoKeyMgmt = cardinality == 0 - || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE) - || allowedKeyManagement.get(KeyMgmt.OWE))); - - boolean hasNoWepKeys = true; - if (wepKeys != null) { - for (int i = 0; i < wepKeys.length; i++) { - if (wepKeys[i] != null) { - hasNoWepKeys = false; - break; - } + /** Check whether wep keys exist. */ + private boolean hasWepKeys() { + if (wepKeys == null) return false; + for (int i = 0; i < wepKeys.length; i++) { + if (wepKeys[i] != null) { + return true; } } + return false; + } - return hasNoKeyMgmt && hasNoWepKeys; + /** + * @hide + * Returns true if this WiFi config is for an Open or Enhanced Open network. + */ + public boolean isOpenNetwork() { + boolean hasNonOpenSecurityType = mSecurityParamsList.stream() + .anyMatch(params -> !params.isOpenSecurityType()); + return !hasNonOpenSecurityType && !hasWepKeys(); } /** @@ -2340,12 +2638,11 @@ public class WifiConfiguration implements Parcelable { */ @UnsupportedAppUsage public boolean isEnterprise() { - return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) - || allowedKeyManagement.get(KeyMgmt.IEEE8021X) - || allowedKeyManagement.get(KeyMgmt.SUITE_B_192) - || allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) + boolean hasEnterpriseSecurityType = mSecurityParamsList.stream() + .anyMatch(params -> params.isEnterpriseSecurityType()); + return (hasEnterpriseSecurityType && enterpriseConfig != null - && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; + && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE); } private static String logTimeOfDay(long millis) { @@ -2525,6 +2822,10 @@ public class WifiConfiguration implements Parcelable { sbuf.append('*'); } + sbuf.append("\nSecurityParams List:\n"); + mSecurityParamsList.stream() + .forEach(params -> sbuf.append(params.toString())); + sbuf.append("\nEnterprise config:\n"); sbuf.append(enterpriseConfig); @@ -2973,6 +3274,7 @@ public class WifiConfiguration implements Parcelable { allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone(); allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone(); + mSecurityParamsList = new ArrayList(source.mSecurityParamsList); enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); defaultGwMacAddress = source.defaultGwMacAddress; @@ -3063,6 +3365,10 @@ public class WifiConfiguration implements Parcelable { writeBitSet(dest, allowedGroupManagementCiphers); writeBitSet(dest, allowedSuiteBCiphers); + dest.writeInt(mSecurityParamsList.size()); + mSecurityParamsList.stream() + .forEach(params -> params.writeToParcel(dest, flags)); + dest.writeParcelable(enterpriseConfig, flags); dest.writeParcelable(mIpConfiguration, flags); @@ -3144,6 +3450,11 @@ public class WifiConfiguration implements Parcelable { config.allowedGroupManagementCiphers = readBitSet(in); config.allowedSuiteBCiphers = readBitSet(in); + int numSecurityParams = in.readInt(); + for (int i = 0; i < numSecurityParams; i++) { + config.mSecurityParamsList.add(SecurityParams.createFromParcel(in)); + } + config.enterpriseConfig = in.readParcelable(null); config.setIpConfiguration(in.readParcelable(null)); config.dhcpServer = in.readString(); @@ -3226,9 +3537,10 @@ public class WifiConfiguration implements Parcelable { * @hide */ public boolean needsPreSharedKey() { - return allowedKeyManagement.get(KeyMgmt.WPA_PSK) - || allowedKeyManagement.get(KeyMgmt.SAE) - || allowedKeyManagement.get(KeyMgmt.WAPI_PSK); + return mSecurityParamsList.stream() + .anyMatch(params -> params.isSecurityType(SECURITY_TYPE_PSK) + || params.isSecurityType(SECURITY_TYPE_SAE) + || params.isSecurityType(SECURITY_TYPE_WAPI_PSK)); } /** diff --git a/wifi/tests/src/android/net/wifi/SecurityParamsTest.java b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java new file mode 100644 index 0000000000000..e581b77c14ad0 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2020 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 android.net.wifi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.net.wifi.WifiConfiguration.GroupCipher; +import android.net.wifi.WifiConfiguration.GroupMgmtCipher; +import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; +import android.os.Parcel; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +import java.util.BitSet; + +/** + * Unit tests for {@link android.net.wifi.WifiInfo}. + */ +@SmallTest +public class SecurityParamsTest { + + private void verifySecurityParams(SecurityParams params, + int expectedSecurityType, + int[] expectedAllowedKeyManagement, + int[] expectedAllowedProtocols, + int[] expectedAllowedAuthAlgorithms, + int[] expectedAllowedPairwiseCiphers, + int[] expectedAllowedGroupCiphers, + boolean expectedRequirePmf) { + assertTrue(params.isSecurityType(expectedSecurityType)); + for (int b: expectedAllowedKeyManagement) { + assertTrue(params.getAllowedKeyManagement().get(b)); + } + for (int b: expectedAllowedProtocols) { + assertTrue(params.getAllowedProtocols().get(b)); + } + for (int b: expectedAllowedAuthAlgorithms) { + assertTrue(params.getAllowedAuthAlgorithms().get(b)); + } + for (int b: expectedAllowedPairwiseCiphers) { + assertTrue(params.getAllowedPairwiseCiphers().get(b)); + } + for (int b: expectedAllowedGroupCiphers) { + assertTrue(params.getAllowedGroupCiphers().get(b)); + } + assertEquals(expectedRequirePmf, params.isRequirePmf()); + } + + /** Verify EAP params creator. */ + @Test + public void testEapCreator() throws Exception { + SecurityParams p = SecurityParams.createWpaWpa2EnterpriseParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify EAP Passpoint params creator. */ + @Test + public void testEapPasspointCreator() throws Exception { + SecurityParams p = SecurityParams.createPasspointParams(false); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + + p = SecurityParams.createPasspointParams(true); + expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Enhanced Open params creator. */ + @Test + public void testEnhancedOpenCreator() throws Exception { + SecurityParams p = SecurityParams.createEnhancedOpenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OWE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OWE}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] { + GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Open params creator. */ + @Test + public void testOpenCreator() throws Exception { + SecurityParams p = SecurityParams.createOpenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify OSEN params creator. */ + @Test + public void testOsenCreator() throws Exception { + SecurityParams p = SecurityParams.createOsenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OSEN}; + int[] expectedAllowedProtocols = new int[] {Protocol.OSEN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WAPI CERT params creator. */ + @Test + public void testWapiCertCreator() throws Exception { + SecurityParams p = SecurityParams.createWapiCertParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_CERT}; + int[] expectedAllowedProtocols = new int[] {Protocol.WAPI}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WAPI PSK params creator. */ + @Test + public void testWapiPskCreator() throws Exception { + SecurityParams p = SecurityParams.createWapiPskParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_PSK}; + int[] expectedAllowedProtocols = new int[] {Protocol.WAPI}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WEP params creator. */ + @Test + public void testWepCreator() throws Exception { + SecurityParams p = SecurityParams.createWepParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WEP; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {AuthAlgorithm.OPEN, AuthAlgorithm.SHARED}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA3 Enterprise 192-bit params creator. */ + @Test + public void testWpa3Enterprise192BitCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3Enterprise192BitParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; + int[] expectedAllowedKeyManagement = new int[] { + KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X, KeyMgmt.SUITE_B_192}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + + assertTrue(p.getAllowedGroupManagementCiphers().get(GroupMgmtCipher.BIP_GMAC_256)); + } + + /** Verify WPA3 Enterprise params creator. */ + @Test + public void testWpa3EnterpriseCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3EnterpriseParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.CCMP, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA3 Personal params creator. */ + @Test + public void testWpa3PersonalCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3PersonalParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_SAE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.SAE}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] { + GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA2 Personal EAP params creator. */ + @Test + public void testWpaWpa2PersonalCreator() throws Exception { + SecurityParams p = SecurityParams.createWpaWpa2PersonalParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_PSK}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify setter/getter methods */ + @Test + public void testCommonSetterGetter() throws Exception { + SecurityParams params = SecurityParams.createWpaWpa2PersonalParams(); + + // PSK setting + BitSet allowedKeyManagement = new BitSet(); + allowedKeyManagement.set(KeyMgmt.WPA_PSK); + + BitSet allowedProtocols = new BitSet(); + allowedProtocols.set(Protocol.RSN); + allowedProtocols.set(Protocol.WPA); + + BitSet allowedPairwiseCiphers = new BitSet(); + allowedPairwiseCiphers.set(PairwiseCipher.CCMP); + allowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + BitSet allowedGroupCiphers = new BitSet(); + allowedGroupCiphers.set(GroupCipher.CCMP); + allowedGroupCiphers.set(GroupCipher.TKIP); + allowedGroupCiphers.set(GroupCipher.WEP40); + allowedGroupCiphers.set(GroupCipher.WEP104); + + assertEquals(allowedKeyManagement, params.getAllowedKeyManagement()); + assertTrue(params.getAllowedKeyManagement().get(KeyMgmt.WPA_PSK)); + + assertEquals(allowedProtocols, params.getAllowedProtocols()); + assertTrue(params.getAllowedProtocols().get(Protocol.RSN)); + assertTrue(params.getAllowedProtocols().get(Protocol.WPA)); + + assertEquals(allowedPairwiseCiphers, params.getAllowedPairwiseCiphers()); + assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.CCMP)); + assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.TKIP)); + + assertEquals(allowedGroupCiphers, params.getAllowedGroupCiphers()); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.CCMP)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.TKIP)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP40)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP104)); + + params.setEnabled(false); + assertFalse(params.isEnabled()); + } + + /** Verify SAE-specific methods */ + @Test + public void testSaeMethods() throws Exception { + SecurityParams p = SecurityParams.createWpa3PersonalParams(); + + assertFalse(p.isAddedByAutoUpgrade()); + p.setIsAddedByAutoUpgrade(true); + assertTrue(p.isAddedByAutoUpgrade()); + + assertFalse(p.isSaeH2eOnlyMode()); + p.enableSaeH2eOnlyMode(true); + assertTrue(p.isSaeH2eOnlyMode()); + + assertFalse(p.isSaePkOnlyMode()); + p.enableSaePkOnlyMode(true); + assertTrue(p.isSaePkOnlyMode()); + } + + /** Verify copy constructor. */ + @Test + public void testCopyConstructor() throws Exception { + SecurityParams params = SecurityParams.createWpaWpa2PersonalParams(); + params.setEnabled(false); + params.setIsAddedByAutoUpgrade(true); + + SecurityParams copiedParams = new SecurityParams(params); + + assertTrue(params.isSameSecurityType(copiedParams)); + assertEquals(params.getAllowedKeyManagement(), copiedParams.getAllowedKeyManagement()); + assertEquals(params.getAllowedProtocols(), copiedParams.getAllowedProtocols()); + assertEquals(params.getAllowedAuthAlgorithms(), copiedParams.getAllowedAuthAlgorithms()); + assertEquals(params.getAllowedPairwiseCiphers(), copiedParams.getAllowedPairwiseCiphers()); + assertEquals(params.getAllowedGroupCiphers(), copiedParams.getAllowedGroupCiphers()); + assertEquals(params.getAllowedGroupManagementCiphers(), + copiedParams.getAllowedGroupManagementCiphers()); + assertEquals(params.getAllowedSuiteBCiphers(), copiedParams.getAllowedSuiteBCiphers()); + assertEquals(params.isRequirePmf(), copiedParams.isRequirePmf()); + assertEquals(params.isEnabled(), copiedParams.isEnabled()); + assertEquals(params.isSaeH2eOnlyMode(), copiedParams.isSaeH2eOnlyMode()); + assertEquals(params.isSaePkOnlyMode(), copiedParams.isSaePkOnlyMode()); + assertEquals(params.isAddedByAutoUpgrade(), copiedParams.isAddedByAutoUpgrade()); + } + + /** Check that two params are equal if and only if their types are the same. */ + @Test + public void testEquals() { + SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams(); + SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams(); + SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams(); + assertEquals(saeParams1, saeParams2); + assertNotEquals(saeParams1, pskParams); + } + + /** Check that hash values are the same if and only if their types are the same. */ + @Test + public void testHashCode() { + SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams(); + SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams(); + SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams(); + assertEquals(saeParams1.hashCode(), saeParams2.hashCode()); + assertNotEquals(saeParams1.hashCode(), pskParams.hashCode()); + } + + /** Verify open network check */ + @Test + public void testIsOpenNetwork() { + SecurityParams[] openSecurityParams = new SecurityParams[] { + SecurityParams.createEnhancedOpenParams(), + SecurityParams.createOpenParams(), + }; + for (SecurityParams p: openSecurityParams) { + assertTrue(p.isOpenSecurityType()); + } + + SecurityParams[] nonOpenSecurityParams = new SecurityParams[] { + SecurityParams.createWpaWpa2EnterpriseParams(), + SecurityParams.createPasspointParams(false), + SecurityParams.createOsenParams(), + SecurityParams.createWapiCertParams(), + SecurityParams.createWapiPskParams(), + SecurityParams.createWepParams(), + SecurityParams.createWpa3Enterprise192BitParams(), + SecurityParams.createWpa3EnterpriseParams(), + SecurityParams.createWpa3PersonalParams(), + SecurityParams.createWpaWpa2PersonalParams(), + }; + for (SecurityParams p: nonOpenSecurityParams) { + assertFalse(p.isOpenSecurityType()); + } + } + + /** Verify enterprise network check */ + @Test + public void testIsEnterpriseNetwork() { + SecurityParams[] enterpriseSecurityParams = new SecurityParams[] { + SecurityParams.createWpaWpa2EnterpriseParams(), + SecurityParams.createPasspointParams(false), + SecurityParams.createWapiCertParams(), + SecurityParams.createWpa3Enterprise192BitParams(), + SecurityParams.createWpa3EnterpriseParams(), + }; + for (SecurityParams p: enterpriseSecurityParams) { + assertTrue(p.isEnterpriseSecurityType()); + } + + SecurityParams[] nonEnterpriseSecurityParams = new SecurityParams[] { + SecurityParams.createEnhancedOpenParams(), + SecurityParams.createOpenParams(), + SecurityParams.createOsenParams(), + SecurityParams.createWapiPskParams(), + SecurityParams.createWepParams(), + SecurityParams.createWpa3PersonalParams(), + SecurityParams.createWpaWpa2PersonalParams(), + }; + for (SecurityParams p: nonEnterpriseSecurityParams) { + assertFalse(p.isEnterpriseSecurityType()); + } + } + + /** Check that parcel marshalling/unmarshalling works */ + @Test + public void testParcelMethods() { + SecurityParams params = SecurityParams.createWpa3PersonalParams(); + + Parcel parcelW = Parcel.obtain(); + params.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + + SecurityParams reParams = SecurityParams.createFromParcel(parcelR); + assertEquals(params, reParams); + } +} diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java index c253746954638..f351e61b5eb82 100644 --- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java @@ -20,11 +20,13 @@ import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OSEN; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OWE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_CERT; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_PSK; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WEP; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -34,9 +36,13 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import android.net.MacAddress; +import android.net.wifi.WifiConfiguration.GroupCipher; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; import android.os.Parcel; +import android.util.Pair; import androidx.test.filters.SmallTest; @@ -45,6 +51,8 @@ import com.android.net.module.util.MacAddressUtils; import org.junit.Before; import org.junit.Test; +import java.util.List; + /** * Unit tests for {@link android.net.wifi.WifiConfiguration}. */ @@ -187,18 +195,24 @@ public class WifiConfigurationTest { @Test public void testIsOpenNetwork_NotOpen_HasAuthType() { - for (int keyMgmt = 0; keyMgmt < WifiConfiguration.KeyMgmt.strings.length; keyMgmt++) { - if (keyMgmt == WifiConfiguration.KeyMgmt.NONE - || keyMgmt == WifiConfiguration.KeyMgmt.OWE) { - continue; - } + int[] securityTypes = new int [] { + SECURITY_TYPE_WEP, + SECURITY_TYPE_PSK, + SECURITY_TYPE_EAP, + SECURITY_TYPE_SAE, + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT, + SECURITY_TYPE_WAPI_PSK, + SECURITY_TYPE_WAPI_CERT, + SECURITY_TYPE_EAP_WPA3_ENTERPRISE, + SECURITY_TYPE_OSEN, + }; + for (int type: securityTypes) { WifiConfiguration config = new WifiConfiguration(); - config.allowedKeyManagement.clear(); - config.allowedKeyManagement.set(keyMgmt); + config.setSecurityParams(type); config.wepKeys = null; - assertFalse("Open network reported when key mgmt was set to " - + WifiConfiguration.KeyMgmt.strings[keyMgmt], config.isOpenNetwork()); + assertFalse("Open network reported when security type was set to " + + type, config.isOpenNetwork()); } } @@ -208,6 +222,7 @@ public class WifiConfigurationTest { config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); config.wepKeys = null; + config.convertLegacyFieldsToSecurityParamsIfNeeded(); assertFalse(config.isOpenNetwork()); } @@ -865,4 +880,243 @@ public class WifiConfigurationTest { } return sb.toString(); } + + private void verifyAllowedKeyManagement(WifiConfiguration config, int[] akms) { + for (int akm: akms) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(akm))); + } + } + + private void verifyAllowedProtocols(WifiConfiguration config, int[] aps) { + for (int ap: aps) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedProtocols().get(ap))); + } + } + + private void verifyAllowedPairwiseCiphers(WifiConfiguration config, int[] apcs) { + for (int apc: apcs) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedPairwiseCiphers().get(apc))); + } + } + + private void verifyAllowedGroupCiphers(WifiConfiguration config, int[] agcs) { + for (int agc: agcs) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedGroupCiphers().get(agc))); + } + } + + /** Verify that adding security types works as expected. */ + @Test + public void testAddSecurityTypes() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + config.addSecurityParams(SecurityParams.createWapiPskParams()); + List paramsList = config.getSecurityParamsList(); + assertEquals(3, paramsList.size()); + + verifyAllowedKeyManagement(config, new int[] { + KeyMgmt.WPA_PSK, KeyMgmt.SAE, KeyMgmt.WAPI_PSK}); + verifyAllowedProtocols(config, new int[] {Protocol.WPA, Protocol.RSN, Protocol.WAPI}); + verifyAllowedPairwiseCiphers(config, new int[] { + PairwiseCipher.CCMP, PairwiseCipher.TKIP, + PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256, + PairwiseCipher.SMS4}); + verifyAllowedGroupCiphers(config, new int[] { + GroupCipher.CCMP, GroupCipher.TKIP, + GroupCipher.GCMP_128, GroupCipher.GCMP_256, + GroupCipher.SMS4}); + } + + /** Check that a personal security type can be added to a personal configuration. */ + @Test + public void testAddPersonalTypeToPersonalConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + } + + /** Check that an enterprise security type can be added to an enterprise configuration. */ + @Test + public void testAddEnterpriseTypeToEnterpriseConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE); + } + + /** Verify that adding an enterprise type to a personal configuration. */ + @Test (expected = IllegalArgumentException.class) + public void testAddEnterpriseTypeToPersonalConfig() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + } + + /** Verify that adding a personal type to an enterprise configuration. */ + @Test (expected = IllegalArgumentException.class) + public void testAddPersonalTypeToEnterpriseConfig() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Check that an open security cannot be added to a non-open configuration. */ + @Test(expected = IllegalArgumentException.class) + public void testAddOpenTypeToNonOpenConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); + } + + /** Check that a non-open security cannot be added to an open configuration. */ + @Test(expected = IllegalArgumentException.class) + public void testAddNonOpenTypeToOpenConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Check that a OSEN security cannot be added as additional type. */ + @Test(expected = IllegalArgumentException.class) + public void testAddOsenTypeToConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OSEN); + } + + /** Verify that adding duplicate security types raises the exception. */ + @Test (expected = IllegalArgumentException.class) + public void testAddDuplicateSecurityTypes() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Verify that adding duplicate security params raises the exception. */ + @Test (expected = IllegalArgumentException.class) + public void testAddDuplicateSecurityParams() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams()); + config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams()); + } + + /** Verify that Suite-B type works as expected. */ + @Test + public void testAddSuiteBSecurityType() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(SecurityParams.createWpa3EnterpriseParams()); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(SecurityParams.createWpa3Enterprise192BitParams()); + + assertFalse(config.isSuiteBCipherEcdheRsaEnabled()); + config.enableSuiteBCiphers(false, true); + assertTrue(config.isSuiteBCipherEcdheRsaEnabled()); + } + + /** Verify that FILS bit can be set correctly. */ + @Test + public void testFilsKeyMgmt() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + + config.enableFils(false, true); + assertFalse(config.isFilsSha256Enabled()); + assertTrue(config.isFilsSha384Enabled()); + } + + /** Verify that SAE mode can be configured correctly. */ + @Test + public void testSaeTypeMethods() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + + SecurityParams saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + assertNotNull(saeParams); + assertFalse(saeParams.isSaeH2eOnlyMode()); + assertFalse(saeParams.isSaePkOnlyMode()); + + config.enableSaeH2eOnlyMode(true); + config.enableSaePkOnlyMode(true); + + saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + assertNotNull(saeParams); + assertTrue(saeParams.isSaeH2eOnlyMode()); + assertTrue(saeParams.isSaePkOnlyMode()); + } + + /** Verify the legacy configuration conversion */ + @Test + public void testLegacyConfigurationConversion() { + Pair[] keyMgmtSecurityTypePairs = new Pair[] { + new Pair<>(KeyMgmt.WAPI_CERT, SECURITY_TYPE_WAPI_CERT), + new Pair<>(KeyMgmt.WAPI_PSK, SECURITY_TYPE_WAPI_PSK), + new Pair<>(KeyMgmt.SUITE_B_192, SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT), + new Pair<>(KeyMgmt.OWE, SECURITY_TYPE_OWE), + new Pair<>(KeyMgmt.SAE, SECURITY_TYPE_SAE), + new Pair<>(KeyMgmt.OSEN, SECURITY_TYPE_OSEN), + new Pair<>(KeyMgmt.WPA2_PSK, SECURITY_TYPE_PSK), + new Pair<>(KeyMgmt.WPA_EAP, SECURITY_TYPE_EAP), + new Pair<>(KeyMgmt.WPA_PSK, SECURITY_TYPE_PSK), + new Pair<>(KeyMgmt.NONE, SECURITY_TYPE_OPEN), + }; + + for (Pair pair: keyMgmtSecurityTypePairs) { + WifiConfiguration config = new WifiConfiguration(); + config.allowedKeyManagement.set((int) pair.first); + config.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(config.getSecurityParams((int) pair.second)); + } + + // If none of key management is set, it should be open. + WifiConfiguration emptyConfig = new WifiConfiguration(); + emptyConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(emptyConfig.getSecurityParams(SECURITY_TYPE_OPEN)); + + // If EAP key management is set and requirePmf is true, it is WPA3 Enterprise. + WifiConfiguration wpa3EnterpriseConfig = new WifiConfiguration(); + wpa3EnterpriseConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP); + wpa3EnterpriseConfig.requirePmf = true; + wpa3EnterpriseConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(wpa3EnterpriseConfig.getSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE)); + + // If key management is NONE and wep key is set, it is WEP type. + WifiConfiguration wepConfig = new WifiConfiguration(); + wepConfig.allowedKeyManagement.set(KeyMgmt.NONE); + wepConfig.wepKeys = new String[] {"\"abcdef\""}; + wepConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(wepConfig.getSecurityParams(SECURITY_TYPE_WEP)); + } + + /** Verify the set security params by SecurityParams objects. */ + @Test + public void testSetBySecurityParamsObject() { + Pair[] securityParamsSecurityTypePairs = new Pair[] { + new Pair<>(SecurityParams.createWapiCertParams(), SECURITY_TYPE_WAPI_CERT), + new Pair<>(SecurityParams.createWapiPskParams(), SECURITY_TYPE_WAPI_PSK), + new Pair<>(SecurityParams.createWpa3Enterprise192BitParams(), + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT), + new Pair<>(SecurityParams.createEnhancedOpenParams(), SECURITY_TYPE_OWE), + new Pair<>(SecurityParams.createWpa3PersonalParams(), SECURITY_TYPE_SAE), + new Pair<>(SecurityParams.createOsenParams(), SECURITY_TYPE_OSEN), + new Pair<>(SecurityParams.createWpaWpa2EnterpriseParams(), SECURITY_TYPE_EAP), + new Pair<>(SecurityParams.createWpaWpa2PersonalParams(), SECURITY_TYPE_PSK), + new Pair<>(SecurityParams.createOpenParams(), SECURITY_TYPE_OPEN), + }; + for (Pair pair: securityParamsSecurityTypePairs) { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams((SecurityParams) pair.first); + assertNotNull(config.getSecurityParams((int) pair.second)); + } + } }