1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.security;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.hardware.biometrics.BiometricConstants;
22 import android.hardware.security.keymint.HardwareAuthToken;
23 import android.hardware.security.keymint.HardwareAuthenticatorType;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 import android.os.ServiceSpecificException;
27 import android.os.StrictMode;
28 import android.security.authorization.IKeystoreAuthorization;
29 import android.system.keystore2.ResponseCode;
30 import android.util.Log;
31 
32 /**
33  * @hide This is the client side for IKeystoreAuthorization AIDL.
34  * It shall only be used by biometric authentication providers and Gatekeeper.
35  */
36 public class KeyStoreAuthorization {
37     private static final String TAG = "KeyStoreAuthorization";
38 
39     public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
40 
41     private static final KeyStoreAuthorization sInstance = new KeyStoreAuthorization();
42 
getInstance()43     public static KeyStoreAuthorization getInstance() {
44         return sInstance;
45     }
46 
47     /**
48      * @return an instance of IKeystoreAuthorization
49      */
getService()50     private IKeystoreAuthorization getService() {
51         return IKeystoreAuthorization.Stub.asInterface(
52                     ServiceManager.checkService("android.security.authorization"));
53     }
54 
55     /**
56      * Adds an auth token to keystore2.
57      *
58      * @param authToken created by Android authenticators.
59      * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
60      */
addAuthToken(@onNull HardwareAuthToken authToken)61     public int addAuthToken(@NonNull HardwareAuthToken authToken) {
62         StrictMode.noteSlowCall("addAuthToken");
63         try {
64             getService().addAuthToken(authToken);
65             return 0;
66         } catch (RemoteException | NullPointerException e) {
67             Log.w(TAG, "Can not connect to keystore", e);
68             return SYSTEM_ERROR;
69         } catch (ServiceSpecificException e) {
70             return e.errorCode;
71         }
72     }
73 
74     /**
75      * Add an auth token to Keystore 2.0 in the legacy serialized auth token format.
76      * @param authToken
77      * @return 0 if successful or a {@code ResponseCode}.
78      */
addAuthToken(@onNull byte[] authToken)79     public int addAuthToken(@NonNull byte[] authToken) {
80         return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken));
81     }
82 
83     /**
84      * Tells Keystore that the device is now unlocked for a user.
85      *
86      * @param userId - the user's Android user ID
87      * @param password - a secret derived from the user's synthetic password, if the unlock method
88      *                   is LSKF (or equivalent) and thus has made the synthetic password available
89      * @return 0 if successful or a {@code ResponseCode}.
90      */
onDeviceUnlocked(int userId, @Nullable byte[] password)91     public int onDeviceUnlocked(int userId, @Nullable byte[] password) {
92         StrictMode.noteDiskWrite();
93         try {
94             getService().onDeviceUnlocked(userId, password);
95             return 0;
96         } catch (RemoteException | NullPointerException e) {
97             Log.w(TAG, "Can not connect to keystore", e);
98             return SYSTEM_ERROR;
99         } catch (ServiceSpecificException e) {
100             return e.errorCode;
101         }
102     }
103 
104     /**
105      * Tells Keystore that the device is now locked for a user.
106      *
107      * @param userId - the user's Android user ID
108      * @param unlockingSids - list of biometric SIDs with which the device may be unlocked again
109      * @param weakUnlockEnabled - true if non-strong biometric or trust agent unlock is enabled
110      * @return 0 if successful or a {@code ResponseCode}.
111      */
onDeviceLocked(int userId, @NonNull long[] unlockingSids, boolean weakUnlockEnabled)112     public int onDeviceLocked(int userId, @NonNull long[] unlockingSids,
113             boolean weakUnlockEnabled) {
114         StrictMode.noteDiskWrite();
115         try {
116             getService().onDeviceLocked(userId, unlockingSids, weakUnlockEnabled);
117             return 0;
118         } catch (RemoteException | NullPointerException e) {
119             Log.w(TAG, "Can not connect to keystore", e);
120             return SYSTEM_ERROR;
121         } catch (ServiceSpecificException e) {
122             return e.errorCode;
123         }
124     }
125 
126     /**
127      * Gets the last authentication time of the given user and authenticators.
128      *
129      * @param userId user id
130      * @param authenticatorTypes an array of {@link HardwareAuthenticatorType}.
131      * @return the last authentication time or
132      * {@link BiometricConstants#BIOMETRIC_NO_AUTHENTICATION}.
133      */
getLastAuthTime(long userId, @HardwareAuthenticatorType int[] authenticatorTypes)134     public long getLastAuthTime(long userId, @HardwareAuthenticatorType int[] authenticatorTypes) {
135         try {
136             return getService().getLastAuthTime(userId, authenticatorTypes);
137         } catch (RemoteException | NullPointerException e) {
138             Log.w(TAG, "Error getting last auth time: " + e);
139             return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
140         } catch (ServiceSpecificException e) {
141             // This is returned when the feature flag test fails in keystore2
142             if (e.errorCode == ResponseCode.PERMISSION_DENIED) {
143                 throw new UnsupportedOperationException();
144             }
145             return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
146         }
147     }
148 
149 }
150