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.keystore2; 18 19 import android.annotation.NonNull; 20 import android.security.KeyStore; 21 import android.security.KeyStore2; 22 import android.security.KeyStoreSecurityLevel; 23 import android.security.keymaster.KeymasterDefs; 24 import android.security.keystore.KeyPermanentlyInvalidatedException; 25 import android.security.keystore.KeyProperties; 26 import android.security.keystore.KeyStoreCryptoOperation; 27 import android.system.keystore2.Authorization; 28 import android.system.keystore2.Domain; 29 import android.system.keystore2.KeyDescriptor; 30 import android.system.keystore2.KeyEntryResponse; 31 import android.system.keystore2.KeyMetadata; 32 import android.system.keystore2.ResponseCode; 33 34 import java.security.KeyPair; 35 import java.security.Provider; 36 import java.security.ProviderException; 37 import java.security.PublicKey; 38 import java.security.Security; 39 import java.security.Signature; 40 import java.security.UnrecoverableKeyException; 41 import java.security.interfaces.ECPublicKey; 42 import java.security.interfaces.RSAPublicKey; 43 44 import javax.crypto.Cipher; 45 import javax.crypto.Mac; 46 import javax.crypto.SecretKey; 47 48 /** 49 * A provider focused on providing JCA interfaces for the Android KeyStore. 50 * 51 * @hide 52 */ 53 public class AndroidKeyStoreProvider extends Provider { 54 private static final String PROVIDER_NAME = "AndroidKeyStore"; 55 56 // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these 57 // classes when this provider is instantiated and installed early on during each app's 58 // initialization process. 59 // 60 // Crypto operations operating on the AndroidKeyStore keys must not be offered by this provider. 61 // Instead, they need to be offered by AndroidKeyStoreBCWorkaroundProvider. See its Javadoc 62 // for details. 63 64 private static final String PACKAGE_NAME = "android.security.keystore2"; 65 66 private static final String DESEDE_SYSTEM_PROPERTY = 67 "ro.hardware.keystore_desede"; 68 69 /** @hide **/ AndroidKeyStoreProvider()70 public AndroidKeyStoreProvider() { 71 super(PROVIDER_NAME, 1.0, "Android KeyStore security provider"); 72 73 boolean supports3DES = "true".equals(android.os.SystemProperties.get(DESEDE_SYSTEM_PROPERTY)); 74 75 // java.security.KeyStore 76 put("KeyStore.AndroidKeyStore", PACKAGE_NAME + ".AndroidKeyStoreSpi"); 77 78 // java.security.KeyPairGenerator 79 put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC"); 80 put("KeyPairGenerator.RSA", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA"); 81 82 // java.security.KeyFactory 83 putKeyFactoryImpl("EC"); 84 putKeyFactoryImpl("RSA"); 85 86 // javax.crypto.KeyGenerator 87 put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES"); 88 put("KeyGenerator.HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA1"); 89 put("KeyGenerator.HmacSHA224", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA224"); 90 put("KeyGenerator.HmacSHA256", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA256"); 91 put("KeyGenerator.HmacSHA384", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA384"); 92 put("KeyGenerator.HmacSHA512", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA512"); 93 94 if (supports3DES) { 95 put("KeyGenerator.DESede", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$DESede"); 96 } 97 98 // javax.crypto.KeyAgreement 99 put("KeyAgreement.ECDH", PACKAGE_NAME + ".AndroidKeyStoreKeyAgreementSpi$ECDH"); 100 101 // java.security.SecretKeyFactory 102 putSecretKeyFactoryImpl("AES"); 103 if (supports3DES) { 104 putSecretKeyFactoryImpl("DESede"); 105 } 106 putSecretKeyFactoryImpl("HmacSHA1"); 107 putSecretKeyFactoryImpl("HmacSHA224"); 108 putSecretKeyFactoryImpl("HmacSHA256"); 109 putSecretKeyFactoryImpl("HmacSHA384"); 110 putSecretKeyFactoryImpl("HmacSHA512"); 111 } 112 113 /** 114 * Installs a new instance of this provider (and the 115 * {@link AndroidKeyStoreBCWorkaroundProvider}). 116 * @hide 117 */ install()118 public static void install() { 119 Provider[] providers = Security.getProviders(); 120 int bcProviderIndex = -1; 121 for (int i = 0; i < providers.length; i++) { 122 Provider provider = providers[i]; 123 if ("BC".equals(provider.getName())) { 124 bcProviderIndex = i; 125 break; 126 } 127 } 128 129 Security.addProvider(new AndroidKeyStoreProvider()); 130 Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider(); 131 if (bcProviderIndex != -1) { 132 // Bouncy Castle provider found -- install the workaround provider above it. 133 // insertProviderAt uses 1-based positions. 134 Security.insertProviderAt(workaroundProvider, bcProviderIndex + 1); 135 } else { 136 // Bouncy Castle provider not found -- install the workaround provider at lowest 137 // priority. 138 Security.addProvider(workaroundProvider); 139 } 140 } 141 putSecretKeyFactoryImpl(String algorithm)142 private void putSecretKeyFactoryImpl(String algorithm) { 143 put("SecretKeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreSecretKeyFactorySpi"); 144 } 145 putKeyFactoryImpl(String algorithm)146 private void putKeyFactoryImpl(String algorithm) { 147 put("KeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreKeyFactorySpi"); 148 } 149 150 /** 151 * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto 152 * primitive. 153 * 154 * <p>The following primitives are supported: {@link Cipher}, {@link Signature} and {@link Mac}. 155 * 156 * @return KeyStore operation handle or {@code 0} if the provided primitive's KeyStore operation 157 * is not in progress. 158 * 159 * @throws IllegalArgumentException if the provided primitive is not supported or is not backed 160 * by AndroidKeyStore provider. 161 * @throws IllegalStateException if the provided primitive is not initialized. 162 * @hide 163 */ getKeyStoreOperationHandle(Object cryptoPrimitive)164 public static long getKeyStoreOperationHandle(Object cryptoPrimitive) { 165 if (cryptoPrimitive == null) { 166 throw new NullPointerException(); 167 } 168 Object spi; 169 if (cryptoPrimitive instanceof Signature) { 170 spi = ((Signature) cryptoPrimitive).getCurrentSpi(); 171 } else if (cryptoPrimitive instanceof Mac) { 172 spi = ((Mac) cryptoPrimitive).getCurrentSpi(); 173 } else if (cryptoPrimitive instanceof Cipher) { 174 spi = ((Cipher) cryptoPrimitive).getCurrentSpi(); 175 } else { 176 throw new IllegalArgumentException("Unsupported crypto primitive: " + cryptoPrimitive 177 + ". Supported: Signature, Mac, Cipher"); 178 } 179 if (spi == null) { 180 throw new IllegalStateException("Crypto primitive not initialized"); 181 } else if (!(spi instanceof KeyStoreCryptoOperation)) { 182 throw new IllegalArgumentException( 183 "Crypto primitive not backed by AndroidKeyStore provider: " + cryptoPrimitive 184 + ", spi: " + spi); 185 } 186 return ((KeyStoreCryptoOperation) spi).getOperationHandle(); 187 } 188 189 /** 190 * This helper function gets called if the key loaded from the keystore daemon 191 * is for an asymmetric algorithm. It constructs an instance of {@link AndroidKeyStorePublicKey} 192 * which implements {@link PublicKey}. 193 * 194 * @param descriptor The original key descriptor that was used to load the key. 195 * 196 * @param metadata The key metadata which includes the public key material, a reference to the 197 * stored private key material, the key characteristics. 198 * @param iSecurityLevel A binder interface that allows using the private key. 199 * @param algorithm Must indicate EC or RSA. 200 * @return AndroidKeyStorePublicKey 201 * @throws UnrecoverableKeyException 202 * @hide 203 */ 204 @NonNull makeAndroidKeyStorePublicKeyFromKeyEntryResponse( @onNull KeyDescriptor descriptor, @NonNull KeyMetadata metadata, @NonNull KeyStoreSecurityLevel iSecurityLevel, int algorithm)205 static AndroidKeyStorePublicKey makeAndroidKeyStorePublicKeyFromKeyEntryResponse( 206 @NonNull KeyDescriptor descriptor, 207 @NonNull KeyMetadata metadata, 208 @NonNull KeyStoreSecurityLevel iSecurityLevel, int algorithm) 209 throws UnrecoverableKeyException { 210 if (metadata.certificate == null) { 211 throw new UnrecoverableKeyException("Failed to obtain X.509 form of public key." 212 + " Keystore has no public certificate stored."); 213 } 214 final byte[] x509PublicCert = metadata.certificate; 215 216 PublicKey publicKey = AndroidKeyStoreSpi.toCertificate(x509PublicCert).getPublicKey(); 217 218 String jcaKeyAlgorithm = publicKey.getAlgorithm(); 219 220 KeyStoreSecurityLevel securityLevel = iSecurityLevel; 221 if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) { 222 223 return new AndroidKeyStoreECPublicKey(descriptor, metadata, 224 iSecurityLevel, (ECPublicKey) publicKey); 225 } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(jcaKeyAlgorithm)) { 226 return new AndroidKeyStoreRSAPublicKey(descriptor, metadata, 227 iSecurityLevel, (RSAPublicKey) publicKey); 228 } else { 229 throw new ProviderException("Unsupported Android Keystore public key algorithm: " 230 + jcaKeyAlgorithm); 231 } 232 } 233 234 /** @hide **/ 235 @NonNull loadAndroidKeyStorePublicKeyFromKeystore( @onNull KeyStore2 keyStore, @NonNull String privateKeyAlias, int namespace)236 public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore( 237 @NonNull KeyStore2 keyStore, @NonNull String privateKeyAlias, int namespace) 238 throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { 239 AndroidKeyStoreKey key = 240 loadAndroidKeyStoreKeyFromKeystore(keyStore, privateKeyAlias, namespace); 241 if (key instanceof AndroidKeyStorePublicKey) { 242 return (AndroidKeyStorePublicKey) key; 243 } else { 244 throw new UnrecoverableKeyException("No asymmetric key found by the given alias."); 245 } 246 } 247 248 /** @hide **/ 249 @NonNull loadAndroidKeyStoreKeyPairFromKeystore( @onNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)250 public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore( 251 @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor) 252 throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { 253 AndroidKeyStoreKey key = 254 loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor); 255 if (key instanceof AndroidKeyStorePublicKey) { 256 AndroidKeyStorePublicKey publicKey = (AndroidKeyStorePublicKey) key; 257 return new KeyPair(publicKey, publicKey.getPrivateKey()); 258 } else { 259 throw new UnrecoverableKeyException("No asymmetric key found by the given alias."); 260 } 261 } 262 263 /** @hide **/ 264 @NonNull loadAndroidKeyStorePrivateKeyFromKeystore( @onNull KeyStore2 keyStore, @NonNull String privateKeyAlias, int namespace)265 public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore( 266 @NonNull KeyStore2 keyStore, @NonNull String privateKeyAlias, int namespace) 267 throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { 268 AndroidKeyStoreKey key = 269 loadAndroidKeyStoreKeyFromKeystore(keyStore, privateKeyAlias, namespace); 270 if (key instanceof AndroidKeyStorePublicKey) { 271 return ((AndroidKeyStorePublicKey) key).getPrivateKey(); 272 } else { 273 throw new UnrecoverableKeyException("No asymmetric key found by the given alias."); 274 } 275 } 276 277 /** @hide **/ 278 @NonNull loadAndroidKeyStoreSecretKeyFromKeystore( @onNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)279 public static SecretKey loadAndroidKeyStoreSecretKeyFromKeystore( 280 @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor) 281 throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { 282 283 AndroidKeyStoreKey key = 284 loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor); 285 if (key instanceof SecretKey) { 286 return (SecretKey) key; 287 } else { 288 throw new UnrecoverableKeyException("No secret key found by the given alias."); 289 } 290 } 291 292 @NonNull makeAndroidKeyStoreSecretKeyFromKeyEntryResponse( @onNull KeyDescriptor descriptor, @NonNull KeyEntryResponse response, int algorithm, int digest)293 private static AndroidKeyStoreSecretKey makeAndroidKeyStoreSecretKeyFromKeyEntryResponse( 294 @NonNull KeyDescriptor descriptor, 295 @NonNull KeyEntryResponse response, int algorithm, int digest) 296 throws UnrecoverableKeyException { 297 @KeyProperties.KeyAlgorithmEnum String keyAlgorithmString; 298 try { 299 keyAlgorithmString = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm( 300 algorithm, digest); 301 } catch (IllegalArgumentException e) { 302 throw (UnrecoverableKeyException) 303 new UnrecoverableKeyException("Unsupported secret key type").initCause(e); 304 } 305 306 return new AndroidKeyStoreSecretKey(descriptor, 307 response.metadata, keyAlgorithmString, 308 new KeyStoreSecurityLevel(response.iSecurityLevel)); 309 } 310 311 /** 312 * Loads an an AndroidKeyStoreKey from the AndroidKeyStore backend. 313 * 314 * @param keyStore The keystore2 backend. 315 * @param alias The alias of the key in the Keystore database. 316 * @param namespace The a Keystore namespace. This is used by system api only to request 317 * Android system specific keystore namespace, which can be configured 318 * in the device's SEPolicy. Third party apps and most system components 319 * set this parameter to -1 to indicate their application specific namespace. 320 * See <a href="https://source.android.com/security/keystore#access-control"> 321 * Keystore 2.0 access control</a> 322 * @hide 323 **/ 324 @NonNull loadAndroidKeyStoreKeyFromKeystore( @onNull KeyStore2 keyStore, @NonNull String alias, int namespace)325 public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore( 326 @NonNull KeyStore2 keyStore, @NonNull String alias, int namespace) 327 throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { 328 KeyDescriptor descriptor = new KeyDescriptor(); 329 if (namespace == KeyProperties.NAMESPACE_APPLICATION) { 330 descriptor.nspace = KeyProperties.NAMESPACE_APPLICATION; // ignored; 331 descriptor.domain = Domain.APP; 332 } else { 333 descriptor.nspace = namespace; 334 descriptor.domain = Domain.SELINUX; 335 } 336 descriptor.alias = alias; 337 descriptor.blob = null; 338 339 final AndroidKeyStoreKey key = loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor); 340 if (key instanceof AndroidKeyStorePublicKey) { 341 return ((AndroidKeyStorePublicKey) key).getPrivateKey(); 342 } else { 343 return key; 344 } 345 } 346 loadAndroidKeyStoreKeyFromKeystore( @onNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)347 private static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore( 348 @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor) 349 throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { 350 KeyEntryResponse response = null; 351 try { 352 response = keyStore.getKeyEntry(descriptor); 353 } catch (android.security.KeyStoreException e) { 354 switch (e.getErrorCode()) { 355 case ResponseCode.KEY_NOT_FOUND: 356 return null; 357 case ResponseCode.KEY_PERMANENTLY_INVALIDATED: 358 throw new KeyPermanentlyInvalidatedException( 359 "User changed or deleted their auth credentials", 360 e); 361 default: 362 throw (UnrecoverableKeyException) 363 new UnrecoverableKeyException("Failed to obtain information about key") 364 .initCause(e); 365 } 366 } 367 368 if (response.iSecurityLevel == null) { 369 // This seems to be a pure certificate entry, nothing to return here. 370 return null; 371 } 372 373 Integer keymasterAlgorithm = null; 374 // We just need one digest for the algorithm name 375 int keymasterDigest = -1; 376 for (Authorization a : response.metadata.authorizations) { 377 switch (a.keyParameter.tag) { 378 case KeymasterDefs.KM_TAG_ALGORITHM: 379 keymasterAlgorithm = a.keyParameter.value.getAlgorithm(); 380 break; 381 case KeymasterDefs.KM_TAG_DIGEST: 382 if (keymasterDigest == -1) keymasterDigest = a.keyParameter.value.getDigest(); 383 break; 384 } 385 } 386 if (keymasterAlgorithm == null) { 387 throw new UnrecoverableKeyException("Key algorithm unknown"); 388 } 389 390 if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC || 391 keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_AES || 392 keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) { 393 return makeAndroidKeyStoreSecretKeyFromKeyEntryResponse(descriptor, response, 394 keymasterAlgorithm, keymasterDigest); 395 } else if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_RSA || 396 keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) { 397 return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata, 398 new KeyStoreSecurityLevel(response.iSecurityLevel), 399 keymasterAlgorithm); 400 } else { 401 throw new UnrecoverableKeyException("Key algorithm unknown"); 402 } 403 } 404 } 405