• 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 static java.nio.charset.StandardCharsets.UTF_8;
20 
21 import java.io.BufferedReader;
22 import java.io.FileReader;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 
32 public class CpuFeatures {
CpuFeatures()33     private CpuFeatures() {}
34 
isAESHardwareAccelerated()35     public static boolean isAESHardwareAccelerated() {
36         List<String> features = getListFromCpuinfo("Features");
37         if (features != null && features.contains("aes")) {
38             return true;
39         }
40 
41         List<String> flags = getListFromCpuinfo("flags");
42         if (flags != null && flags.contains("aes")) {
43             return true;
44         }
45 
46         features = getCpuFeaturesMac();
47         if (features != null && features.contains("aes")) {
48             return true;
49         }
50 
51         // If we're in an emulated ABI, Conscrypt's NativeCrypto might bridge to
52         // a library that has accelerated AES instructions. See if Conscrypt
53         // detects that condition.
54         Class<?> nativeCrypto = findNativeCrypto();
55         if (nativeCrypto != null) {
56             try {
57                 Method EVP_has_aes_hardware =
58                         nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware");
59                 EVP_has_aes_hardware.setAccessible(true);
60                 return ((Integer) EVP_has_aes_hardware.invoke(null)) == 1;
61             } catch (NoSuchMethodException | SecurityException | IllegalAccessException
62                     | IllegalArgumentException ignored) {
63             } catch (InvocationTargetException e) {
64                 throw new IllegalArgumentException(e);
65             }
66         }
67 
68         return false;
69     }
70 
findNativeCrypto()71     private static Class<?> findNativeCrypto() {
72         for (String packageName : new String[]{"com.android.org.conscrypt", "org.conscrypt"}) {
73             String name = packageName + ".NativeCrypto";
74             try {
75                 return Class.forName(name);
76             } catch (ClassNotFoundException e) {
77                 // Try the next one.
78             }
79         }
80         return null;
81     }
82 
getFieldFromCpuinfo(String field)83     private static String getFieldFromCpuinfo(String field) {
84         try {
85             @SuppressWarnings("DefaultCharset")
86             BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"));
87             Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)");
88 
89             try {
90                 String line;
91                 while ((line = br.readLine()) != null) {
92                     Matcher m = p.matcher(line);
93                     if (m.matches()) {
94                         return m.group(1);
95                     }
96                 }
97             } finally {
98                 br.close();
99             }
100         } catch (IOException ignored) {
101             // Ignored.
102         }
103 
104         return null;
105     }
106 
getListFromCpuinfo(String fieldName)107     private static List<String> getListFromCpuinfo(String fieldName) {
108         String features = getFieldFromCpuinfo(fieldName);
109         if (features == null)
110             return null;
111 
112         return Arrays.asList(features.split("\\s"));
113     }
114 
getCpuFeaturesMac()115     private static List<String> getCpuFeaturesMac() {
116         try {
117             StringBuilder output = new StringBuilder();
118             Process proc = Runtime.getRuntime().exec("sysctl -a");
119             if (proc.waitFor() == 0) {
120                 BufferedReader reader =
121                         new BufferedReader(new InputStreamReader(proc.getInputStream(), UTF_8));
122 
123                 final String linePrefix = "machdep.cpu.features:";
124 
125                 String line;
126                 while ((line = reader.readLine()) != null) {
127                     line = line.toLowerCase();
128                     if (line.startsWith(linePrefix)) {
129                         // Strip the line prefix from the results.
130                         output.append(line.substring(linePrefix.length())).append(' ');
131                     }
132                 }
133                 if (output.length() > 0) {
134                     String outputString = output.toString();
135                     String[] parts = outputString.split("\\s+");
136                     return Arrays.asList(parts);
137                 }
138             }
139         } catch (Exception ignored) {
140             // Ignored.
141         }
142 
143         return null;
144     }
145 }
146