1 /*
2  * Copyright (C) 2012 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.keystore;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SystemApi;
21 import android.compat.annotation.UnsupportedAppUsage;
22 import android.security.KeyStore;
23 
24 import java.io.IOException;
25 import java.security.KeyStoreException;
26 import java.security.NoSuchAlgorithmException;
27 import java.security.NoSuchProviderException;
28 import java.security.Provider;
29 import java.security.cert.CertificateException;
30 
31 import javax.crypto.Cipher;
32 import javax.crypto.Mac;
33 
34 /**
35  * A provider focused on providing JCA interfaces for the Android KeyStore.
36  *
37  * @hide
38  */
39 @SystemApi
40 public class AndroidKeyStoreProvider extends Provider {
41     private static final String PROVIDER_NAME = "AndroidKeyStore";
42 
43     /** @hide */
AndroidKeyStoreProvider(@onNull String name)44     public AndroidKeyStoreProvider(@NonNull String name) {
45         super(name, 1.0, "Android KeyStore security provider");
46         throw new IllegalStateException("Should not be instantiated.");
47     }
48 
49     /**
50      * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto
51      * primitive.
52      *
53      * <p>The following primitives are supported: {@link Cipher} and {@link Mac}.
54      *
55      * @return KeyStore operation handle or {@code 0} if the provided primitive's KeyStore operation
56      *         is not in progress.
57      *
58      * @throws IllegalArgumentException if the provided primitive is not supported or is not backed
59      *         by AndroidKeyStore provider.
60      * @throws IllegalStateException if the provided primitive is not initialized.
61      * @hide
62      */
63     @UnsupportedAppUsage
getKeyStoreOperationHandle(Object cryptoPrimitive)64     public static long getKeyStoreOperationHandle(Object cryptoPrimitive) {
65         return android.security.keystore2.AndroidKeyStoreProvider
66                 .getKeyStoreOperationHandle(cryptoPrimitive);
67     }
68 
69     /**
70      * Returns an {@code AndroidKeyStore} {@link java.security.KeyStore}} of the specified UID.
71      * The {@code KeyStore} contains keys and certificates owned by that UID. Such cross-UID
72      * access is permitted to a few system UIDs and only to a few other UIDs (e.g., Wi-Fi, VPN)
73      * all of which are system.
74      *
75      * <p>Note: the returned {@code KeyStore} is already initialized/loaded. Thus, there is
76      * no need to invoke {@code load} on it.
77      *
78      * @param uid Uid for which the keystore provider is requested.
79      * @throws KeyStoreException if a KeyStoreSpi implementation for the specified type is not
80      * available from the specified provider.
81      * @throws NoSuchProviderException If the specified provider is not registered in the security
82      * provider list.
83      * @hide
84      */
85     @SystemApi
86     @NonNull
getKeyStoreForUid(int uid)87     public static java.security.KeyStore getKeyStoreForUid(int uid)
88             throws KeyStoreException, NoSuchProviderException {
89         final java.security.KeyStore.LoadStoreParameter loadParameter =
90                 new android.security.keystore2.AndroidKeyStoreLoadStoreParameter(
91                         KeyProperties.legacyUidToNamespace(uid));
92         java.security.KeyStore result = java.security.KeyStore.getInstance(PROVIDER_NAME);
93         try {
94             result.load(loadParameter);
95         } catch (NoSuchAlgorithmException | CertificateException | IOException e) {
96             throw new KeyStoreException(
97                     "Failed to load AndroidKeyStore KeyStore for UID " + uid, e);
98         }
99         return result;
100     }
101 }
102