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