blob: 4c4c8a00c0bd27ca0e296bfeecfb000b37aa51bc [file] [log] [blame]
Kenny Root7e8a8262016-03-18 15:01:39 -07001/*
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
17package libcore.java.security;
18
19import java.io.BufferedReader;
20import java.io.FileReader;
21import java.io.IOException;
Kenny Root562ab6c2016-04-21 15:06:17 -070022import java.lang.reflect.InvocationTargetException;
23import java.lang.reflect.Method;
Kenny Root7e8a8262016-03-18 15:01:39 -070024import java.util.Arrays;
25import java.util.List;
26import java.util.regex.Matcher;
27import java.util.regex.Pattern;
28
Pete Bentley57580fe2018-10-04 14:47:44 +010029import dalvik.system.VMRuntime;
30
Paul Duffin6e8778e2018-12-17 15:30:41 +000031class CpuFeatures {
Kenny Root7e8a8262016-03-18 15:01:39 -070032 private CpuFeatures() {
33 }
34
Pete Bentley57580fe2018-10-04 14:47:44 +010035 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 }
Kenny Root7e8a8262016-03-18 15:01:39 -070056 }
57
Pete Bentley57580fe2018-10-04 14:47:44 +010058 // 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.
Kenny Root562ab6c2016-04-21 15:06:17 -070060 try {
61 Class<?> nativeCrypto = Class.forName("com.android.org.conscrypt.NativeCrypto");
62 Method EVP_has_aes_hardware = nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware");
Adam Vartanian8a2d3342017-08-11 10:06:52 +010063 EVP_has_aes_hardware.setAccessible(true);
Kenny Root562ab6c2016-04-21 15:06:17 -070064 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
Kenny Root7e8a8262016-03-18 15:01:39 -070071 return false;
72 }
73
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
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}