From ec1b13eb72b30c59da9c8a424202f695710287c0 Mon Sep 17 00:00:00 2001 From: Haijie Hong Date: Thu, 23 Nov 2023 17:10:29 +0800 Subject: [PATCH] Skip authentication in Wifi sharing if the device is unlocked recently BUG: 311168955 Test: atest com.android.settings.wifi.dpp.WifiDppConfiguratorAuthActivityTest Change-Id: I59674788e04d843541e8fcc3f3305ba295e8d8b1 --- .../dpp/WifiDppConfiguratorAuthActivity.java | 6 +- .../settings/wifi/dpp/WifiDppUtils.java | 56 +++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorAuthActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorAuthActivity.java index aa77dc178e3..010607ff7a2 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorAuthActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorAuthActivity.java @@ -37,6 +37,8 @@ import com.android.settings.core.InstrumentedActivity; * Sharing a Wi-Fi network by QR code after unlocking. Used by {@code InternetDialog} in QS. */ public class WifiDppConfiguratorAuthActivity extends InstrumentedActivity { + private static final String WIFI_SHARING_KEY_ALIAS = "wifi_sharing_auth_key"; + private static final int MAX_UNLOCK_SECONDS = 60; @Override public void onCreate(Bundle savedInstanceState) { @@ -46,7 +48,9 @@ public class WifiDppConfiguratorAuthActivity extends InstrumentedActivity { Intent authIntent = getSystemService(KeyguardManager.class) .createConfirmDeviceCredentialIntent( getText(R.string.wifi_dpp_lockscreen_title), null, getUserId()); - if (authIntent == null) { + if (authIntent == null + || WifiDppUtils.isUnlockedWithinSeconds( + WIFI_SHARING_KEY_ALIAS, MAX_UNLOCK_SECONDS)) { startQrCodeActivity(); finish(); } else { diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java index 83a1571eec0..23a6a5423e4 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java +++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java @@ -30,6 +30,8 @@ import android.os.Looper; import android.os.UserHandle; import android.os.VibrationEffect; import android.os.Vibrator; +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; import android.text.TextUtils; import com.android.settings.R; @@ -37,9 +39,19 @@ import com.android.settings.Utils; import com.android.settingslib.wifi.AccessPoint; import com.android.wifitrackerlib.WifiEntry; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.time.Duration; import java.util.List; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.KeyGenerator; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; + /** * Here are the items shared by both WifiDppConfiguratorActivity & WifiDppEnrolleeActivity * @@ -97,6 +109,8 @@ public class WifiDppUtils { private static final Duration VIBRATE_DURATION_QR_CODE_RECOGNITION = Duration.ofMillis(3); + private static final String AES_CBC_PKCS7_PADDING = "AES/CBC/PKCS7Padding"; + /** * Returns whether the device support WiFi DPP. */ @@ -366,6 +380,48 @@ public class WifiDppUtils { intent.putExtra(EXTRA_WIFI_HIDDEN_SSID, wifiConfiguration.hiddenSSID); } + /** + * Checks whether the device is unlocked recently. + * + * @param keyStoreAlias key + * @param seconds how many seconds since the device is unlocked + * @return whether the device is unlocked within the time + */ + public static boolean isUnlockedWithinSeconds(String keyStoreAlias, int seconds) { + try { + Cipher cipher = Cipher.getInstance(AES_CBC_PKCS7_PADDING); + cipher.init(Cipher.ENCRYPT_MODE, generateSecretKey(keyStoreAlias, seconds)); + cipher.doFinal(); + return true; + } catch (NoSuchPaddingException + | IllegalBlockSizeException + | NoSuchAlgorithmException + | BadPaddingException + | InvalidKeyException e) { + return false; + } + } + + private static SecretKey generateSecretKey(String keyStoreAlias, int seconds) { + KeyGenParameterSpec spec = new KeyGenParameterSpec + .Builder(keyStoreAlias, KeyProperties.PURPOSE_ENCRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) + .setUserAuthenticationRequired(true) + .setUserAuthenticationParameters( + seconds, + KeyProperties.AUTH_DEVICE_CREDENTIAL | KeyProperties.AUTH_BIOMETRIC_STRONG) + .build(); + try { + KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES); + keyGenerator.init(spec); + return keyGenerator.generateKey(); + } catch (NoSuchAlgorithmException + | InvalidAlgorithmParameterException e) { + return null; + } + } + /** * Shows authentication screen to confirm credentials (pin, pattern or password) for the current * user of the device.