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