2 * Copyright (C) 2009 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android.security;
19 import com.android.org.conscrypt.NativeCrypto;
21 import android.os.RemoteException;
22 import android.os.ServiceManager;
23 import android.util.Log;
25 import java.util.Locale;
28 * @hide This should not be made public in its present form because it
29 * assumes that private and secret key bytes are available and would
30 * preclude the use of hardware crypto.
32 public class KeyStore {
33 private static final String TAG = "KeyStore";
36 public static final int NO_ERROR = 1;
37 public static final int LOCKED = 2;
38 public static final int UNINITIALIZED = 3;
39 public static final int SYSTEM_ERROR = 4;
40 public static final int PROTOCOL_ERROR = 5;
41 public static final int PERMISSION_DENIED = 6;
42 public static final int KEY_NOT_FOUND = 7;
43 public static final int VALUE_CORRUPTED = 8;
44 public static final int UNDEFINED_ACTION = 9;
45 public static final int WRONG_PASSWORD = 10;
47 // Used for UID field to indicate the calling UID.
48 public static final int UID_SELF = -1;
50 // Flags for "put" "import" and "generate"
51 public static final int FLAG_NONE = 0;
52 public static final int FLAG_ENCRYPTED = 1;
55 public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
57 private int mError = NO_ERROR;
59 private final IKeystoreService mBinder;
61 private KeyStore(IKeystoreService binder) {
65 public static KeyStore getInstance() {
66 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
67 .getService("android.security.keystore"));
68 return new KeyStore(keystore);
71 static int getKeyTypeForAlgorithm(String keyType) throws IllegalArgumentException {
72 if ("RSA".equalsIgnoreCase(keyType)) {
73 return NativeCrypto.EVP_PKEY_RSA;
74 } else if ("EC".equalsIgnoreCase(keyType)) {
75 return NativeCrypto.EVP_PKEY_EC;
77 throw new IllegalArgumentException("Unsupported key type: " + keyType);
81 public State state() {
85 } catch (RemoteException e) {
86 Log.w(TAG, "Cannot connect to keystore", e);
87 throw new AssertionError(e);
91 case NO_ERROR: return State.UNLOCKED;
92 case LOCKED: return State.LOCKED;
93 case UNINITIALIZED: return State.UNINITIALIZED;
94 default: throw new AssertionError(mError);
98 public boolean isUnlocked() {
99 return state() == State.UNLOCKED;
102 public byte[] get(String key) {
104 return mBinder.get(key);
105 } catch (RemoteException e) {
106 Log.w(TAG, "Cannot connect to keystore", e);
111 public boolean put(String key, byte[] value, int uid, int flags) {
113 return mBinder.insert(key, value, uid, flags) == NO_ERROR;
114 } catch (RemoteException e) {
115 Log.w(TAG, "Cannot connect to keystore", e);
120 public boolean delete(String key, int uid) {
122 return mBinder.del(key, uid) == NO_ERROR;
123 } catch (RemoteException e) {
124 Log.w(TAG, "Cannot connect to keystore", e);
129 public boolean delete(String key) {
130 return delete(key, UID_SELF);
133 public boolean contains(String key, int uid) {
135 return mBinder.exist(key, uid) == NO_ERROR;
136 } catch (RemoteException e) {
137 Log.w(TAG, "Cannot connect to keystore", e);
142 public boolean contains(String key) {
143 return contains(key, UID_SELF);
146 public String[] saw(String prefix, int uid) {
148 return mBinder.saw(prefix, uid);
149 } catch (RemoteException e) {
150 Log.w(TAG, "Cannot connect to keystore", e);
155 public String[] saw(String prefix) {
156 return saw(prefix, UID_SELF);
159 public boolean reset() {
161 return mBinder.reset() == NO_ERROR;
162 } catch (RemoteException e) {
163 Log.w(TAG, "Cannot connect to keystore", e);
168 public boolean password(String password) {
170 return mBinder.password(password) == NO_ERROR;
171 } catch (RemoteException e) {
172 Log.w(TAG, "Cannot connect to keystore", e);
177 public boolean lock() {
179 return mBinder.lock() == NO_ERROR;
180 } catch (RemoteException e) {
181 Log.w(TAG, "Cannot connect to keystore", e);
186 public boolean unlock(String password) {
188 mError = mBinder.unlock(password);
189 return mError == NO_ERROR;
190 } catch (RemoteException e) {
191 Log.w(TAG, "Cannot connect to keystore", e);
196 public boolean isEmpty() {
198 return mBinder.zero() == KEY_NOT_FOUND;
199 } catch (RemoteException e) {
200 Log.w(TAG, "Cannot connect to keystore", e);
205 public boolean generate(String key, int uid, int keyType, int keySize, int flags,
208 return mBinder.generate(key, uid, keyType, keySize, flags,
209 new KeystoreArguments(args)) == NO_ERROR;
210 } catch (RemoteException e) {
211 Log.w(TAG, "Cannot connect to keystore", e);
216 public boolean importKey(String keyName, byte[] key, int uid, int flags) {
218 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
219 } catch (RemoteException e) {
220 Log.w(TAG, "Cannot connect to keystore", e);
225 public byte[] getPubkey(String key) {
227 return mBinder.get_pubkey(key);
228 } catch (RemoteException e) {
229 Log.w(TAG, "Cannot connect to keystore", e);
234 public boolean delKey(String key, int uid) {
236 return mBinder.del_key(key, uid) == NO_ERROR;
237 } catch (RemoteException e) {
238 Log.w(TAG, "Cannot connect to keystore", e);
243 public boolean delKey(String key) {
244 return delKey(key, UID_SELF);
247 public byte[] sign(String key, byte[] data) {
249 return mBinder.sign(key, data);
250 } catch (RemoteException e) {
251 Log.w(TAG, "Cannot connect to keystore", e);
256 public boolean verify(String key, byte[] data, byte[] signature) {
258 return mBinder.verify(key, data, signature) == NO_ERROR;
259 } catch (RemoteException e) {
260 Log.w(TAG, "Cannot connect to keystore", e);
265 public boolean grant(String key, int uid) {
267 return mBinder.grant(key, uid) == NO_ERROR;
268 } catch (RemoteException e) {
269 Log.w(TAG, "Cannot connect to keystore", e);
274 public boolean ungrant(String key, int uid) {
276 return mBinder.ungrant(key, uid) == NO_ERROR;
277 } catch (RemoteException e) {
278 Log.w(TAG, "Cannot connect to keystore", e);
284 * Returns the last modification time of the key in milliseconds since the
285 * epoch. Will return -1L if the key could not be found or other error.
287 public long getmtime(String key) {
289 final long millis = mBinder.getmtime(key);
294 return millis * 1000L;
295 } catch (RemoteException e) {
296 Log.w(TAG, "Cannot connect to keystore", e);
301 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
303 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
304 } catch (RemoteException e) {
305 Log.w(TAG, "Cannot connect to keystore", e);
310 // TODO remove this when it's removed from Settings
311 public boolean isHardwareBacked() {
312 return isHardwareBacked("RSA");
315 public boolean isHardwareBacked(String keyType) {
317 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR;
318 } catch (RemoteException e) {
319 Log.w(TAG, "Cannot connect to keystore", e);
324 public boolean clearUid(int uid) {
326 return mBinder.clear_uid(uid) == NO_ERROR;
327 } catch (RemoteException e) {
328 Log.w(TAG, "Cannot connect to keystore", e);
333 public boolean resetUid(int uid) {
335 mError = mBinder.reset_uid(uid);
336 return mError == NO_ERROR;
337 } catch (RemoteException e) {
338 Log.w(TAG, "Cannot connect to keystore", e);
343 public boolean syncUid(int sourceUid, int targetUid) {
345 mError = mBinder.sync_uid(sourceUid, targetUid);
346 return mError == NO_ERROR;
347 } catch (RemoteException e) {
348 Log.w(TAG, "Cannot connect to keystore", e);
353 public boolean passwordUid(String password, int uid) {
355 mError = mBinder.password_uid(password, uid);
356 return mError == NO_ERROR;
357 } catch (RemoteException e) {
358 Log.w(TAG, "Cannot connect to keystore", e);
363 public int getLastError() {