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 com.android.cts.verifier.biometrics; 18 19 import android.app.AlertDialog; 20 import android.content.Context; 21 import android.content.DialogInterface; 22 import android.security.keystore.KeyGenParameterSpec; 23 import android.security.keystore.KeyProperties; 24 25 import java.security.KeyStore; 26 import java.security.PrivateKey; 27 import java.security.Signature; 28 29 import javax.crypto.Cipher; 30 import javax.crypto.KeyGenerator; 31 import javax.crypto.Mac; 32 import javax.crypto.SecretKey; 33 34 public class Utils { 35 private static final String TAG = "BiometricTestUtils"; 36 createBiometricBoundKey(String keyName, boolean useStrongBox)37 static void createBiometricBoundKey(String keyName, boolean useStrongBox) throws Exception { 38 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 39 keyStore.load(null); 40 KeyGenerator keyGenerator = KeyGenerator.getInstance( 41 KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); 42 43 // Set the alias of the entry in Android KeyStore where the key will appear 44 // and the constrains (purposes) in the constructor of the Builder 45 keyGenerator.init(new KeyGenParameterSpec.Builder(keyName, 46 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 47 .setBlockModes(KeyProperties.BLOCK_MODE_CBC) 48 .setUserAuthenticationRequired(true) 49 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) 50 .setIsStrongBoxBacked(useStrongBox) 51 .setInvalidatedByBiometricEnrollment(true) 52 .build()); 53 keyGenerator.generateKey(); 54 } 55 createTimeBoundSecretKey_deprecated(String keyName, boolean useStrongBox)56 static void createTimeBoundSecretKey_deprecated(String keyName, boolean useStrongBox) 57 throws Exception { 58 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 59 keyStore.load(null); 60 KeyGenerator keyGenerator = KeyGenerator.getInstance( 61 KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); 62 63 // Set the alias of the entry in Android KeyStore where the key will appear 64 // and the constrains (purposes) in the constructor of the Builder 65 keyGenerator.init(new KeyGenParameterSpec.Builder(keyName, 66 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) 67 .setBlockModes(KeyProperties.BLOCK_MODE_CBC) 68 .setUserAuthenticationRequired(true) 69 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) 70 .setIsStrongBoxBacked(useStrongBox) 71 .setUserAuthenticationValidityDurationSeconds(5 /* seconds */) 72 .build()); 73 keyGenerator.generateKey(); 74 } 75 initCipher(String keyName)76 static Cipher initCipher(String keyName) throws Exception { 77 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 78 keyStore.load(null); 79 SecretKey secretKey = (SecretKey) keyStore.getKey(keyName, null); 80 81 Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" 82 + KeyProperties.BLOCK_MODE_CBC + "/" 83 + KeyProperties.ENCRYPTION_PADDING_PKCS7); 84 cipher.init(Cipher.ENCRYPT_MODE, secretKey); 85 return cipher; 86 } 87 initAeadCipher(String keyName)88 static Cipher initAeadCipher(String keyName) throws Exception { 89 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 90 keyStore.load(null); 91 SecretKey secretKey = (SecretKey) keyStore.getKey(keyName, null); 92 93 Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" 94 + KeyProperties.BLOCK_MODE_GCM + "/" 95 + KeyProperties.ENCRYPTION_PADDING_NONE); 96 cipher.init(Cipher.ENCRYPT_MODE, secretKey); 97 return cipher; 98 } 99 initSignature(String keyName)100 static Signature initSignature(String keyName) throws Exception { 101 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 102 keyStore.load(null); 103 104 KeyStore.Entry entry = keyStore.getEntry(keyName, null); 105 106 PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); 107 108 // TODO: This can be used to verify signature 109 // PublicKey publicKey = keyStore.getCertificate(keyName).getPublicKey(); 110 111 Signature signature = Signature.getInstance("SHA256withECDSA"); 112 signature.initSign(privateKey); 113 return signature; 114 } 115 initMac(String keyName)116 static Mac initMac(String keyName) throws Exception { 117 KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); 118 keyStore.load(null); 119 120 SecretKey secretKey = (SecretKey) keyStore.getKey(keyName, null); 121 122 Mac mac = Mac.getInstance("HmacSHA256"); 123 mac.init(secretKey); 124 return mac; 125 } 126 doEncrypt(Cipher cipher, byte[] data)127 static byte[] doEncrypt(Cipher cipher, byte[] data) throws Exception { 128 return cipher.doFinal(data); 129 } 130 doSign(Signature signature, byte[] data)131 static byte[] doSign(Signature signature, byte[] data) throws Exception { 132 signature.update(data); 133 return signature.sign(); 134 } 135 showInstructionDialog(Context context, int titleRes, int messageRes, int positiveButtonRes, DialogInterface.OnClickListener listener)136 static void showInstructionDialog(Context context, int titleRes, int messageRes, 137 int positiveButtonRes, DialogInterface.OnClickListener listener) { 138 AlertDialog.Builder builder = new AlertDialog.Builder(context); 139 builder.setTitle(titleRes); 140 builder.setMessage(messageRes); 141 builder.setPositiveButton(positiveButtonRes, listener); 142 AlertDialog dialog = builder.create(); 143 dialog.show(); 144 } 145 } 146