1 /*
2  * Copyright (C) 2019 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.authboundkeyapp;
18 
19 import static junit.framework.Assert.assertFalse;
20 
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.fail;
25 
26 import android.content.BroadcastReceiver;
27 import android.content.Context;
28 import android.security.keystore.KeyGenParameterSpec;
29 import android.security.keystore.KeyInfo;
30 import android.security.keystore.KeyPermanentlyInvalidatedException;
31 import android.security.keystore.KeyProperties;
32 import android.test.AndroidTestCase;
33 import android.test.MoreAsserts;
34 import android.util.Log;
35 
36 import java.security.KeyPair;
37 import java.security.KeyPairGenerator;
38 import java.security.KeyStore;
39 import java.security.PrivateKey;
40 import java.security.UnrecoverableKeyException;
41 
42 import javax.crypto.Cipher;
43 import javax.crypto.KeyGenerator;
44 import javax.crypto.SecretKey;
45 import javax.crypto.SecretKeyFactory;
46 
47 public class AuthBoundKeyAppTest extends AndroidTestCase {
48     private static final String KEY_NAME = "nice_key";
49     private static final String KEYSTORE = "AndroidKeyStore";
testGenerateAuthBoundKey()50     public void testGenerateAuthBoundKey() throws Exception {
51         KeyStore keyStore = KeyStore.getInstance(KEYSTORE);
52         keyStore.load(null);
53         KeyGenerator keyGenerator = KeyGenerator.getInstance(
54                 KeyProperties.KEY_ALGORITHM_AES, KEYSTORE);
55         KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(
56                         KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
57                         .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
58                         .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
59                         .setUserAuthenticationRequired(true)
60                         .setUserAuthenticationParameters(0, KeyProperties.AUTH_DEVICE_CREDENTIAL)
61                         .build();
62         assertEquals(spec.getUserAuthenticationType(), KeyProperties.AUTH_DEVICE_CREDENTIAL);
63         keyGenerator.init(spec);
64         SecretKey key = keyGenerator.generateKey();
65         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(key.getAlgorithm(),
66                                                                    "AndroidKeyStore");
67         KeyInfo info = (KeyInfo) keyFactory.getKeySpec(key, KeyInfo.class);
68         assertEquals(0, info.getUserAuthenticationValidityDurationSeconds());
69         assertEquals(KeyProperties.AUTH_DEVICE_CREDENTIAL, info.getUserAuthenticationType());
70     }
71 
testUseKey()72     public void testUseKey() throws Exception {
73         KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
74         keyStore.load(null);
75         try {
76             SecretKey secretKey = (SecretKey) keyStore.getKey(KEY_NAME, null);
77 	    // This test verifies that the given key is no longer usable after removing the LSKF.
78             // In Keystore 2.0 we don't keep invalidated keys around. So we cannot diagnose that
79             // a key was invalidated. It simply does not exist. Thus we expect null.
80 	    // An UnrecoverableKeyException is also acceptable (see below) and was the typical
81 	    // behavior for Keystore 1.0.
82             if (secretKey == null) return;
83         } catch (UnrecoverableKeyException e) {
84             return;
85         }
86         fail("Expected an UnrecoverableKeyException or null");
87     }
88 
89 }
90