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