• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 libcore.java.security;
18 
19 import java.io.BufferedReader;
20 import java.io.FileReader;
21 import java.io.IOException;
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.Arrays;
25 import java.util.List;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28 
29 import dalvik.system.VMRuntime;
30 
31 class CpuFeatures {
CpuFeatures()32     private CpuFeatures() {
33     }
34 
isAESHardwareAccelerated()35     static boolean isAESHardwareAccelerated() {
36         // Expectations based on CPU type: If these aren't met then Conscrypt
37         // integration tests will fail and the cause should be investigated.
38         String instructionSet = VMRuntime.getCurrentInstructionSet();
39         if (instructionSet.startsWith("arm")) {
40             // All ARM CPUs with the "aes" feature should have hardware AES.
41             List<String> features = getListFromCpuinfo("Features");
42             if (features != null && features.contains("aes")) {
43                 return true;
44             }
45         } else if (instructionSet.startsWith("x86")) {
46             // x86 CPUs with the "aes" flag and running in 64bit mode should have hardware AES.
47             if (VMRuntime.is64BitInstructionSet(instructionSet)) {
48                 List<String> flags = getListFromCpuinfo("flags");
49                 if (flags != null && flags.contains("aes")) {
50                     return true;
51                 }
52             } else {
53                 // Hardware AES not supported in 32bit mode.
54                 return false;
55             }
56         }
57 
58         // Otherwise trust Conscrypt NativeCrypto's own checks, for example if we're in an
59         // emulated ABI, it might bridge to a library that has accelerated AES instructions.
60         try {
61             Class<?> nativeCrypto = Class.forName("com.android.org.conscrypt.NativeCrypto");
62             Method EVP_has_aes_hardware = nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware");
63             EVP_has_aes_hardware.setAccessible(true);
64             return ((Integer) EVP_has_aes_hardware.invoke(null)) == 1;
65         } catch (ClassNotFoundException | NoSuchMethodException | SecurityException
66                 | IllegalAccessException | IllegalArgumentException ignored) {
67         } catch (InvocationTargetException e) {
68             throw new IllegalArgumentException(e);
69         }
70 
71         return false;
72     }
73 
getFieldFromCpuinfo(String field)74     private static String getFieldFromCpuinfo(String field) {
75         try {
76             BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"));
77             Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)");
78 
79             try {
80                 String line;
81                 while ((line = br.readLine()) != null) {
82                     Matcher m = p.matcher(line);
83                     if (m.matches()) {
84                         return m.group(1);
85                     }
86                 }
87             } finally {
88                 br.close();
89             }
90         } catch (IOException ignored) {
91         }
92 
93         return null;
94     }
95 
getListFromCpuinfo(String fieldName)96     private static List<String> getListFromCpuinfo(String fieldName) {
97         String features = getFieldFromCpuinfo(fieldName);
98         if (features == null)
99             return null;
100 
101         return Arrays.asList(features.split("\\s"));
102     }
103 }
104