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.cts;
18 
19 import com.android.compatibility.common.util.CddTest;
20 import com.android.compatibility.common.util.PropertyUtil;
21 
22 import android.platform.test.annotations.AppModeFull;
23 import android.platform.test.annotations.SecurityTest;
24 import android.test.AndroidTestCase;
25 import junit.framework.TestCase;
26 
27 import android.os.Build;
28 import android.util.Log;
29 
30 @SecurityTest
31 public class EncryptionTest extends AndroidTestCase {
32     static {
33         System.loadLibrary("ctssecurity_jni");
34     }
35 
36     private static final int MIN_ENCRYPTION_REQUIRED_API_LEVEL = 23;
37 
38     // First API level where there are no speed exemptions.
39     private static final int MIN_ALL_SPEEDS_API_LEVEL = Build.VERSION_CODES.Q;
40 
41     // First API level at which file based encryption must be used.
42     private static final int MIN_FBE_REQUIRED_API_LEVEL = Build.VERSION_CODES.Q;
43 
44     private static final String TAG = "EncryptionTest";
45 
aesIsFast()46     private static native boolean aesIsFast();
47 
handleUnencryptedDevice()48     private void handleUnencryptedDevice() {
49         if (PropertyUtil.getFirstApiLevel() < MIN_ENCRYPTION_REQUIRED_API_LEVEL) {
50             Log.d(TAG, "Exempt from encryption due to an old starting API level.");
51             return;
52         }
53         // In older API levels, we grant an exemption if AES is not fast enough.
54         if (PropertyUtil.getFirstApiLevel() < MIN_ALL_SPEEDS_API_LEVEL) {
55             // Note: aesIsFast() takes ~2 second to run, so it's worth rearranging
56             //     test logic to delay calling this.
57             if (!aesIsFast()) {
58                 Log.d(TAG, "Exempt from encryption because AES performance is too low.");
59                 return;
60             }
61         }
62         fail("Device encryption is required");
63     }
64 
handleEncryptedDevice()65     private void handleEncryptedDevice() {
66         if ("file".equals(PropertyUtil.getProperty("ro.crypto.type"))) {
67             Log.d(TAG, "Device is encrypted with file-based encryption.");
68             // TODO(b/111311698): If we're able to determine if the hardware
69             //     has AES instructions, confirm that AES, and only AES,
70             //     is in use.  If the hardware does not have AES instructions,
71             //     confirm that either AES or Adiantum is in use.
72             return;
73         }
74         if (PropertyUtil.getFirstApiLevel() < MIN_FBE_REQUIRED_API_LEVEL) {
75             Log.d(TAG, "Device is encrypted.");
76             return;
77         }
78         fail("File-based encryption is required");
79     }
80 
81     // "getprop", used by PropertyUtil.getProperty(), is not executable
82     // to instant apps
83     @AppModeFull
84     @CddTest(requirement="9.9.2/C-0-1,C-0-2,C-0-3")
testEncryption()85     public void testEncryption() throws Exception {
86         if ("encrypted".equals(PropertyUtil.getProperty("ro.crypto.state"))) {
87             handleEncryptedDevice();
88         } else {
89             handleUnencryptedDevice();
90         }
91     }
92 }
93