/src/nss/lib/freebl/blinit.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifdef FREEBL_NO_DEPEND |
6 | | #include "stubs.h" |
7 | | #endif |
8 | | |
9 | | #include "blapii.h" |
10 | | #include "mpi.h" |
11 | | #include "secerr.h" |
12 | | #include "prtypes.h" |
13 | | #include "prinit.h" |
14 | | #include "prenv.h" |
15 | | |
16 | | #if defined(_MSC_VER) && !defined(_M_IX86) |
17 | | #include <intrin.h> /* for _xgetbv() */ |
18 | | #endif |
19 | | |
20 | | #if defined(_WIN64) && defined(__aarch64__) |
21 | | #include <windows.h> |
22 | | #endif |
23 | | |
24 | | #if defined(DARWIN) |
25 | | #include <TargetConditionals.h> |
26 | | #endif |
27 | | |
28 | | static PRCallOnceType coFreeblInit; |
29 | | |
30 | | /* State variables. */ |
31 | | static PRBool aesni_support_ = PR_FALSE; |
32 | | static PRBool clmul_support_ = PR_FALSE; |
33 | | static PRBool sha_support_ = PR_FALSE; |
34 | | static PRBool avx_support_ = PR_FALSE; |
35 | | static PRBool avx2_support_ = PR_FALSE; |
36 | | static PRBool adx_support_ = PR_FALSE; |
37 | | static PRBool ssse3_support_ = PR_FALSE; |
38 | | static PRBool sse4_1_support_ = PR_FALSE; |
39 | | static PRBool sse4_2_support_ = PR_FALSE; |
40 | | static PRBool arm_neon_support_ = PR_FALSE; |
41 | | static PRBool arm_aes_support_ = PR_FALSE; |
42 | | static PRBool arm_sha1_support_ = PR_FALSE; |
43 | | static PRBool arm_sha2_support_ = PR_FALSE; |
44 | | static PRBool arm_pmull_support_ = PR_FALSE; |
45 | | static PRBool ppc_crypto_support_ = PR_FALSE; |
46 | | |
47 | | #ifdef NSS_X86_OR_X64 |
48 | | /* |
49 | | * Adapted from the example code in "How to detect New Instruction support in |
50 | | * the 4th generation Intel Core processor family" by Max Locktyukhin. |
51 | | * https://www.intel.com/content/dam/develop/external/us/en/documents/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf |
52 | | * |
53 | | * XGETBV: |
54 | | * Reads an extended control register (XCR) specified by ECX into EDX:EAX. |
55 | | */ |
56 | | static PRBool |
57 | | check_xcr0_ymm() |
58 | 4 | { |
59 | 4 | PRUint32 xcr0; |
60 | | #if defined(_MSC_VER) |
61 | | #if defined(_M_IX86) |
62 | | __asm { |
63 | | mov ecx, 0 |
64 | | xgetbv |
65 | | mov xcr0, eax |
66 | | } |
67 | | #else |
68 | | xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */ |
69 | | #endif /* _M_IX86 */ |
70 | | #else /* _MSC_VER */ |
71 | | /* Old OSX compilers don't support xgetbv. Use byte form. */ |
72 | 4 | __asm__(".byte 0x0F, 0x01, 0xd0" |
73 | 4 | : "=a"(xcr0) |
74 | 4 | : "c"(0) |
75 | 4 | : "%edx"); |
76 | 4 | #endif /* _MSC_VER */ |
77 | | /* Check if xmm and ymm state are enabled in XCR0. */ |
78 | 4 | return (xcr0 & 6) == 6; |
79 | 4 | } |
80 | | |
81 | 4 | #define ECX_AESNI (1 << 25) |
82 | 4 | #define ECX_CLMUL (1 << 1) |
83 | 8 | #define ECX_XSAVE (1 << 26) |
84 | 8 | #define ECX_OSXSAVE (1 << 27) |
85 | 8 | #define ECX_AVX (1 << 28) |
86 | 8 | #define EBX_AVX2 (1 << 5) |
87 | 4 | #define EBX_ADX (1 << 19) |
88 | 8 | #define EBX_BMI1 (1 << 3) |
89 | 8 | #define EBX_BMI2 (1 << 8) |
90 | 4 | #define EBX_SHA (1 << 29) |
91 | 8 | #define ECX_FMA (1 << 12) |
92 | 8 | #define ECX_MOVBE (1 << 22) |
93 | 4 | #define ECX_SSSE3 (1 << 9) |
94 | 4 | #define ECX_SSE4_1 (1 << 19) |
95 | 4 | #define ECX_SSE4_2 (1 << 20) |
96 | 8 | #define AVX_BITS (ECX_XSAVE | ECX_OSXSAVE | ECX_AVX) |
97 | 12 | #define AVX2_EBX_BITS (EBX_AVX2 | EBX_BMI1 | EBX_BMI2) |
98 | 12 | #define AVX2_ECX_BITS (ECX_FMA | ECX_MOVBE) |
99 | | |
100 | | void |
101 | | CheckX86CPUSupport() |
102 | 4 | { |
103 | 4 | unsigned long eax, ebx, ecx, edx; |
104 | 4 | unsigned long eax7, ebx7, ecx7, edx7; |
105 | 4 | char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); |
106 | 4 | char *disable_pclmul = PR_GetEnvSecure("NSS_DISABLE_PCLMUL"); |
107 | 4 | char *disable_hw_sha = PR_GetEnvSecure("NSS_DISABLE_HW_SHA"); |
108 | 4 | char *disable_avx = PR_GetEnvSecure("NSS_DISABLE_AVX"); |
109 | 4 | char *disable_avx2 = PR_GetEnvSecure("NSS_DISABLE_AVX2"); |
110 | 4 | char *disable_adx = PR_GetEnvSecure("NSS_DISABLE_ADX"); |
111 | 4 | char *disable_ssse3 = PR_GetEnvSecure("NSS_DISABLE_SSSE3"); |
112 | 4 | char *disable_sse4_1 = PR_GetEnvSecure("NSS_DISABLE_SSE4_1"); |
113 | 4 | char *disable_sse4_2 = PR_GetEnvSecure("NSS_DISABLE_SSE4_2"); |
114 | 4 | freebl_cpuid(1, &eax, &ebx, &ecx, &edx); |
115 | 4 | freebl_cpuid(7, &eax7, &ebx7, &ecx7, &edx7); |
116 | 4 | aesni_support_ = (PRBool)((ecx & ECX_AESNI) != 0 && disable_hw_aes == NULL); |
117 | 4 | clmul_support_ = (PRBool)((ecx & ECX_CLMUL) != 0 && disable_pclmul == NULL); |
118 | 4 | sha_support_ = (PRBool)((ebx7 & EBX_SHA) != 0 && disable_hw_sha == NULL); |
119 | | /* For AVX we ensure that: |
120 | | * - The AVX, OSXSAVE, and XSAVE bits of ECX from CPUID(EAX=1) are set, and |
121 | | * - the SSE and AVX state bits of XCR0 are set (check_xcr0_ymm). |
122 | | */ |
123 | 4 | avx_support_ = (PRBool)((ecx & AVX_BITS) == AVX_BITS) && check_xcr0_ymm() && |
124 | 4 | disable_avx == NULL; |
125 | | /* For AVX2 we ensure that: |
126 | | * - AVX is supported, |
127 | | * - the AVX2, BMI1, and BMI2 bits of EBX from CPUID(EAX=7) are set, and |
128 | | * - the FMA, and MOVBE bits of ECX from CPUID(EAX=1) are set. |
129 | | * We do not check for LZCNT support. |
130 | | */ |
131 | 4 | avx2_support_ = (PRBool)(avx_support_ == PR_TRUE && |
132 | 4 | (ebx7 & AVX2_EBX_BITS) == AVX2_EBX_BITS && |
133 | 4 | (ecx & AVX2_ECX_BITS) == AVX2_ECX_BITS && |
134 | 4 | disable_avx2 == NULL); |
135 | | /* CPUID.(EAX=07H, ECX=0H):EBX.ADX[bit 19]=1 indicates |
136 | | the processor supports ADCX and ADOX instructions.*/ |
137 | 4 | adx_support_ = (PRBool)((ebx7 & EBX_ADX) != 0 && disable_adx == NULL); |
138 | 4 | ssse3_support_ = (PRBool)((ecx & ECX_SSSE3) != 0 && |
139 | 4 | disable_ssse3 == NULL); |
140 | 4 | sse4_1_support_ = (PRBool)((ecx & ECX_SSE4_1) != 0 && |
141 | 4 | disable_sse4_1 == NULL); |
142 | 4 | sse4_2_support_ = (PRBool)((ecx & ECX_SSE4_2) != 0 && |
143 | 4 | disable_sse4_2 == NULL); |
144 | 4 | } |
145 | | #endif /* NSS_X86_OR_X64 */ |
146 | | |
147 | | /* clang-format off */ |
148 | | #if (defined(__aarch64__) || defined(__arm__)) && !defined(TARGET_OS_IPHONE) |
149 | | #ifndef __has_include |
150 | | #define __has_include(x) 0 |
151 | | #endif |
152 | | #if (__has_include(<sys/auxv.h>) || defined(__linux__)) && \ |
153 | | defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__) |
154 | | /* This might be conflict with host compiler */ |
155 | | #if !defined(__ANDROID__) |
156 | | #include <sys/auxv.h> |
157 | | #endif |
158 | | extern unsigned long getauxval(unsigned long type) __attribute__((weak)); |
159 | | #elif defined(__arm__) || (!defined(__OpenBSD__) && !defined(_WIN64)) |
160 | | static unsigned long (*getauxval)(unsigned long) = NULL; |
161 | | #endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/ |
162 | | |
163 | | #if defined(__FreeBSD__) && !defined(__aarch64__) && __has_include(<sys/auxv.h>) |
164 | | /* Avoid conflict with static declaration above */ |
165 | | #define getauxval freebl_getauxval |
166 | | static unsigned long getauxval(unsigned long type) |
167 | | { |
168 | | /* Only AT_HWCAP* return unsigned long */ |
169 | | if (type != AT_HWCAP && type != AT_HWCAP2) { |
170 | | return 0; |
171 | | } |
172 | | |
173 | | unsigned long ret = 0; |
174 | | elf_aux_info(type, &ret, sizeof(ret)); |
175 | | return ret; |
176 | | } |
177 | | #endif |
178 | | |
179 | | #ifndef AT_HWCAP2 |
180 | | #define AT_HWCAP2 26 |
181 | | #endif |
182 | | #ifndef AT_HWCAP |
183 | | #define AT_HWCAP 16 |
184 | | #endif |
185 | | |
186 | | #endif /* defined(__aarch64__) || defined(__arm__) */ |
187 | | /* clang-format on */ |
188 | | |
189 | | #if defined(__aarch64__) |
190 | | |
191 | | #if defined(__linux__) |
192 | | // Defines from hwcap.h in Linux kernel - ARM64 |
193 | | #ifndef HWCAP_AES |
194 | | #define HWCAP_AES (1 << 3) |
195 | | #endif |
196 | | #ifndef HWCAP_PMULL |
197 | | #define HWCAP_PMULL (1 << 4) |
198 | | #endif |
199 | | #ifndef HWCAP_SHA1 |
200 | | #define HWCAP_SHA1 (1 << 5) |
201 | | #endif |
202 | | #ifndef HWCAP_SHA2 |
203 | | #define HWCAP_SHA2 (1 << 6) |
204 | | #endif |
205 | | #endif /* defined(__linux__) */ |
206 | | |
207 | | #if defined(__FreeBSD__) |
208 | | #include <stdint.h> |
209 | | #include <machine/armreg.h> |
210 | | // Support for older version of armreg.h |
211 | | #ifndef ID_AA64ISAR0_AES_VAL |
212 | | #define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES |
213 | | #endif |
214 | | #ifndef ID_AA64ISAR0_SHA1_VAL |
215 | | #define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1 |
216 | | #endif |
217 | | #ifndef ID_AA64ISAR0_SHA2_VAL |
218 | | #define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2 |
219 | | #endif |
220 | | #endif /* defined(__FreeBSD__) */ |
221 | | |
222 | | #if defined(__OpenBSD__) |
223 | | #include <sys/sysctl.h> |
224 | | #include <machine/cpu.h> |
225 | | #include <machine/armreg.h> |
226 | | #endif /* defined(__OpenBSD__) */ |
227 | | |
228 | | void |
229 | | CheckARMSupport() |
230 | | { |
231 | | #if defined(_WIN64) |
232 | | BOOL arm_crypto_support = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); |
233 | | arm_aes_support_ = arm_crypto_support; |
234 | | arm_pmull_support_ = arm_crypto_support; |
235 | | arm_sha1_support_ = arm_crypto_support; |
236 | | arm_sha2_support_ = arm_crypto_support; |
237 | | #elif defined(__linux__) |
238 | | if (getauxval) { |
239 | | long hwcaps = getauxval(AT_HWCAP); |
240 | | arm_aes_support_ = (hwcaps & HWCAP_AES) == HWCAP_AES; |
241 | | arm_pmull_support_ = (hwcaps & HWCAP_PMULL) == HWCAP_PMULL; |
242 | | arm_sha1_support_ = (hwcaps & HWCAP_SHA1) == HWCAP_SHA1; |
243 | | arm_sha2_support_ = (hwcaps & HWCAP_SHA2) == HWCAP_SHA2; |
244 | | } |
245 | | #elif defined(__FreeBSD__) |
246 | | /* qemu-user does not support register access from userspace */ |
247 | | if (PR_GetEnvSecure("QEMU_EMULATING") == NULL) { |
248 | | uint64_t isar0 = READ_SPECIALREG(id_aa64isar0_el1); |
249 | | arm_aes_support_ = ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_BASE; |
250 | | arm_pmull_support_ = ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_PMULL; |
251 | | arm_sha1_support_ = ID_AA64ISAR0_SHA1_VAL(isar0) >= ID_AA64ISAR0_SHA1_BASE; |
252 | | arm_sha2_support_ = ID_AA64ISAR0_SHA2_VAL(isar0) >= ID_AA64ISAR0_SHA2_BASE; |
253 | | } |
254 | | #elif defined(__OpenBSD__) |
255 | | const int isar0_mib[] = { CTL_MACHDEP, CPU_ID_AA64ISAR0 }; |
256 | | uint64_t isar0; |
257 | | size_t len = sizeof(isar0); |
258 | | if (sysctl(isar0_mib, 2, &isar0, &len, NULL, 0) < 0) |
259 | | return; |
260 | | arm_aes_support_ = ID_AA64ISAR0_AES(isar0) >= ID_AA64ISAR0_AES_BASE; |
261 | | arm_pmull_support_ = ID_AA64ISAR0_AES(isar0) >= ID_AA64ISAR0_AES_PMULL; |
262 | | arm_sha1_support_ = ID_AA64ISAR0_SHA1(isar0) >= ID_AA64ISAR0_SHA1_BASE; |
263 | | arm_sha2_support_ = ID_AA64ISAR0_SHA2(isar0) >= ID_AA64ISAR0_SHA2_BASE; |
264 | | #elif defined(__ARM_FEATURE_CRYPTO) |
265 | | /* |
266 | | * Although no feature detection, default compiler option allows ARM |
267 | | * Crypto Extension. |
268 | | */ |
269 | | arm_aes_support_ = PR_TRUE; |
270 | | arm_pmull_support_ = PR_TRUE; |
271 | | arm_sha1_support_ = PR_TRUE; |
272 | | arm_sha2_support_ = PR_TRUE; |
273 | | #endif |
274 | | /* aarch64 must support NEON. */ |
275 | | arm_neon_support_ = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON") == NULL; |
276 | | arm_aes_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_AES") == NULL; |
277 | | arm_pmull_support_ &= PR_GetEnvSecure("NSS_DISABLE_PMULL") == NULL; |
278 | | arm_sha1_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA1") == NULL; |
279 | | arm_sha2_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA2") == NULL; |
280 | | } |
281 | | #endif /* defined(__aarch64__) */ |
282 | | |
283 | | #if defined(__arm__) |
284 | | // Defines from hwcap.h in Linux kernel - ARM |
285 | | /* |
286 | | * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP |
287 | | */ |
288 | | #ifndef HWCAP_NEON |
289 | | #define HWCAP_NEON (1 << 12) |
290 | | #endif |
291 | | |
292 | | /* |
293 | | * HWCAP2 flags - for elf_hwcap2 (in kernel) and AT_HWCAP2 |
294 | | */ |
295 | | #ifndef HWCAP2_AES |
296 | | #define HWCAP2_AES (1 << 0) |
297 | | #endif |
298 | | #ifndef HWCAP2_PMULL |
299 | | #define HWCAP2_PMULL (1 << 1) |
300 | | #endif |
301 | | #ifndef HWCAP2_SHA1 |
302 | | #define HWCAP2_SHA1 (1 << 2) |
303 | | #endif |
304 | | #ifndef HWCAP2_SHA2 |
305 | | #define HWCAP2_SHA2 (1 << 3) |
306 | | #endif |
307 | | |
308 | | PRBool |
309 | | GetNeonSupport() |
310 | | { |
311 | | char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON"); |
312 | | if (disable_arm_neon) { |
313 | | return PR_FALSE; |
314 | | } |
315 | | #if defined(__ARM_NEON) || defined(__ARM_NEON__) |
316 | | // Compiler generates NEON instruction as default option. |
317 | | // If no getauxval, compiler generate NEON instruction by default, |
318 | | // we should allow NOEN support. |
319 | | return PR_TRUE; |
320 | | #elif !defined(__ANDROID__) |
321 | | // Android's cpu-features.c detects features by the following logic |
322 | | // |
323 | | // - Call getauxval(AT_HWCAP) |
324 | | // - Parse /proc/self/auxv if getauxval is nothing or returns 0 |
325 | | // - Parse /proc/cpuinfo if both cannot detect features |
326 | | // |
327 | | // But we don't use it for Android since Android document |
328 | | // (https://developer.android.com/ndk/guides/cpu-features) says |
329 | | // one problem with AT_HWCAP sometimes devices (Nexus 4 and emulator) |
330 | | // are mistaken for IDIV. |
331 | | if (getauxval) { |
332 | | return (getauxval(AT_HWCAP) & HWCAP_NEON); |
333 | | } |
334 | | #endif /* defined(__ARM_NEON) || defined(__ARM_NEON__) */ |
335 | | return PR_FALSE; |
336 | | } |
337 | | |
338 | | #ifdef __linux__ |
339 | | static long |
340 | | ReadCPUInfoForHWCAP2() |
341 | | { |
342 | | FILE *cpuinfo; |
343 | | char buf[512]; |
344 | | char *p; |
345 | | long hwcap2 = 0; |
346 | | |
347 | | cpuinfo = fopen("/proc/cpuinfo", "r"); |
348 | | if (!cpuinfo) { |
349 | | return 0; |
350 | | } |
351 | | while (fgets(buf, 511, cpuinfo)) { |
352 | | if (!memcmp(buf, "Features", 8)) { |
353 | | p = strstr(buf, " aes"); |
354 | | if (p && (p[4] == ' ' || p[4] == '\n')) { |
355 | | hwcap2 |= HWCAP2_AES; |
356 | | } |
357 | | p = strstr(buf, " sha1"); |
358 | | if (p && (p[5] == ' ' || p[5] == '\n')) { |
359 | | hwcap2 |= HWCAP2_SHA1; |
360 | | } |
361 | | p = strstr(buf, " sha2"); |
362 | | if (p && (p[5] == ' ' || p[5] == '\n')) { |
363 | | hwcap2 |= HWCAP2_SHA2; |
364 | | } |
365 | | p = strstr(buf, " pmull"); |
366 | | if (p && (p[6] == ' ' || p[6] == '\n')) { |
367 | | hwcap2 |= HWCAP2_PMULL; |
368 | | } |
369 | | break; |
370 | | } |
371 | | } |
372 | | |
373 | | fclose(cpuinfo); |
374 | | return hwcap2; |
375 | | } |
376 | | #endif /* __linux__ */ |
377 | | |
378 | | void |
379 | | CheckARMSupport() |
380 | | { |
381 | | char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); |
382 | | if (getauxval) { |
383 | | // Android's cpu-features.c uses AT_HWCAP2 for newer features. |
384 | | // AT_HWCAP2 is implemented on newer devices / kernel, so we can trust |
385 | | // it since cpu-features.c doesn't have workaround / fallback. |
386 | | // Also, AT_HWCAP2 is supported by glibc 2.18+ on Linux/arm, If |
387 | | // AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will |
388 | | // returns 0. |
389 | | long hwcaps = getauxval(AT_HWCAP2); |
390 | | #ifdef __linux__ |
391 | | if (!hwcaps) { |
392 | | // Some ARMv8 devices may not implement AT_HWCAP2. So we also |
393 | | // read /proc/cpuinfo if AT_HWCAP2 is 0. |
394 | | hwcaps = ReadCPUInfoForHWCAP2(); |
395 | | } |
396 | | #endif |
397 | | arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL; |
398 | | arm_pmull_support_ = hwcaps & HWCAP2_PMULL; |
399 | | arm_sha1_support_ = hwcaps & HWCAP2_SHA1; |
400 | | arm_sha2_support_ = hwcaps & HWCAP2_SHA2; |
401 | | } |
402 | | arm_neon_support_ = GetNeonSupport(); |
403 | | arm_sha1_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA1") == NULL; |
404 | | arm_sha2_support_ &= PR_GetEnvSecure("NSS_DISABLE_HW_SHA2") == NULL; |
405 | | } |
406 | | #endif /* defined(__arm__) */ |
407 | | |
408 | | // Enable when Firefox can use it for Android API 16 and 17. |
409 | | // #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__)) |
410 | | // #include <cpu-features.h> |
411 | | // void |
412 | | // CheckARMSupport() |
413 | | // { |
414 | | // char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON"); |
415 | | // char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); |
416 | | // AndroidCpuFamily family = android_getCpuFamily(); |
417 | | // uint64_t features = android_getCpuFeatures(); |
418 | | // if (family == ANDROID_CPU_FAMILY_ARM64) { |
419 | | // arm_aes_support_ = features & ANDROID_CPU_ARM64_FEATURE_AES && |
420 | | // disable_hw_aes == NULL; |
421 | | // arm_pmull_support_ = features & ANDROID_CPU_ARM64_FEATURE_PMULL; |
422 | | // arm_sha1_support_ = features & ANDROID_CPU_ARM64_FEATURE_SHA1; |
423 | | // arm_sha2_support_ = features & ANDROID_CPU_ARM64_FEATURE_SHA2; |
424 | | // arm_neon_support_ = disable_arm_neon == NULL; |
425 | | // } |
426 | | // if (family == ANDROID_CPU_FAMILY_ARM) { |
427 | | // arm_aes_support_ = features & ANDROID_CPU_ARM_FEATURE_AES && |
428 | | // disable_hw_aes == NULL; |
429 | | // arm_pmull_support_ = features & ANDROID_CPU_ARM_FEATURE_PMULL; |
430 | | // arm_sha1_support_ = features & ANDROID_CPU_ARM_FEATURE_SHA1; |
431 | | // arm_sha2_support_ = features & ANDROID_CPU_ARM_FEATURE_SHA2; |
432 | | // arm_neon_support_ = hwcaps & ANDROID_CPU_ARM_FEATURE_NEON && |
433 | | // disable_arm_neon == NULL; |
434 | | // } |
435 | | // } |
436 | | // #endif /* defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__)) */ |
437 | | |
438 | | PRBool |
439 | | aesni_support() |
440 | 378k | { |
441 | 378k | return aesni_support_; |
442 | 378k | } |
443 | | PRBool |
444 | | clmul_support() |
445 | 54.6k | { |
446 | 54.6k | return clmul_support_; |
447 | 54.6k | } |
448 | | PRBool |
449 | | sha_support() |
450 | 1.55M | { |
451 | 1.55M | return sha_support_; |
452 | 1.55M | } |
453 | | PRBool |
454 | | avx_support() |
455 | 0 | { |
456 | 0 | return avx_support_; |
457 | 0 | } |
458 | | PRBool |
459 | | avx2_support() |
460 | 19.7k | { |
461 | 19.7k | return avx2_support_; |
462 | 19.7k | } |
463 | | PRBool |
464 | | adx_support() |
465 | 0 | { |
466 | 0 | return adx_support_; |
467 | 0 | } |
468 | | PRBool |
469 | | ssse3_support() |
470 | 0 | { |
471 | 0 | return ssse3_support_; |
472 | 0 | } |
473 | | PRBool |
474 | | sse4_1_support() |
475 | 0 | { |
476 | 0 | return sse4_1_support_; |
477 | 0 | } |
478 | | PRBool |
479 | | sse4_2_support() |
480 | 0 | { |
481 | 0 | return sse4_2_support_; |
482 | 0 | } |
483 | | PRBool |
484 | | arm_neon_support() |
485 | 0 | { |
486 | 0 | return arm_neon_support_; |
487 | 0 | } |
488 | | PRBool |
489 | | arm_aes_support() |
490 | 0 | { |
491 | 0 | return arm_aes_support_; |
492 | 0 | } |
493 | | PRBool |
494 | | arm_pmull_support() |
495 | 0 | { |
496 | 0 | return arm_pmull_support_; |
497 | 0 | } |
498 | | PRBool |
499 | | arm_sha1_support() |
500 | 0 | { |
501 | 0 | return arm_sha1_support_; |
502 | 0 | } |
503 | | PRBool |
504 | | arm_sha2_support() |
505 | 1.55M | { |
506 | 1.55M | return arm_sha2_support_; |
507 | 1.55M | } |
508 | | PRBool |
509 | | ppc_crypto_support() |
510 | 0 | { |
511 | 0 | return ppc_crypto_support_; |
512 | 0 | } |
513 | | |
514 | | #if defined(__powerpc__) |
515 | | |
516 | | #ifndef __has_include |
517 | | #define __has_include(x) 0 |
518 | | #endif |
519 | | |
520 | | /* clang-format off */ |
521 | | #if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD__ >= 12) |
522 | | #if __has_include(<sys/auxv.h>) |
523 | | #include <sys/auxv.h> |
524 | | #endif |
525 | | #elif (defined(__FreeBSD__) && __FreeBSD__ < 12) |
526 | | #include <sys/sysctl.h> |
527 | | #endif |
528 | | |
529 | | // Defines from cputable.h in Linux kernel - PPC, letting us build on older kernels |
530 | | #ifndef PPC_FEATURE2_VEC_CRYPTO |
531 | | #define PPC_FEATURE2_VEC_CRYPTO 0x02000000 |
532 | | #endif |
533 | | |
534 | | static void |
535 | | CheckPPCSupport() |
536 | | { |
537 | | char *disable_hw_crypto = PR_GetEnvSecure("NSS_DISABLE_PPC_GHASH"); |
538 | | |
539 | | unsigned long hwcaps = 0; |
540 | | #if defined(__linux__) |
541 | | #if __has_include(<sys/auxv.h>) |
542 | | hwcaps = getauxval(AT_HWCAP2); |
543 | | #endif |
544 | | #elif defined(__FreeBSD__) |
545 | | #if __FreeBSD__ >= 12 |
546 | | #if __has_include(<sys/auxv.h>) |
547 | | elf_aux_info(AT_HWCAP2, &hwcaps, sizeof(hwcaps)); |
548 | | #endif |
549 | | #else |
550 | | size_t len = sizeof(hwcaps); |
551 | | sysctlbyname("hw.cpu_features2", &hwcaps, &len, NULL, 0); |
552 | | #endif |
553 | | #endif |
554 | | |
555 | | ppc_crypto_support_ = hwcaps & PPC_FEATURE2_VEC_CRYPTO && disable_hw_crypto == NULL; |
556 | | } |
557 | | /* clang-format on */ |
558 | | |
559 | | #endif /* __powerpc__ */ |
560 | | |
561 | | static PRStatus |
562 | | FreeblInit(void) |
563 | 4 | { |
564 | 4 | #ifdef NSS_X86_OR_X64 |
565 | 4 | CheckX86CPUSupport(); |
566 | | #elif (defined(__aarch64__) || defined(__arm__)) |
567 | | CheckARMSupport(); |
568 | | #elif (defined(__powerpc__)) |
569 | | CheckPPCSupport(); |
570 | | #endif |
571 | 4 | return PR_SUCCESS; |
572 | 4 | } |
573 | | |
574 | | SECStatus |
575 | | BL_Init(void) |
576 | 4 | { |
577 | 4 | if (PR_CallOnce(&coFreeblInit, FreeblInit) != PR_SUCCESS) { |
578 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
579 | 0 | return SECFailure; |
580 | 0 | } |
581 | 4 | RSA_Init(); |
582 | | |
583 | 4 | return SECSuccess; |
584 | 4 | } |