KeyStore.java revision 21a76df55cf4b956f4d34f57c7b9e694d0363f54
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, args) == NO_ERROR; 209 } catch (RemoteException e) { 210 Log.w(TAG, "Cannot connect to keystore", e); 211 return false; 212 } 213 } 214 215 public boolean importKey(String keyName, byte[] key, int uid, int flags) { 216 try { 217 return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR; 218 } catch (RemoteException e) { 219 Log.w(TAG, "Cannot connect to keystore", e); 220 return false; 221 } 222 } 223 224 public byte[] getPubkey(String key) { 225 try { 226 return mBinder.get_pubkey(key); 227 } catch (RemoteException e) { 228 Log.w(TAG, "Cannot connect to keystore", e); 229 return null; 230 } 231 } 232 233 public boolean delKey(String key, int uid) { 234 try { 235 return mBinder.del_key(key, uid) == NO_ERROR; 236 } catch (RemoteException e) { 237 Log.w(TAG, "Cannot connect to keystore", e); 238 return false; 239 } 240 } 241 242 public boolean delKey(String key) { 243 return delKey(key, UID_SELF); 244 } 245 246 public byte[] sign(String key, byte[] data) { 247 try { 248 return mBinder.sign(key, data); 249 } catch (RemoteException e) { 250 Log.w(TAG, "Cannot connect to keystore", e); 251 return null; 252 } 253 } 254 255 public boolean verify(String key, byte[] data, byte[] signature) { 256 try { 257 return mBinder.verify(key, data, signature) == NO_ERROR; 258 } catch (RemoteException e) { 259 Log.w(TAG, "Cannot connect to keystore", e); 260 return false; 261 } 262 } 263 264 public boolean grant(String key, int uid) { 265 try { 266 return mBinder.grant(key, uid) == NO_ERROR; 267 } catch (RemoteException e) { 268 Log.w(TAG, "Cannot connect to keystore", e); 269 return false; 270 } 271 } 272 273 public boolean ungrant(String key, int uid) { 274 try { 275 return mBinder.ungrant(key, uid) == NO_ERROR; 276 } catch (RemoteException e) { 277 Log.w(TAG, "Cannot connect to keystore", e); 278 return false; 279 } 280 } 281 282 /** 283 * Returns the last modification time of the key in milliseconds since the 284 * epoch. Will return -1L if the key could not be found or other error. 285 */ 286 public long getmtime(String key) { 287 try { 288 final long millis = mBinder.getmtime(key); 289 if (millis == -1L) { 290 return -1L; 291 } 292 293 return millis * 1000L; 294 } catch (RemoteException e) { 295 Log.w(TAG, "Cannot connect to keystore", e); 296 return -1L; 297 } 298 } 299 300 public boolean duplicate(String srcKey, int srcUid, String destKey, int destUid) { 301 try { 302 return mBinder.duplicate(srcKey, srcUid, destKey, destUid) == NO_ERROR; 303 } catch (RemoteException e) { 304 Log.w(TAG, "Cannot connect to keystore", e); 305 return false; 306 } 307 } 308 309 // TODO remove this when it's removed from Settings 310 public boolean isHardwareBacked() { 311 return isHardwareBacked("RSA"); 312 } 313 314 public boolean isHardwareBacked(String keyType) { 315 try { 316 return mBinder.is_hardware_backed(keyType.toUpperCase(Locale.US)) == 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 boolean resetUid(int uid) { 333 try { 334 mError = mBinder.reset_uid(uid); 335 return mError == NO_ERROR; 336 } catch (RemoteException e) { 337 Log.w(TAG, "Cannot connect to keystore", e); 338 return false; 339 } 340 } 341 342 public boolean syncUid(int sourceUid, int targetUid) { 343 try { 344 mError = mBinder.sync_uid(sourceUid, targetUid); 345 return mError == NO_ERROR; 346 } catch (RemoteException e) { 347 Log.w(TAG, "Cannot connect to keystore", e); 348 return false; 349 } 350 } 351 352 public boolean passwordUid(String password, int uid) { 353 try { 354 mError = mBinder.password_uid(password, uid); 355 return mError == NO_ERROR; 356 } catch (RemoteException e) { 357 Log.w(TAG, "Cannot connect to keystore", e); 358 return false; 359 } 360 } 361 362 public int getLastError() { 363 return mError; 364 } 365} 366