KeyStore.java revision dae79e540844741fc35c648efe8bbb00fc8ab781
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.Binder; 22import android.os.IBinder; 23import android.os.RemoteException; 24import android.os.ServiceManager; 25import android.security.keymaster.ExportResult; 26import android.security.keymaster.KeyCharacteristics; 27import android.security.keymaster.KeymasterArguments; 28import android.security.keymaster.KeymasterBlob; 29import android.security.keymaster.OperationResult; 30import android.util.Log; 31 32import java.util.Locale; 33 34/** 35 * @hide This should not be made public in its present form because it 36 * assumes that private and secret key bytes are available and would 37 * preclude the use of hardware crypto. 38 */ 39public class KeyStore { 40 private static final String TAG = "KeyStore"; 41 42 // ResponseCodes 43 public static final int NO_ERROR = 1; 44 public static final int LOCKED = 2; 45 public static final int UNINITIALIZED = 3; 46 public static final int SYSTEM_ERROR = 4; 47 public static final int PROTOCOL_ERROR = 5; 48 public static final int PERMISSION_DENIED = 6; 49 public static final int KEY_NOT_FOUND = 7; 50 public static final int VALUE_CORRUPTED = 8; 51 public static final int UNDEFINED_ACTION = 9; 52 public static final int WRONG_PASSWORD = 10; 53 54 // Used for UID field to indicate the calling UID. 55 public static final int UID_SELF = -1; 56 57 // Flags for "put" "import" and "generate" 58 public static final int FLAG_NONE = 0; 59 public static final int FLAG_ENCRYPTED = 1; 60 61 // States 62 public enum State { UNLOCKED, LOCKED, UNINITIALIZED }; 63 64 private int mError = NO_ERROR; 65 66 private final IKeystoreService mBinder; 67 68 private IBinder mToken; 69 70 private KeyStore(IKeystoreService binder) { 71 mBinder = binder; 72 } 73 74 public static KeyStore getInstance() { 75 IKeystoreService keystore = IKeystoreService.Stub.asInterface(ServiceManager 76 .getService("android.security.keystore")); 77 return new KeyStore(keystore); 78 } 79 80 private synchronized IBinder getToken() { 81 if (mToken == null) { 82 mToken = new Binder(); 83 } 84 return mToken; 85 } 86 87 static int getKeyTypeForAlgorithm(String keyType) { 88 if ("RSA".equalsIgnoreCase(keyType)) { 89 return NativeCrypto.EVP_PKEY_RSA; 90 } else if ("EC".equalsIgnoreCase(keyType)) { 91 return NativeCrypto.EVP_PKEY_EC; 92 } else { 93 return -1; 94 } 95 } 96 97 public State state() { 98 final int ret; 99 try { 100 ret = mBinder.test(); 101 } catch (RemoteException e) { 102 Log.w(TAG, "Cannot connect to keystore", e); 103 throw new AssertionError(e); 104 } 105 106 switch (ret) { 107 case NO_ERROR: return State.UNLOCKED; 108 case LOCKED: return State.LOCKED; 109 case UNINITIALIZED: return State.UNINITIALIZED; 110 default: throw new AssertionError(mError); 111 } 112 } 113 114 public boolean isUnlocked() { 115 return state() == State.UNLOCKED; 116 } 117 118 public byte[] get(String key) { 119 try { 120 return mBinder.get(key); 121 } catch (RemoteException e) { 122 Log.w(TAG, "Cannot connect to keystore", e); 123 return null; 124 } 125 } 126 127 public boolean put(String key, byte[] value, int uid, int flags) { 128 try { 129 return mBinder.insert(key, value, uid, flags) == NO_ERROR; 130 } catch (RemoteException e) { 131 Log.w(TAG, "Cannot connect to keystore", e); 132 return false; 133 } 134 } 135 136 public boolean delete(String key, int uid) { 137 try { 138 return mBinder.del(key, uid) == NO_ERROR; 139 } catch (RemoteException e) { 140 Log.w(TAG, "Cannot connect to keystore", e); 141 return false; 142 } 143 } 144 145 public boolean delete(String key) { 146 return delete(key, UID_SELF); 147 } 148 149 public boolean contains(String key, int uid) { 150 try { 151 return mBinder.exist(key, uid) == NO_ERROR; 152 } catch (RemoteException e) { 153 Log.w(TAG, "Cannot connect to keystore", e); 154 return false; 155 } 156 } 157 158 public boolean contains(String key) { 159 return contains(key, UID_SELF); 160 } 161 162 public String[] saw(String prefix, int uid) { 163 try { 164 return mBinder.saw(prefix, uid); 165 } catch (RemoteException e) { 166 Log.w(TAG, "Cannot connect to keystore", e); 167 return null; 168 } 169 } 170 171 public String[] saw(String prefix) { 172 return saw(prefix, UID_SELF); 173 } 174 175 public boolean reset() { 176 try { 177 return mBinder.reset() == NO_ERROR; 178 } catch (RemoteException e) { 179 Log.w(TAG, "Cannot connect to keystore", e); 180 return false; 181 } 182 } 183 184 public boolean password(String password) { 185 try { 186 return mBinder.password(password) == NO_ERROR; 187 } catch (RemoteException e) { 188 Log.w(TAG, "Cannot connect to keystore", e); 189 return false; 190 } 191 } 192 193 public boolean lock() { 194 try { 195 return mBinder.lock() == NO_ERROR; 196 } catch (RemoteException e) { 197 Log.w(TAG, "Cannot connect to keystore", e); 198 return false; 199 } 200 } 201 202 public boolean unlock(String password) { 203 try { 204 mError = mBinder.unlock(password); 205 return mError == NO_ERROR; 206 } catch (RemoteException e) { 207 Log.w(TAG, "Cannot connect to keystore", e); 208 return false; 209 } 210 } 211 212 public boolean isEmpty() { 213 try { 214 return mBinder.zero() == KEY_NOT_FOUND; 215 } catch (RemoteException e) { 216 Log.w(TAG, "Cannot connect to keystore", e); 217 return false; 218 } 219 } 220 221 public boolean generate(String key, int uid, int keyType, int keySize, int flags, 222 byte[][] args) { 223 try { 224 return mBinder.generate(key, uid, keyType, keySize, flags, 225 new KeystoreArguments(args)) == NO_ERROR; 226 } catch (RemoteException e) { 227 Log.w(TAG, "Cannot connect to keystore", e); 228 return false; 229 } 230 } 231 232 public boolean importKey(String keyName, byte[] key, int uid, int flags) { 233 try { 234 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR; 235 } catch (RemoteException e) { 236 Log.w(TAG, "Cannot connect to keystore", e); 237 return false; 238 } 239 } 240 241 public byte[] getPubkey(String key) { 242 try { 243 return mBinder.get_pubkey(key); 244 } catch (RemoteException e) { 245 Log.w(TAG, "Cannot connect to keystore", e); 246 return null; 247 } 248 } 249 250 public boolean delKey(String key, int uid) { 251 try { 252 return mBinder.del_key(key, uid) == NO_ERROR; 253 } catch (RemoteException e) { 254 Log.w(TAG, "Cannot connect to keystore", e); 255 return false; 256 } 257 } 258 259 public boolean delKey(String key) { 260 return delKey(key, UID_SELF); 261 } 262 263 public byte[] sign(String key, byte[] data) { 264 try { 265 return mBinder.sign(key, data); 266 } catch (RemoteException e) { 267 Log.w(TAG, "Cannot connect to keystore", e); 268 return null; 269 } 270 } 271 272 public boolean verify(String key, byte[] data, byte[] signature) { 273 try { 274 return mBinder.verify(key, data, signature) == NO_ERROR; 275 } catch (RemoteException e) { 276 Log.w(TAG, "Cannot connect to keystore", e); 277 return false; 278 } 279 } 280 281 public boolean grant(String key, int uid) { 282 try { 283 return mBinder.grant(key, uid) == NO_ERROR; 284 } catch (RemoteException e) { 285 Log.w(TAG, "Cannot connect to keystore", e); 286 return false; 287 } 288 } 289 290 public boolean ungrant(String key, int uid) { 291 try { 292 return mBinder.ungrant(key, uid) == NO_ERROR; 293 } catch (RemoteException e) { 294 Log.w(TAG, "Cannot connect to keystore", e); 295 return false; 296 } 297 } 298 299 /** 300 * Returns the last modification time of the key in milliseconds since the 301 * epoch. Will return -1L if the key could not be found or other error. 302 */ 303 public long getmtime(String key) { 304 try { 305 final long millis = mBinder.getmtime(key); 306 if (millis == -1L) { 307 return -1L; 308 } 309 310 return millis * 1000L; 311 } catch (RemoteException e) { 312 Log.w(TAG, "Cannot connect to keystore", e); 313 return -1L; 314 } 315 } 316 317 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) { 318 try { 319 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR; 320 } catch (RemoteException e) { 321 Log.w(TAG, "Cannot connect to keystore", e); 322 return false; 323 } 324 } 325 326 // TODO remove this when it's removed from Settings 327 public boolean isHardwareBacked() { 328 return isHardwareBacked("RSA"); 329 } 330 331 public boolean isHardwareBacked(String keyType) { 332 try { 333 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == NO_ERROR; 334 } catch (RemoteException e) { 335 Log.w(TAG, "Cannot connect to keystore", e); 336 return false; 337 } 338 } 339 340 public boolean clearUid(int uid) { 341 try { 342 return mBinder.clear_uid(uid) == NO_ERROR; 343 } catch (RemoteException e) { 344 Log.w(TAG, "Cannot connect to keystore", e); 345 return false; 346 } 347 } 348 349 public boolean resetUid(int uid) { 350 try { 351 mError = mBinder.reset_uid(uid); 352 return mError == NO_ERROR; 353 } catch (RemoteException e) { 354 Log.w(TAG, "Cannot connect to keystore", e); 355 return false; 356 } 357 } 358 359 public boolean syncUid(int sourceUid, int targetUid) { 360 try { 361 mError = mBinder.sync_uid(sourceUid, targetUid); 362 return mError == NO_ERROR; 363 } catch (RemoteException e) { 364 Log.w(TAG, "Cannot connect to keystore", e); 365 return false; 366 } 367 } 368 369 public boolean passwordUid(String password, int uid) { 370 try { 371 mError = mBinder.password_uid(password, uid); 372 return mError == NO_ERROR; 373 } catch (RemoteException e) { 374 Log.w(TAG, "Cannot connect to keystore", e); 375 return false; 376 } 377 } 378 379 public int getLastError() { 380 return mError; 381 } 382 383 public boolean addRngEntropy(byte[] data) { 384 try { 385 return mBinder.addRngEntropy(data) == NO_ERROR; 386 } catch (RemoteException e) { 387 Log.w(TAG, "Cannot connect to keystore", e); 388 return false; 389 } 390 } 391 392 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid, 393 int flags, KeyCharacteristics outCharacteristics) { 394 try { 395 return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics); 396 } catch (RemoteException e) { 397 Log.w(TAG, "Cannot connect to keystore", e); 398 return SYSTEM_ERROR; 399 } 400 } 401 402 public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int flags, 403 KeyCharacteristics outCharacteristics) { 404 return generateKey(alias, args, entropy, UID_SELF, flags, outCharacteristics); 405 } 406 407 public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId, 408 KeyCharacteristics outCharacteristics) { 409 try { 410 return mBinder.getKeyCharacteristics(alias, clientId, appId, outCharacteristics); 411 } catch (RemoteException e) { 412 Log.w(TAG, "Cannot connect to keystore", e); 413 return SYSTEM_ERROR; 414 } 415 } 416 417 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 418 int uid, int flags, KeyCharacteristics outCharacteristics) { 419 try { 420 return mBinder.importKey(alias, args, format, keyData, uid, flags, 421 outCharacteristics); 422 } catch (RemoteException e) { 423 Log.w(TAG, "Cannot connect to keystore", e); 424 return SYSTEM_ERROR; 425 } 426 } 427 428 public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData, 429 int flags, KeyCharacteristics outCharacteristics) { 430 return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics); 431 } 432 433 public ExportResult exportKey(String alias, int format, KeymasterBlob clientId, 434 KeymasterBlob appId) { 435 try { 436 return mBinder.exportKey(alias, format, clientId, appId); 437 } catch (RemoteException e) { 438 Log.w(TAG, "Cannot connect to keystore", e); 439 return null; 440 } 441 } 442 443 public OperationResult begin(String alias, int purpose, boolean pruneable, 444 KeymasterArguments args, byte[] entropy, KeymasterArguments outArgs) { 445 try { 446 return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, outArgs); 447 } catch (RemoteException e) { 448 Log.w(TAG, "Cannot connect to keystore", e); 449 return null; 450 } 451 } 452 453 public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) { 454 try { 455 return mBinder.update(token, arguments, input); 456 } catch (RemoteException e) { 457 Log.w(TAG, "Cannot connect to keystore", e); 458 return null; 459 } 460 } 461 462 public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature) { 463 try { 464 return mBinder.finish(token, arguments, signature); 465 } catch (RemoteException e) { 466 Log.w(TAG, "Cannot connect to keystore", e); 467 return null; 468 } 469 } 470 471 public int abort(IBinder token) { 472 try { 473 return mBinder.abort(token); 474 } catch (RemoteException e) { 475 Log.w(TAG, "Cannot connect to keystore", e); 476 return SYSTEM_ERROR; 477 } 478 } 479} 480