11864f965419c5b14ac9317c576c8a0f7169c067enmittler/* 21864f965419c5b14ac9317c576c8a0f7169c067enmittler * Copyright 2016 The Android Open Source Project 31864f965419c5b14ac9317c576c8a0f7169c067enmittler * 41864f965419c5b14ac9317c576c8a0f7169c067enmittler * Licensed under the Apache License, Version 2.0 (the "License"); 51864f965419c5b14ac9317c576c8a0f7169c067enmittler * you may not use this file except in compliance with the License. 61864f965419c5b14ac9317c576c8a0f7169c067enmittler * You may obtain a copy of the License at 71864f965419c5b14ac9317c576c8a0f7169c067enmittler * 81864f965419c5b14ac9317c576c8a0f7169c067enmittler * http://www.apache.org/licenses/LICENSE-2.0 91864f965419c5b14ac9317c576c8a0f7169c067enmittler * 101864f965419c5b14ac9317c576c8a0f7169c067enmittler * Unless required by applicable law or agreed to in writing, software 111864f965419c5b14ac9317c576c8a0f7169c067enmittler * distributed under the License is distributed on an "AS IS" BASIS, 121864f965419c5b14ac9317c576c8a0f7169c067enmittler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131864f965419c5b14ac9317c576c8a0f7169c067enmittler * See the License for the specific language governing permissions and 141864f965419c5b14ac9317c576c8a0f7169c067enmittler * limitations under the License. 151864f965419c5b14ac9317c576c8a0f7169c067enmittler */ 161864f965419c5b14ac9317c576c8a0f7169c067enmittler 171864f965419c5b14ac9317c576c8a0f7169c067enmittlerpackage libcore.java.security; 181864f965419c5b14ac9317c576c8a0f7169c067enmittler 19d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittlerimport static java.nio.charset.StandardCharsets.UTF_8; 20d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler 211864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.io.BufferedReader; 221864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.io.FileReader; 231864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.io.IOException; 24d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittlerimport java.io.InputStreamReader; 251864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.lang.reflect.InvocationTargetException; 261864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.lang.reflect.Method; 271864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.util.Arrays; 281864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.util.List; 291864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.util.regex.Matcher; 301864f965419c5b14ac9317c576c8a0f7169c067enmittlerimport java.util.regex.Pattern; 311864f965419c5b14ac9317c576c8a0f7169c067enmittler 321864f965419c5b14ac9317c576c8a0f7169c067enmittlerpublic class CpuFeatures { 331864f965419c5b14ac9317c576c8a0f7169c067enmittler private CpuFeatures() {} 341864f965419c5b14ac9317c576c8a0f7169c067enmittler 351864f965419c5b14ac9317c576c8a0f7169c067enmittler public static boolean isAESHardwareAccelerated() { 361864f965419c5b14ac9317c576c8a0f7169c067enmittler List<String> features = getListFromCpuinfo("Features"); 371864f965419c5b14ac9317c576c8a0f7169c067enmittler if (features != null && features.contains("aes")) { 381864f965419c5b14ac9317c576c8a0f7169c067enmittler return true; 391864f965419c5b14ac9317c576c8a0f7169c067enmittler } 401864f965419c5b14ac9317c576c8a0f7169c067enmittler 411864f965419c5b14ac9317c576c8a0f7169c067enmittler List<String> flags = getListFromCpuinfo("flags"); 421864f965419c5b14ac9317c576c8a0f7169c067enmittler if (flags != null && flags.contains("aes")) { 431864f965419c5b14ac9317c576c8a0f7169c067enmittler return true; 441864f965419c5b14ac9317c576c8a0f7169c067enmittler } 451864f965419c5b14ac9317c576c8a0f7169c067enmittler 46d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler features = getCpuFeaturesMac(); 47d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler if (features != null && features.contains("aes")) { 48d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler return true; 49d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 50d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler 511864f965419c5b14ac9317c576c8a0f7169c067enmittler // If we're in an emulated ABI, Conscrypt's NativeCrypto might bridge to 521864f965419c5b14ac9317c576c8a0f7169c067enmittler // a library that has accelerated AES instructions. See if Conscrypt 531864f965419c5b14ac9317c576c8a0f7169c067enmittler // detects that condition. 546321f7ae67de5eb2542c48e16ee86763463de5f2Nathan Mittler Class<?> nativeCrypto = findNativeCrypto(); 55d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler if (nativeCrypto != null) { 56d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler try { 57d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler Method EVP_has_aes_hardware = 58d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler nativeCrypto.getDeclaredMethod("EVP_has_aes_hardware"); 59d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler EVP_has_aes_hardware.setAccessible(true); 60d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler return ((Integer) EVP_has_aes_hardware.invoke(null)) == 1; 61401f1c4645f5ec715516ee9674c662448d115e66Nathan Mittler } catch (NoSuchMethodException ignored) { 62401f1c4645f5ec715516ee9674c662448d115e66Nathan Mittler } catch (SecurityException ignored) { 63401f1c4645f5ec715516ee9674c662448d115e66Nathan Mittler } catch (IllegalAccessException ignored) { 64401f1c4645f5ec715516ee9674c662448d115e66Nathan Mittler } catch (IllegalArgumentException ignored) { 65d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } catch (InvocationTargetException e) { 66d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler throw new IllegalArgumentException(e); 67d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 681864f965419c5b14ac9317c576c8a0f7169c067enmittler } 691864f965419c5b14ac9317c576c8a0f7169c067enmittler 701864f965419c5b14ac9317c576c8a0f7169c067enmittler return false; 711864f965419c5b14ac9317c576c8a0f7169c067enmittler } 721864f965419c5b14ac9317c576c8a0f7169c067enmittler 736321f7ae67de5eb2542c48e16ee86763463de5f2Nathan Mittler private static Class<?> findNativeCrypto() { 746321f7ae67de5eb2542c48e16ee86763463de5f2Nathan Mittler for (String packageName : new String[]{"com.android.org.conscrypt", "org.conscrypt"}) { 756321f7ae67de5eb2542c48e16ee86763463de5f2Nathan Mittler String name = packageName + ".NativeCrypto"; 76d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler try { 77d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler return Class.forName(name); 78d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } catch (ClassNotFoundException e) { 796321f7ae67de5eb2542c48e16ee86763463de5f2Nathan Mittler // Try the next one. 80d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 81d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 82d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler return null; 83d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 84d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler 851864f965419c5b14ac9317c576c8a0f7169c067enmittler private static String getFieldFromCpuinfo(String field) { 861864f965419c5b14ac9317c576c8a0f7169c067enmittler try { 8729916ef38dc9cb4e4c6e3fdb87d4e921546d3ef4Nathan Mittler @SuppressWarnings("DefaultCharset") 881864f965419c5b14ac9317c576c8a0f7169c067enmittler BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo")); 891864f965419c5b14ac9317c576c8a0f7169c067enmittler Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)"); 901864f965419c5b14ac9317c576c8a0f7169c067enmittler 911864f965419c5b14ac9317c576c8a0f7169c067enmittler try { 921864f965419c5b14ac9317c576c8a0f7169c067enmittler String line; 931864f965419c5b14ac9317c576c8a0f7169c067enmittler while ((line = br.readLine()) != null) { 941864f965419c5b14ac9317c576c8a0f7169c067enmittler Matcher m = p.matcher(line); 951864f965419c5b14ac9317c576c8a0f7169c067enmittler if (m.matches()) { 961864f965419c5b14ac9317c576c8a0f7169c067enmittler return m.group(1); 971864f965419c5b14ac9317c576c8a0f7169c067enmittler } 981864f965419c5b14ac9317c576c8a0f7169c067enmittler } 991864f965419c5b14ac9317c576c8a0f7169c067enmittler } finally { 1001864f965419c5b14ac9317c576c8a0f7169c067enmittler br.close(); 1011864f965419c5b14ac9317c576c8a0f7169c067enmittler } 1021864f965419c5b14ac9317c576c8a0f7169c067enmittler } catch (IOException ignored) { 103d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler // Ignored. 1041864f965419c5b14ac9317c576c8a0f7169c067enmittler } 1051864f965419c5b14ac9317c576c8a0f7169c067enmittler 1061864f965419c5b14ac9317c576c8a0f7169c067enmittler return null; 1071864f965419c5b14ac9317c576c8a0f7169c067enmittler } 1081864f965419c5b14ac9317c576c8a0f7169c067enmittler 1091864f965419c5b14ac9317c576c8a0f7169c067enmittler private static List<String> getListFromCpuinfo(String fieldName) { 1101864f965419c5b14ac9317c576c8a0f7169c067enmittler String features = getFieldFromCpuinfo(fieldName); 1111864f965419c5b14ac9317c576c8a0f7169c067enmittler if (features == null) 1121864f965419c5b14ac9317c576c8a0f7169c067enmittler return null; 1131864f965419c5b14ac9317c576c8a0f7169c067enmittler 1141864f965419c5b14ac9317c576c8a0f7169c067enmittler return Arrays.asList(features.split("\\s")); 1151864f965419c5b14ac9317c576c8a0f7169c067enmittler } 116d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler 117d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler private static List<String> getCpuFeaturesMac() { 118d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler try { 119d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler StringBuilder output = new StringBuilder(); 120d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler Process proc = Runtime.getRuntime().exec("sysctl -a"); 121d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler if (proc.waitFor() == 0) { 122d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler BufferedReader reader = 123d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler new BufferedReader(new InputStreamReader(proc.getInputStream(), UTF_8)); 124d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler 125d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler final String linePrefix = "machdep.cpu.features:"; 126d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler 127d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler String line; 128d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler while ((line = reader.readLine()) != null) { 129d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler line = line.toLowerCase(); 130d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler if (line.startsWith(linePrefix)) { 131d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler // Strip the line prefix from the results. 132d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler output.append(line.substring(linePrefix.length())).append(' '); 133d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 134d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 135d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler if (output.length() > 0) { 136d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler String outputString = output.toString(); 137d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler String[] parts = outputString.split("\\s+"); 138d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler return Arrays.asList(parts); 139d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 140d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 141d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } catch (Exception ignored) { 142d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler // Ignored. 143d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 144d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler 145d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler return null; 146d4d974d98b4f232abf0a03b631a69ebc4df0b50dNathan Mittler } 1471864f965419c5b14ac9317c576c8a0f7169c067enmittler} 148