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;
22708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubinimport android.content.Context;
232d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubinimport android.hardware.fingerprint.FingerprintManager;
24e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.os.Binder;
25e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.os.IBinder;
26a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubakerimport android.os.Process;
276b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Rootimport android.os.RemoteException;
286b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Rootimport android.os.ServiceManager;
29a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubakerimport android.os.UserHandle;
30e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.security.keymaster.ExportResult;
31e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.security.keymaster.KeyCharacteristics;
32e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubakerimport android.security.keymaster.KeymasterArguments;
335e73c0eec2bc77222a5a87fb2a135d8303836411Chad Brubakerimport android.security.keymaster.KeymasterBlob;
348d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willdenimport android.security.keymaster.KeymasterCertificateChain;
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
9612b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu    /**
9712b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu     * A private flag that's only available to system server to indicate that this key is part of
9812b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu     * device encryption flow so it receives special treatment from keystore. For example this key
9912b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu     * will not be super encrypted, and it will be stored separately under an unique UID instead
10012b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu     * of the caller UID i.e. SYSTEM.
10112b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu     *
10212b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu     * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
10312b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu     */
10412b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu    public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
10512b644d275b121dd952a4a564fa65b9c18c9b22cRubin Xu
1065cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    // States
1075cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom    public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
10844039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
10944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    private int mError = NO_ERROR;
11044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1116b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    private final IKeystoreService mBinder;
1122d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin    private final Context mContext;
1136b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root
114e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    private IBinder mToken;
115e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
1166b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    private KeyStore(IKeystoreService binder) {
1176b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        mBinder = binder;
1183f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin        mContext = getApplicationContext();
1192d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin    }
1202d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin
121dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin    public static Context getApplicationContext() {
122a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        Application application = ActivityThread.currentApplication();
1232d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        if (application == null) {
1242d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin            throw new IllegalStateException(
125a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin                    "Failed to obtain application Context from ActivityThread");
1262d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        }
1272d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        return application;
1286b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    }
12944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
13044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public static KeyStore getInstance() {
1316b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
1326b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root                .getService("android.security.keystore"));
1336b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        return new KeyStore(keystore);
13444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
13544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
136e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    private synchronized IBinder getToken() {
137e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        if (mToken == null) {
138e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            mToken = new Binder();
139e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
140e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        return mToken;
141e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
142e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
143e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public State state(int userId) {
1446b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        final int ret;
1456b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
146e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            ret = mBinder.getState(userId);
1476b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1486b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1496b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            throw new AssertionError(e);
1506b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
1516b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root
1526b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        switch (ret) {
1535cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case NO_ERROR: return State.UNLOCKED;
1545cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case LOCKED: return State.LOCKED;
1555cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            case UNINITIALIZED: return State.UNINITIALIZED;
1565cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom            default: throw new AssertionError(mError);
1575cfee3fabb3482c6a6df1c8b6f21e843cf214527Brian Carlstrom        }
158b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root    }
159b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root
160e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public State state() {
161e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return state(UserHandle.myUserId());
162e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
163e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
164b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root    public boolean isUnlocked() {
165b9594ce9ebb3f5f303a280f04312ae5754ce3560Kenny Root        return state() == State.UNLOCKED;
16644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
16744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1685bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    public byte[] get(String key, int uid) {
1696b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
1705bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            return mBinder.get(key, uid);
1716b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1726b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1736b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return null;
1746b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
17544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
17644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
1775bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    public byte[] get(String key) {
1785bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker        return get(key, UID_SELF);
1795bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    }
1805bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker
181a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root    public boolean put(String key, byte[] value, int uid, int flags) {
1823ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin        return insert(key, value, uid, flags) == NO_ERROR;
1833ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin    }
1843ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin
1853ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin    public int insert(String key, byte[] value, int uid, int flags) {
1866b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
1873ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin            return mBinder.insert(key, value, uid, flags);
1886b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1896b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
1903ceb1a04b44539c2b2c3afec6df487fe128911f2Alex Klyubin            return SYSTEM_ERROR;
1916b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
19244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
19344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
19478ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean delete(String key, int uid) {
1956b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
196e4487ea288e9fea837995d9bc4608c8a4a253ec8Robin Lee            int ret = mBinder.del(key, uid);
197e4487ea288e9fea837995d9bc4608c8a4a253ec8Robin Lee            return (ret == NO_ERROR || ret == KEY_NOT_FOUND);
1986b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
1996b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2006b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2016b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
20244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
20344039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
20478ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean delete(String key) {
2052eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        return delete(key, UID_SELF);
20678ad849163a7b01073b46fbd7d818392720005d1Kenny Root    }
20778ad849163a7b01073b46fbd7d818392720005d1Kenny Root
20878ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean contains(String key, int uid) {
2096b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
21078ad849163a7b01073b46fbd7d818392720005d1Kenny Root            return mBinder.exist(key, uid) == NO_ERROR;
2116b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2126b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2136b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2146b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
21544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
21644039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
21778ad849163a7b01073b46fbd7d818392720005d1Kenny Root    public boolean contains(String key) {
2182eeda7286f3c7cb79f7eb71ae6464cad213d12a3Kenny Root        return contains(key, UID_SELF);
21978ad849163a7b01073b46fbd7d818392720005d1Kenny Root    }
22078ad849163a7b01073b46fbd7d818392720005d1Kenny Root
221e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    /**
222e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * List all entries in the keystore for {@code uid} starting with {@code prefix}.
223e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     */
224e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public String[] list(String prefix, int uid) {
2256b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
226e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            return mBinder.list(prefix, uid);
2276b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2286b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
22944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh            return null;
23044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh        }
23144039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
23244039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
233e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public String[] list(String prefix) {
234e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return list(prefix, UID_SELF);
235e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
236e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
23744039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    public boolean reset() {
2386b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
2396b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.reset() == 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    /**
247e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * Attempt to lock the keystore for {@code user}.
248e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     *
249e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * @param user Android user to lock.
250e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * @return whether {@code user}'s keystore was locked.
251e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     */
252e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean lock(int userId) {
2536b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
254e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            return mBinder.lock(userId) == NO_ERROR;
2556b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2566b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2576b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2586b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
25944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
26044039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
261e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean lock() {
262e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return lock(UserHandle.myUserId());
263e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
264e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
265a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    /**
266a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * Attempt to unlock the keystore for {@code user} with the password {@code password}.
267a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
268a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * created.
269a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     *
270a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param user Android user ID to operate on
271a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param password user's keystore password. Should be the most recent value passed to
272a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * {@link #onUserPasswordChanged} for the user.
273a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     *
274a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @return whether the keystore was unlocked.
275a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     */
276a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean unlock(int userId, String password) {
2776b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
278a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            mError = mBinder.unlock(userId, password);
2796b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mError == NO_ERROR;
2806b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
2816b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
2826b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
2836b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
28444039172627d1c15737ea73836ad375559d76211Chia-chi Yeh    }
28544039172627d1c15737ea73836ad375559d76211Chia-chi Yeh
286a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean unlock(String password) {
287a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        return unlock(UserHandle.getUserId(Process.myUid()), password);
288a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    }
289a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker
290e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    /**
291e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     * Check if the keystore for {@code userId} is empty.
292e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker     */
293e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean isEmpty(int userId) {
2946b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
295e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker            return mBinder.isEmpty(userId) != 0;
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
302e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    public boolean isEmpty() {
303e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker        return isEmpty(UserHandle.myUserId());
304e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker    }
305e35d49f0d2853b79470ec890113bf4dcef03ab88Chad Brubaker
306a39859889b7de0ad3190386cc732fa4bdcbe5504Kenny Root    public boolean generate(String key, int uid, int keyType, int keySize, int flags,
307a39859889b7de0ad3190386cc732fa4bdcbe5504Kenny Root            byte[][] args) {
3086b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3097a2c973db7756a60f1cdd6cf67411115c1576081Chad Brubaker            return mBinder.generate(key, uid, keyType, keySize, flags,
3107a2c973db7756a60f1cdd6cf67411115c1576081Chad Brubaker                    new KeystoreArguments(args)) == NO_ERROR;
3116b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3126b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3136b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
3146b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3155423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3165423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
317a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root    public boolean importKey(String keyName, byte[] key, int uid, int flags) {
3186b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
319a3788b00bb221e20abdd42f747d2af419e0a088cKenny Root            return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
3206b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3216b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3226b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
3236b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3245423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
32578ad849163a7b01073b46fbd7d818392720005d1Kenny Root
3265423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public byte[] sign(String key, byte[] data) {
3276b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3286b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.sign(key, data);
3296b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3306b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3316b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return null;
3326b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3335423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3345423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
3355423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean verify(String key, byte[] data, byte[] signature) {
3366b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3376b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.verify(key, data, signature) == NO_ERROR;
3386b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3396b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3406b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
3416b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3425423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3435423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
3445423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean grant(String key, int uid) {
3456b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3466b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.grant(key, uid) == NO_ERROR;
3476b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3486b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3496b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
3506b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        }
3515423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    }
3525423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root
3535423e68d5dbe048ec6f042cce52a33f94184e9fbKenny Root    public boolean ungrant(String key, int uid) {
3546b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        try {
3556b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return mBinder.ungrant(key, uid) == NO_ERROR;
3566b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3576b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3586b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return false;
359473c712b19bad992ab4eafcd43175fdce77b913dKenny Root        }
360473c712b19bad992ab4eafcd43175fdce77b913dKenny Root    }
361473c712b19bad992ab4eafcd43175fdce77b913dKenny Root
362473c712b19bad992ab4eafcd43175fdce77b913dKenny Root    /**
363473c712b19bad992ab4eafcd43175fdce77b913dKenny Root     * Returns the last modification time of the key in milliseconds since the
364473c712b19bad992ab4eafcd43175fdce77b913dKenny Root     * epoch. Will return -1L if the key could not be found or other error.
365473c712b19bad992ab4eafcd43175fdce77b913dKenny Root     */
3665bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    public long getmtime(String key, int uid) {
3675b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        try {
3685bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            final long millis = mBinder.getmtime(key, uid);
369e66769ad5194cb4533d1087416a2e804ac384285Kenny Root            if (millis == -1L) {
370e66769ad5194cb4533d1087416a2e804ac384285Kenny Root                return -1L;
371e66769ad5194cb4533d1087416a2e804ac384285Kenny Root            }
372e66769ad5194cb4533d1087416a2e804ac384285Kenny Root
373e66769ad5194cb4533d1087416a2e804ac384285Kenny Root            return millis * 1000L;
3746b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        } catch (RemoteException e) {
3756b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
3766b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root            return -1L;
3775b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom        }
3785b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom    }
3795b1f037829bff93877a6257db69f4e7723a27e20Brian Carlstrom
3805bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    public long getmtime(String key) {
3815bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker        return getmtime(key, UID_SELF);
3825bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    }
3835bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker
3845f1d965f7d7e1df50981ffed8faa11fbcc17ca22Kenny Root    public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
385bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root        try {
3865f1d965f7d7e1df50981ffed8faa11fbcc17ca22Kenny Root            return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
387bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root        } catch (RemoteException e) {
388bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
389bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root            return false;
390bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root        }
391bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root    }
392bd79419ef84ae31f3765721b50aa413fa462d1d1Kenny Root
393469cbf5156ad54650726ade59f2ee5aa01359ec2Alex Klyubin    // TODO: remove this when it's removed from Settings
3945cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root    public boolean isHardwareBacked() {
395b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root        return isHardwareBacked("RSA");
396b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root    }
397b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root
398b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root    public boolean isHardwareBacked(String keyType) {
3995cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root        try {
400b91773bce1126d28a93f73fbef18f3a79245f24eKenny Root            return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
4015cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root        } catch (RemoteException e) {
4025cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root            Log.w(TAG, "Cannot connect to keystore", e);
4035cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root            return false;
4045cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root        }
4055cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root    }
4065cb5cec6a4a4d5432d4ce6468c12de9508db1633Kenny Root
407d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root    public boolean clearUid(int uid) {
408d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root        try {
409d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root            return mBinder.clear_uid(uid) == NO_ERROR;
410d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root        } catch (RemoteException e) {
411d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root            Log.w(TAG, "Cannot connect to keystore", e);
412d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root            return false;
413d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root        }
414d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root    }
415d72317abd79ddf95d48c8f35bf1070900ff55b5eKenny Root
4166b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root    public int getLastError() {
4176b77645aa9ac51ce33ea67adba226aaf1a6e8846Kenny Root        return mError;
41834c47c855815d731e6deb55748ff690b0ec7b53fNick Kralevich    }
419e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
420e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public boolean addRngEntropy(byte[] data) {
421e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
422e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.addRngEntropy(data) == NO_ERROR;
423e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
424e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
425e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return false;
426e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
427e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
428e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
429dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
430dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker            int flags, KeyCharacteristics outCharacteristics) {
431e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
432dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker            return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
433e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
434e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
435e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
436e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
437e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
438e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
439dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker    public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags,
440e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            KeyCharacteristics outCharacteristics) {
441dae79e540844741fc35c648efe8bbb00fc8ab781Chad Brubaker        return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics);
442e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
443e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4445e73c0eec2bc77222a5a87fb2a135d8303836411Chad Brubaker    public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
4455bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            int uid, KeyCharacteristics outCharacteristics) {
446e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
4475bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
448e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
449e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
450e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
451e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
452e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
453e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4545bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
4555bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            KeyCharacteristics outCharacteristics) {
4565bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker        return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
4575bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    }
4585bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker
459e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
460e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            int uid, int flags, KeyCharacteristics outCharacteristics) {
461e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
462e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.importKey(alias, args, format, keyData, uid, flags,
463e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker                    outCharacteristics);
464e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
465e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
466e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
467e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
468e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
469e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
470e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
471e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            int flags, KeyCharacteristics outCharacteristics) {
472e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
473e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
474e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4755e73c0eec2bc77222a5a87fb2a135d8303836411Chad Brubaker    public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
4765bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            KeymasterBlob appId, int uid) {
477e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
4785bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            return mBinder.exportKey(alias, format, clientId, appId, uid);
479e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
480e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
481e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
482e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
483e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
4845bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
4855bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            KeymasterBlob appId) {
4865bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker        return exportKey(alias, format, clientId, appId, UID_SELF);
4875bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    }
488e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
489e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public OperationResult begin(String alias, int purpose, boolean pruneable,
4905bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            KeymasterArguments args, byte[] entropy, int uid) {
491e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
4925bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
493e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
494e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
495e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
496e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
497e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
498e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
4995bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    public OperationResult begin(String alias, int purpose, boolean pruneable,
5005bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker            KeymasterArguments args, byte[] entropy) {
5015bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker        return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
5025bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker    }
5035bbf04803f050296a6deab10a3c7104743c4e38cChad Brubaker
504e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
505e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
506e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.update(token, arguments, input);
507e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
508e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
509e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
510e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
511e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
512e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
5138a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
5148a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker            byte[] entropy) {
515e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
5168a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker            return mBinder.finish(token, arguments, signature, entropy);
517e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
518e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
519e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return null;
520e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
521e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
522e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker
5238a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker    public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) {
5248a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker        return finish(token, arguments, signature, null);
5258a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker    }
5268a07701f3817ad0b76b82cfc464868e8f57e359dChad Brubaker
527e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    public int abort(IBinder token) {
528e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        try {
529e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return mBinder.abort(token);
530e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        } catch (RemoteException e) {
531e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
532e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker            return SYSTEM_ERROR;
533e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker        }
534e6a461341ccf3b952427daf40c973d9914cdb270Chad Brubaker    }
5355654b36b4667431e49d27c07a06d275656071e75Chad Brubaker
5365654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    /**
5375654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * Check if the operation referenced by {@code token} is currently authorized.
5385654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     *
539708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin     * @param token An operation token returned by a call to
540708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin     * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
5415654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     */
5425654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    public boolean isOperationAuthorized(IBinder token) {
5435654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        try {
5445654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return mBinder.isOperationAuthorized(token);
5455654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        } catch (RemoteException e) {
5465654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
5475654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return false;
5485654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        }
5495654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    }
5505654b36b4667431e49d27c07a06d275656071e75Chad Brubaker
5515654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    /**
5525654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * Add an authentication record to the keystore authorization table.
5535654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     *
5545654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * @param authToken The packed bytes of a hw_auth_token_t to be provided to keymaster.
5555654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
5565654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
5575654b36b4667431e49d27c07a06d275656071e75Chad Brubaker     */
5585654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    public int addAuthToken(byte[] authToken) {
5595654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        try {
5605654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return mBinder.addAuthToken(authToken);
5615654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        } catch (RemoteException e) {
5625654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
5635654b36b4667431e49d27c07a06d275656071e75Chad Brubaker            return SYSTEM_ERROR;
5645654b36b4667431e49d27c07a06d275656071e75Chad Brubaker        }
5655654b36b4667431e49d27c07a06d275656071e75Chad Brubaker    }
566b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin
567ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin    /**
568a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * Notify keystore that a user's password has changed.
569a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     *
570a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param userId the user whose password changed.
571a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     * @param newPassword the new password or "" if the password was removed.
572a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker     */
573a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean onUserPasswordChanged(int userId, String newPassword) {
574a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        // Parcel.cpp doesn't support deserializing null strings and treats them as "". Make that
575a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        // explicit here.
576a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        if (newPassword == null) {
577a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            newPassword = "";
578a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        }
579a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        try {
580a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            return mBinder.onUserPasswordChanged(userId, newPassword) == NO_ERROR;
581a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        } catch (RemoteException e) {
582a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
583a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker            return false;
584a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        }
585a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    }
586a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker
58783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    /**
58883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * Notify keystore that a user was added.
58983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     *
59083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param userId the new user.
59183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param parentId the parent of the new user, or -1 if the user has no parent. If parentId is
59283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * specified then the new user's keystore will be intialized with the same secure lockscreen
59383ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * password as the parent.
59483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     */
59583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    public void onUserAdded(int userId, int parentId) {
59683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        try {
59783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            mBinder.onUserAdded(userId, parentId);
59883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        } catch (RemoteException e) {
59983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
60083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        }
60183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    }
60283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker
60383ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    /**
60483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * Notify keystore that a user was added.
60583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     *
60683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param userId the new user.
60783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     */
60883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    public void onUserAdded(int userId) {
60983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        onUserAdded(userId, -1);
61083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    }
61183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker
61283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    /**
61383ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * Notify keystore that a user was removed.
61483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     *
61583ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     * @param userId the removed user.
61683ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker     */
61783ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    public void onUserRemoved(int userId) {
61883ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        try {
61983ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            mBinder.onUserRemoved(userId);
62083ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        } catch (RemoteException e) {
62183ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker            Log.w(TAG, "Cannot connect to keystore", e);
62283ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker        }
62383ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker    }
62483ce095c848b972156256855d0f2a2ff4aa068fdChad Brubaker
625a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    public boolean onUserPasswordChanged(String newPassword) {
626a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker        return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
627a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    }
628a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker
6298d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden    public int attestKey(
6308d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden            String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
6318d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden        try {
6328d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden            return mBinder.attestKey(alias, params, outChain);
6338d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden        } catch (RemoteException e) {
6348d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden            Log.w(TAG, "Cannot connect to keystore", e);
6358d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden            return SYSTEM_ERROR;
6368d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden        }
6378d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden    }
6388d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden
639237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski    public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) {
640237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski        try {
641237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski            return mBinder.attestDeviceIds(params, outChain);
642237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski        } catch (RemoteException e) {
643237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski            Log.w(TAG, "Cannot connect to keystore", e);
644237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski            return SYSTEM_ERROR;
645237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski        }
646237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski    }
647237f4b369bfd8021882007d103b9921fca789263Bartosz Fabianowski
648b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro    /**
649b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro     * Notify keystore that the device went off-body.
650b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro     */
651b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro    public void onDeviceOffBody() {
652b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro        try {
653b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro            mBinder.onDeviceOffBody();
654b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro        } catch (RemoteException e) {
655b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro            Log.w(TAG, "Cannot connect to keystore", e);
656b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro        }
657b32aae2a46bc3678e11c7f0ca88e01a192829490Tucker Sylvestro    }
6588d8c7477746c357d54f586fc92e8d422a4fc6441Shawn Willden
659a91a8504191d91d288c55821caa5bf00c9be26a2Chad Brubaker    /**
660ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * Returns a {@link KeyStoreException} corresponding to the provided keystore/keymaster error
661ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * code.
662ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     */
663dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin    public static KeyStoreException getKeyStoreException(int errorCode) {
664b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        if (errorCode > 0) {
665b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            // KeyStore layer error
666b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            switch (errorCode) {
667b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case NO_ERROR:
668b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "OK");
669b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case LOCKED:
6705418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin                    return new KeyStoreException(errorCode, "User authentication required");
671b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case UNINITIALIZED:
672b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Keystore not initialized");
673b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case SYSTEM_ERROR:
674b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "System error");
675b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case PERMISSION_DENIED:
676b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Permission denied");
677b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case KEY_NOT_FOUND:
678b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Key not found");
679b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case VALUE_CORRUPTED:
680b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, "Key blob corrupted");
681058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin                case OP_AUTH_NEEDED:
682058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin                    return new KeyStoreException(errorCode, "Operation requires authorization");
683b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                default:
684b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode, String.valueOf(errorCode));
685b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            }
686b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        } else {
687b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            // Keymaster layer error
688b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            switch (errorCode) {
689b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
690b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    // The name of this parameter significantly differs between Keymaster and
691b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    // framework APIs. Use the framework wording to make life easier for developers.
692b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode,
693b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                            "Invalid user authentication validity duration");
694b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                default:
695b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                    return new KeyStoreException(errorCode,
696b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                            KeymasterDefs.getErrorMessage(errorCode));
697b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            }
698b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        }
699b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin    }
700b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin
701ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin    /**
702ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * Returns an {@link InvalidKeyException} corresponding to the provided
703ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * {@link KeyStoreException}.
704ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     */
705dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin    public InvalidKeyException getInvalidKeyException(
7063876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin            String keystoreKeyAlias, int uid, KeyStoreException e) {
707b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        switch (e.getErrorCode()) {
7085418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin            case LOCKED:
7095418393c58d1d80fe37a209ab931f6d56bd46a86Alex Klyubin                return new UserNotAuthenticatedException();
710b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
711b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                return new KeyExpiredException();
712b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
713b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin                return new KeyNotYetValidException();
714b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
715058de02073a129301d391c22b050f2d65adadb0fAlex Klyubin            case OP_AUTH_NEEDED:
716708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin            {
717708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // We now need to determine whether the key/operation can become usable if user
718708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // authentication is performed, or whether it can never become usable again.
719708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // User authentication requirements are contained in the key's characteristics. We
720708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // need to check whether these requirements can be be satisfied by asking the user
721708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // to authenticate.
722708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
723708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                int getKeyCharacteristicsErrorCode =
7243876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin                        getKeyCharacteristics(keystoreKeyAlias, null, null, uid,
7253876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin                                keyCharacteristics);
726708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                if (getKeyCharacteristicsErrorCode != NO_ERROR) {
727708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new InvalidKeyException(
728708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                            "Failed to obtained key characteristics",
729708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                            getKeyStoreException(getKeyCharacteristicsErrorCode));
730708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
731ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                List<BigInteger> keySids =
732ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                        keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
733708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                if (keySids.isEmpty()) {
734708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // Key is not bound to any SIDs -- no amount of authentication will help here.
735708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new KeyPermanentlyInvalidatedException();
736708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
737708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                long rootSid = GateKeeper.getSecureUserId();
738ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                if ((rootSid != 0) && (keySids.contains(KeymasterArguments.toUint64(rootSid)))) {
739708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // One of the key's SIDs is the current root SID -- user can be authenticated
740708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // against that SID.
741708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new UserNotAuthenticatedException();
742708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
743708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin
744708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                long fingerprintOnlySid = getFingerprintOnlySid();
745708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                if ((fingerprintOnlySid != 0)
746ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin                        && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
747708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // One of the key's SIDs is the current fingerprint SID -- user can be
748708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    // authenticated against that SID.
749708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                    return new UserNotAuthenticatedException();
750708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                }
751708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin
752708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                // None of the key's SIDs can ever be authenticated
753708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin                return new KeyPermanentlyInvalidatedException();
754708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin            }
755b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin            default:
756ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin                return new InvalidKeyException("Keystore operation failed", e);
757b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin        }
758b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin    }
759b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin
7602d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin    private long getFingerprintOnlySid() {
761a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class);
7622d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        if (fingerprintManager == null) {
763708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin            return 0;
764708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin        }
765708fc9404501ac42b6cac925fe3e10801b5f633bAlex Klyubin
766a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        // TODO: Restore USE_FINGERPRINT permission check in
767a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin        // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
7682d7a85cd2b2ab4dbbe09354c6ae1668bff51a514Alex Klyubin        return fingerprintManager.getAuthenticatorId();
7692dac95d03399bb9fa59999e4964d7f8bcd485c38Svetoslav    }
7702dac95d03399bb9fa59999e4964d7f8bcd485c38Svetoslav
771ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin    /**
772ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
773ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     * code.
774ad9ba10ecda10c14e46d00f40fc3e431cc2d9bc2Alex Klyubin     */
7753876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin    public InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int uid,
7763876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin            int errorCode) {
7773876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin        return getInvalidKeyException(keystoreKeyAlias, uid, getKeyStoreException(errorCode));
778b4834ae3fa09e8013f7ab743a12def063ae999e3Alex Klyubin    }
77944039172627d1c15737ea73836ad375559d76211Chia-chi Yeh}
780