1 /*
2  * Copyright (C) 2015 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.GateKeeper;
21 import android.security.KeyStore;
22 import android.security.keymaster.KeymasterArguments;
23 import android.security.keymaster.KeymasterDefs;
24 import android.security.keystore.KeyGenParameterSpec;
25 import android.security.keystore.KeyInfo;
26 import android.security.keystore.KeyProperties;
27 import android.system.keystore2.Authorization;
28 
29 import java.math.BigInteger;
30 import java.security.InvalidKeyException;
31 import java.security.ProviderException;
32 import java.security.spec.InvalidKeySpecException;
33 import java.security.spec.KeySpec;
34 import java.util.ArrayList;
35 import java.util.Date;
36 import java.util.List;
37 
38 import javax.crypto.SecretKey;
39 import javax.crypto.SecretKeyFactorySpi;
40 import javax.crypto.spec.SecretKeySpec;
41 
42 /**
43  * {@link SecretKeyFactorySpi} backed by Android Keystore.
44  *
45  * @hide
46  */
47 public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
48 
49     private final KeyStore mKeyStore = KeyStore.getInstance();
50 
51     @Override
engineGetKeySpec(SecretKey key, @SuppressWarnings(R) Class keySpecClass)52     protected KeySpec engineGetKeySpec(SecretKey key,
53             @SuppressWarnings("rawtypes") Class keySpecClass) throws InvalidKeySpecException {
54         if (keySpecClass == null) {
55             throw new InvalidKeySpecException("keySpecClass == null");
56         }
57         if (!(key instanceof AndroidKeyStoreSecretKey)) {
58             throw new InvalidKeySpecException("Only Android KeyStore secret keys supported: " +
59                     ((key != null) ? key.getClass().getName() : "null"));
60         }
61         if (SecretKeySpec.class.isAssignableFrom(keySpecClass)) {
62             throw new InvalidKeySpecException(
63                     "Key material export of Android KeyStore keys is not supported");
64         }
65         if (!KeyInfo.class.equals(keySpecClass)) {
66             throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName());
67         }
68         AndroidKeyStoreKey keystoreKey = (AndroidKeyStoreKey) key;
69 
70         return getKeyInfo(keystoreKey);
71     }
72 
getKeyInfo(@onNull AndroidKeyStoreKey key)73     static @NonNull KeyInfo getKeyInfo(@NonNull AndroidKeyStoreKey key) {
74 
75         @KeyProperties.SecurityLevelEnum int securityLevel =
76                 KeyProperties.SECURITY_LEVEL_SOFTWARE;
77         boolean insideSecureHardware = false;
78         @KeyProperties.OriginEnum int origin = -1;
79         int keySize = -1;
80         @KeyProperties.PurposeEnum int purposes = 0;
81         String[] encryptionPaddings;
82         String[] signaturePaddings;
83         List<String> digestsList = new ArrayList<>();
84         List<String> blockModesList = new ArrayList<>();
85         int keymasterSwEnforcedUserAuthenticators = 0;
86         int keymasterHwEnforcedUserAuthenticators = 0;
87         List<BigInteger> keymasterSecureUserIds = new ArrayList<BigInteger>();
88         List<String> encryptionPaddingsList = new ArrayList<String>();
89         List<String> signaturePaddingsList = new ArrayList<String>();
90         Date keyValidityStart = null;
91         Date keyValidityForOriginationEnd = null;
92         Date keyValidityForConsumptionEnd = null;
93         long userAuthenticationValidityDurationSeconds = 0;
94         boolean userAuthenticationRequired = true;
95         boolean userAuthenticationValidWhileOnBody = false;
96         boolean trustedUserPresenceRequired = false;
97         boolean trustedUserConfirmationRequired = false;
98         int remainingUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT;
99         try {
100             for (Authorization a : key.getAuthorizations()) {
101                 switch (a.keyParameter.tag) {
102                     case KeymasterDefs.KM_TAG_ORIGIN:
103                         insideSecureHardware =
104                                 KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
105                         securityLevel = a.securityLevel;
106                         origin = KeyProperties.Origin.fromKeymaster(
107                                 a.keyParameter.value.getOrigin());
108                         break;
109                     case KeymasterDefs.KM_TAG_KEY_SIZE:
110                         long keySizeUnsigned = KeyStore2ParameterUtils.getUnsignedInt(a);
111                         if (keySizeUnsigned > Integer.MAX_VALUE) {
112                             throw new ProviderException(
113                                     "Key too large: " + keySizeUnsigned + " bits");
114                         }
115                         keySize = (int) keySizeUnsigned;
116                         break;
117                     case KeymasterDefs.KM_TAG_PURPOSE:
118                         purposes |= KeyProperties.Purpose.fromKeymaster(
119                                 a.keyParameter.value.getKeyPurpose());
120                         break;
121                     case KeymasterDefs.KM_TAG_PADDING:
122                         int paddingMode = a.keyParameter.value.getPaddingMode();
123                         try {
124                             if (paddingMode == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN
125                                     || paddingMode == KeymasterDefs.KM_PAD_RSA_PSS) {
126                                 @KeyProperties.SignaturePaddingEnum String padding =
127                                         KeyProperties.SignaturePadding.fromKeymaster(
128                                                 paddingMode);
129                                 signaturePaddingsList.add(padding);
130                             } else {
131                                 @KeyProperties.EncryptionPaddingEnum String jcaPadding =
132                                         KeyProperties.EncryptionPadding.fromKeymaster(
133                                                 paddingMode);
134                                 encryptionPaddingsList.add(jcaPadding);
135                             }
136                         } catch (IllegalArgumentException e) {
137                             throw new ProviderException("Unsupported padding: "
138                                                 + paddingMode);
139                         }
140                         break;
141                     case KeymasterDefs.KM_TAG_DIGEST:
142                         digestsList.add(KeyProperties.Digest.fromKeymaster(
143                                 a.keyParameter.value.getDigest()));
144                         break;
145                     case KeymasterDefs.KM_TAG_BLOCK_MODE:
146                         blockModesList.add(
147                                 KeyProperties.BlockMode.fromKeymaster(
148                                         a.keyParameter.value.getBlockMode())
149                         );
150                         break;
151                     case KeymasterDefs.KM_TAG_USER_AUTH_TYPE:
152                         int authenticatorType = a.keyParameter.value.getHardwareAuthenticatorType();
153                         if (KeyStore2ParameterUtils.isSecureHardware(a.securityLevel)) {
154                             keymasterHwEnforcedUserAuthenticators = authenticatorType;
155                         } else {
156                             keymasterSwEnforcedUserAuthenticators = authenticatorType;
157                         }
158                         break;
159                     case KeymasterDefs.KM_TAG_USER_SECURE_ID:
160                         keymasterSecureUserIds.add(
161                                 KeymasterArguments.toUint64(
162                                         a.keyParameter.value.getLongInteger()));
163                         break;
164                     case KeymasterDefs.KM_TAG_ACTIVE_DATETIME:
165                         keyValidityStart = KeyStore2ParameterUtils.getDate(a);
166                         break;
167                     case KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME:
168                         keyValidityForOriginationEnd =
169                                 KeyStore2ParameterUtils.getDate(a);
170                         break;
171                     case KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME:
172                         keyValidityForConsumptionEnd =
173                                 KeyStore2ParameterUtils.getDate(a);
174                         break;
175                     case KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED:
176                         userAuthenticationRequired = false;
177                         break;
178                     case KeymasterDefs.KM_TAG_AUTH_TIMEOUT:
179                         userAuthenticationValidityDurationSeconds =
180                                 KeyStore2ParameterUtils.getUnsignedInt(a);
181                         if (userAuthenticationValidityDurationSeconds > Integer.MAX_VALUE) {
182                             throw new ProviderException(
183                                     "User authentication timeout validity too long: "
184                                     + userAuthenticationValidityDurationSeconds + " seconds");
185                         }
186                         break;
187                     case KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY:
188                         userAuthenticationValidWhileOnBody =
189                                 KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
190                         break;
191                     case KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
192                         trustedUserPresenceRequired =
193                                 KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
194                         break;
195                     case KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
196                         trustedUserConfirmationRequired =
197                                 KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
198                         break;
199                     case KeymasterDefs.KM_TAG_USAGE_COUNT_LIMIT:
200                         long remainingUsageCountUnsigned =
201                                 KeyStore2ParameterUtils.getUnsignedInt(a);
202                         if (remainingUsageCountUnsigned > Integer.MAX_VALUE) {
203                             throw new ProviderException(
204                                     "Usage count of limited use key too long: "
205                                      + remainingUsageCountUnsigned);
206                         }
207                         remainingUsageCount = (int) remainingUsageCountUnsigned;
208                         break;
209                 }
210             }
211         } catch (IllegalArgumentException e) {
212             throw new ProviderException("Unsupported key characteristic", e);
213         }
214         if (keySize == -1) {
215             throw new ProviderException("Key size not available");
216         }
217         if (origin == -1) {
218             throw new ProviderException("Key origin not available");
219         }
220 
221         encryptionPaddings =
222                 encryptionPaddingsList.toArray(new String[0]);
223         signaturePaddings =
224                 signaturePaddingsList.toArray(new String[0]);
225 
226         boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired)
227                 && (keymasterHwEnforcedUserAuthenticators != 0)
228                 && (keymasterSwEnforcedUserAuthenticators == 0);
229 
230         String[] digests = digestsList.toArray(new String[0]);
231         String[] blockModes = blockModesList.toArray(new String[0]);
232 
233         boolean invalidatedByBiometricEnrollment = false;
234         if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC
235             || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC) {
236             // Fingerprint-only key; will be invalidated if the root SID isn't in the SID list.
237             invalidatedByBiometricEnrollment = !keymasterSecureUserIds.isEmpty()
238                     && !keymasterSecureUserIds.contains(getGateKeeperSecureUserId());
239         }
240 
241         return new KeyInfo(key.getUserKeyDescriptor().alias,
242                 insideSecureHardware,
243                 origin,
244                 keySize,
245                 keyValidityStart,
246                 keyValidityForOriginationEnd,
247                 keyValidityForConsumptionEnd,
248                 purposes,
249                 encryptionPaddings,
250                 signaturePaddings,
251                 digests,
252                 blockModes,
253                 userAuthenticationRequired,
254                 (int) userAuthenticationValidityDurationSeconds,
255                 userAuthenticationRequirementEnforcedBySecureHardware
256                         ? keymasterHwEnforcedUserAuthenticators
257                         : keymasterSwEnforcedUserAuthenticators,
258                 userAuthenticationRequirementEnforcedBySecureHardware,
259                 userAuthenticationValidWhileOnBody,
260                 trustedUserPresenceRequired,
261                 invalidatedByBiometricEnrollment,
262                 trustedUserConfirmationRequired,
263                 securityLevel,
264                 remainingUsageCount);
265     }
266 
getGateKeeperSecureUserId()267     private static BigInteger getGateKeeperSecureUserId() throws ProviderException {
268     	try {
269     		return BigInteger.valueOf(GateKeeper.getSecureUserId());
270     	} catch (IllegalStateException e) {
271     		throw new ProviderException("Failed to get GateKeeper secure user ID", e);
272     	}
273     }
274 
275     @Override
engineGenerateSecret(KeySpec keySpec)276     protected SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException {
277         throw new InvalidKeySpecException(
278                 "To generate secret key in Android Keystore, use KeyGenerator initialized with "
279                         + KeyGenParameterSpec.class.getName());
280     }
281 
282     @Override
engineTranslateKey(SecretKey key)283     protected SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException {
284         if (key == null) {
285             throw new InvalidKeyException("key == null");
286         } else if (!(key instanceof AndroidKeyStoreSecretKey)) {
287             throw new InvalidKeyException(
288                     "To import a secret key into Android Keystore, use KeyStore.setEntry");
289         }
290 
291         return key;
292     }
293 }
294