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