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