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