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.security.keymaster.KeymasterDefs; 27 import android.system.keystore2.Domain; 28 import android.system.keystore2.IKeystoreService; 29 import android.system.keystore2.KeyDescriptor; 30 import android.system.keystore2.KeyEntryResponse; 31 import android.system.keystore2.ResponseCode; 32 import android.util.Log; 33 34 import java.util.Calendar; 35 import java.util.Objects; 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 getService(boolean retryLookup)141 @NonNull private synchronized IKeystoreService getService(boolean retryLookup) { 142 if (mBinder == null || retryLookup) { 143 mBinder = IKeystoreService.Stub.asInterface(ServiceManager 144 .getService(KEYSTORE2_SERVICE_NAME)); 145 Binder.allowBlocking(mBinder.asBinder()); 146 } 147 return Objects.requireNonNull(mBinder); 148 } 149 delete(KeyDescriptor descriptor)150 void delete(KeyDescriptor descriptor) throws KeyStoreException { 151 handleRemoteExceptionWithRetry((service) -> { 152 service.deleteKey(descriptor); 153 return 0; 154 }); 155 } 156 157 /** 158 * List all entries in the keystore for in the given namespace. 159 */ list(int domain, long namespace)160 public KeyDescriptor[] list(int domain, long namespace) throws KeyStoreException { 161 return handleRemoteExceptionWithRetry((service) -> service.listEntries(domain, namespace)); 162 } 163 164 /** 165 * List all entries in the keystore for in the given namespace. 166 */ listBatch(int domain, long namespace, String startPastAlias)167 public KeyDescriptor[] listBatch(int domain, long namespace, String startPastAlias) 168 throws KeyStoreException { 169 return handleRemoteExceptionWithRetry( 170 (service) -> service.listEntriesBatched(domain, namespace, startPastAlias)); 171 } 172 173 /** 174 * Grant string prefix as used by the keystore boringssl engine. Must be kept in sync 175 * with system/security/keystore-engine. Note: The prefix here includes the 0x which 176 * std::stringstream used in keystore-engine needs to identify the number as hex represented. 177 * Here we include it in the prefix, because Long#parseUnsignedLong does not understand it 178 * and gets the radix as explicit argument. 179 * @hide 180 */ 181 private static final String KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX = 182 "ks2_keystore-engine_grant_id:0x"; 183 184 /** 185 * This function turns a grant identifier into a specific string that is understood by the 186 * keystore-engine in system/security/keystore-engine. Is only used by VPN and WI-FI components 187 * to allow certain system components like racoon or vendor components like WPA supplicant 188 * to use keystore keys with boring ssl. 189 * 190 * @param grantId the grant id as returned by {@link #grant} in the {@code nspace} filed of 191 * the resulting {@code KeyDescriptor}. 192 * @return The grant descriptor string. 193 * @hide 194 */ makeKeystoreEngineGrantString(long grantId)195 public static String makeKeystoreEngineGrantString(long grantId) { 196 return String.format("%s%016X", KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX, grantId); 197 } 198 199 /** 200 * Convenience function to turn a keystore engine grant string as returned by 201 * {@link #makeKeystoreEngineGrantString(long)} back into a grant KeyDescriptor. 202 * 203 * @param grantString As string returned by {@link #makeKeystoreEngineGrantString(long)} 204 * @return The grant key descriptor. 205 * @hide 206 */ keystoreEngineGrantString2KeyDescriptor(String grantString)207 public static KeyDescriptor keystoreEngineGrantString2KeyDescriptor(String grantString) { 208 KeyDescriptor key = new KeyDescriptor(); 209 key.domain = Domain.GRANT; 210 key.nspace = Long.parseUnsignedLong( 211 grantString.substring(KEYSTORE_ENGINE_GRANT_ALIAS_PREFIX.length()), 16); 212 key.alias = null; 213 key.blob = null; 214 return key; 215 } 216 217 /** 218 * Create a grant that allows the grantee identified by {@code granteeUid} to use 219 * the key specified by {@code descriptor} withint the restrictions given by 220 * {@code accessVectore}. 221 * @see IKeystoreService#grant(KeyDescriptor, int, int) for more details. 222 * @param descriptor 223 * @param granteeUid 224 * @param accessVector 225 * @return 226 * @throws KeyStoreException 227 * @hide 228 */ grant(KeyDescriptor descriptor, int granteeUid, int accessVector)229 public KeyDescriptor grant(KeyDescriptor descriptor, int granteeUid, int accessVector) 230 throws KeyStoreException { 231 return handleRemoteExceptionWithRetry( 232 (service) -> service.grant(descriptor, granteeUid, accessVector) 233 ); 234 } 235 236 /** 237 * Destroys a grant. 238 * @see IKeystoreService#ungrant(KeyDescriptor, int) for more details. 239 * @param descriptor 240 * @param granteeUid 241 * @throws KeyStoreException 242 * @hide 243 */ ungrant(KeyDescriptor descriptor, int granteeUid)244 public void ungrant(KeyDescriptor descriptor, int granteeUid) 245 throws KeyStoreException { 246 handleRemoteExceptionWithRetry((service) -> { 247 service.ungrant(descriptor, granteeUid); 248 return 0; 249 }); 250 } 251 252 /** 253 * Retrieves a key entry from the keystore backend. 254 * @see IKeystoreService#getKeyEntry(KeyDescriptor) for more details. 255 * @param descriptor 256 * @return 257 * @throws KeyStoreException 258 * @hide 259 */ getKeyEntry(@onNull KeyDescriptor descriptor)260 public KeyEntryResponse getKeyEntry(@NonNull KeyDescriptor descriptor) 261 throws KeyStoreException { 262 return handleRemoteExceptionWithRetry((service) -> service.getKeyEntry(descriptor)); 263 } 264 265 /** 266 * Get the security level specific keystore interface from the keystore daemon. 267 * @see IKeystoreService#getSecurityLevel(int) for more details. 268 * @param securityLevel 269 * @return 270 * @throws KeyStoreException 271 * @hide 272 */ getSecurityLevel(int securityLevel)273 public KeyStoreSecurityLevel getSecurityLevel(int securityLevel) 274 throws KeyStoreException { 275 return handleRemoteExceptionWithRetry((service) -> 276 new KeyStoreSecurityLevel( 277 service.getSecurityLevel(securityLevel) 278 ) 279 ); 280 } 281 282 /** 283 * Update the subcomponents of a key entry designated by the key descriptor. 284 * @see IKeystoreService#updateSubcomponent(KeyDescriptor, byte[], byte[]) for more details. 285 * @param key 286 * @param publicCert 287 * @param publicCertChain 288 * @throws KeyStoreException 289 * @hide 290 */ updateSubcomponents(@onNull KeyDescriptor key, byte[] publicCert, byte[] publicCertChain)291 public void updateSubcomponents(@NonNull KeyDescriptor key, byte[] publicCert, 292 byte[] publicCertChain) throws KeyStoreException { 293 handleRemoteExceptionWithRetry((service) -> { 294 service.updateSubcomponent(key, publicCert, publicCertChain); 295 return 0; 296 }); 297 } 298 299 /** 300 * Delete the key designed by the key descriptor. 301 * @see IKeystoreService#deleteKey(KeyDescriptor) for more details. 302 * @param descriptor 303 * @throws KeyStoreException 304 * @hide 305 */ deleteKey(@onNull KeyDescriptor descriptor)306 public void deleteKey(@NonNull KeyDescriptor descriptor) 307 throws KeyStoreException { 308 handleRemoteExceptionWithRetry((service) -> { 309 service.deleteKey(descriptor); 310 return 0; 311 }); 312 } 313 314 /** 315 * Returns the number of Keystore entries for a given domain and namespace. 316 */ getNumberOfEntries(int domain, long namespace)317 public int getNumberOfEntries(int domain, long namespace) throws KeyStoreException { 318 return handleRemoteExceptionWithRetry((service) 319 -> service.getNumberOfEntries(domain, namespace)); 320 } interruptedPreservingSleep(long millis)321 protected static void interruptedPreservingSleep(long millis) { 322 boolean wasInterrupted = false; 323 Calendar calendar = Calendar.getInstance(); 324 long target = calendar.getTimeInMillis() + millis; 325 while (true) { 326 try { 327 Thread.sleep(target - calendar.getTimeInMillis()); 328 break; 329 } catch (InterruptedException e) { 330 wasInterrupted = true; 331 } catch (IllegalArgumentException e) { 332 // This means that the argument to sleep was negative. 333 // So we are done sleeping. 334 break; 335 } 336 } 337 if (wasInterrupted) { 338 Thread.currentThread().interrupt(); 339 } 340 } 341 getKeyStoreException(int errorCode, String serviceErrorMessage)342 static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) { 343 if (errorCode > 0) { 344 // KeyStore layer error 345 switch (errorCode) { 346 case ResponseCode.LOCKED: 347 return new KeyStoreException(errorCode, "User authentication required", 348 serviceErrorMessage); 349 case ResponseCode.UNINITIALIZED: 350 return new KeyStoreException(errorCode, "Keystore not initialized", 351 serviceErrorMessage); 352 case ResponseCode.SYSTEM_ERROR: 353 return new KeyStoreException(errorCode, "System error", serviceErrorMessage); 354 case ResponseCode.PERMISSION_DENIED: 355 return new KeyStoreException(errorCode, "Permission denied", 356 serviceErrorMessage); 357 case ResponseCode.KEY_NOT_FOUND: 358 return new KeyStoreException(errorCode, "Key not found", serviceErrorMessage); 359 case ResponseCode.VALUE_CORRUPTED: 360 return new KeyStoreException(errorCode, "Key blob corrupted", 361 serviceErrorMessage); 362 case ResponseCode.KEY_PERMANENTLY_INVALIDATED: 363 return new KeyStoreException(errorCode, "Key permanently invalidated", 364 serviceErrorMessage); 365 case ResponseCode.OUT_OF_KEYS: 366 // Getting a more specific RKP status requires the security level, which we 367 // don't have here. Higher layers of the stack can interpret this exception 368 // and add more flavor. 369 return new KeyStoreException(errorCode, serviceErrorMessage, 370 KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE); 371 default: 372 return new KeyStoreException(errorCode, String.valueOf(errorCode), 373 serviceErrorMessage); 374 } 375 } else { 376 // Keymaster layer error 377 switch (errorCode) { 378 case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT: 379 // The name of this parameter significantly differs between Keymaster and 380 // framework APIs. Use the framework wording to make life easier for developers. 381 return new KeyStoreException(errorCode, 382 "Invalid user authentication validity duration", 383 serviceErrorMessage); 384 default: 385 return new KeyStoreException(errorCode, 386 KeymasterDefs.getErrorMessage(errorCode), 387 serviceErrorMessage); 388 } 389 } 390 } 391 392 } 393