diff --git a/core/api/system-current.txt b/core/api/system-current.txt index c7744a415db59..cee7a9bee105b 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -9218,6 +9218,15 @@ package android.se.omapi { } +package android.security { + + public final class KeyChain { + method @Nullable @WorkerThread public static String getWifiKeyGrantAsUser(@NonNull android.content.Context, @NonNull android.os.UserHandle, @NonNull String); + method @WorkerThread public static boolean hasWifiKeyGrantAsUser(@NonNull android.content.Context, @NonNull android.os.UserHandle, @NonNull String); + } + +} + package android.security.keystore { public class AndroidKeyStoreProvider extends java.security.Provider { diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index 684eebe6ffdeb..091f5795784f8 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -68,4 +68,7 @@ interface IKeyChainService { // APIs used by KeyChainActivity void setGrant(int uid, String alias, boolean value); boolean hasGrant(int uid, String alias); + + // API used by Wifi + String getWifiKeyGrantAsUser(String alias); } diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 65a81cd57f417..11cb2b7c724b6 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -23,6 +23,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; import android.annotation.TestApi; import android.annotation.WorkerThread; import android.app.Activity; @@ -1012,6 +1013,54 @@ public final class KeyChain { return bindAsUser(context, null, user); } + /** + * Returns a persistable grant string that allows WiFi stack to access the key using Keystore + * SSL engine. + * + * @return grant string or null if key is not granted or doesn't exist. + * + * The key should be granted to Process.WIFI_UID. + * @hide + */ + @SystemApi + @Nullable + @WorkerThread + public static String getWifiKeyGrantAsUser( + @NonNull Context context, @NonNull UserHandle user, @NonNull String alias) { + try (KeyChainConnection keyChainConnection = + bindAsUser(context.getApplicationContext(), user)) { + return keyChainConnection.getService().getWifiKeyGrantAsUser(alias); + } catch (RemoteException | RuntimeException e) { + Log.i(LOG, "Couldn't get grant for wifi", e); + return null; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + Log.i(LOG, "Interrupted while getting grant for wifi", e); + return null; + } + } + + /** + * Returns whether the key is granted to WiFi stack. + * @hide + */ + @SystemApi + @WorkerThread + public static boolean hasWifiKeyGrantAsUser( + @NonNull Context context, @NonNull UserHandle user, @NonNull String alias) { + try (KeyChainConnection keyChainConnection = + bindAsUser(context.getApplicationContext(), user)) { + return keyChainConnection.getService().hasGrant(Process.WIFI_UID, alias); + } catch (RemoteException | RuntimeException e) { + Log.i(LOG, "Couldn't query grant for wifi", e); + return false; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + Log.i(LOG, "Interrupted while querying grant for wifi", e); + return false; + } + } + /** * Bind to KeyChainService in the target user. * Caller should call unbindService on the result when finished.