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