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