Home | History | Annotate | Download | only in security
      1 /*
      2  * Copyright (C) 2009 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.app.ActivityManager;
     20 import android.app.ActivityThread;
     21 import android.app.Application;
     22 import android.app.KeyguardManager;
     23 import android.content.Context;
     24 import android.content.pm.PackageManager;
     25 import android.hardware.fingerprint.FingerprintManager;
     26 import android.os.Binder;
     27 import android.os.IBinder;
     28 import android.os.Process;
     29 import android.os.RemoteException;
     30 import android.os.ServiceManager;
     31 import android.os.UserHandle;
     32 import android.security.keymaster.ExportResult;
     33 import android.security.keymaster.KeyCharacteristics;
     34 import android.security.keymaster.KeymasterArguments;
     35 import android.security.keymaster.KeymasterBlob;
     36 import android.security.keymaster.KeymasterCertificateChain;
     37 import android.security.keymaster.KeymasterDefs;
     38 import android.security.keymaster.OperationResult;
     39 import android.security.keystore.KeyExpiredException;
     40 import android.security.keystore.KeyNotYetValidException;
     41 import android.security.keystore.KeyPermanentlyInvalidatedException;
     42 import android.security.keystore.StrongBoxUnavailableException;
     43 import android.security.keystore.UserNotAuthenticatedException;
     44 import android.util.Log;
     45 
     46 import java.math.BigInteger;
     47 import java.security.InvalidKeyException;
     48 import java.util.List;
     49 import java.util.Locale;
     50 
     51 /**
     52  * @hide This should not be made public in its present form because it
     53  * assumes that private and secret key bytes are available and would
     54  * preclude the use of hardware crypto.
     55  */
     56 public class KeyStore {
     57     private static final String TAG = "KeyStore";
     58 
     59     // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
     60     public static final int NO_ERROR = 1;
     61     public static final int LOCKED = 2;
     62     public static final int UNINITIALIZED = 3;
     63     public static final int SYSTEM_ERROR = 4;
     64     public static final int PROTOCOL_ERROR = 5;
     65     public static final int PERMISSION_DENIED = 6;
     66     public static final int KEY_NOT_FOUND = 7;
     67     public static final int VALUE_CORRUPTED = 8;
     68     public static final int UNDEFINED_ACTION = 9;
     69     public static final int WRONG_PASSWORD = 10;
     70     public static final int CANNOT_ATTEST_IDS = -66;
     71     public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
     72 
     73     /**
     74      * Per operation authentication is needed before this operation is valid.
     75      * This is returned from {@link #begin} when begin succeeds but the operation uses
     76      * per-operation authentication and must authenticate before calling {@link #update} or
     77      * {@link #finish}.
     78      */
     79     public static final int OP_AUTH_NEEDED = 15;
     80 
     81     // Used for UID field to indicate the calling UID.
     82     public static final int UID_SELF = -1;
     83 
     84     // Flags for "put" "import" and "generate"
     85     public static final int FLAG_NONE = 0;
     86 
     87     /**
     88      * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key
     89      * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern).
     90      *
     91      * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set
     92      * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key
     93      * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or
     94      * a Device Administrator). Finally, this key (or key pair) cannot be used until the user
     95      * unlocks the secure lock screen after boot.
     96      *
     97      * @see KeyguardManager#isDeviceSecure()
     98      */
     99     public static final int FLAG_ENCRYPTED = 1;
    100 
    101     /**
    102      * Select Software keymaster device, which as of this writing is the lowest security
    103      * level available on an android device. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
    104      * A TEE based keymaster implementation is implied.
    105      *
    106      * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
    107      * For historical reasons this corresponds to the KEYSTORE_FLAG_FALLBACK flag.
    108      */
    109     public static final int FLAG_SOFTWARE = 1 << 1;
    110 
    111     /**
    112      * A private flag that's only available to system server to indicate that this key is part of
    113      * device encryption flow so it receives special treatment from keystore. For example this key
    114      * will not be super encrypted, and it will be stored separately under an unique UID instead
    115      * of the caller UID i.e. SYSTEM.
    116      *
    117      * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
    118      */
    119     public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
    120 
    121     /**
    122      * Select Strongbox keymaster device, which as of this writing the the highest security level
    123      * available an android devices. If neither FLAG_STRONGBOX nor FLAG_SOFTWARE is provided
    124      * A TEE based keymaster implementation is implied.
    125      *
    126      * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
    127      */
    128     public static final int FLAG_STRONGBOX = 1 << 4;
    129 
    130     // States
    131     public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
    132 
    133     private int mError = NO_ERROR;
    134 
    135     private final IKeystoreService mBinder;
    136     private final Context mContext;
    137 
    138     private IBinder mToken;
    139 
    140     private KeyStore(IKeystoreService binder) {
    141         mBinder = binder;
    142         mContext = getApplicationContext();
    143     }
    144 
    145     public static Context getApplicationContext() {
    146         Application application = ActivityThread.currentApplication();
    147         if (application == null) {
    148             throw new IllegalStateException(
    149                     "Failed to obtain application Context from ActivityThread");
    150         }
    151         return application;
    152     }
    153 
    154     public static KeyStore getInstance() {
    155         IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
    156                 .getService("android.security.keystore"));
    157         return new KeyStore(keystore);
    158     }
    159 
    160     private synchronized IBinder getToken() {
    161         if (mToken == null) {
    162             mToken = new Binder();
    163         }
    164         return mToken;
    165     }
    166 
    167     public State state(int userId) {
    168         final int ret;
    169         try {
    170             ret = mBinder.getState(userId);
    171         } catch (RemoteException e) {
    172             Log.w(TAG, "Cannot connect to keystore", e);
    173             throw new AssertionError(e);
    174         }
    175 
    176         switch (ret) {
    177             case NO_ERROR: return State.UNLOCKED;
    178             case LOCKED: return State.LOCKED;
    179             case UNINITIALIZED: return State.UNINITIALIZED;
    180             default: throw new AssertionError(mError);
    181         }
    182     }
    183 
    184     public State state() {
    185         return state(UserHandle.myUserId());
    186     }
    187 
    188     public boolean isUnlocked() {
    189         return state() == State.UNLOCKED;
    190     }
    191 
    192     public byte[] get(String key, int uid) {
    193         try {
    194             key = key != null ? key : "";
    195             return mBinder.get(key, uid);
    196         } catch (RemoteException e) {
    197             Log.w(TAG, "Cannot connect to keystore", e);
    198             return null;
    199         } catch (android.os.ServiceSpecificException e) {
    200             Log.w(TAG, "KeyStore exception", e);
    201             return null;
    202         }
    203     }
    204 
    205     public byte[] get(String key) {
    206         return get(key, UID_SELF);
    207     }
    208 
    209     public boolean put(String key, byte[] value, int uid, int flags) {
    210         return insert(key, value, uid, flags) == NO_ERROR;
    211     }
    212 
    213     public int insert(String key, byte[] value, int uid, int flags) {
    214         try {
    215             if (value == null) {
    216                 value = new byte[0];
    217             }
    218             return mBinder.insert(key, value, uid, flags);
    219         } catch (RemoteException e) {
    220             Log.w(TAG, "Cannot connect to keystore", e);
    221             return SYSTEM_ERROR;
    222         }
    223     }
    224 
    225     public boolean delete(String key, int uid) {
    226         try {
    227             int ret = mBinder.del(key, uid);
    228             return (ret == NO_ERROR || ret == KEY_NOT_FOUND);
    229         } catch (RemoteException e) {
    230             Log.w(TAG, "Cannot connect to keystore", e);
    231             return false;
    232         }
    233     }
    234 
    235     public boolean delete(String key) {
    236         return delete(key, UID_SELF);
    237     }
    238 
    239     public boolean contains(String key, int uid) {
    240         try {
    241             return mBinder.exist(key, uid) == NO_ERROR;
    242         } catch (RemoteException e) {
    243             Log.w(TAG, "Cannot connect to keystore", e);
    244             return false;
    245         }
    246     }
    247 
    248     public boolean contains(String key) {
    249         return contains(key, UID_SELF);
    250     }
    251 
    252     /**
    253      * List all entries in the keystore for {@code uid} starting with {@code prefix}.
    254      */
    255     public String[] list(String prefix, int uid) {
    256         try {
    257             return mBinder.list(prefix, uid);
    258         } catch (RemoteException e) {
    259             Log.w(TAG, "Cannot connect to keystore", e);
    260             return null;
    261         } catch (android.os.ServiceSpecificException e) {
    262             Log.w(TAG, "KeyStore exception", e);
    263             return null;
    264         }
    265     }
    266 
    267     public String[] list(String prefix) {
    268         return list(prefix, UID_SELF);
    269     }
    270 
    271     public boolean reset() {
    272         try {
    273             return mBinder.reset() == NO_ERROR;
    274         } catch (RemoteException e) {
    275             Log.w(TAG, "Cannot connect to keystore", e);
    276             return false;
    277         }
    278     }
    279 
    280     /**
    281      * Attempt to lock the keystore for {@code user}.
    282      *
    283      * @param userId Android user to lock.
    284      * @return whether {@code user}'s keystore was locked.
    285      */
    286     public boolean lock(int userId) {
    287         try {
    288             return mBinder.lock(userId) == NO_ERROR;
    289         } catch (RemoteException e) {
    290             Log.w(TAG, "Cannot connect to keystore", e);
    291             return false;
    292         }
    293     }
    294 
    295     public boolean lock() {
    296         return lock(UserHandle.myUserId());
    297     }
    298 
    299     /**
    300      * Attempt to unlock the keystore for {@code user} with the password {@code password}.
    301      * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
    302      * created.
    303      *
    304      * @param userId Android user ID to operate on
    305      * @param password user's keystore password. Should be the most recent value passed to
    306      * {@link #onUserPasswordChanged} for the user.
    307      *
    308      * @return whether the keystore was unlocked.
    309      */
    310     public boolean unlock(int userId, String password) {
    311         try {
    312             password = password != null ? password : "";
    313             mError = mBinder.unlock(userId, password);
    314             return mError == NO_ERROR;
    315         } catch (RemoteException e) {
    316             Log.w(TAG, "Cannot connect to keystore", e);
    317             return false;
    318         }
    319     }
    320 
    321     public boolean unlock(String password) {
    322         return unlock(UserHandle.getUserId(Process.myUid()), password);
    323     }
    324 
    325     /**
    326      * Check if the keystore for {@code userId} is empty.
    327      */
    328     public boolean isEmpty(int userId) {
    329         try {
    330             return mBinder.isEmpty(userId) != 0;
    331         } catch (RemoteException e) {
    332             Log.w(TAG, "Cannot connect to keystore", e);
    333             return false;
    334         }
    335     }
    336 
    337     public boolean isEmpty() {
    338         return isEmpty(UserHandle.myUserId());
    339     }
    340 
    341     public boolean generate(String key, int uid, int keyType, int keySize, int flags,
    342             byte[][] args) {
    343         try {
    344             return mBinder.generate(key, uid, keyType, keySize, flags,
    345                     new KeystoreArguments(args)) == NO_ERROR;
    346         } catch (RemoteException e) {
    347             Log.w(TAG, "Cannot connect to keystore", e);
    348             return false;
    349         }
    350     }
    351 
    352     public boolean importKey(String keyName, byte[] key, int uid, int flags) {
    353         try {
    354             return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
    355         } catch (RemoteException e) {
    356             Log.w(TAG, "Cannot connect to keystore", e);
    357             return false;
    358         }
    359     }
    360 
    361     public byte[] sign(String key, byte[] data) {
    362         try {
    363             return mBinder.sign(key, data);
    364         } catch (RemoteException e) {
    365             Log.w(TAG, "Cannot connect to keystore", e);
    366             return null;
    367         } catch (android.os.ServiceSpecificException e) {
    368             Log.w(TAG, "KeyStore exception", e);
    369             return null;
    370         }
    371 
    372     }
    373 
    374     public boolean verify(String key, byte[] data, byte[] signature) {
    375         try {
    376             signature = signature != null ? signature : new byte[0];
    377             return mBinder.verify(key, data, signature) == NO_ERROR;
    378         } catch (RemoteException e) {
    379             Log.w(TAG, "Cannot connect to keystore", e);
    380             return false;
    381         } catch (android.os.ServiceSpecificException e) {
    382             Log.w(TAG, "KeyStore exception", e);
    383             return false;
    384         }
    385 
    386     }
    387 
    388     public String grant(String key, int uid) {
    389         try {
    390             String grantAlias =  mBinder.grant(key, uid);
    391             if (grantAlias == "") return null;
    392             return grantAlias;
    393         } catch (RemoteException e) {
    394             Log.w(TAG, "Cannot connect to keystore", e);
    395             return null;
    396         }
    397     }
    398 
    399     public boolean ungrant(String key, int uid) {
    400         try {
    401             return mBinder.ungrant(key, uid) == NO_ERROR;
    402         } catch (RemoteException e) {
    403             Log.w(TAG, "Cannot connect to keystore", e);
    404             return false;
    405         }
    406     }
    407 
    408     /**
    409      * Returns the last modification time of the key in milliseconds since the
    410      * epoch. Will return -1L if the key could not be found or other error.
    411      */
    412     public long getmtime(String key, int uid) {
    413         try {
    414             final long millis = mBinder.getmtime(key, uid);
    415             if (millis == -1L) {
    416                 return -1L;
    417             }
    418 
    419             return millis * 1000L;
    420         } catch (RemoteException e) {
    421             Log.w(TAG, "Cannot connect to keystore", e);
    422             return -1L;
    423         }
    424     }
    425 
    426     public long getmtime(String key) {
    427         return getmtime(key, UID_SELF);
    428     }
    429 
    430     // TODO: remove this when it's removed from Settings
    431     public boolean isHardwareBacked() {
    432         return isHardwareBacked("RSA");
    433     }
    434 
    435     public boolean isHardwareBacked(String keyType) {
    436         try {
    437             return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
    438         } catch (RemoteException e) {
    439             Log.w(TAG, "Cannot connect to keystore", e);
    440             return false;
    441         }
    442     }
    443 
    444     public boolean clearUid(int uid) {
    445         try {
    446             return mBinder.clear_uid(uid) == NO_ERROR;
    447         } catch (RemoteException e) {
    448             Log.w(TAG, "Cannot connect to keystore", e);
    449             return false;
    450         }
    451     }
    452 
    453     public int getLastError() {
    454         return mError;
    455     }
    456 
    457     public boolean addRngEntropy(byte[] data, int flags) {
    458         try {
    459             return mBinder.addRngEntropy(data, flags) == NO_ERROR;
    460         } catch (RemoteException e) {
    461             Log.w(TAG, "Cannot connect to keystore", e);
    462             return false;
    463         }
    464     }
    465 
    466     public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
    467             int flags, KeyCharacteristics outCharacteristics) {
    468         try {
    469             entropy = entropy != null ? entropy : new byte[0];
    470             args = args != null ? args : new KeymasterArguments();
    471             return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
    472         } catch (RemoteException e) {
    473             Log.w(TAG, "Cannot connect to keystore", e);
    474             return SYSTEM_ERROR;
    475         }
    476     }
    477 
    478     public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
    479             KeyCharacteristics outCharacteristics) {
    480         return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
    481     }
    482 
    483     public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
    484             int uid, KeyCharacteristics outCharacteristics) {
    485         try {
    486             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
    487             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
    488             return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
    489         } catch (RemoteException e) {
    490             Log.w(TAG, "Cannot connect to keystore", e);
    491             return SYSTEM_ERROR;
    492         }
    493     }
    494 
    495     public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
    496             KeyCharacteristics outCharacteristics) {
    497         return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
    498     }
    499 
    500     public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
    501             int uid, int flags, KeyCharacteristics outCharacteristics) {
    502         try {
    503             return mBinder.importKey(alias, args, format, keyData, uid, flags,
    504                     outCharacteristics);
    505         } catch (RemoteException e) {
    506             Log.w(TAG, "Cannot connect to keystore", e);
    507             return SYSTEM_ERROR;
    508         }
    509     }
    510 
    511     public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
    512             int flags, KeyCharacteristics outCharacteristics) {
    513         return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
    514     }
    515 
    516     public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
    517             String wrappingKeyAlias,
    518             byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
    519             KeyCharacteristics outCharacteristics) {
    520         try {
    521             return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
    522                     maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
    523         } catch (RemoteException e) {
    524             Log.w(TAG, "Cannot connect to keystore", e);
    525             return SYSTEM_ERROR;
    526         }
    527     }
    528 
    529     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
    530             KeymasterBlob appId, int uid) {
    531         try {
    532             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
    533             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
    534             return mBinder.exportKey(alias, format, clientId, appId, uid);
    535         } catch (RemoteException e) {
    536             Log.w(TAG, "Cannot connect to keystore", e);
    537             return null;
    538         }
    539     }
    540     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
    541             KeymasterBlob appId) {
    542         return exportKey(alias, format, clientId, appId, UID_SELF);
    543     }
    544 
    545     public OperationResult begin(String alias, int purpose, boolean pruneable,
    546             KeymasterArguments args, byte[] entropy, int uid) {
    547         try {
    548             args = args != null ? args : new KeymasterArguments();
    549             entropy = entropy != null ? entropy : new byte[0];
    550             return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
    551         } catch (RemoteException e) {
    552             Log.w(TAG, "Cannot connect to keystore", e);
    553             return null;
    554         }
    555     }
    556 
    557     public OperationResult begin(String alias, int purpose, boolean pruneable,
    558             KeymasterArguments args, byte[] entropy) {
    559         entropy = entropy != null ? entropy : new byte[0];
    560         args = args != null ? args : new KeymasterArguments();
    561         return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
    562     }
    563 
    564     public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
    565         try {
    566             arguments = arguments != null ? arguments : new KeymasterArguments();
    567             input = input != null ? input : new byte[0];
    568             return mBinder.update(token, arguments, input);
    569         } catch (RemoteException e) {
    570             Log.w(TAG, "Cannot connect to keystore", e);
    571             return null;
    572         }
    573     }
    574 
    575     public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
    576             byte[] entropy) {
    577         try {
    578             arguments = arguments != null ? arguments : new KeymasterArguments();
    579             entropy = entropy != null ? entropy : new byte[0];
    580             signature = signature != null ? signature : new byte[0];
    581             return mBinder.finish(token, arguments, signature, entropy);
    582         } catch (RemoteException e) {
    583             Log.w(TAG, "Cannot connect to keystore", e);
    584             return null;
    585         }
    586     }
    587 
    588     public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
    589         return finish(token, arguments, signature, null);
    590     }
    591 
    592     public int abort(IBinder token) {
    593         try {
    594             return mBinder.abort(token);
    595         } catch (RemoteException e) {
    596             Log.w(TAG, "Cannot connect to keystore", e);
    597             return SYSTEM_ERROR;
    598         }
    599     }
    600 
    601     /**
    602      * Check if the operation referenced by {@code token} is currently authorized.
    603      *
    604      * @param token An operation token returned by a call to
    605      * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
    606      */
    607     public boolean isOperationAuthorized(IBinder token) {
    608         try {
    609             return mBinder.isOperationAuthorized(token);
    610         } catch (RemoteException e) {
    611             Log.w(TAG, "Cannot connect to keystore", e);
    612             return false;
    613         }
    614     }
    615 
    616     /**
    617      * Add an authentication record to the keystore authorization table.
    618      *
    619      * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
    620      * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
    621      * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
    622      */
    623     public int addAuthToken(byte[] authToken) {
    624         try {
    625             return mBinder.addAuthToken(authToken);
    626         } catch (RemoteException e) {
    627             Log.w(TAG, "Cannot connect to keystore", e);
    628             return SYSTEM_ERROR;
    629         }
    630     }
    631 
    632     /**
    633      * Notify keystore that a user's password has changed.
    634      *
    635      * @param userId the user whose password changed.
    636      * @param newPassword the new password or "" if the password was removed.
    637      */
    638     public boolean onUserPasswordChanged(int userId, String newPassword) {
    639         // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
    640         // explicit here.
    641         if (newPassword == null) {
    642             newPassword = "";
    643         }
    644         try {
    645             return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
    646         } catch (RemoteException e) {
    647             Log.w(TAG, "Cannot connect to keystore", e);
    648             return false;
    649         }
    650     }
    651 
    652     /**
    653      * Notify keystore that a user was added.
    654      *
    655      * @param userId the new user.
    656      * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
    657      * specified then the new user's keystore will be intialized with the same secure lockscreen
    658      * password as the parent.
    659      */
    660     public void onUserAdded(int userId, int parentId) {
    661         try {
    662             mBinder.onUserAdded(userId, parentId);
    663         } catch (RemoteException e) {
    664             Log.w(TAG, "Cannot connect to keystore", e);
    665         }
    666     }
    667 
    668     /**
    669      * Notify keystore that a user was added.
    670      *
    671      * @param userId the new user.
    672      */
    673     public void onUserAdded(int userId) {
    674         onUserAdded(userId, -1);
    675     }
    676 
    677     /**
    678      * Notify keystore that a user was removed.
    679      *
    680      * @param userId the removed user.
    681      */
    682     public void onUserRemoved(int userId) {
    683         try {
    684             mBinder.onUserRemoved(userId);
    685         } catch (RemoteException e) {
    686             Log.w(TAG, "Cannot connect to keystore", e);
    687         }
    688     }
    689 
    690     public boolean onUserPasswordChanged(String newPassword) {
    691         return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
    692     }
    693 
    694     public int attestKey(
    695             String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
    696         try {
    697             if (params == null) {
    698                 params = new KeymasterArguments();
    699             }
    700             if (outChain == null) {
    701                 outChain = new KeymasterCertificateChain();
    702             }
    703             return mBinder.attestKey(alias, params, outChain);
    704         } catch (RemoteException e) {
    705             Log.w(TAG, "Cannot connect to keystore", e);
    706             return SYSTEM_ERROR;
    707         }
    708     }
    709 
    710     public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) {
    711         try {
    712             if (params == null) {
    713                 params = new KeymasterArguments();
    714             }
    715             if (outChain == null) {
    716                 outChain = new KeymasterCertificateChain();
    717             }
    718             return mBinder.attestDeviceIds(params, outChain);
    719         } catch (RemoteException e) {
    720             Log.w(TAG, "Cannot connect to keystore", e);
    721             return SYSTEM_ERROR;
    722         }
    723     }
    724 
    725     /**
    726      * Notify keystore that the device went off-body.
    727      */
    728     public void onDeviceOffBody() {
    729         try {
    730             mBinder.onDeviceOffBody();
    731         } catch (RemoteException e) {
    732             Log.w(TAG, "Cannot connect to keystore", e);
    733         }
    734     }
    735 
    736     // Keep in sync with confirmationui/1.0/types.hal.
    737     public static final int CONFIRMATIONUI_OK = 0;
    738     public static final int CONFIRMATIONUI_CANCELED = 1;
    739     public static final int CONFIRMATIONUI_ABORTED = 2;
    740     public static final int CONFIRMATIONUI_OPERATION_PENDING = 3;
    741     public static final int CONFIRMATIONUI_IGNORED = 4;
    742     public static final int CONFIRMATIONUI_SYSTEM_ERROR = 5;
    743     public static final int CONFIRMATIONUI_UNIMPLEMENTED = 6;
    744     public static final int CONFIRMATIONUI_UNEXPECTED = 7;
    745     public static final int CONFIRMATIONUI_UIERROR = 0x10000;
    746     public static final int CONFIRMATIONUI_UIERROR_MISSING_GLYPH = 0x10001;
    747     public static final int CONFIRMATIONUI_UIERROR_MESSAGE_TOO_LONG = 0x10002;
    748     public static final int CONFIRMATIONUI_UIERROR_MALFORMED_UTF8_ENCODING = 0x10003;
    749 
    750     /**
    751      * Requests keystore call into the confirmationui HAL to display a prompt.
    752      *
    753      * @param listener the binder to use for callbacks.
    754      * @param promptText the prompt to display.
    755      * @param extraData extra data / nonce from application.
    756      * @param locale the locale as a BCP 47 langauge tag.
    757      * @param uiOptionsAsFlags the UI options to use, as flags.
    758      * @return one of the {@code CONFIRMATIONUI_*} constants, for
    759      * example {@code KeyStore.CONFIRMATIONUI_OK}.
    760      */
    761     public int presentConfirmationPrompt(IBinder listener, String promptText, byte[] extraData,
    762                                          String locale, int uiOptionsAsFlags) {
    763         try {
    764             return mBinder.presentConfirmationPrompt(listener, promptText, extraData, locale,
    765                                                      uiOptionsAsFlags);
    766         } catch (RemoteException e) {
    767             Log.w(TAG, "Cannot connect to keystore", e);
    768             return CONFIRMATIONUI_SYSTEM_ERROR;
    769         }
    770     }
    771 
    772     /**
    773      * Requests keystore call into the confirmationui HAL to cancel displaying a prompt.
    774      *
    775      * @param listener the binder passed to the {@link #presentConfirmationPrompt} method.
    776      * @return one of the {@code CONFIRMATIONUI_*} constants, for
    777      * example {@code KeyStore.CONFIRMATIONUI_OK}.
    778      */
    779     public int cancelConfirmationPrompt(IBinder listener) {
    780         try {
    781             return mBinder.cancelConfirmationPrompt(listener);
    782         } catch (RemoteException e) {
    783             Log.w(TAG, "Cannot connect to keystore", e);
    784             return CONFIRMATIONUI_SYSTEM_ERROR;
    785         }
    786     }
    787 
    788     /**
    789      * Requests keystore to check if the confirmationui HAL is available.
    790      *
    791      * @return whether the confirmationUI HAL is available.
    792      */
    793     public boolean isConfirmationPromptSupported() {
    794         try {
    795             return mBinder.isConfirmationPromptSupported();
    796         } catch (RemoteException e) {
    797             Log.w(TAG, "Cannot connect to keystore", e);
    798             return false;
    799         }
    800     }
    801 
    802     /**
    803      * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
    804      * code.
    805      */
    806     public static KeyStoreException getKeyStoreException(int errorCode) {
    807         if (errorCode > 0) {
    808             // KeyStore layer error
    809             switch (errorCode) {
    810                 case NO_ERROR:
    811                     return new KeyStoreException(errorCode, "OK");
    812                 case LOCKED:
    813                     return new KeyStoreException(errorCode, "User authentication required");
    814                 case UNINITIALIZED:
    815                     return new KeyStoreException(errorCode, "Keystore not initialized");
    816                 case SYSTEM_ERROR:
    817                     return new KeyStoreException(errorCode, "System error");
    818                 case PERMISSION_DENIED:
    819                     return new KeyStoreException(errorCode, "Permission denied");
    820                 case KEY_NOT_FOUND:
    821                     return new KeyStoreException(errorCode, "Key not found");
    822                 case VALUE_CORRUPTED:
    823                     return new KeyStoreException(errorCode, "Key blob corrupted");
    824                 case OP_AUTH_NEEDED:
    825                     return new KeyStoreException(errorCode, "Operation requires authorization");
    826                 default:
    827                     return new KeyStoreException(errorCode, String.valueOf(errorCode));
    828             }
    829         } else {
    830             // Keymaster layer error
    831             switch (errorCode) {
    832                 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
    833                     // The name of this parameter significantly differs between Keymaster and
    834                     // framework APIs. Use the framework wording to make life easier for developers.
    835                     return new KeyStoreException(errorCode,
    836                             "Invalid user authentication validity duration");
    837                 default:
    838                     return new KeyStoreException(errorCode,
    839                             KeymasterDefs.getErrorMessage(errorCode));
    840             }
    841         }
    842     }
    843 
    844     /**
    845      * Returns an {@link InvalidKeyException} corresponding to the provided
    846      * {@link KeyStoreException}.
    847      */
    848     public InvalidKeyException getInvalidKeyException(
    849             String keystoreKeyAlias, int uid, KeyStoreException e) {
    850         switch (e.getErrorCode()) {
    851             case LOCKED:
    852                 return new UserNotAuthenticatedException();
    853             case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
    854                 return new KeyExpiredException();
    855             case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
    856                 return new KeyNotYetValidException();
    857             case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
    858             case OP_AUTH_NEEDED:
    859             {
    860                 // We now need to determine whether the key/operation can become usable if user
    861                 // authentication is performed, or whether it can never become usable again.
    862                 // User authentication requirements are contained in the key's characteristics. We
    863                 // need to check whether these requirements can be be satisfied by asking the user
    864                 // to authenticate.
    865                 KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
    866                 int getKeyCharacteristicsErrorCode =
    867                         getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
    868                                 keyCharacteristics);
    869                 if (getKeyCharacteristicsErrorCode != NO_ERROR) {
    870                     return new InvalidKeyException(
    871                             "Failed to obtained key characteristics",
    872                             getKeyStoreException(getKeyCharacteristicsErrorCode));
    873                 }
    874                 List<BigInteger> keySids =
    875                         keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
    876                 if (keySids.isEmpty()) {
    877                     // Key is not bound to any SIDs -- no amount of authentication will help here.
    878                     return new KeyPermanentlyInvalidatedException();
    879                 }
    880                 long rootSid = GateKeeper.getSecureUserId();
    881                 if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
    882                     // One of the key's SIDs is the current root SID -- user can be authenticated
    883                     // against that SID.
    884                     return new UserNotAuthenticatedException();
    885                 }
    886 
    887                 long fingerprintOnlySid = getFingerprintOnlySid();
    888                 if ((fingerprintOnlySid != 0)
    889                         && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
    890                     // One of the key's SIDs is the current fingerprint SID -- user can be
    891                     // authenticated against that SID.
    892                     return new UserNotAuthenticatedException();
    893                 }
    894 
    895                 // None of the key's SIDs can ever be authenticated
    896                 return new KeyPermanentlyInvalidatedException();
    897             }
    898             case UNINITIALIZED:
    899                 return new KeyPermanentlyInvalidatedException();
    900             default:
    901                 return new InvalidKeyException("Keystore operation failed", e);
    902         }
    903     }
    904 
    905     private long getFingerprintOnlySid() {
    906         final PackageManager packageManager = mContext.getPackageManager();
    907         if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
    908             return 0;
    909         }
    910         FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
    911         if (fingerprintManager == null) {
    912             return 0;
    913         }
    914 
    915         // TODO: Restore USE_FINGERPRINT permission check in
    916         // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
    917         return fingerprintManager.getAuthenticatorId();
    918     }
    919 
    920     /**
    921      * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
    922      * code.
    923      */
    924     public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
    925             int errorCode) {
    926         return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
    927     }
    928 }
    929