1 /* 2 * Copyright (C) 2020 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.hardware.biometrics.BiometricManager; 21 import android.hardware.security.keymint.KeyParameter; 22 import android.hardware.security.keymint.KeyParameterValue; 23 import android.hardware.security.keymint.SecurityLevel; 24 import android.hardware.security.keymint.Tag; 25 import android.security.GateKeeper; 26 import android.security.keymaster.KeymasterDefs; 27 import android.security.keystore.KeyProperties; 28 import android.security.keystore.UserAuthArgs; 29 import android.system.keystore2.Authorization; 30 31 import java.math.BigInteger; 32 import java.security.ProviderException; 33 import java.util.ArrayList; 34 import java.util.Date; 35 import java.util.List; 36 import java.util.function.Consumer; 37 38 /** 39 * @hide 40 */ 41 public abstract class KeyStore2ParameterUtils { 42 43 /** 44 * This function constructs a {@link KeyParameter} expressing a boolean value. 45 * @param tag Must be KeyMint tag with the associated type BOOL. 46 * @return An instance of {@link KeyParameter}. 47 * @hide 48 */ makeBool(int tag)49 static @NonNull KeyParameter makeBool(int tag) { 50 int type = KeymasterDefs.getTagType(tag); 51 if (type != KeymasterDefs.KM_BOOL) { 52 throw new IllegalArgumentException("Not a boolean tag: " + tag); 53 } 54 KeyParameter p = new KeyParameter(); 55 p.tag = tag; 56 p.value = KeyParameterValue.boolValue(true); 57 return p; 58 } 59 60 /** 61 * This function constructs a {@link KeyParameter} expressing an enum value. 62 * @param tag Must be KeyMint tag with the associated type ENUM or ENUM_REP. 63 * @param v A 32bit integer. 64 * @return An instance of {@link KeyParameter}. 65 * @hide 66 */ makeEnum(int tag, int v)67 static @NonNull KeyParameter makeEnum(int tag, int v) { 68 KeyParameter kp = new KeyParameter(); 69 kp.tag = tag; 70 switch (tag) { 71 case Tag.PURPOSE: 72 kp.value = KeyParameterValue.keyPurpose(v); 73 break; 74 case Tag.ALGORITHM: 75 kp.value = KeyParameterValue.algorithm(v); 76 break; 77 case Tag.BLOCK_MODE: 78 kp.value = KeyParameterValue.blockMode(v); 79 break; 80 case Tag.DIGEST: 81 kp.value = KeyParameterValue.digest(v); 82 break; 83 case Tag.EC_CURVE: 84 kp.value = KeyParameterValue.ecCurve(v); 85 break; 86 case Tag.ORIGIN: 87 kp.value = KeyParameterValue.origin(v); 88 break; 89 case Tag.PADDING: 90 kp.value = KeyParameterValue.paddingMode(v); 91 break; 92 case Tag.USER_AUTH_TYPE: 93 kp.value = KeyParameterValue.hardwareAuthenticatorType(v); 94 break; 95 case Tag.HARDWARE_TYPE: 96 kp.value = KeyParameterValue.securityLevel(v); 97 break; 98 default: 99 throw new IllegalArgumentException("Not an enum or repeatable enum tag: " + tag); 100 } 101 return kp; 102 } 103 104 /** 105 * This function constructs a {@link KeyParameter} expressing an integer value. 106 * @param tag Must be KeyMint tag with the associated type UINT or UINT_REP. 107 * @param v A 32bit integer. 108 * @return An instance of {@link KeyParameter}. 109 * @hide 110 */ makeInt(int tag, int v)111 static @NonNull KeyParameter makeInt(int tag, int v) { 112 int type = KeymasterDefs.getTagType(tag); 113 if (type != KeymasterDefs.KM_UINT && type != KeymasterDefs.KM_UINT_REP) { 114 throw new IllegalArgumentException("Not an int or repeatable int tag: " + tag); 115 } 116 KeyParameter p = new KeyParameter(); 117 p.tag = tag; 118 p.value = KeyParameterValue.integer(v); 119 return p; 120 } 121 122 /** 123 * This function constructs a {@link KeyParameter} expressing a long integer value. 124 * @param tag Must be KeyMint tag with the associated type ULONG or ULONG_REP. 125 * @param v A 64bit integer. 126 * @return An instance of {@link KeyParameter}. 127 * @hide 128 */ makeLong(int tag, long v)129 static @NonNull KeyParameter makeLong(int tag, long v) { 130 int type = KeymasterDefs.getTagType(tag); 131 if (type != KeymasterDefs.KM_ULONG && type != KeymasterDefs.KM_ULONG_REP) { 132 throw new IllegalArgumentException("Not a long or repeatable long tag: " + tag); 133 } 134 KeyParameter p = new KeyParameter(); 135 p.tag = tag; 136 p.value = KeyParameterValue.longInteger(v); 137 return p; 138 } 139 140 /** 141 * This function constructs a {@link KeyParameter} expressing a blob. 142 * @param tag Must be KeyMint tag with the associated type BYTES. 143 * @param b A byte array to be stored in the new key parameter. 144 * @return An instance of {@link KeyParameter}. 145 * @hide 146 */ makeBytes(int tag, @NonNull byte[] b)147 static @NonNull KeyParameter makeBytes(int tag, @NonNull byte[] b) { 148 if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BYTES) { 149 throw new IllegalArgumentException("Not a bytes tag: " + tag); 150 } 151 KeyParameter p = new KeyParameter(); 152 p.tag = tag; 153 p.value = KeyParameterValue.blob(b); 154 return p; 155 } 156 157 /** 158 * This function constructs a {@link KeyParameter} expressing a Bignum. 159 * @param tag Must be KeyMint tag with the associated type BIGNUM. 160 * @param b A BitInteger to be stored in the new key parameter. 161 * @return An instance of {@link KeyParameter}. 162 * @hide 163 */ makeBignum(int tag, @NonNull BigInteger b)164 static @NonNull KeyParameter makeBignum(int tag, @NonNull BigInteger b) { 165 if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_BIGNUM) { 166 throw new IllegalArgumentException("Not a bignum tag: " + tag); 167 } 168 KeyParameter p = new KeyParameter(); 169 p.tag = tag; 170 p.value = KeyParameterValue.blob(b.toByteArray()); 171 return p; 172 } 173 174 /** 175 * This function constructs a {@link KeyParameter} expressing date. 176 * @param tag Must be KeyMint tag with the associated type DATE. 177 * @param date A date 178 * @return An instance of {@link KeyParameter}. 179 * @hide 180 */ makeDate(int tag, @NonNull Date date)181 static @NonNull KeyParameter makeDate(int tag, @NonNull Date date) { 182 if (KeymasterDefs.getTagType(tag) != KeymasterDefs.KM_DATE) { 183 throw new IllegalArgumentException("Not a date tag: " + tag); 184 } 185 KeyParameter p = new KeyParameter(); 186 p.tag = tag; 187 p.value = KeyParameterValue.dateTime(date.getTime()); 188 return p; 189 } 190 /** 191 * Returns true if the given security level is TEE or Strongbox. 192 * 193 * @param securityLevel the security level to query 194 * @return truw if the given security level is TEE or Strongbox. 195 */ isSecureHardware(@ecurityLevel int securityLevel)196 static boolean isSecureHardware(@SecurityLevel int securityLevel) { 197 return securityLevel == SecurityLevel.TRUSTED_ENVIRONMENT 198 || securityLevel == SecurityLevel.STRONGBOX; 199 } 200 getUnsignedInt(@onNull Authorization param)201 static long getUnsignedInt(@NonNull Authorization param) { 202 if (KeymasterDefs.getTagType(param.keyParameter.tag) != KeymasterDefs.KM_UINT) { 203 throw new IllegalArgumentException("Not an int tag: " + param.keyParameter.tag); 204 } 205 // KM_UINT is 32 bits wide so we must suppress sign extension. 206 return ((long) param.keyParameter.value.getInteger()) & 0xffffffffL; 207 } 208 getDate(@onNull Authorization param)209 static @NonNull Date getDate(@NonNull Authorization param) { 210 if (KeymasterDefs.getTagType(param.keyParameter.tag) != KeymasterDefs.KM_DATE) { 211 throw new IllegalArgumentException("Not a date tag: " + param.keyParameter.tag); 212 } 213 if (param.keyParameter.value.getDateTime() < 0) { 214 throw new IllegalArgumentException("Date Value too large: " 215 + param.keyParameter.value.getDateTime()); 216 } 217 return new Date(param.keyParameter.value.getDateTime()); 218 } 219 forEachSetFlag(int flags, Consumer<Integer> consumer)220 static void forEachSetFlag(int flags, Consumer<Integer> consumer) { 221 int offset = 0; 222 while (flags != 0) { 223 if ((flags & 1) == 1) { 224 consumer.accept(1 << offset); 225 } 226 offset += 1; 227 flags >>>= 1; 228 } 229 } 230 getRootSid()231 private static long getRootSid() { 232 long rootSid = GateKeeper.getSecureUserId(); 233 if (rootSid == 0) { 234 throw new IllegalStateException("Secure lock screen must be enabled" 235 + " to create keys requiring user authentication"); 236 } 237 return rootSid; 238 } 239 addSids(@onNull List<KeyParameter> params, @NonNull UserAuthArgs spec)240 private static void addSids(@NonNull List<KeyParameter> params, @NonNull UserAuthArgs spec) { 241 // If both biometric and credential are accepted, then just use the root sid from gatekeeper 242 if (spec.getUserAuthenticationType() == (KeyProperties.AUTH_BIOMETRIC_STRONG 243 | KeyProperties.AUTH_DEVICE_CREDENTIAL)) { 244 if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) { 245 params.add(makeLong( 246 KeymasterDefs.KM_TAG_USER_SECURE_ID, 247 spec.getBoundToSpecificSecureUserId() 248 )); 249 } else { 250 // The key is authorized for use for the specified amount of time after the user has 251 // authenticated. Whatever unlocks the secure lock screen should authorize this key. 252 params.add(makeLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, getRootSid())); 253 } 254 } else { 255 List<Long> sids = new ArrayList<>(); 256 if ((spec.getUserAuthenticationType() & KeyProperties.AUTH_BIOMETRIC_STRONG) != 0) { 257 final BiometricManager bm = android.app.AppGlobals.getInitialApplication() 258 .getSystemService(BiometricManager.class); 259 260 // TODO: Restore permission check in getAuthenticatorIds once the ID is no longer 261 // needed here. 262 263 final long[] biometricSids = bm.getAuthenticatorIds(); 264 265 if (biometricSids.length == 0) { 266 throw new IllegalStateException( 267 "At least one biometric must be enrolled to create keys requiring user" 268 + " authentication for every use"); 269 } 270 271 if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) { 272 sids.add(spec.getBoundToSpecificSecureUserId()); 273 } else if (spec.isInvalidatedByBiometricEnrollment()) { 274 // The biometric-only SIDs will change on biometric enrollment or removal of all 275 // enrolled templates, invalidating the key. 276 for (long sid : biometricSids) { 277 sids.add(sid); 278 } 279 } else { 280 // The root SID will *not* change on fingerprint enrollment, or removal of all 281 // enrolled fingerprints, allowing the key to remain valid. 282 sids.add(getRootSid()); 283 } 284 } else if ((spec.getUserAuthenticationType() & KeyProperties.AUTH_DEVICE_CREDENTIAL) 285 != 0) { 286 sids.add(getRootSid()); 287 } else { 288 throw new IllegalStateException("Invalid or no authentication type specified."); 289 } 290 291 for (int i = 0; i < sids.size(); i++) { 292 params.add(makeLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, sids.get(i))); 293 } 294 } 295 } 296 297 /** 298 * Adds keymaster arguments to express the key's authorization policy supported by user 299 * authentication. 300 * 301 * @param args The arguments sent to keymaster that need to be populated from the spec 302 * @param spec The user authentication relevant portions of the spec passed in from the caller. 303 * This spec will be translated into the relevant keymaster tags to be loaded into args. 304 * @throws IllegalStateException if user authentication is required but the system is in a wrong 305 * state (e.g., secure lock screen not set up) for generating or importing keys that 306 * require user authentication. 307 */ addUserAuthArgs(@onNull List<KeyParameter> args, @NonNull UserAuthArgs spec)308 static void addUserAuthArgs(@NonNull List<KeyParameter> args, 309 @NonNull UserAuthArgs spec) { 310 311 if (spec.isUserConfirmationRequired()) { 312 args.add(KeyStore2ParameterUtils.makeBool( 313 KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED)); 314 } 315 if (spec.isUserPresenceRequired()) { 316 args.add(KeyStore2ParameterUtils.makeBool( 317 KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED)); 318 } 319 if (spec.isUnlockedDeviceRequired()) { 320 args.add(KeyStore2ParameterUtils.makeBool( 321 KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED)); 322 } 323 if (!spec.isUserAuthenticationRequired()) { 324 args.add(KeyStore2ParameterUtils.makeBool( 325 KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED)); 326 } else { 327 if (spec.getUserAuthenticationValidityDurationSeconds() == 0) { 328 // Every use of this key needs to be authorized by the user. 329 addSids(args, spec); 330 args.add(KeyStore2ParameterUtils.makeEnum( 331 KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType() 332 )); 333 334 if (spec.isUserAuthenticationValidWhileOnBody()) { 335 throw new ProviderException( 336 "Key validity extension while device is on-body is not " 337 + "supported for keys requiring fingerprint authentication"); 338 } 339 } else { 340 addSids(args, spec); 341 args.add(KeyStore2ParameterUtils.makeEnum( 342 KeymasterDefs.KM_TAG_USER_AUTH_TYPE, spec.getUserAuthenticationType() 343 )); 344 args.add(KeyStore2ParameterUtils.makeInt( 345 KeymasterDefs.KM_TAG_AUTH_TIMEOUT, 346 spec.getUserAuthenticationValidityDurationSeconds() 347 )); 348 if (spec.isUserAuthenticationValidWhileOnBody()) { 349 args.add(KeyStore2ParameterUtils.makeBool( 350 KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY 351 )); 352 } 353 } 354 } 355 } 356 } 357