diff options
author | 2025-02-18 21:22:54 -0800 | |
---|---|---|
committer | 2025-03-17 20:09:47 -0700 | |
commit | f51443e4bc465e1169aae55808067f145416028d (patch) | |
tree | ce0bb7aa29b71bd3026b17fa992255823f06e28d | |
parent | a3b21c326cb5efb483bd32d07b617dc988719cf8 (diff) |
Update pre-shared key for secure ranging
Bug: 388601492
Test: atest RttServiceImplTest
Flag: EXEMPT bug fix
Change-Id: I2c717f6ebe5afec6546ca89b2834a11d2aaa3ba5
7 files changed, 201 insertions, 5 deletions
diff --git a/framework/java/android/net/wifi/rtt/PasnConfig.java b/framework/java/android/net/wifi/rtt/PasnConfig.java index 550fa6f5ea..547d94bb67 100644 --- a/framework/java/android/net/wifi/rtt/PasnConfig.java +++ b/framework/java/android/net/wifi/rtt/PasnConfig.java @@ -184,7 +184,7 @@ public final class PasnConfig implements Parcelable { private final int mBaseAkms; @Cipher private final int mCiphers; - private final String mPassword; + private String mPassword; private final WifiSsid mWifiSsid; private final byte[] mPasnComebackCookie; @@ -213,6 +213,13 @@ public final class PasnConfig implements Parcelable { } /** + * @hide + */ + public void setPassword(String password) { + mPassword = password; + } + + /** * Get Wifi SSID which is used to retrieve saved network profile if {@link #getPassword()} * is null. If Wifi SSID and password are not set and there is no saved profile corresponding to * the responder, unauthenticated PASN will be used if {@link RangingRequest#getSecurityMode()} diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index 3eb3d0ed49..c996782c11 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -817,6 +817,31 @@ public class WifiConfigManager { } /** + * Retrieves the configured network corresponding to the provided SSID and security type. The + * WifiConfiguration object will have the password in plain text. + * + * WARNING: Don't use this to pass network configurations to external apps. Should only be + * sent to system apps/wifi stack, when there is a need for passwords in plaintext. + * + * @param ssid SSID of the requested network. + * @param securityType security type of the requested network. + * @return WifiConfiguration object if found, null otherwise. + */ + public @Nullable WifiConfiguration getConfiguredNetworkWithPassword(@NonNull WifiSsid ssid, + @WifiConfiguration.SecurityType int securityType) { + List<WifiConfiguration> wifiConfigurations = getConfiguredNetworks(false, false, + Process.WIFI_UID); + for (WifiConfiguration wifiConfiguration : wifiConfigurations) { + // Match ssid and security type + if (ssid.equals(WifiSsid.fromString(wifiConfiguration.SSID)) + && wifiConfiguration.isSecurityType(securityType)) { + return new WifiConfiguration(wifiConfiguration); + } + } + return null; + } + + /** * Retrieves the list of all configured networks with the passwords masked. * * @return List of WifiConfiguration objects representing the networks. diff --git a/service/java/com/android/server/wifi/rtt/RttService.java b/service/java/com/android/server/wifi/rtt/RttService.java index aa13c0b6c0..9242992a08 100644 --- a/service/java/com/android/server/wifi/rtt/RttService.java +++ b/service/java/com/android/server/wifi/rtt/RttService.java @@ -62,7 +62,8 @@ public class RttService extends SystemService { mImpl.start(handlerThread.getLooper(), wifiInjector.getClock(), awareManager, rttMetrics, wifiPermissionsUtil, wifiInjector.getSettingsConfigStore(), - wifiInjector.getHalDeviceManager()); + wifiInjector.getHalDeviceManager(), wifiInjector.getWifiConfigManager(), + wifiInjector.getSsidTranslator()); } else if (phase == SystemService.PHASE_BOOT_COMPLETED) { mImpl.handleBootCompleted(); } diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java index 930368e1b0..87ab51926a 100644 --- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java +++ b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java @@ -38,17 +38,21 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.location.LocationManager; import android.net.MacAddress; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; +import android.net.wifi.WifiSsid; import android.net.wifi.aware.IWifiAwareMacAddressProvider; import android.net.wifi.aware.MacAddrMapping; import android.net.wifi.aware.WifiAwareManager; import android.net.wifi.rtt.IRttCallback; import android.net.wifi.rtt.IWifiRttManager; +import android.net.wifi.rtt.PasnConfig; import android.net.wifi.rtt.RangingRequest; import android.net.wifi.rtt.RangingResult; import android.net.wifi.rtt.RangingResultCallback; import android.net.wifi.rtt.ResponderConfig; import android.net.wifi.rtt.ResponderLocation; +import android.net.wifi.rtt.SecureRangingConfig; import android.net.wifi.rtt.WifiRttManager; import android.os.Binder; import android.os.Bundle; @@ -73,7 +77,9 @@ import com.android.server.wifi.BuildProperties; import com.android.server.wifi.Clock; import com.android.server.wifi.FrameworkFacade; import com.android.server.wifi.HalDeviceManager; +import com.android.server.wifi.SsidTranslator; import com.android.server.wifi.SystemBuildProperties; +import com.android.server.wifi.WifiConfigManager; import com.android.server.wifi.WifiSettingsConfigStore; import com.android.server.wifi.hal.WifiRttController; import com.android.server.wifi.proto.nano.WifiMetricsProto; @@ -116,8 +122,8 @@ public class RttServiceImpl extends IWifiRttManager.Stub { private final BuildProperties mBuildProperties; private FrameworkFacade mFrameworkFacade; private WifiRttController.Capabilities mCapabilities; - private RttServiceSynchronized mRttServiceSynchronized; + private SsidTranslator mWifiSsidTranslator; /* package */ static final String HAL_RANGING_TIMEOUT_TAG = TAG + " HAL Ranging Timeout"; @@ -128,6 +134,7 @@ public class RttServiceImpl extends IWifiRttManager.Stub { // arbitrary, larger than anything reasonable /* package */ static final int MAX_QUEUED_PER_UID = 20; + private WifiConfigManager mWifiConfigManager; private final WifiRttController.RttControllerRangingResultsCallback mRangingResultsCallback = new WifiRttController.RttControllerRangingResultsCallback() { @@ -311,10 +318,14 @@ public class RttServiceImpl extends IWifiRttManager.Stub { * @param wifiPermissionsUtil Utility for permission checks. * @param settingsConfigStore Used for retrieving verbose logging level. * @param halDeviceManager The HAL device manager object. + * @param wifiConfigManager The Wi-Fi configuration manager used to retrieve credentials for + * secure ranging + * @param ssidTranslator SSID translator */ public void start(Looper looper, Clock clock, WifiAwareManager awareManager, RttMetrics rttMetrics, WifiPermissionsUtil wifiPermissionsUtil, - WifiSettingsConfigStore settingsConfigStore, HalDeviceManager halDeviceManager) { + WifiSettingsConfigStore settingsConfigStore, HalDeviceManager halDeviceManager, + WifiConfigManager wifiConfigManager, SsidTranslator ssidTranslator) { mClock = clock; mAwareManager = awareManager; mHalDeviceManager = halDeviceManager; @@ -323,6 +334,8 @@ public class RttServiceImpl extends IWifiRttManager.Stub { mRttServiceSynchronized = new RttServiceSynchronized(looper); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); mPowerManager = mContext.getSystemService(PowerManager.class); + mWifiConfigManager = wifiConfigManager; + mWifiSsidTranslator = ssidTranslator; mRttServiceSynchronized.mHandler.post(() -> { IntentFilter intentFilter = new IntentFilter(); @@ -516,6 +529,63 @@ public class RttServiceImpl extends IWifiRttManager.Stub { } } + private @WifiConfiguration.SecurityType int getSecurityTypeFromPasnAkms( + @PasnConfig.AkmType int akms) { + @WifiConfiguration.SecurityType int securityType; + // IEEE 802.11az supports PASN authentication with FT, PASN authentication with SAE and + // PASN authentication with FILS shared key. On FT PSK and SAE needs pre-shared key or + // password. + if (akms == PasnConfig.AKM_PASN) { + securityType = WifiConfiguration.SECURITY_TYPE_OPEN; + } else if ((akms & PasnConfig.AKM_SAE) != 0) { + securityType = WifiConfiguration.SECURITY_TYPE_SAE; + } else if ((akms & PasnConfig.AKM_FT_PSK_SHA256) != 0 + || (akms & PasnConfig.AKM_FT_PSK_SHA384) != 0) { + // Note: WifiConfiguration is created as PSK. The fast transition (FT) flag is added + // before saving to wpa_supplicant. So check for SECURITY_TYPE_PSK. + securityType = WifiConfiguration.SECURITY_TYPE_PSK; + } else { + securityType = WifiConfiguration.SECURITY_TYPE_EAP; + } + return securityType; + } + + /** + * Update the PASN password from WifiConfiguration. + */ + private void updatePasswordIfRequired(@NonNull PasnConfig pasnConfig) { + if (pasnConfig.getPassword() != null || pasnConfig.getWifiSsid() == null) { + return; + } + int securityType = getSecurityTypeFromPasnAkms(pasnConfig.getBaseAkms()); + if (securityType == WifiConfiguration.SECURITY_TYPE_SAE + || securityType == WifiConfiguration.SECURITY_TYPE_PSK) { + // The SSID within PasnConfig is supplied by an 11az secure ranging application, + // which doesn't guarantee UTF-8 encoding. Therefore, a UTF-8 conversion step is + // necessary before the SSID can be reliably used by service code. + WifiSsid translatedSsid = mWifiSsidTranslator.getTranslatedSsid( + pasnConfig.getWifiSsid()); + WifiConfiguration wifiConfiguration = + mWifiConfigManager.getConfiguredNetworkWithPassword(translatedSsid, + securityType); + if (wifiConfiguration != null) { + pasnConfig.setPassword(wifiConfiguration.preSharedKey); + } + } + } + + /** + * Update the secure ranging parameters if required. + */ + private void updateSecureRangingParams(RangingRequest request) { + for (ResponderConfig rttPeer : request.mRttPeers) { + SecureRangingConfig secureRangingConfig = rttPeer.getSecureRangingConfig(); + if (secureRangingConfig != null) { + updatePasswordIfRequired(secureRangingConfig.getPasnConfig()); + } + } + } + /** * Binder interface API to start a ranging operation. Called on binder thread, operations needs * to be posted to handler thread. @@ -620,6 +690,7 @@ public class RttServiceImpl extends IWifiRttManager.Stub { } override11azOverlays(request); + updateSecureRangingParams(request); mRttServiceSynchronized.mHandler.post(() -> { WorkSource sourceToUse = ws; diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java index 83cff646df..3d25fdada6 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java @@ -17,6 +17,7 @@ package com.android.server.wifi; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE; import static android.net.wifi.WifiManager.AddNetworkResult.STATUS_INVALID_CONFIGURATION_ENTERPRISE; import static com.android.server.wifi.TestUtil.createCapabilityBitset; @@ -8502,4 +8503,33 @@ public class WifiConfigManagerTest extends WifiBaseTest { result = updateNetworkToWifiConfigManager(config); assertFalse(result.isSuccess()); } + + /** + * Verify that the configured network with password is correctly retrieved using SSID and Key + * management. + */ + @Test + public void testConfiguredNetworkWithPassword() { + + NetworkSelectionStatus.Builder builder = new NetworkSelectionStatus.Builder(); + NetworkSelectionStatus networkSelectionStatus = builder.build(); + SecurityParams params = SecurityParams.createSecurityParamsBySecurityType( + SECURITY_TYPE_SAE); + networkSelectionStatus.setCandidateSecurityParams(params); + WifiConfiguration saeNetwork = WifiConfigurationTestUtil.createSaeNetwork(TEST_SSID); + saeNetwork.setNetworkSelectionStatus(networkSelectionStatus); + NetworkUpdateResult result = verifyAddNetworkToWifiConfigManager(saeNetwork); + + // Get the configured network with password + WifiConfiguration wifiConfig = mWifiConfigManager.getConfiguredNetworkWithPassword( + WifiSsid.fromString(TEST_SSID), SECURITY_TYPE_SAE); + // Test the retrieved network is the same network that was added for TEST_SSID and SAE + assertNotNull(wifiConfig); + assertEquals(saeNetwork.networkId, result.getNetworkId()); + assertEquals(WifiConfigurationTestUtil.TEST_PSK, wifiConfig.preSharedKey); + wifiConfig = mWifiConfigManager.getConfiguredNetworkWithPassword( + WifiSsid.fromString(TEST_SSID), SECURITY_TYPE_PSK); + // Test there is no network with TEST_SSID and FT_PSK + assertNull(wifiConfig); + } } diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java index cc570c77c7..be9982e60a 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java +++ b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttServiceImplTest.java @@ -23,10 +23,12 @@ import static android.net.wifi.rtt.WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_ON import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_VERBOSE_LOGGING_ENABLED; import static com.android.server.wifi.rtt.RttTestUtils.compareListContentsNoOrdering; +import static com.android.server.wifi.rtt.RttTestUtils.getDummyRangingResults; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; @@ -55,7 +57,9 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.location.LocationManager; import android.net.MacAddress; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; +import android.net.wifi.WifiSsid; import android.net.wifi.aware.IWifiAwareMacAddressProvider; import android.net.wifi.aware.MacAddrMapping; import android.net.wifi.aware.PeerHandle; @@ -84,7 +88,9 @@ import com.android.modules.utils.build.SdkLevel; import com.android.server.wifi.Clock; import com.android.server.wifi.HalDeviceManager; import com.android.server.wifi.MockResources; +import com.android.server.wifi.SsidTranslator; import com.android.server.wifi.WifiBaseTest; +import com.android.server.wifi.WifiConfigManager; import com.android.server.wifi.WifiSettingsConfigStore; import com.android.server.wifi.hal.WifiRttController; import com.android.server.wifi.proto.nano.WifiMetricsProto; @@ -178,6 +184,11 @@ public class RttServiceImplTest extends WifiBaseTest { @Mock WifiSettingsConfigStore mWifiSettingsConfigStore; + @Mock + WifiConfigManager mWifiConfigManager; + WifiConfiguration mWifiConfiguration = new WifiConfiguration(); + @Mock + SsidTranslator mSsidTranslator; /** * Using instead of spy to avoid native crash failures - possibly due to @@ -248,7 +259,8 @@ public class RttServiceImplTest extends WifiBaseTest { doAnswer(mBinderUnlinkToDeathCounter).when(mockIbinder).unlinkToDeath(any(), anyInt()); mDut.start(mMockLooper.getLooper(), mockClock, mockAwareManager, mockMetrics, - mockPermissionUtil, mWifiSettingsConfigStore, mockHalDeviceManager); + mockPermissionUtil, mWifiSettingsConfigStore, mockHalDeviceManager, + mWifiConfigManager, mSsidTranslator); mMockLooper.dispatchAll(); ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = ArgumentCaptor.forClass( BroadcastReceiver.class); @@ -371,6 +383,55 @@ public class RttServiceImplTest extends WifiBaseTest { } /** + * Validate a successful secure ranging flow. + */ + @Test + public void testSecureRanging() throws RemoteException { + RangingRequest request = RttTestUtils.getDummySecureRangingRequest( + RangingRequest.SECURITY_MODE_OPPORTUNISTIC); + mWifiConfiguration.preSharedKey = "TEST_PASSWORD"; + WifiSsid ssid = request.mRttPeers.get( + 1).getSecureRangingConfig().getPasnConfig().getWifiSsid(); + when(mWifiConfigManager.getConfiguredNetworkWithPassword(eq(ssid), + eq(WifiConfiguration.SECURITY_TYPE_SAE))).thenReturn(mWifiConfiguration); + when(mSsidTranslator.getTranslatedSsid(eq(ssid))).thenReturn(ssid); + + // Make sure the second peer is configured with no password for SAE. + assertNull(request.mRttPeers.get(1).getSecureRangingConfig().getPasnConfig().getPassword()); + + ClockAnswer clock = new ClockAnswer(); + doAnswer(clock).when(mockClock).getWallClockMillis(); + clock.time = 100; + mDut.startRanging(mockIbinder, mPackageName, mFeatureId, null, request, mockCallback, + mExtras); + mMockLooper.dispatchAll(); + verify(mockRttControllerHal).rangeRequest(mIntCaptor.capture(), mRequestCaptor.capture()); + verifyWakeupSet(false, 0); + RangingRequest halRequest = mRequestCaptor.getValue(); + assertNotEquals("Request to WifiRttController is not null", null, halRequest); + assertEquals("Size of request", request.mRttPeers.size(), halRequest.mRttPeers.size()); + + for (int i = 0; i < request.mRttPeers.size(); ++i) { + assertEquals("SecureRangingConfig is not same", + request.mRttPeers.get(i).getSecureRangingConfig(), + halRequest.mRttPeers.get(i).getSecureRangingConfig()); + } + + // Make sure password is set for second peer from WifiConfiguration for the SAE. + assertEquals("Password is not set", "TEST_PASSWORD", halRequest.mRttPeers.get( + 1).getSecureRangingConfig().getPasnConfig().getPassword()); + + mRangingResultsCbCaptor.getValue().onRangingResults(mIntCaptor.getValue(), + getDummyRangingResults(request).second); + mMockLooper.dispatchAll(); + + verify(mockCallback).onRangingResults(mListCaptor.capture()); + verifyWakeupCancelled(); + verifyNoMoreInteractions(mockRttControllerHal, mockCallback, + mAlarmManager.getAlarmManager()); + } + + /** * Validate a successful ranging flow with PeerHandles (i.e. verify translations) */ @Test diff --git a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java index d7e8afbf40..ecbf2bf585 100644 --- a/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java +++ b/service/tests/wifitests/src/com/android/server/wifi/rtt/RttTestUtils.java @@ -114,6 +114,7 @@ public class RttTestUtils { // SAE with no password configured pasnConfig = new PasnConfig .Builder(PasnConfig.AKM_SAE, PasnConfig.CIPHER_GCMP_256) + .setWifiSsid(WifiSsid.fromString("\"TEST_SSID\"")) .build(); secureRangingConfig = new SecureRangingConfig .Builder(pasnConfig) |