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