144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh/*
244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Copyright (C) 2009 The Android Open Source Project
344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *
444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * you may not use this file except in compliance with the License.
644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * You may obtain a copy of the License at
744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *
844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh *
1044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software
1144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
1244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * See the License for the specific language governing permissions and
1444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh * limitations under the License.
1544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh */
1644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1744039172627d1c15737ea73836ad375559d76211Chia-chi Yehpackage android.security;
1844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
192dac95d03399bb9fa59999e4964d7f8bcd485c38Svetoslavimport android.app.ActivityThread;
202dac95d03399bb9fa59999e4964d7f8bcd485c38Svetoslavimport android.app.Application;
215418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubinimport android.app.KeyguardManager;
22a39859889b7de0ad3190386cc732fa4bdcbe5504Kenny Root
23708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubinimport android.content.Context;
242d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubinimport android.hardware.fingerprint.FingerprintManager;
25e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.os.Binder;
26e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.os.IBinder;
27a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubakerimport android.os.Process;
286b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Rootimport android.os.RemoteException;
296b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Rootimport android.os.ServiceManager;
30a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubakerimport android.os.UserHandle;
31e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.security.keymaster.ExportResult;
32e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.security.keymaster.KeyCharacteristics;
33e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.security.keymaster.KeymasterArguments;
345e73c0eec2bc77222a5a87fb2a135d8303836411Chad Brubakerimport android.security.keymaster.KeymasterBlob;
35b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubinimport android.security.keymaster.KeymasterDefs;
36e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.security.keymaster.OperationResult;
373f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubinimport android.security.keystore.KeyExpiredException;
383f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubinimport android.security.keystore.KeyNotYetValidException;
393f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubinimport android.security.keystore.KeyPermanentlyInvalidatedException;
403f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubinimport android.security.keystore.UserNotAuthenticatedException;
416b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Rootimport android.util.Log;
4244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
43ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubinimport java.math.BigInteger;
44ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubinimport java.security.InvalidKeyException;
45708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubinimport java.util.List;
46b91773bce1126d28a93f73fbef18f3a79245f24eKenny Rootimport java.util.Locale;
47b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root
4844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh/**
4946703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * @hide This should not be made public in its present form because it
5046703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * assumes that private and secret key bytes are available and would
5146703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom * preclude the use of hardware crypto.
5244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh */
5344039172627d1c15737ea73836ad375559d76211Chia-chi Yehpublic class KeyStore {
546b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    private static final String TAG = "KeyStore";
555cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom
565cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    // ResponseCodes
577e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int NO_ERROR = 1;
587e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int LOCKED = 2;
597e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int UNINITIALIZED = 3;
607e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int SYSTEM_ERROR = 4;
617e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int PROTOCOL_ERROR = 5;
627e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int PERMISSION_DENIED = 6;
637e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int KEY_NOT_FOUND = 7;
647e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int VALUE_CORRUPTED = 8;
657e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int UNDEFINED_ACTION = 9;
667e4b1a488dd02c4bf6156379e36834e9e01c5b1bBrian Carlstrom    public static final int WRONG_PASSWORD = 10;
675cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom
68560d653e554882218232cd0fe4711be42145727aChad Brubaker    /**
69560d653e554882218232cd0fe4711be42145727aChad Brubaker     * Per operation authentication is needed before this operation is valid.
70560d653e554882218232cd0fe4711be42145727aChad Brubaker     * This is returned from {@link #begin} when begin succeeds but the operation uses
71560d653e554882218232cd0fe4711be42145727aChad Brubaker     * per-operation authentication and must authenticate before calling {@link #update} or
72560d653e554882218232cd0fe4711be42145727aChad Brubaker     * {@link #finish}.
73560d653e554882218232cd0fe4711be42145727aChad Brubaker     */
74560d653e554882218232cd0fe4711be42145727aChad Brubaker    public static final int OP_AUTH_NEEDED = 15;
75560d653e554882218232cd0fe4711be42145727aChad Brubaker
762eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root    // Used for UID field to indicate the calling UID.
772eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root    public static final int UID_SELF = -1;
782eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root
792eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root    // Flags for "put" "import" and "generate"
802eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root    public static final int FLAG_NONE = 0;
815418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin
825418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin    /**
835418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * Indicates that this key (or key pair) must be encrypted at rest. This will protect the key
845418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * (or key pair) with the secure lock screen credential (e.g., password, PIN, or pattern).
855418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     *
865418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * <p>Note that this requires that the secure lock screen (e.g., password, PIN, pattern) is set
875418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * up, otherwise key (or key pair) generation or import will fail. Moreover, this key (or key
885418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * pair) will be deleted when the secure lock screen is disabled or reset (e.g., by the user or
895418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * a Device Administrator). Finally, this key (or key pair) cannot be used until the user
905418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * unlocks the secure lock screen after boot.
915418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     *
925418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     * @see KeyguardManager#isDeviceSecure()
935418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin     */
94a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root    public static final int FLAG_ENCRYPTED = 1;
95a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root
965cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    // States
975cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
9844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
9944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    private int mError = NO_ERROR;
10044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1016b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    private final IKeystoreService mBinder;
1022d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin    private final Context mContext;
1036b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root
104e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    private IBinder mToken;
105e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
1066b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    private KeyStore(IKeystoreService binder) {
1076b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        mBinder = binder;
1083f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin        mContext = getApplicationContext();
1092d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin    }
1102d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin
111dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin    public static Context getApplicationContext() {
112a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        Application application = ActivityThread.currentApplication();
1132d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        if (application == null) {
1142d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin            throw new IllegalStateException(
115a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin                    "Failed to obtain application Context from ActivityThread");
1162d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        }
1172d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        return application;
1186b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    }
11944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
12044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public static KeyStore getInstance() {
1216b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
1226b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root                .getService("android.security.keystore"));
1236b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        return new KeyStore(keystore);
12444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
12544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
126e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    private synchronized IBinder getToken() {
127e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        if (mToken == null) {
128e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            mToken = new Binder();
129e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
130e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        return mToken;
131e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
132e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
133e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public State state(int userId) {
1346b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        final int ret;
1356b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
136e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            ret = mBinder.getState(userId);
1376b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1386b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1396b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            throw new AssertionError(e);
1406b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
1416b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root
1426b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        switch (ret) {
1435cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case NO_ERROR: return State.UNLOCKED;
1445cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case LOCKED: return State.LOCKED;
1455cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case UNINITIALIZED: return State.UNINITIALIZED;
1465cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            default: throw new AssertionError(mError);
1475cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom        }
148b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root    }
149b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root
150e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public State state() {
151e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return state(UserHandle.myUserId());
152e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
153e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
154b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root    public boolean isUnlocked() {
155b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root        return state() == State.UNLOCKED;
15644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
15744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1585cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public byte[] get(String key) {
1596b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
1606b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.get(key);
1616b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1626b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1636b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return null;
1646b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
16544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
16644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
167a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root    public boolean put(String key, byte[] value, int uid, int flags) {
1683ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin        return insert(key, value, uid, flags) == NO_ERROR;
1693ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin    }
1703ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin
1713ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin    public int insert(String key, byte[] value, int uid, int flags) {
1726b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
1733ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin            return mBinder.insert(key, value, uid, flags);
1746b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1756b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1763ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin            return SYSTEM_ERROR;
1776b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
17844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
17944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
18078ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean delete(String key, int uid) {
1816b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
18278ad849163a7b01073b46fbd7d818392720005d1Kenny Root            return mBinder.del(key, uid) == NO_ERROR;
1836b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1846b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1856b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
1866b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
18744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
18844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
18978ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean delete(String key) {
1902eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        return delete(key, UID_SELF);
19178ad849163a7b01073b46fbd7d818392720005d1Kenny Root    }
19278ad849163a7b01073b46fbd7d818392720005d1Kenny Root
19378ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean contains(String key, int uid) {
1946b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
19578ad849163a7b01073b46fbd7d818392720005d1Kenny Root            return mBinder.exist(key, uid) == NO_ERROR;
1966b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1976b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1986b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
1996b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
20044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
20144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
20278ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean contains(String key) {
2032eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        return contains(key, UID_SELF);
20478ad849163a7b01073b46fbd7d818392720005d1Kenny Root    }
20578ad849163a7b01073b46fbd7d818392720005d1Kenny Root
206e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    /**
207e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * List all entries in the keystore for {@code uid} starting with {@code prefix}.
208e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     */
209e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public String[] list(String prefix, int uid) {
2106b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
211e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            return mBinder.list(prefix, uid);
2126b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2136b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
21444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            return null;
21544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        }
21644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
21744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
218e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public String[] list(String prefix) {
219e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return list(prefix, UID_SELF);
220e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
221e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
22244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean reset() {
2236b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
2246b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.reset() == NO_ERROR;
2256b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2266b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2276b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2286b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
22944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
23044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
231e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    /**
232e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * Attempt to lock the keystore for {@code user}.
233e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     *
234e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * @param user Android user to lock.
235e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * @return whether {@code user}'s keystore was locked.
236e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     */
237e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean lock(int userId) {
2386b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
239e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            return mBinder.lock(userId) == NO_ERROR;
2406b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2416b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2426b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2436b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
24444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
24544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
246e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean lock() {
247e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return lock(UserHandle.myUserId());
248e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
249e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
250a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    /**
251a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * Attempt to unlock the keystore for {@code user} with the password {@code password}.
252a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
253a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * created.
254a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     *
255a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param user Android user ID to operate on
256a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param password user's keystore password. Should be the most recent value passed to
257a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * {@link #onUserPasswordChanged} for the user.
258a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     *
259a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @return whether the keystore was unlocked.
260a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     */
261a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean unlock(int userId, String password) {
2626b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
263a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            mError = mBinder.unlock(userId, password);
2646b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mError == NO_ERROR;
2656b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2666b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2676b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2686b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
26944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
27044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
271a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean unlock(String password) {
272a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        return unlock(UserHandle.getUserId(Process.myUid()), password);
273a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    }
274a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker
275e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    /**
276e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * Check if the keystore for {@code userId} is empty.
277e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     */
278e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean isEmpty(int userId) {
2796b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
280e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            return mBinder.isEmpty(userId) != 0;
2816b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2826b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2836b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2846b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
2855423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
2865423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
287e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean isEmpty() {
288e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return isEmpty(UserHandle.myUserId());
289e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
290e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
291a39859889b7de0ad3190386cc732fa4bdcbe5504Kenny Root    public boolean generate(String key, int uid, int keyType, int keySize, int flags,
292a39859889b7de0ad3190386cc732fa4bdcbe5504Kenny Root            byte[][] args) {
2936b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
2947a2c973db7756a60f1cdd6cf67411115c1576081Chad Brubaker            return mBinder.generate(key, uid, keyType, keySize, flags,
2957a2c973db7756a60f1cdd6cf67411115c1576081Chad Brubaker                    new KeystoreArguments(args)) == NO_ERROR;
2966b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2976b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2986b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2996b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3005423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3015423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
302a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root    public boolean importKey(String keyName, byte[] key, int uid, int flags) {
3036b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
304a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root            return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
3056b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3066b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3076b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
3086b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3095423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
31078ad849163a7b01073b46fbd7d818392720005d1Kenny Root
3115423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public byte[] sign(String key, byte[] data) {
3126b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3136b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.sign(key, data);
3146b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3156b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3166b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return null;
3176b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3185423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3195423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
3205423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean verify(String key, byte[] data, byte[] signature) {
3216b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3226b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.verify(key, data, signature) == NO_ERROR;
3236b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3246b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3256b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
3266b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3275423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3285423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
3295423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean grant(String key, int uid) {
3306b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3316b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.grant(key, uid) == NO_ERROR;
3326b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3336b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3346b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
3356b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3365423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3375423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
3385423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean ungrant(String key, int uid) {
3396b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3406b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.ungrant(key, uid) == NO_ERROR;
3416b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3426b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3436b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
344473c712b19bad992ab4eafcd43175fdce77b913dKenny Root        }
345473c712b19bad992ab4eafcd43175fdce77b913dKenny Root    }
346473c712b19bad992ab4eafcd43175fdce77b913dKenny Root
347473c712b19bad992ab4eafcd43175fdce77b913dKenny Root    /**
348473c712b19bad992ab4eafcd43175fdce77b913dKenny Root     * Returns the last modification time of the key in milliseconds since the
349473c712b19bad992ab4eafcd43175fdce77b913dKenny Root     * epoch. Will return -1L if the key could not be found or other error.
350473c712b19bad992ab4eafcd43175fdce77b913dKenny Root     */
351473c712b19bad992ab4eafcd43175fdce77b913dKenny Root    public long getmtime(String key) {
3525b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        try {
353e66769ad5194cb4533d1087416a2e804ac384285Kenny Root            final long millis = mBinder.getmtime(key);
354e66769ad5194cb4533d1087416a2e804ac384285Kenny Root            if (millis == -1L) {
355e66769ad5194cb4533d1087416a2e804ac384285Kenny Root                return -1L;
356e66769ad5194cb4533d1087416a2e804ac384285Kenny Root            }
357e66769ad5194cb4533d1087416a2e804ac384285Kenny Root
358e66769ad5194cb4533d1087416a2e804ac384285Kenny Root            return millis * 1000L;
3596b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3606b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3616b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return -1L;
3625b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        }
3635b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    }
3645b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom
3655f1d965f7d7e1df50981ffed8faa11fbcc17ca22Kenny Root    public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
366bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root        try {
3675f1d965f7d7e1df50981ffed8faa11fbcc17ca22Kenny Root            return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
368bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root        } catch (RemoteException e) {
369bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
370bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root            return false;
371bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root        }
372bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root    }
373bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root
374469cbf5156ad54650726ade59f2ee5aa01359ec2Alex Klyubin    // TODO: remove this when it's removed from Settings
3755cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root    public boolean isHardwareBacked() {
376b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root        return isHardwareBacked("RSA");
377b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root    }
378b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root
379b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root    public boolean isHardwareBacked(String keyType) {
3805cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root        try {
381b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root            return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
3825cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root        } catch (RemoteException e) {
3835cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3845cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root            return false;
3855cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root        }
3865cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root    }
3875cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root
388d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root    public boolean clearUid(int uid) {
389d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root        try {
390d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root            return mBinder.clear_uid(uid) == NO_ERROR;
391d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root        } catch (RemoteException e) {
392d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root            Log.w(TAG, "Cannot connect to keystore", e);
393d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root            return false;
394d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root        }
395d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root    }
396d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root
3976b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    public int getLastError() {
3986b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        return mError;
39934c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich    }
400e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
401e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public boolean addRngEntropy(byte[] data) {
402e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
403e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.addRngEntropy(data) == NO_ERROR;
404e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
405e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
406e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return false;
407e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
408e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
409e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
410dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
411dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker            int flags, KeyCharacteristics outCharacteristics) {
412e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
413dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker            return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
414e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
415e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
416e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
417e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
418e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
419e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
420dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
421e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            KeyCharacteristics outCharacteristics) {
422dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker        return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
423e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
424e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4255e73c0eec2bc77222a5a87fb2a135d8303836411Chad Brubaker    public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
426e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            KeyCharacteristics outCharacteristics) {
427e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
428e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.getKeyCharacteristics(alias, clientId, appId, outCharacteristics);
429e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
430e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
431e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
432e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
433e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
434e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
435e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
436e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            int uid, int flags, KeyCharacteristics outCharacteristics) {
437e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
438e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.importKey(alias, args, format, keyData, uid, flags,
439e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker                    outCharacteristics);
440e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
441e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
442e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
443e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
444e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
445e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
446e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
447e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            int flags, KeyCharacteristics outCharacteristics) {
448e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
449e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
450e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4515e73c0eec2bc77222a5a87fb2a135d8303836411Chad Brubaker    public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
4525e73c0eec2bc77222a5a87fb2a135d8303836411Chad Brubaker            KeymasterBlob appId) {
453e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
454e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.exportKey(alias, format, clientId, appId);
455e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
456e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
457e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
458e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
459e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
460e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
461e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public OperationResult begin(String alias, int purpose, boolean pruneable,
462966486e134c901ea61195b352fdd81476b3639b4Chad Brubaker            KeymasterArguments args, byte[] entropy) {
463e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
464966486e134c901ea61195b352fdd81476b3639b4Chad Brubaker            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy);
465e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
466e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
467e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
468e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
469e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
470e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
471e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
472e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
473e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.update(token, arguments, input);
474e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
475e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
476e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
477e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
478e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
479e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4808a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
4818a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker            byte[] entropy) {
482e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
4838a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker            return mBinder.finish(token, arguments, signature, entropy);
484e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
485e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
486e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
487e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
488e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
489e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4908a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
4918a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker        return finish(token, arguments, signature, null);
4928a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker    }
4938a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker
494e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public int abort(IBinder token) {
495e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
496e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.abort(token);
497e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
498e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
499e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
500e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
501e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
5025654b36b4667431e49d27c07a06d275656071e75Chad Brubaker
5035654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    /**
5045654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * Check if the operation referenced by {@code token} is currently authorized.
5055654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     *
506708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin     * @param token An operation token returned by a call to
507708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin     * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
5085654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     */
5095654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    public boolean isOperationAuthorized(IBinder token) {
5105654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        try {
5115654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return mBinder.isOperationAuthorized(token);
5125654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        } catch (RemoteException e) {
5135654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
5145654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return false;
5155654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        }
5165654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    }
5175654b36b4667431e49d27c07a06d275656071e75Chad Brubaker
5185654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    /**
5195654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * Add an authentication record to the keystore authorization table.
5205654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     *
5215654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
5225654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
5235654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
5245654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     */
5255654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    public int addAuthToken(byte[] authToken) {
5265654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        try {
5275654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return mBinder.addAuthToken(authToken);
5285654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        } catch (RemoteException e) {
5295654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
5305654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return SYSTEM_ERROR;
5315654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        }
5325654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    }
533b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin
534ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin    /**
535a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * Notify keystore that a user's password has changed.
536a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     *
537a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param userId the user whose password changed.
538a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param newPassword the new password or "" if the password was removed.
539a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     */
540a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean onUserPasswordChanged(int userId, String newPassword) {
541a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
542a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        // explicit here.
543a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        if (newPassword == null) {
544a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            newPassword = "";
545a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        }
546a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        try {
547a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
548a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        } catch (RemoteException e) {
549a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
550a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            return false;
551a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        }
552a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    }
553a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker
55483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    /**
55583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * Notify keystore that a user was added.
55683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     *
55783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param userId the new user.
55883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
55983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * specified then the new user's keystore will be intialized with the same secure lockscreen
56083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * password as the parent.
56183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     */
56283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    public void onUserAdded(int userId, int parentId) {
56383ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        try {
56483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            mBinder.onUserAdded(userId, parentId);
56583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        } catch (RemoteException e) {
56683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
56783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        }
56883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    }
56983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker
57083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    /**
57183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * Notify keystore that a user was added.
57283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     *
57383ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param userId the new user.
57483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     */
57583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    public void onUserAdded(int userId) {
57683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        onUserAdded(userId, -1);
57783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    }
57883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker
57983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    /**
58083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * Notify keystore that a user was removed.
58183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     *
58283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param userId the removed user.
58383ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     */
58483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    public void onUserRemoved(int userId) {
58583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        try {
58683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            mBinder.onUserRemoved(userId);
58783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        } catch (RemoteException e) {
58883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
58983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        }
59083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    }
59183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker
592a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean onUserPasswordChanged(String newPassword) {
593a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
594a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    }
595a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker
596a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    /**
597ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
598ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * code.
599ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     */
600dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin    public static KeyStoreException getKeyStoreException(int errorCode) {
601b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        if (errorCode > 0) {
602b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            // KeyStore layer error
603b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            switch (errorCode) {
604b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case NO_ERROR:
605b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "OK");
606b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case LOCKED:
6075418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin                    return new KeyStoreException(errorCode, "User authentication required");
608b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case UNINITIALIZED:
609b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Keystore not initialized");
610b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case SYSTEM_ERROR:
611b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "System error");
612b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case PERMISSION_DENIED:
613b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Permission denied");
614b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case KEY_NOT_FOUND:
615b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Key not found");
616b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case VALUE_CORRUPTED:
617b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Key blob corrupted");
618058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin                case OP_AUTH_NEEDED:
619058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin                    return new KeyStoreException(errorCode, "Operation requires authorization");
620b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                default:
621b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, String.valueOf(errorCode));
622b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            }
623b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        } else {
624b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            // Keymaster layer error
625b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            switch (errorCode) {
626b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
627b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    // The name of this parameter significantly differs between Keymaster and
628b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    // framework APIs. Use the framework wording to make life easier for developers.
629b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode,
630b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                            "Invalid user authentication validity duration");
631b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                default:
632b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode,
633b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                            KeymasterDefs.getErrorMessage(errorCode));
634b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            }
635b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        }
636b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin    }
637b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin
638ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin    /**
639ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * Returns an {@link InvalidKeyException} corresponding to the provided
640ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * {@link KeyStoreException}.
641ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     */
642dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin    public InvalidKeyException getInvalidKeyException(
643dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin            String keystoreKeyAlias, KeyStoreException e) {
644b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        switch (e.getErrorCode()) {
6455418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin            case LOCKED:
6465418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin                return new UserNotAuthenticatedException();
647b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
648b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                return new KeyExpiredException();
649b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
650b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                return new KeyNotYetValidException();
651b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
652058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin            case OP_AUTH_NEEDED:
653708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin            {
654708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // We now need to determine whether the key/operation can become usable if user
655708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // authentication is performed, or whether it can never become usable again.
656708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // User authentication requirements are contained in the key's characteristics. We
657708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // need to check whether these requirements can be be satisfied by asking the user
658708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // to authenticate.
659708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
660708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                int getKeyCharacteristicsErrorCode =
661708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                        getKeyCharacteristics(keystoreKeyAlias, null, null, keyCharacteristics);
662708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                if (getKeyCharacteristicsErrorCode != NO_ERROR) {
663708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new InvalidKeyException(
664708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                            "Failed to obtained key characteristics",
665708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                            getKeyStoreException(getKeyCharacteristicsErrorCode));
666708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
667ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                List<BigInteger> keySids =
668ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                        keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
669708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                if (keySids.isEmpty()) {
670708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // Key is not bound to any SIDs -- no amount of authentication will help here.
671708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new KeyPermanentlyInvalidatedException();
672708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
673708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                long rootSid = GateKeeper.getSecureUserId();
674ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
675708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // One of the key's SIDs is the current root SID -- user can be authenticated
676708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // against that SID.
677708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new UserNotAuthenticatedException();
678708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
679708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin
680708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                long fingerprintOnlySid = getFingerprintOnlySid();
681708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                if ((fingerprintOnlySid != 0)
682ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                        && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
683708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // One of the key's SIDs is the current fingerprint SID -- user can be
684708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // authenticated against that SID.
685708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new UserNotAuthenticatedException();
686708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
687708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin
688708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // None of the key's SIDs can ever be authenticated
689708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                return new KeyPermanentlyInvalidatedException();
690708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin            }
691b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            default:
692ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin                return new InvalidKeyException("Keystore operation failed", e);
693b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        }
694b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin    }
695b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin
6962d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin    private long getFingerprintOnlySid() {
697a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
6982d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        if (fingerprintManager == null) {
699708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin            return 0;
700708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin        }
701708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin
702a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        // TODO: Restore USE_FINGERPRINT permission check in
703a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
7042d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        return fingerprintManager.getAuthenticatorId();
7052dac95d03399bb9fa59999e4964d7f8bcd485c38Svetoslav    }
7062dac95d03399bb9fa59999e4964d7f8bcd485c38Svetoslav
707ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin    /**
708ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
709ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * code.
710ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     */
711dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin    public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int errorCode) {
712708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin        return getInvalidKeyException(keystoreKeyAlias, getKeyStoreException(errorCode));
713b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin    }
71444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh}
715