KeyStore.java revision a3788b00bb221e20abdd42f747d2af419e0a088c
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.security;
18
19import android.os.RemoteException;
20import android.os.ServiceManager;
21import android.util.Log;
22
23/**
24 * @hide This should not be made public in its present form because it
25 * assumes that private and secret key bytes are available and would
26 * preclude the use of hardware crypto.
27 */
28public class KeyStore {
29    private static final String TAG = "KeyStore";
30
31    // ResponseCodes
32    public static final int NO_ERROR = 1;
33    public static final int LOCKED = 2;
34    public static final int UNINITIALIZED = 3;
35    public static final int SYSTEM_ERROR = 4;
36    public static final int PROTOCOL_ERROR = 5;
37    public static final int PERMISSION_DENIED = 6;
38    public static final int KEY_NOT_FOUND = 7;
39    public static final int VALUE_CORRUPTED = 8;
40    public static final int UNDEFINED_ACTION = 9;
41    public static final int WRONG_PASSWORD = 10;
42
43    // Flags for "put" and "import"
44    public static final int FLAG_ENCRYPTED = 1;
45
46    // States
47    public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
48
49    private int mError = NO_ERROR;
50
51    private final IKeystoreService mBinder;
52
53    private KeyStore(IKeystoreService binder) {
54        mBinder = binder;
55    }
56
57    public static KeyStore getInstance() {
58        IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager
59                .getService("android.security.keystore"));
60        return new KeyStore(keystore);
61    }
62
63    public State state() {
64        final int ret;
65        try {
66            ret = mBinder.test();
67        } catch (RemoteException e) {
68            Log.w(TAG, "Cannot connect to keystore", e);
69            throw new AssertionError(e);
70        }
71
72        switch (ret) {
73            case NO_ERROR: return State.UNLOCKED;
74            case LOCKED: return State.LOCKED;
75            case UNINITIALIZED: return State.UNINITIALIZED;
76            default: throw new AssertionError(mError);
77        }
78    }
79
80    public boolean isUnlocked() {
81        return state() == State.UNLOCKED;
82    }
83
84    public byte[] get(String key) {
85        try {
86            return mBinder.get(key);
87        } catch (RemoteException e) {
88            Log.w(TAG, "Cannot connect to keystore", e);
89            return null;
90        }
91    }
92
93    public boolean put(String key, byte[] value, int uid, int flags) {
94        try {
95            return mBinder.insert(key, value, uid, flags) == NO_ERROR;
96        } catch (RemoteException e) {
97            Log.w(TAG, "Cannot connect to keystore", e);
98            return false;
99        }
100    }
101
102    public boolean put(String key, byte[] value, int uid) {
103        return put(key, value, uid, FLAG_ENCRYPTED);
104    }
105
106    public boolean put(String key, byte[] value) {
107        return put(key, value, -1);
108    }
109
110    public boolean delete(String key, int uid) {
111        try {
112            return mBinder.del(key, uid) == NO_ERROR;
113        } catch (RemoteException e) {
114            Log.w(TAG, "Cannot connect to keystore", e);
115            return false;
116        }
117    }
118
119    public boolean delete(String key) {
120        return delete(key, -1);
121    }
122
123    public boolean contains(String key, int uid) {
124        try {
125            return mBinder.exist(key, uid) == NO_ERROR;
126        } catch (RemoteException e) {
127            Log.w(TAG, "Cannot connect to keystore", e);
128            return false;
129        }
130    }
131
132    public boolean contains(String key) {
133        return contains(key, -1);
134    }
135
136    public String[] saw(String prefix, int uid) {
137        try {
138            return mBinder.saw(prefix, uid);
139        } catch (RemoteException e) {
140            Log.w(TAG, "Cannot connect to keystore", e);
141            return null;
142        }
143    }
144
145    public String[] saw(String prefix) {
146        return saw(prefix, -1);
147    }
148
149    public boolean reset() {
150        try {
151            return mBinder.reset() == NO_ERROR;
152        } catch (RemoteException e) {
153            Log.w(TAG, "Cannot connect to keystore", e);
154            return false;
155        }
156    }
157
158    public boolean password(String password) {
159        try {
160            return mBinder.password(password) == NO_ERROR;
161        } catch (RemoteException e) {
162            Log.w(TAG, "Cannot connect to keystore", e);
163            return false;
164        }
165    }
166
167    public boolean lock() {
168        try {
169            return mBinder.lock() == NO_ERROR;
170        } catch (RemoteException e) {
171            Log.w(TAG, "Cannot connect to keystore", e);
172            return false;
173        }
174    }
175
176    public boolean unlock(String password) {
177        try {
178            mError = mBinder.unlock(password);
179            return mError == NO_ERROR;
180        } catch (RemoteException e) {
181            Log.w(TAG, "Cannot connect to keystore", e);
182            return false;
183        }
184    }
185
186    public boolean isEmpty() {
187        try {
188            return mBinder.zero() == KEY_NOT_FOUND;
189        } catch (RemoteException e) {
190            Log.w(TAG, "Cannot connect to keystore", e);
191            return false;
192        }
193    }
194
195    public boolean generate(String key, int uid, int flags) {
196        try {
197            return mBinder.generate(key, uid, flags) == NO_ERROR;
198        } catch (RemoteException e) {
199            Log.w(TAG, "Cannot connect to keystore", e);
200            return false;
201        }
202    }
203
204    public boolean generate(String key, int uid) {
205        return generate(key, uid, FLAG_ENCRYPTED);
206    }
207
208    public boolean generate(String key) {
209        return generate(key, -1);
210    }
211
212    public boolean importKey(String keyName, byte[] key, int uid, int flags) {
213        try {
214            return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
215        } catch (RemoteException e) {
216            Log.w(TAG, "Cannot connect to keystore", e);
217            return false;
218        }
219    }
220
221    public boolean importKey(String keyName, byte[] key, int uid) {
222        return importKey(keyName, key, uid, FLAG_ENCRYPTED);
223    }
224
225    public boolean importKey(String keyName, byte[] key) {
226        return importKey(keyName, key, -1);
227    }
228
229    public byte[] getPubkey(String key) {
230        try {
231            return mBinder.get_pubkey(key);
232        } catch (RemoteException e) {
233            Log.w(TAG, "Cannot connect to keystore", e);
234            return null;
235        }
236    }
237
238    public boolean delKey(String key, int uid) {
239        try {
240            return mBinder.del_key(key, uid) == NO_ERROR;
241        } catch (RemoteException e) {
242            Log.w(TAG, "Cannot connect to keystore", e);
243            return false;
244        }
245    }
246
247    public boolean delKey(String key) {
248        return delKey(key, -1);
249    }
250
251    public byte[] sign(String key, byte[] data) {
252        try {
253            return mBinder.sign(key, data);
254        } catch (RemoteException e) {
255            Log.w(TAG, "Cannot connect to keystore", e);
256            return null;
257        }
258    }
259
260    public boolean verify(String key, byte[] data, byte[] signature) {
261        try {
262            return mBinder.verify(key, data, signature) == NO_ERROR;
263        } catch (RemoteException e) {
264            Log.w(TAG, "Cannot connect to keystore", e);
265            return false;
266        }
267    }
268
269    public boolean grant(String key, int uid) {
270        try {
271            return mBinder.grant(key, uid) == NO_ERROR;
272        } catch (RemoteException e) {
273            Log.w(TAG, "Cannot connect to keystore", e);
274            return false;
275        }
276    }
277
278    public boolean ungrant(String key, int uid) {
279        try {
280            return mBinder.ungrant(key, uid) == NO_ERROR;
281        } catch (RemoteException e) {
282            Log.w(TAG, "Cannot connect to keystore", e);
283            return false;
284        }
285    }
286
287    /**
288     * Returns the last modification time of the key in milliseconds since the
289     * epoch. Will return -1L if the key could not be found or other error.
290     */
291    public long getmtime(String key) {
292        try {
293            final long millis = mBinder.getmtime(key);
294            if (millis == -1L) {
295                return -1L;
296            }
297
298            return millis * 1000L;
299        } catch (RemoteException e) {
300            Log.w(TAG, "Cannot connect to keystore", e);
301            return -1L;
302        }
303    }
304
305    public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) {
306        try {
307            return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR;
308        } catch (RemoteException e) {
309            Log.w(TAG, "Cannot connect to keystore", e);
310            return false;
311        }
312    }
313
314    public boolean isHardwareBacked() {
315        try {
316            return mBinder.is_hardware_backed() == NO_ERROR;
317        } catch (RemoteException e) {
318            Log.w(TAG, "Cannot connect to keystore", e);
319            return false;
320        }
321    }
322
323    public boolean clearUid(int uid) {
324        try {
325            return mBinder.clear_uid(uid) == NO_ERROR;
326        } catch (RemoteException e) {
327            Log.w(TAG, "Cannot connect to keystore", e);
328            return false;
329        }
330    }
331
332    public int getLastError() {
333        return mError;
334    }
335}
336