xref: /openbsd-src/lib/libcrypto/arch/arm/armcap.c (revision f681f7ca6f2943f05a6045dea4ea2328849bd5e7)
1*f681f7caSderaadt /* $OpenBSD: armcap.c,v 1.3 2024/08/29 03:30:05 deraadt Exp $ */
2d45a68f6Stb #include <stdio.h>
3d45a68f6Stb #include <stdlib.h>
4d45a68f6Stb #include <string.h>
5d45a68f6Stb #include <setjmp.h>
6d45a68f6Stb #include <signal.h>
7d45a68f6Stb #include <openssl/crypto.h>
8d45a68f6Stb 
9d45a68f6Stb #include "arm_arch.h"
10d45a68f6Stb 
11d45a68f6Stb unsigned int OPENSSL_armcap_P;
12d45a68f6Stb 
13d45a68f6Stb #if __ARM_ARCH__ >= 7
14d45a68f6Stb static sigset_t all_masked;
15d45a68f6Stb 
16d45a68f6Stb static sigjmp_buf ill_jmp;
17*f681f7caSderaadt 
18*f681f7caSderaadt static void
19*f681f7caSderaadt ill_handler(int sig)
20*f681f7caSderaadt {
21*f681f7caSderaadt 	siglongjmp(ill_jmp, sig);
22d45a68f6Stb }
23d45a68f6Stb 
24d45a68f6Stb /*
25d45a68f6Stb  * Following subroutines could have been inlined, but it's not all
26d45a68f6Stb  * ARM compilers support inline assembler...
27d45a68f6Stb  */
28d45a68f6Stb void _armv7_neon_probe(void);
29d45a68f6Stb void _armv8_aes_probe(void);
30d45a68f6Stb void _armv8_sha1_probe(void);
31d45a68f6Stb void _armv8_sha256_probe(void);
32d45a68f6Stb void _armv8_pmull_probe(void);
33d45a68f6Stb #endif
34d45a68f6Stb 
35d45a68f6Stb void
36d45a68f6Stb OPENSSL_cpuid_setup(void)
37d45a68f6Stb {
38d45a68f6Stb #if __ARM_ARCH__ >= 7
39d45a68f6Stb 	struct sigaction	ill_oact, ill_act;
40d45a68f6Stb 	sigset_t		oset;
41d45a68f6Stb #endif
42d45a68f6Stb 	static int trigger = 0;
43d45a68f6Stb 
44d45a68f6Stb 	if (trigger)
45d45a68f6Stb 		return;
46d45a68f6Stb 	trigger = 1;
47d45a68f6Stb 
48d45a68f6Stb 	OPENSSL_armcap_P = 0;
49d45a68f6Stb 
50d45a68f6Stb #if __ARM_ARCH__ >= 7
51d45a68f6Stb 	sigfillset(&all_masked);
52d45a68f6Stb 	sigdelset(&all_masked, SIGILL);
53d45a68f6Stb 	sigdelset(&all_masked, SIGTRAP);
54d45a68f6Stb 	sigdelset(&all_masked, SIGFPE);
55d45a68f6Stb 	sigdelset(&all_masked, SIGBUS);
56d45a68f6Stb 	sigdelset(&all_masked, SIGSEGV);
57d45a68f6Stb 
58d45a68f6Stb 	memset(&ill_act, 0, sizeof(ill_act));
59d45a68f6Stb 	ill_act.sa_handler = ill_handler;
60d45a68f6Stb 	ill_act.sa_mask = all_masked;
61d45a68f6Stb 
62d45a68f6Stb 	sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
63d45a68f6Stb 	sigaction(SIGILL, &ill_act, &ill_oact);
64d45a68f6Stb 
65d45a68f6Stb 	if (sigsetjmp(ill_jmp, 1) == 0) {
66d45a68f6Stb 		_armv7_neon_probe();
67d45a68f6Stb 		OPENSSL_armcap_P |= ARMV7_NEON;
68d45a68f6Stb 		if (sigsetjmp(ill_jmp, 1) == 0) {
69d45a68f6Stb 			_armv8_pmull_probe();
70d45a68f6Stb 			OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES;
71d45a68f6Stb 		} else if (sigsetjmp(ill_jmp, 1) == 0) {
72d45a68f6Stb 			_armv8_aes_probe();
73d45a68f6Stb 			OPENSSL_armcap_P |= ARMV8_AES;
74d45a68f6Stb 		}
75d45a68f6Stb 		if (sigsetjmp(ill_jmp, 1) == 0) {
76d45a68f6Stb 			_armv8_sha1_probe();
77d45a68f6Stb 			OPENSSL_armcap_P |= ARMV8_SHA1;
78d45a68f6Stb 		}
79d45a68f6Stb 		if (sigsetjmp(ill_jmp, 1) == 0) {
80d45a68f6Stb 			_armv8_sha256_probe();
81d45a68f6Stb 			OPENSSL_armcap_P |= ARMV8_SHA256;
82d45a68f6Stb 		}
83d45a68f6Stb 	}
84d45a68f6Stb 
85d45a68f6Stb 	sigaction (SIGILL, &ill_oact, NULL);
86d45a68f6Stb 	sigprocmask(SIG_SETMASK, &oset, NULL);
87d45a68f6Stb #endif
88d45a68f6Stb }
89