/* * Copyright (C) 2021 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.security; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.security.maintenance.IKeystoreMaintenance; import android.system.keystore2.Domain; import android.system.keystore2.KeyDescriptor; import android.system.keystore2.ResponseCode; import android.util.Log; /** * @hide This is the client side for IKeystoreUserManager AIDL. * It shall only be used by the LockSettingsService. */ public class AndroidKeyStoreMaintenance { private static final String TAG = "AndroidKeyStoreMaintenance"; public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR; public static final int INVALID_ARGUMENT = ResponseCode.INVALID_ARGUMENT; public static final int PERMISSION_DENIED = ResponseCode.PERMISSION_DENIED; public static final int KEY_NOT_FOUND = ResponseCode.KEY_NOT_FOUND; private static IKeystoreMaintenance getService() { return IKeystoreMaintenance.Stub.asInterface( ServiceManager.checkService("android.security.maintenance")); } /** * Informs Keystore 2.0 about adding a user * * @param userId - Android user id of the user being added * @return 0 if successful or a {@code ResponseCode} * @hide */ public static int onUserAdded(@NonNull int userId) { try { getService().onUserAdded(userId); return 0; } catch (ServiceSpecificException e) { Log.e(TAG, "onUserAdded failed", e); return e.errorCode; } catch (Exception e) { Log.e(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } } /** * Informs Keystore 2.0 about removing a usergit mer * * @param userId - Android user id of the user being removed * @return 0 if successful or a {@code ResponseCode} * @hide */ public static int onUserRemoved(int userId) { try { getService().onUserRemoved(userId); return 0; } catch (ServiceSpecificException e) { Log.e(TAG, "onUserRemoved failed", e); return e.errorCode; } catch (Exception e) { Log.e(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } } /** * Informs Keystore 2.0 about changing user's password * * @param userId - Android user id of the user * @param password - a secret derived from the synthetic password provided by the * LockSettingService * @return 0 if successful or a {@code ResponseCode} * @hide */ public static int onUserPasswordChanged(int userId, @Nullable byte[] password) { try { getService().onUserPasswordChanged(userId, password); return 0; } catch (ServiceSpecificException e) { Log.e(TAG, "onUserPasswordChanged failed", e); return e.errorCode; } catch (Exception e) { Log.e(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } } /** * Informs Keystore 2.0 that an app was uninstalled and the corresponding namspace is to * be cleared. */ public static int clearNamespace(@Domain int domain, long namespace) { try { getService().clearNamespace(domain, namespace); return 0; } catch (ServiceSpecificException e) { Log.e(TAG, "clearNamespace failed", e); return e.errorCode; } catch (Exception e) { Log.e(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } } /** * Queries user state from Keystore 2.0. * * @param userId - Android user id of the user. * @return UserState enum variant as integer if successful or an error */ public static int getState(int userId) { try { return getService().getState(userId); } catch (ServiceSpecificException e) { Log.e(TAG, "getState failed", e); return e.errorCode; } catch (Exception e) { Log.e(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } } /** * Informs Keystore 2.0 that an off body event was detected. */ public static void onDeviceOffBody() { try { getService().onDeviceOffBody(); } catch (Exception e) { // TODO This fails open. This is not a regression with respect to keystore1 but it // should get fixed. Log.e(TAG, "Error while reporting device off body event.", e); } } /** * Migrates a key given by the source descriptor to the location designated by the destination * descriptor. * * @param source - The key to migrate may be specified by Domain.APP, Domain.SELINUX, or * Domain.KEY_ID. The caller needs the permissions use, delete, and grant for the * source namespace. * @param destination - The new designation for the key may be specified by Domain.APP or * Domain.SELINUX. The caller need the permission rebind for the destination * namespace. * * @return * 0 on success * * KEY_NOT_FOUND if the source did not exists. * * PERMISSION_DENIED if any of the required permissions was missing. * * INVALID_ARGUMENT if the destination was occupied or any domain value other than * the allowed once were specified. * * SYSTEM_ERROR if an unexpected error occurred. */ public static int migrateKeyNamespace(KeyDescriptor source, KeyDescriptor destination) { try { getService().migrateKeyNamespace(source, destination); return 0; } catch (ServiceSpecificException e) { Log.e(TAG, "migrateKeyNamespace failed", e); return e.errorCode; } catch (Exception e) { Log.e(TAG, "Can not connect to keystore", e); return SYSTEM_ERROR; } } }