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.app.ActivityThread; 20 import android.hardware.biometrics.BiometricManager; 21 import android.hardware.security.keymint.ErrorCode; 22 import android.security.GateKeeper; 23 import android.security.KeyStore; 24 import android.security.KeyStoreException; 25 import android.security.KeyStoreOperation; 26 import android.security.keymaster.KeymasterDefs; 27 import android.security.keystore.KeyExpiredException; 28 import android.security.keystore.KeyNotYetValidException; 29 import android.security.keystore.KeyPermanentlyInvalidatedException; 30 import android.security.keystore.UserNotAuthenticatedException; 31 import android.system.keystore2.Authorization; 32 import android.system.keystore2.ResponseCode; 33 import android.util.Log; 34 35 import libcore.util.EmptyArray; 36 37 import java.security.GeneralSecurityException; 38 import java.security.InvalidAlgorithmParameterException; 39 import java.security.InvalidKeyException; 40 import java.security.SecureRandom; 41 import java.util.ArrayList; 42 import java.util.List; 43 import java.util.Random; 44 45 /** 46 * Assorted utility methods for implementing crypto operations on top of KeyStore. 47 * 48 * @hide 49 */ 50 abstract class KeyStoreCryptoOperationUtils { 51 52 private static volatile SecureRandom sRng; 53 private static final Random sRandom = new Random(); 54 KeyStoreCryptoOperationUtils()55 private KeyStoreCryptoOperationUtils() {} 56 57 canUserAuthorizationSucceed(AndroidKeyStoreKey key)58 public static boolean canUserAuthorizationSucceed(AndroidKeyStoreKey key) { 59 List<Long> keySids = new ArrayList<Long>(); 60 for (Authorization p : key.getAuthorizations()) { 61 switch(p.keyParameter.tag) { 62 case KeymasterDefs.KM_TAG_USER_SECURE_ID: 63 keySids.add(p.keyParameter.value.getLongInteger()); 64 break; 65 default: 66 break; 67 } 68 } 69 if (keySids.isEmpty()) { 70 // Key is not bound to any SIDs -- no amount of authentication will help here. 71 return false; 72 } 73 long rootSid = GateKeeper.getSecureUserId(); 74 if ((rootSid != 0) && (keySids.contains(rootSid))) { 75 // One of the key's SIDs is the current root SID -- user can be authenticated 76 // against that SID. 77 return true; 78 } 79 80 long[] biometricSids = ActivityThread 81 .currentApplication() 82 .getSystemService(BiometricManager.class) 83 .getAuthenticatorIds(); 84 85 // The key must contain every biometric SID. This is because the current API surface 86 // treats all biometrics (capable of keystore integration) equally. e.g. if the 87 // device has multiple keystore-capable sensors, and one of the sensor's SIDs 88 // changed, 1) there is no way for a developer to specify authentication with a 89 // specific sensor (the one that hasn't changed), and 2) currently the only 90 // signal to developers is the UserNotAuthenticatedException, which doesn't 91 // indicate a specific sensor. 92 boolean canUnlockViaBiometrics = biometricSids.length > 0; 93 for (long sid : biometricSids) { 94 if (!keySids.contains(sid)) { 95 canUnlockViaBiometrics = false; 96 break; 97 } 98 } 99 100 if (canUnlockViaBiometrics) { 101 // All of the biometric SIDs are contained in the key's SIDs. 102 return true; 103 } 104 105 // None of the key's SIDs can ever be authenticated 106 return false; 107 } 108 109 /** 110 * Returns an {@link InvalidKeyException} corresponding to the provided 111 * {@link KeyStoreException}. 112 */ getInvalidKeyException( AndroidKeyStoreKey key, KeyStoreException e)113 public static InvalidKeyException getInvalidKeyException( 114 AndroidKeyStoreKey key, KeyStoreException e) { 115 switch (e.getErrorCode()) { 116 case KeymasterDefs.KM_ERROR_KEY_EXPIRED: 117 return new KeyExpiredException(); 118 case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: 119 return new KeyNotYetValidException(); 120 case ResponseCode.KEY_NOT_FOUND: 121 // TODO is this the right exception in this case? 122 case ResponseCode.KEY_PERMANENTLY_INVALIDATED: 123 return new KeyPermanentlyInvalidatedException(); 124 case ResponseCode.LOCKED: 125 case ResponseCode.UNINITIALIZED: 126 case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: 127 // TODO b/173111727 remove response codes LOCKED and UNINITIALIZED 128 return new UserNotAuthenticatedException(); 129 default: 130 return new InvalidKeyException("Keystore operation failed", e); 131 } 132 } 133 134 /** 135 * Returns the exception to be thrown by the {@code Cipher.init} method of the crypto operation 136 * in response to {@code KeyStore.begin} operation or {@code null} if the {@code init} method 137 * should succeed. 138 */ getExceptionForCipherInit( AndroidKeyStoreKey key, KeyStoreException e)139 public static GeneralSecurityException getExceptionForCipherInit( 140 AndroidKeyStoreKey key, KeyStoreException e) { 141 if (e.getErrorCode() == KeyStore.NO_ERROR) { 142 return null; 143 } 144 145 // Cipher-specific cases 146 switch (e.getErrorCode()) { 147 case KeymasterDefs.KM_ERROR_INVALID_NONCE: 148 return new InvalidAlgorithmParameterException("Invalid IV"); 149 case KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED: 150 return new InvalidAlgorithmParameterException("Caller-provided IV not permitted"); 151 } 152 153 // General cases 154 return getInvalidKeyException(key, e); 155 } 156 157 /** 158 * Returns the requested number of random bytes to mix into keystore/keymaster RNG. 159 * 160 * @param rng RNG from which to obtain the random bytes or {@code null} for the platform-default 161 * RNG. 162 */ getRandomBytesToMixIntoKeystoreRng(SecureRandom rng, int sizeBytes)163 static byte[] getRandomBytesToMixIntoKeystoreRng(SecureRandom rng, int sizeBytes) { 164 if (sizeBytes <= 0) { 165 return EmptyArray.BYTE; 166 } 167 if (rng == null) { 168 rng = getRng(); 169 } 170 byte[] result = new byte[sizeBytes]; 171 rng.nextBytes(result); 172 return result; 173 } 174 getRng()175 private static SecureRandom getRng() { 176 // IMPLEMENTATION NOTE: It's OK to share a SecureRandom instance because SecureRandom is 177 // required to be thread-safe. 178 if (sRng == null) { 179 sRng = new SecureRandom(); 180 } 181 return sRng; 182 } 183 abortOperation(KeyStoreOperation operation)184 static void abortOperation(KeyStoreOperation operation) { 185 if (operation != null) { 186 try { 187 operation.abort(); 188 } catch (KeyStoreException e) { 189 // Invalid operation handle is very common at this point. It occurs every time 190 // an already finalized operation gets aborted. 191 if (e.getErrorCode() != ErrorCode.INVALID_OPERATION_HANDLE) { 192 // This error gets logged but ignored. Dropping the reference 193 // to the KeyStoreOperation is enough to clean up all related resources even 194 // in the Keystore daemon. It gets logged anyway, because it may indicate some 195 // underlying problem that is worth debugging. 196 Log.w( 197 "KeyStoreCryptoOperationUtils", 198 "Encountered error trying to abort a keystore operation.", 199 e 200 ); 201 } 202 } 203 } 204 } 205 getOrMakeOperationChallenge(KeyStoreOperation operation, AndroidKeyStoreKey key)206 static long getOrMakeOperationChallenge(KeyStoreOperation operation, AndroidKeyStoreKey key) 207 throws KeyPermanentlyInvalidatedException { 208 if (operation.getChallenge() != null) { 209 if (!KeyStoreCryptoOperationUtils.canUserAuthorizationSucceed(key)) { 210 throw new KeyPermanentlyInvalidatedException(); 211 } 212 return operation.getChallenge(); 213 } else { 214 // Keystore won't give us an operation challenge if the operation doesn't 215 // need user authorization. So we make our own. 216 return sRandom.nextLong(); 217 } 218 } 219 } 220