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