KeyStore.java revision 590c068e8380ba73a6571ddf797d4ce02b390bcb
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 com.android.org.conscrypt.NativeCrypto; 20 21import android.os.RemoteException; 22import android.os.ServiceManager; 23import android.util.Log; 24 25import java.util.Locale; 26 27/** 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. 31 */ 32public class KeyStore { 33 private static final String TAG = "KeyStore"; 34 35 // ResponseCodes 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; 46 47 // Used for UID field to indicate the calling UID. 48 public static final int UID_SELF = -1; 49 50 // Flags for "put" "import" and "generate" 51 public static final int FLAG_NONE = 0; 52 public static final int FLAG_ENCRYPTED = 1; 53 54 // States 55 public enum State { UNLOCKED, LOCKED, UNINITIALIZED }; 56 57 private int mError = NO_ERROR; 58 59 private final IKeystoreService mBinder; 60 61 private KeyStore(IKeystoreService binder) { 62 mBinder = binder; 63 } 64 65 public static KeyStore getInstance() { 66 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager 67 .getService("android.security.keystore")); 68 return new KeyStore(keystore); 69 } 70 71 static int getKeyTypeForAlgorithm(String keyType) { 72 if ("RSA".equalsIgnoreCase(keyType)) { 73 return NativeCrypto.EVP_PKEY_RSA; 74 } else if ("EC".equalsIgnoreCase(keyType)) { 75 return NativeCrypto.EVP_PKEY_EC; 76 } else { 77 return -1; 78 } 79 } 80 81 public State state() { 82 final int ret; 83 try { 84 ret = mBinder.test(); 85 } catch (RemoteException e) { 86 Log.w(TAG, "Cannot connect to keystore", e); 87 throw new AssertionError(e); 88 } 89 90 switch (ret) { 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); 95 } 96 } 97 98 public boolean isUnlocked() { 99 return state() == State.UNLOCKED; 100 } 101 102 public byte[] get(String key) { 103 try { 104 return mBinder.get(key); 105 } catch (RemoteException e) { 106 Log.w(TAG, "Cannot connect to keystore", e); 107 return null; 108 } 109 } 110 111 public boolean put(String key, byte[] value, int uid, int flags) { 112 try { 113 return mBinder.insert(key, value, uid, flags) == NO_ERROR; 114 } catch (RemoteException e) { 115 Log.w(TAG, "Cannot connect to keystore", e); 116 return false; 117 } 118 } 119 120 public boolean delete(String key, int uid) { 121 try { 122 return mBinder.del(key, uid) == NO_ERROR; 123 } catch (RemoteException e) { 124 Log.w(TAG, "Cannot connect to keystore", e); 125 return false; 126 } 127 } 128 129 public boolean delete(String key) { 130 return delete(key, UID_SELF); 131 } 132 133 public boolean contains(String key, int uid) { 134 try { 135 return mBinder.exist(key, uid) == NO_ERROR; 136 } catch (RemoteException e) { 137 Log.w(TAG, "Cannot connect to keystore", e); 138 return false; 139 } 140 } 141 142 public boolean contains(String key) { 143 return contains(key, UID_SELF); 144 } 145 146 public String[] saw(String prefix, int uid) { 147 try { 148 return mBinder.saw(prefix, uid); 149 } catch (RemoteException e) { 150 Log.w(TAG, "Cannot connect to keystore", e); 151 return null; 152 } 153 } 154 155 public String[] saw(String prefix) { 156 return saw(prefix, UID_SELF); 157 } 158 159 public boolean reset() { 160 try { 161 return mBinder.reset() == NO_ERROR; 162 } catch (RemoteException e) { 163 Log.w(TAG, "Cannot connect to keystore", e); 164 return false; 165 } 166 } 167 168 public boolean password(String password) { 169 try { 170 return mBinder.password(password) == NO_ERROR; 171 } catch (RemoteException e) { 172 Log.w(TAG, "Cannot connect to keystore", e); 173 return false; 174 } 175 } 176 177 public boolean lock() { 178 try { 179 return mBinder.lock() == NO_ERROR; 180 } catch (RemoteException e) { 181 Log.w(TAG, "Cannot connect to keystore", e); 182 return false; 183 } 184 } 185 186 public boolean unlock(String password) { 187 try { 188 mError = mBinder.unlock(password); 189 return mError == NO_ERROR; 190 } catch (RemoteException e) { 191 Log.w(TAG, "Cannot connect to keystore", e); 192 return false; 193 } 194 } 195 196 public boolean isEmpty() { 197 try { 198 return mBinder.zero() == KEY_NOT_FOUND; 199 } catch (RemoteException e) { 200 Log.w(TAG, "Cannot connect to keystore", e); 201 return false; 202 } 203 } 204 205 public boolean generate(String key, int uid, int keyType, int keySize, int flags, 206 byte[][] args) { 207 try { 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); 212 return false; 213 } 214 } 215 216 public boolean importKey(String keyName, byte[] key, int uid, int flags) { 217 try { 218 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR; 219 } catch (RemoteException e) { 220 Log.w(TAG, "Cannot connect to keystore", e); 221 return false; 222 } 223 } 224 225 public byte[] getPubkey(String key) { 226 try { 227 return mBinder.get_pubkey(key); 228 } catch (RemoteException e) { 229 Log.w(TAG, "Cannot connect to keystore", e); 230 return null; 231 } 232 } 233 234 public boolean delKey(String key, int uid) { 235 try { 236 return mBinder.del_key(key, uid) == NO_ERROR; 237 } catch (RemoteException e) { 238 Log.w(TAG, "Cannot connect to keystore", e); 239 return false; 240 } 241 } 242 243 public boolean delKey(String key) { 244 return delKey(key, UID_SELF); 245 } 246 247 public byte[] sign(String key, byte[] data) { 248 try { 249 return mBinder.sign(key, data); 250 } catch (RemoteException e) { 251 Log.w(TAG, "Cannot connect to keystore", e); 252 return null; 253 } 254 } 255 256 public boolean verify(String key, byte[] data, byte[] signature) { 257 try { 258 return mBinder.verify(key, data, signature) == NO_ERROR; 259 } catch (RemoteException e) { 260 Log.w(TAG, "Cannot connect to keystore", e); 261 return false; 262 } 263 } 264 265 public boolean grant(String key, int uid) { 266 try { 267 return mBinder.grant(key, uid) == NO_ERROR; 268 } catch (RemoteException e) { 269 Log.w(TAG, "Cannot connect to keystore", e); 270 return false; 271 } 272 } 273 274 public boolean ungrant(String key, int uid) { 275 try { 276 return mBinder.ungrant(key, uid) == NO_ERROR; 277 } catch (RemoteException e) { 278 Log.w(TAG, "Cannot connect to keystore", e); 279 return false; 280 } 281 } 282 283 /** 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. 286 */ 287 public long getmtime(String key) { 288 try { 289 final long millis = mBinder.getmtime(key); 290 if (millis == -1L) { 291 return -1L; 292 } 293 294 return millis * 1000L; 295 } catch (RemoteException e) { 296 Log.w(TAG, "Cannot connect to keystore", e); 297 return -1L; 298 } 299 } 300 301 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) { 302 try { 303 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR; 304 } catch (RemoteException e) { 305 Log.w(TAG, "Cannot connect to keystore", e); 306 return false; 307 } 308 } 309 310 // TODO remove this when it's removed from Settings 311 public boolean isHardwareBacked() { 312 return isHardwareBacked("RSA"); 313 } 314 315 public boolean isHardwareBacked(String keyType) { 316 try { 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); 320 return false; 321 } 322 } 323 324 public boolean clearUid(int uid) { 325 try { 326 return mBinder.clear_uid(uid) == NO_ERROR; 327 } catch (RemoteException e) { 328 Log.w(TAG, "Cannot connect to keystore", e); 329 return false; 330 } 331 } 332 333 public boolean resetUid(int uid) { 334 try { 335 mError = mBinder.reset_uid(uid); 336 return mError == NO_ERROR; 337 } catch (RemoteException e) { 338 Log.w(TAG, "Cannot connect to keystore", e); 339 return false; 340 } 341 } 342 343 public boolean syncUid(int sourceUid, int targetUid) { 344 try { 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); 349 return false; 350 } 351 } 352 353 public boolean passwordUid(String password, int uid) { 354 try { 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); 359 return false; 360 } 361 } 362 363 public int getLastError() { 364 return mError; 365 } 366} 367