1 /* 2 * Copyright (C) 2020 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 android.annotation.NonNull; 20 import android.compat.annotation.ChangeId; 21 import android.compat.annotation.Disabled; 22 import android.os.Binder; 23 import android.os.RemoteException; 24 import android.os.ServiceManager; 25 import android.os.ServiceSpecificException; 26 import android.os.StrictMode; 27 import android.security.keymaster.KeymasterDefs; 28 import android.system.keystore2.Domain; 29 import android.system.keystore2.IKeystoreService; 30 import android.system.keystore2.KeyDescriptor; 31 import android.system.keystore2.KeyEntryResponse; 32 import android.system.keystore2.ResponseCode; 33 import android.util.Log; 34 35 import java.util.Calendar; 36 37 /** 38 * @hide This should not be made public in its present form because it 39 * assumes that private and secret key bytes are available and would 40 * preclude the use of hardware crypto. 41 */ 42 public class KeyStore2 { 43 private static final String TAG = "KeyStore"; 44 45 private static final int RECOVERY_GRACE_PERIOD_MS = 50; 46 47 /** 48 * Keystore operation creation may fail 49 * 50 * Keystore used to work under the assumption that the creation of cryptographic operations 51 * always succeeds. However, the KeyMint backend has only a limited number of operation slots. 52 * In order to keep up the appearance of "infinite" operation slots, the Keystore daemon 53 * would prune least recently used operations if there is no available operation slot. 54 * As a result, good operations could be terminated prematurely. 55 * 56 * This opens AndroidKeystore up to denial-of-service and unintended livelock situations. 57 * E.g.: if multiple apps wake up at the same time, e.g., due to power management optimizations, 58 * and attempt to perform crypto operations, they start terminating each others operations 59 * without making any progress. 60 * 61 * To break out of livelocks and to discourage DoS attempts we have changed the pruning 62 * strategy such that it prefers clients that use few operation slots and only briefly. 63 * As a result we can, almost, guarantee that single operations that don't linger inactive 64 * for more than 5 seconds will conclude unhampered by the pruning strategy. "Almost", 65 * because there are operations related to file system encryption that can prune even 66 * these operations, but those are extremely rare. 67 * 68 * As a side effect of this new pruning strategy operation creation can now fail if the 69 * client has a lower pruning power than all of the existing operations. 70 * 71 * Pruning strategy 72 * 73 * To find a suitable candidate we compute the malus for the caller and each existing 74 * operation. The malus is the inverse of the pruning power (caller) or pruning 75 * resistance (existing operation). For the caller to be able to prune an operation it must 76 * find an operation with a malus higher than its own. 77 * 78 * For more detail on the pruning strategy consult the implementation at 79 * https://android.googlesource.com/platform/system/security/+/refs/heads/master/keystore2/src/operation.rs 80 * 81 * For older SDK version, KeyStore2 will poll the Keystore daemon for a free operation 82 * slot. So to applications, targeting earlier SDK versions, it will still look like cipher and 83 * signature object initialization always succeeds, however, it may take longer to get an 84 * operation. 85 * 86 * All SDK version benefit from fairer operation slot scheduling and a better chance to 87 * successfully conclude an operation. 88 */ 89 @ChangeId 90 @Disabled // See b/180133780 91 static final long KEYSTORE_OPERATION_CREATION_MAY_FAIL = 169897160L; 92 93 // Never use mBinder directly, use KeyStore2.getService() instead or better yet 94 // handleRemoteExceptionWithRetry which retries connecting to Keystore once in case 95 // of a remote exception. 96 private IKeystoreService mBinder; 97 98 99 @FunctionalInterface 100 interface CheckedRemoteRequest<R> { execute(IKeystoreService service)101 R execute(IKeystoreService service) throws RemoteException; 102 } 103 handleRemoteExceptionWithRetry(@onNull CheckedRemoteRequest<R> request)104 private <R> R handleRemoteExceptionWithRetry(@NonNull CheckedRemoteRequest<R> request) 105 throws KeyStoreException { 106 IKeystoreService service = getService(false /* retryLookup */); 107 boolean firstTry = true; 108 while (true) { 109 try { 110 return request.execute(service); 111 } catch (ServiceSpecificException e) { 112 throw getKeyStoreException(e.errorCode, e.getMessage()); 113 } catch (RemoteException e) { 114 if (firstTry) { 115 Log.w(TAG, "Looks like we may have lost connection to the Keystore " 116 + "daemon."); 117 Log.w(TAG, "Retrying after giving Keystore " 118 + RECOVERY_GRACE_PERIOD_MS + "ms to recover."); 119 interruptedPreservingSleep(RECOVERY_GRACE_PERIOD_MS); 120 service = getService(true /* retry Lookup */); 121 firstTry = false; 122 } else { 123 Log.e(TAG, "Cannot connect to Keystore daemon.", e); 124 throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage()); 125 } 126 } 127 } 128 } 129 130 private static final String KEYSTORE2_SERVICE_NAME = 131 "android.system.keystore2.IKeystoreService/default"; 132 KeyStore2()133 private KeyStore2() { 134 mBinder = null; 135 } 136 getInstance()137 public static KeyStore2 getInstance() { 138 return new KeyStore2(); 139 } 140 141 /** 142 * Gets the {@link IKeystoreService} that should be started in early_hal in Android. 143 * 144 * @throws IllegalStateException if the KeystoreService is not available or has not 145 * been initialized when called. This is a state that should not happen and indicates 146 * and error somewhere in the stack or with the calling processes access permissions. 147 */ getService(boolean retryLookup)148 @NonNull private synchronized IKeystoreService getService(boolean retryLookup) { 149 if (mBinder == null || retryLookup) { 150 mBinder = IKeystoreService.Stub.asInterface(ServiceManager 151 .getService(KEYSTORE2_SERVICE_NAME)); 152 } 153 if (mBinder == null) { 154 throw new IllegalStateException( 155 "Could not connect to Keystore service. Keystore may have crashed or not been" 156 + " initialized"); 157 } 158 Binder.allowBlocking(mBinder.asBinder()); 159 return mBinder; 160 } 161 delete(KeyDescriptor descriptor)162 void delete(KeyDescriptor descriptor) throws KeyStoreException { 163 StrictMode.noteDiskWrite(); 164 165 handleRemoteExceptionWithRetry((service) -> { 166 service.deleteKey(descriptor); 167 return 0; 168 }); 169 } 170 171 /** 172 * List all entries in the keystore for in the given namespace. 173 */ list(int domain, long namespace)174 public KeyDescriptor[] list(int domain, long namespace) throws KeyStoreException { 175 StrictMode.noteDiskRead(); 176 177 return handleRemoteExceptionWithRetry((service) -> service.listEntries(domain, namespace)); 178 } 179 180 /** 181 * List all entries in the keystore for in the given namespace. 182 */ listBatch(int domain, long namespace, String startPastAlias)183 public KeyDescriptor[] listBatch(int domain, long namespace, String startPastAlias) 184 throws KeyStoreException { 185 StrictMode.noteDiskRead(); 186 187 return handleRemoteExceptionWithRetry( 188 (service) -> service.listEntriesBatched(domain, namespace, startPastAlias)); 189 } 190 191 /** 192 * Grant string prefix as used by the keystore boringssl engine. Must be kept in sync 193 * with system/security/keystore-engine. Note: The prefix here includes the 0x which 194 * std::stringstream used in keystore-engine needs to identify the number as hex represented. 195 * Here we include it in the prefix, because Long#parseUnsignedLong does not understand it 196 * and gets the radix as explicit argument. 197 * @hide 198 */ 199 private static final String KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX = 200 "ks2_keystore-engine_grant_id:0x"; 201 202 /** 203 * This function turns a grant identifier into a specific string that is understood by the 204 * keystore-engine in system/security/keystore-engine. Is only used by VPN and WI-FI components 205 * to allow certain system components like racoon or vendor components like WPA supplicant 206 * to use keystore keys with boring ssl. 207 * 208 * @param grantId the grant id as returned by {@link #grant} in the {@code nspace} filed of 209 * the resulting {@code KeyDescriptor}. 210 * @return The grant descriptor string. 211 * @hide 212 */ makeKeystoreEngineGrantString(long grantId)213 public static String makeKeystoreEngineGrantString(long grantId) { 214 return String.format("%s%016X", KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX, grantId); 215 } 216 217 /** 218 * Convenience function to turn a keystore engine grant string as returned by 219 * {@link #makeKeystoreEngineGrantString(long)} back into a grant KeyDescriptor. 220 * 221 * @param grantString As string returned by {@link #makeKeystoreEngineGrantString(long)} 222 * @return The grant key descriptor. 223 * @hide 224 */ keystoreEngineGrantString2KeyDescriptor(String grantString)225 public static KeyDescriptor keystoreEngineGrantString2KeyDescriptor(String grantString) { 226 KeyDescriptor key = new KeyDescriptor(); 227 key.domain = Domain.GRANT; 228 key.nspace = Long.parseUnsignedLong( 229 grantString.substring(KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX.length()), 16); 230 key.alias = null; 231 key.blob = null; 232 return key; 233 } 234 235 /** 236 * Create a grant that allows the grantee identified by {@code granteeUid} to use 237 * the key specified by {@code descriptor} withint the restrictions given by 238 * {@code accessVectore}. 239 * @see IKeystoreService#grant(KeyDescriptor, int, int) for more details. 240 * @param descriptor 241 * @param granteeUid 242 * @param accessVector 243 * @return 244 * @throws KeyStoreException 245 * @hide 246 */ grant(KeyDescriptor descriptor, int granteeUid, int accessVector)247 public KeyDescriptor grant(KeyDescriptor descriptor, int granteeUid, int accessVector) 248 throws KeyStoreException { 249 StrictMode.noteDiskWrite(); 250 251 return handleRemoteExceptionWithRetry( 252 (service) -> service.grant(descriptor, granteeUid, accessVector) 253 ); 254 } 255 256 /** 257 * Destroys a grant. 258 * @see IKeystoreService#ungrant(KeyDescriptor, int) for more details. 259 * @param descriptor 260 * @param granteeUid 261 * @throws KeyStoreException 262 * @hide 263 */ ungrant(KeyDescriptor descriptor, int granteeUid)264 public void ungrant(KeyDescriptor descriptor, int granteeUid) 265 throws KeyStoreException { 266 StrictMode.noteDiskWrite(); 267 268 handleRemoteExceptionWithRetry((service) -> { 269 service.ungrant(descriptor, granteeUid); 270 return 0; 271 }); 272 } 273 274 /** 275 * Retrieves a key entry from the keystore backend. 276 * @see IKeystoreService#getKeyEntry(KeyDescriptor) for more details. 277 * @param descriptor 278 * @return 279 * @throws KeyStoreException 280 * @hide 281 */ getKeyEntry(@onNull KeyDescriptor descriptor)282 public KeyEntryResponse getKeyEntry(@NonNull KeyDescriptor descriptor) 283 throws KeyStoreException { 284 StrictMode.noteDiskRead(); 285 286 return handleRemoteExceptionWithRetry((service) -> service.getKeyEntry(descriptor)); 287 } 288 289 /** 290 * Get the security level specific keystore interface from the keystore daemon. 291 * @see IKeystoreService#getSecurityLevel(int) for more details. 292 * @param securityLevel 293 * @return 294 * @throws KeyStoreException 295 * @hide 296 */ getSecurityLevel(int securityLevel)297 public KeyStoreSecurityLevel getSecurityLevel(int securityLevel) 298 throws KeyStoreException { 299 return handleRemoteExceptionWithRetry((service) -> 300 new KeyStoreSecurityLevel( 301 service.getSecurityLevel(securityLevel) 302 ) 303 ); 304 } 305 306 /** 307 * Update the subcomponents of a key entry designated by the key descriptor. 308 * @see IKeystoreService#updateSubcomponent(KeyDescriptor, byte[], byte[]) for more details. 309 * @param key 310 * @param publicCert 311 * @param publicCertChain 312 * @throws KeyStoreException 313 * @hide 314 */ updateSubcomponents(@onNull KeyDescriptor key, byte[] publicCert, byte[] publicCertChain)315 public void updateSubcomponents(@NonNull KeyDescriptor key, byte[] publicCert, 316 byte[] publicCertChain) throws KeyStoreException { 317 StrictMode.noteDiskWrite(); 318 319 handleRemoteExceptionWithRetry((service) -> { 320 service.updateSubcomponent(key, publicCert, publicCertChain); 321 return 0; 322 }); 323 } 324 325 /** 326 * Delete the key designed by the key descriptor. 327 * @see IKeystoreService#deleteKey(KeyDescriptor) for more details. 328 * @param descriptor 329 * @throws KeyStoreException 330 * @hide 331 */ deleteKey(@onNull KeyDescriptor descriptor)332 public void deleteKey(@NonNull KeyDescriptor descriptor) 333 throws KeyStoreException { 334 StrictMode.noteDiskWrite(); 335 336 handleRemoteExceptionWithRetry((service) -> { 337 service.deleteKey(descriptor); 338 return 0; 339 }); 340 } 341 342 /** 343 * Returns the number of Keystore entries for a given domain and namespace. 344 */ getNumberOfEntries(int domain, long namespace)345 public int getNumberOfEntries(int domain, long namespace) throws KeyStoreException { 346 StrictMode.noteDiskRead(); 347 348 return handleRemoteExceptionWithRetry((service) 349 -> service.getNumberOfEntries(domain, namespace)); 350 } interruptedPreservingSleep(long millis)351 protected static void interruptedPreservingSleep(long millis) { 352 boolean wasInterrupted = false; 353 Calendar calendar = Calendar.getInstance(); 354 long target = calendar.getTimeInMillis() + millis; 355 while (true) { 356 try { 357 Thread.sleep(target - calendar.getTimeInMillis()); 358 break; 359 } catch (InterruptedException e) { 360 wasInterrupted = true; 361 } catch (IllegalArgumentException e) { 362 // This means that the argument to sleep was negative. 363 // So we are done sleeping. 364 break; 365 } 366 } 367 if (wasInterrupted) { 368 Thread.currentThread().interrupt(); 369 } 370 } 371 getKeyStoreException(int errorCode, String serviceErrorMessage)372 static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) { 373 if (errorCode > 0) { 374 // KeyStore layer error 375 switch (errorCode) { 376 case ResponseCode.LOCKED: 377 return new KeyStoreException(errorCode, "User authentication required", 378 serviceErrorMessage); 379 case ResponseCode.UNINITIALIZED: 380 return new KeyStoreException(errorCode, "Keystore not initialized", 381 serviceErrorMessage); 382 case ResponseCode.SYSTEM_ERROR: 383 return new KeyStoreException(errorCode, "System error", serviceErrorMessage); 384 case ResponseCode.PERMISSION_DENIED: 385 return new KeyStoreException(errorCode, "Permission denied", 386 serviceErrorMessage); 387 case ResponseCode.KEY_NOT_FOUND: 388 return new KeyStoreException(errorCode, "Key not found", serviceErrorMessage); 389 case ResponseCode.VALUE_CORRUPTED: 390 return new KeyStoreException(errorCode, "Key blob corrupted", 391 serviceErrorMessage); 392 case ResponseCode.KEY_PERMANENTLY_INVALIDATED: 393 return new KeyStoreException(errorCode, "Key permanently invalidated", 394 serviceErrorMessage); 395 case ResponseCode.OUT_OF_KEYS: 396 // Getting a more specific RKP status requires the security level, which we 397 // don't have here. Higher layers of the stack can interpret this exception 398 // and add more flavor. 399 return new KeyStoreException(errorCode, serviceErrorMessage, 400 KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE); 401 default: 402 return new KeyStoreException(errorCode, String.valueOf(errorCode), 403 serviceErrorMessage); 404 } 405 } else { 406 // Keymaster layer error 407 switch (errorCode) { 408 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT: 409 // The name of this parameter significantly differs between Keymaster and 410 // framework APIs. Use the framework wording to make life easier for developers. 411 return new KeyStoreException(errorCode, 412 "Invalid user authentication validity duration", 413 serviceErrorMessage); 414 default: 415 return new KeyStoreException(errorCode, 416 KeymasterDefs.getErrorMessage(errorCode), 417 serviceErrorMessage); 418 } 419 } 420 } 421 422 } 423