1cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin/* 2cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * Copyright (C) 2015 The Android Open Source Project 3cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * 4cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * Licensed under the Apache License, Version 2.0 (the "License"); 5cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * you may not use this file except in compliance with the License. 6cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * You may obtain a copy of the License at 7cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * 8cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * http://www.apache.org/licenses/LICENSE-2.0 9cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * 10cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * Unless required by applicable law or agreed to in writing, software 11cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * distributed under the License is distributed on an "AS IS" BASIS, 12cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * See the License for the specific language governing permissions and 14cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin * limitations under the License. 15cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin */ 16cc21bb3a56915842b545a577d3481047005b1764Alex Klyubin 17dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinpackage android.security.keystore; 18acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 19dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinimport android.security.Credentials; 20c38eae5229a820966008ae1885af90cd27c265e7Shawn Willdenimport android.security.GateKeeper; 21dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinimport android.security.KeyStore; 22acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport android.security.keymaster.KeyCharacteristics; 23acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport android.security.keymaster.KeymasterDefs; 24acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 25c38eae5229a820966008ae1885af90cd27c265e7Shawn Willdenimport java.math.BigInteger; 26acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport java.security.InvalidKeyException; 2797a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubinimport java.security.ProviderException; 28acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport java.security.spec.InvalidKeySpecException; 29acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport java.security.spec.KeySpec; 305927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubinimport java.util.ArrayList; 315045b7189cf1bae19c25efa7fb0c5f33ea1422ceAlex Klyubinimport java.util.Date; 325927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubinimport java.util.List; 33acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 34acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport javax.crypto.SecretKey; 35acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport javax.crypto.SecretKeyFactorySpi; 36acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubinimport javax.crypto.spec.SecretKeySpec; 37acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 38acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin/** 3997a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin * {@link SecretKeyFactorySpi} backed by Android Keystore. 40acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin * 41acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin * @hide 42acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin */ 43dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinpublic class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { 44acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 45acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin private final KeyStore mKeyStore = KeyStore.getInstance(); 46acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 47acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin @Override 48acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin protected KeySpec engineGetKeySpec(SecretKey key, 49acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin @SuppressWarnings("rawtypes") Class keySpecClass) throws InvalidKeySpecException { 50acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin if (keySpecClass == null) { 51acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin throw new InvalidKeySpecException("keySpecClass == null"); 52acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 53dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubin if (!(key instanceof AndroidKeyStoreSecretKey)) { 54acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin throw new InvalidKeySpecException("Only Android KeyStore secret keys supported: " + 55acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin ((key != null) ? key.getClass().getName() : "null")); 56acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 57acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin if (SecretKeySpec.class.isAssignableFrom(keySpecClass)) { 58acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin throw new InvalidKeySpecException( 59acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin "Key material export of Android KeyStore keys is not supported"); 60acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 613f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin if (!KeyInfo.class.equals(keySpecClass)) { 62acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName()); 63acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 643876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin AndroidKeyStoreKey keystoreKey = (AndroidKeyStoreKey) key; 653876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin String keyAliasInKeystore = keystoreKey.getAlias(); 66acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin String entryAlias; 67acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin if (keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) { 68acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin entryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length()); 69acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } else { 70acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore); 71acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 72acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 733876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin return getKeyInfo(mKeyStore, entryAlias, keyAliasInKeystore, keystoreKey.getUid()); 7497a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin } 7597a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin 763876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin static KeyInfo getKeyInfo(KeyStore keyStore, String entryAlias, String keyAliasInKeystore, 773876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin int keyUid) { 78acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); 793876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin int errorCode = keyStore.getKeyCharacteristics( 803876b1be27e3aefde9a72eb2e4f856e94fc5f946Alex Klyubin keyAliasInKeystore, null, null, keyUid, keyCharacteristics); 81acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin if (errorCode != KeyStore.NO_ERROR) { 8297a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin throw new ProviderException("Failed to obtain information about key." 83acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin + " Keystore error: " + errorCode); 84acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 85acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 86eae1da7788f0f9f37fa142a2df34bfaec1f4253eAlex Klyubin boolean insideSecureHardware; 873f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin @KeyProperties.OriginEnum int origin; 88acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin int keySize; 893f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin @KeyProperties.PurposeEnum int purposes; 905927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin String[] encryptionPaddings; 9197a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin String[] signaturePaddings; 923f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin @KeyProperties.DigestEnum String[] digests; 933f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin @KeyProperties.BlockModeEnum String[] blockModes; 941eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin int keymasterSwEnforcedUserAuthenticators; 951eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin int keymasterHwEnforcedUserAuthenticators; 96c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden List<BigInteger> keymasterSecureUserIds; 97acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin try { 98b503c52f07ff658b9192411580151eb746408d5aAlex Klyubin if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) { 99eae1da7788f0f9f37fa142a2df34bfaec1f4253eAlex Klyubin insideSecureHardware = true; 1003f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin origin = KeyProperties.Origin.fromKeymaster( 101ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1)); 102b503c52f07ff658b9192411580151eb746408d5aAlex Klyubin } else if (keyCharacteristics.swEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) { 103eae1da7788f0f9f37fa142a2df34bfaec1f4253eAlex Klyubin insideSecureHardware = false; 1043f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin origin = KeyProperties.Origin.fromKeymaster( 105ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1)); 106b503c52f07ff658b9192411580151eb746408d5aAlex Klyubin } else { 10797a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin throw new ProviderException("Key origin not available"); 108acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 109ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin long keySizeUnsigned = 110ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1); 111ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (keySizeUnsigned == -1) { 11297a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin throw new ProviderException("Key size not available"); 113ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } else if (keySizeUnsigned > Integer.MAX_VALUE) { 114ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new ProviderException("Key too large: " + keySizeUnsigned + " bits"); 115acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 116ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keySize = (int) keySizeUnsigned; 1173f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin purposes = KeyProperties.Purpose.allFromKeymaster( 118ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PURPOSE)); 1195927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin 1205927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin List<String> encryptionPaddingsList = new ArrayList<String>(); 12197a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin List<String> signaturePaddingsList = new ArrayList<String>(); 12297a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin // Keymaster stores both types of paddings in the same array -- we split it into two. 123ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin for (int keymasterPadding : keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PADDING)) { 1245927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin try { 12597a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin @KeyProperties.EncryptionPaddingEnum String jcaPadding = 12697a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding); 12797a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin encryptionPaddingsList.add(jcaPadding); 1285927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin } catch (IllegalArgumentException e) { 12997a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin try { 13097a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin @KeyProperties.SignaturePaddingEnum String padding = 13197a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin KeyProperties.SignaturePadding.fromKeymaster(keymasterPadding); 13297a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin signaturePaddingsList.add(padding); 13397a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin } catch (IllegalArgumentException e2) { 13497a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin throw new ProviderException( 13597a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin "Unsupported encryption padding: " + keymasterPadding); 13697a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin } 1375927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin } 13897a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin 139acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 1405927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin encryptionPaddings = 1415927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin encryptionPaddingsList.toArray(new String[encryptionPaddingsList.size()]); 14297a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin signaturePaddings = 14397a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin signaturePaddingsList.toArray(new String[signaturePaddingsList.size()]); 1445927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin 1453f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin digests = KeyProperties.Digest.allFromKeymaster( 146ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_DIGEST)); 1473f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin blockModes = KeyProperties.BlockMode.allFromKeymaster( 148ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_BLOCK_MODE)); 1491eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin keymasterSwEnforcedUserAuthenticators = 150ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); 1511eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin keymasterHwEnforcedUserAuthenticators = 152ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); 153c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden keymasterSecureUserIds = 154c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID); 155acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } catch (IllegalArgumentException e) { 15697a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin throw new ProviderException("Unsupported key characteristic", e); 157acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 158acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 1595927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin Date keyValidityStart = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME); 1605927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin Date keyValidityForOriginationEnd = 1615927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME); 1625927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin Date keyValidityForConsumptionEnd = 1635927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin keyCharacteristics.getDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME); 1641eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin boolean userAuthenticationRequired = 1651eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); 166ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin long userAuthenticationValidityDurationSeconds = 167ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1); 168ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin if (userAuthenticationValidityDurationSeconds > Integer.MAX_VALUE) { 169ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin throw new ProviderException("User authentication timeout validity too long: " 170ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin + userAuthenticationValidityDurationSeconds + " seconds"); 171ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin } 172eae1da7788f0f9f37fa142a2df34bfaec1f4253eAlex Klyubin boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired) 1731eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin && (keymasterHwEnforcedUserAuthenticators != 0) 1741eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin && (keymasterSwEnforcedUserAuthenticators == 0); 175adef49640d6339e6b4a6ad736c5815e35d9b8803Shawn Willden boolean userAuthenticationValidWhileOnBody = 176adef49640d6339e6b4a6ad736c5815e35d9b8803Shawn Willden keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY); 1772ea13d42689ab10456a575772d069c91ae9b6075Alex Klyubin 178c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden boolean invalidatedByBiometricEnrollment = false; 179c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT 180c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT) { 181c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden // Fingerprint-only key; will be invalidated if the root SID isn't in the SID list. 182c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden invalidatedByBiometricEnrollment = keymasterSecureUserIds != null 183c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden && !keymasterSecureUserIds.isEmpty() 184c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden && !keymasterSecureUserIds.contains(getGateKeeperSecureUserId()); 185c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden } 186c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden 1873f8d4d840894468f2be8a5b56ff266cef2d71c50Alex Klyubin return new KeyInfo(entryAlias, 188eae1da7788f0f9f37fa142a2df34bfaec1f4253eAlex Klyubin insideSecureHardware, 189acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin origin, 190acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin keySize, 1915045b7189cf1bae19c25efa7fb0c5f33ea1422ceAlex Klyubin keyValidityStart, 1925045b7189cf1bae19c25efa7fb0c5f33ea1422ceAlex Klyubin keyValidityForOriginationEnd, 1935045b7189cf1bae19c25efa7fb0c5f33ea1422ceAlex Klyubin keyValidityForConsumptionEnd, 194acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin purposes, 1955927c9f1b12f597839a664c1c6593114175cbcd8Alex Klyubin encryptionPaddings, 19697a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin signaturePaddings, 197c46e9e7da4558f6bc99262361fd1ca35c3a44090Alex Klyubin digests, 198c46e9e7da4558f6bc99262361fd1ca35c3a44090Alex Klyubin blockModes, 1991eda77ae2122e2b85084eb429fbeecec0b9962e5Alex Klyubin userAuthenticationRequired, 200ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin (int) userAuthenticationValidityDurationSeconds, 201adef49640d6339e6b4a6ad736c5815e35d9b8803Shawn Willden userAuthenticationRequirementEnforcedBySecureHardware, 202c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden userAuthenticationValidWhileOnBody, 203c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden invalidatedByBiometricEnrollment); 204c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden } 205c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden 206c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden private static BigInteger getGateKeeperSecureUserId() throws ProviderException { 207c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden try { 208c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden return BigInteger.valueOf(GateKeeper.getSecureUserId()); 209c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden } catch (IllegalStateException e) { 210c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden throw new ProviderException("Failed to get GateKeeper secure user ID", e); 211c38eae5229a820966008ae1885af90cd27c265e7Shawn Willden } 212acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 213acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 214acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin @Override 215acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin protected SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException { 2166f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin throw new InvalidKeySpecException( 2176f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin "To generate secret key in Android Keystore, use KeyGenerator initialized with " 21897a27a73e6c5f5800303596ceebf314d90429d35Alex Klyubin + KeyGenParameterSpec.class.getName()); 219acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 220acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin 221acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin @Override 222acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin protected SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException { 2236f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin if (key == null) { 2246f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin throw new InvalidKeyException("key == null"); 2256f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin } else if (!(key instanceof AndroidKeyStoreSecretKey)) { 2266f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin throw new InvalidKeyException( 2276f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin "To import a secret key into Android Keystore, use KeyStore.setEntry"); 2286f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin } 2296f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin 2306f2eb6d7a642b842976f5eeac2733b6f7e128711Alex Klyubin return key; 231acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin } 232acc835f3857c1a1bf2618fabb7307794aba5d76aAlex Klyubin} 233