summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2024-11-08 13:34:24 +0000
committerjsing <>2024-11-08 13:34:24 +0000
commitf631c6b6c7297cc0d3ef18ebf1277dc9b7d3d70d (patch)
tree21d180efdc7bb015f190011aada458b9e8a920db /src/lib
parent699f5c2e0bf9095e5e50dc5a5fc7753e50f3f154 (diff)
downloadopenbsd-f631c6b6c7297cc0d3ef18ebf1277dc9b7d3d70d.tar.gz
openbsd-f631c6b6c7297cc0d3ef18ebf1277dc9b7d3d70d.tar.bz2
openbsd-f631c6b6c7297cc0d3ef18ebf1277dc9b7d3d70d.zip
Replace aarch64 CPU capabilities detection code.
Replace the aarch64 CPU detection code with a version that parses ISAR0, avoiding signal handling and SIGILL. This gets ISAR0 via sysctl(), but this can be adapted to other mechanisms for other platforms (or alternatively the same can be achieved via HWCAP). This now follows the same naming/design as used by amd64 and i386, hence define HAVE_CRYPTO_CPU_CAPS_INIT for aarch64. ok kettenis@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/arch/aarch64/Makefile.inc12
-rw-r--r--src/lib/libcrypto/arch/aarch64/arm64_arch.h59
-rw-r--r--src/lib/libcrypto/arch/aarch64/arm64cap.c138
-rw-r--r--src/lib/libcrypto/arch/aarch64/arm64cpuid.S53
-rw-r--r--src/lib/libcrypto/arch/aarch64/crypto_arch.h17
-rw-r--r--src/lib/libcrypto/arch/aarch64/crypto_cpu_caps.c96
6 files changed, 114 insertions, 261 deletions
diff --git a/src/lib/libcrypto/arch/aarch64/Makefile.inc b/src/lib/libcrypto/arch/aarch64/Makefile.inc
index a17ef7f5a9..20a634dc99 100644
--- a/src/lib/libcrypto/arch/aarch64/Makefile.inc
+++ b/src/lib/libcrypto/arch/aarch64/Makefile.inc
@@ -1,15 +1,7 @@
1# $OpenBSD: Makefile.inc,v 1.13 2024/03/29 07:24:09 jsing Exp $ 1# $OpenBSD: Makefile.inc,v 1.14 2024/11/08 13:34:24 jsing Exp $
2 2
3# aarch64-specific libcrypto build rules 3# aarch64-specific libcrypto build rules
4 4
5.for dir f in ${SSLASM} 5SRCS += crypto_cpu_caps.c
6SRCS+= ${f}.S
7GENERATED+=${f}.S
8${f}.S: ${LCRYPTO_SRC}/${dir}/asm/${f}.pl
9 /usr/bin/perl \
10 ${LCRYPTO_SRC}/${dir}/asm/${f}.pl void ${.TARGET} > ${.TARGET}
11.endfor
12 6
13CFLAGS+= -DOPENSSL_CPUID_OBJ
14AFLAGS+= -mmark-bti-property 7AFLAGS+= -mmark-bti-property
15SRCS+= arm64cpuid.S arm64cap.c
diff --git a/src/lib/libcrypto/arch/aarch64/arm64_arch.h b/src/lib/libcrypto/arch/aarch64/arm64_arch.h
deleted file mode 100644
index 7f35acaa7d..0000000000
--- a/src/lib/libcrypto/arch/aarch64/arm64_arch.h
+++ /dev/null
@@ -1,59 +0,0 @@
1/* $OpenBSD: arm64_arch.h,v 1.1 2022/03/23 15:13:31 tb Exp $ */
2#ifndef __ARM_ARCH_H__
3#define __ARM_ARCH_H__
4
5#if !defined(__ARM_ARCH__)
6# if defined(__CC_ARM)
7# define __ARM_ARCH__ __TARGET_ARCH_ARM
8# if defined(__BIG_ENDIAN)
9# define __ARMEB__
10# else
11# define __ARMEL__
12# endif
13# elif defined(__GNUC__)
14 /*
15 * Why doesn't gcc define __ARM_ARCH__? Instead it defines
16 * bunch of below macros. See all_architectures[] table in
17 * gcc/config/arm/arm.c. On a side note it defines
18 * __ARMEL__/__ARMEB__ for little-/big-endian.
19 */
20# if defined(__ARM_ARCH)
21# define __ARM_ARCH__ __ARM_ARCH
22# elif defined(__ARM_ARCH_8A__)
23# define __ARM_ARCH__ 8
24# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
25 defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
26 defined(__ARM_ARCH_7EM__)
27# define __ARM_ARCH__ 7
28# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
29 defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \
30 defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \
31 defined(__ARM_ARCH_6T2__)
32# define __ARM_ARCH__ 6
33# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
34 defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \
35 defined(__ARM_ARCH_5TEJ__)
36# define __ARM_ARCH__ 5
37# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
38# define __ARM_ARCH__ 4
39# else
40# error "unsupported ARM architecture"
41# endif
42# endif
43#endif
44
45#if !defined(__ASSEMBLER__)
46extern unsigned int OPENSSL_armcap_P;
47
48#define ARMV7_NEON (1<<0)
49#define ARMV8_AES (1<<1)
50#define ARMV8_SHA1 (1<<2)
51#define ARMV8_SHA256 (1<<3)
52#define ARMV8_PMULL (1<<4)
53#endif
54
55#if defined(__OpenBSD__)
56#define __STRICT_ALIGNMENT
57#endif
58
59#endif
diff --git a/src/lib/libcrypto/arch/aarch64/arm64cap.c b/src/lib/libcrypto/arch/aarch64/arm64cap.c
deleted file mode 100644
index aeacebfcb4..0000000000
--- a/src/lib/libcrypto/arch/aarch64/arm64cap.c
+++ /dev/null
@@ -1,138 +0,0 @@
1/* $OpenBSD: arm64cap.c,v 1.4 2024/08/29 03:30:05 deraadt 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#if defined(__OpenBSD__)
10#include <sys/sysctl.h>
11#include <machine/cpu.h> /* CPU_ID_AA64ISAR0 */
12#endif
13
14#include "arm64_arch.h"
15
16/* ID_AA64ISAR0_EL1 required for OPENSSL_cpuid_setup */
17#define ID_AA64ISAR0_AES_SHIFT 4
18#define ID_AA64ISAR0_AES_MASK (0xf << ID_AA64ISAR0_AES_SHIFT)
19#define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK)
20#define ID_AA64ISAR0_AES_BASE (0x1 << ID_AA64ISAR0_AES_SHIFT)
21#define ID_AA64ISAR0_AES_PMULL (0x2 << ID_AA64ISAR0_AES_SHIFT)
22#define ID_AA64ISAR0_SHA1_SHIFT 8
23#define ID_AA64ISAR0_SHA1_MASK (0xf << ID_AA64ISAR0_SHA1_SHIFT)
24#define ID_AA64ISAR0_SHA1(x) ((x) & ID_AA64ISAR0_SHA1_MASK)
25#define ID_AA64ISAR0_SHA1_BASE (0x1 << ID_AA64ISAR0_SHA1_SHIFT)
26#define ID_AA64ISAR0_SHA2_SHIFT 12
27#define ID_AA64ISAR0_SHA2_MASK (0xf << ID_AA64ISAR0_SHA2_SHIFT)
28#define ID_AA64ISAR0_SHA2(x) ((x) & ID_AA64ISAR0_SHA2_MASK)
29#define ID_AA64ISAR0_SHA2_BASE (0x1 << ID_AA64ISAR0_SHA2_SHIFT)
30
31unsigned int OPENSSL_armcap_P;
32
33#if defined(CPU_ID_AA64ISAR0)
34void
35OPENSSL_cpuid_setup(void)
36{
37 int isar0_mib[] = { CTL_MACHDEP, CPU_ID_AA64ISAR0 };
38 size_t len = sizeof(uint64_t);
39 uint64_t cpu_id = 0;
40
41 if (OPENSSL_armcap_P != 0)
42 return;
43
44 if (sysctl(isar0_mib, 2, &cpu_id, &len, NULL, 0) < 0)
45 return;
46
47 OPENSSL_armcap_P |= ARMV7_NEON;
48
49 if (ID_AA64ISAR0_AES(cpu_id) >= ID_AA64ISAR0_AES_BASE)
50 OPENSSL_armcap_P |= ARMV8_AES;
51
52 if (ID_AA64ISAR0_AES(cpu_id) >= ID_AA64ISAR0_AES_PMULL)
53 OPENSSL_armcap_P |= ARMV8_PMULL;
54
55 if (ID_AA64ISAR0_SHA1(cpu_id) >= ID_AA64ISAR0_SHA1_BASE)
56 OPENSSL_armcap_P |= ARMV8_SHA1;
57
58 if (ID_AA64ISAR0_SHA2(cpu_id) >= ID_AA64ISAR0_SHA2_BASE)
59 OPENSSL_armcap_P |= ARMV8_SHA256;
60}
61#else
62#if __ARM_ARCH__ >= 7
63static sigset_t all_masked;
64
65static sigjmp_buf ill_jmp;
66
67static void
68ill_handler(int sig)
69{
70 siglongjmp(ill_jmp, sig);
71}
72
73/*
74 * Following subroutines could have been inlined, but it's not all
75 * ARM compilers support inline assembler...
76 */
77void _armv7_neon_probe(void);
78void _armv8_aes_probe(void);
79void _armv8_sha1_probe(void);
80void _armv8_sha256_probe(void);
81void _armv8_pmull_probe(void);
82#endif
83
84void
85OPENSSL_cpuid_setup(void)
86{
87#if __ARM_ARCH__ >= 7
88 struct sigaction ill_oact, ill_act;
89 sigset_t oset;
90#endif
91 static int trigger = 0;
92
93 if (trigger)
94 return;
95 trigger = 1;
96
97 OPENSSL_armcap_P = 0;
98
99#if __ARM_ARCH__ >= 7
100 sigfillset(&all_masked);
101 sigdelset(&all_masked, SIGILL);
102 sigdelset(&all_masked, SIGTRAP);
103 sigdelset(&all_masked, SIGFPE);
104 sigdelset(&all_masked, SIGBUS);
105 sigdelset(&all_masked, SIGSEGV);
106
107 memset(&ill_act, 0, sizeof(ill_act));
108 ill_act.sa_handler = ill_handler;
109 ill_act.sa_mask = all_masked;
110
111 sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
112 sigaction(SIGILL, &ill_act, &ill_oact);
113
114 if (sigsetjmp(ill_jmp, 1) == 0) {
115 _armv7_neon_probe();
116 OPENSSL_armcap_P |= ARMV7_NEON;
117 if (sigsetjmp(ill_jmp, 1) == 0) {
118 _armv8_pmull_probe();
119 OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES;
120 } else if (sigsetjmp(ill_jmp, 1) == 0) {
121 _armv8_aes_probe();
122 OPENSSL_armcap_P |= ARMV8_AES;
123 }
124 if (sigsetjmp(ill_jmp, 1) == 0) {
125 _armv8_sha1_probe();
126 OPENSSL_armcap_P |= ARMV8_SHA1;
127 }
128 if (sigsetjmp(ill_jmp, 1) == 0) {
129 _armv8_sha256_probe();
130 OPENSSL_armcap_P |= ARMV8_SHA256;
131 }
132 }
133
134 sigaction (SIGILL, &ill_oact, NULL);
135 sigprocmask(SIG_SETMASK, &oset, NULL);
136#endif
137}
138#endif
diff --git a/src/lib/libcrypto/arch/aarch64/arm64cpuid.S b/src/lib/libcrypto/arch/aarch64/arm64cpuid.S
deleted file mode 100644
index 96a9c76fb1..0000000000
--- a/src/lib/libcrypto/arch/aarch64/arm64cpuid.S
+++ /dev/null
@@ -1,53 +0,0 @@
1#include "arm64_arch.h"
2
3.text
4.arch armv8-a+crypto+sha3
5
6.align 5
7.globl _armv7_neon_probe
8.type _armv7_neon_probe,%function
9_armv7_neon_probe:
10 bti c
11 orr v15.16b, v15.16b, v15.16b
12 ret
13.size _armv7_neon_probe,.-_armv7_neon_probe
14
15.globl _armv8_aes_probe
16.type _armv8_aes_probe,%function
17_armv8_aes_probe:
18 bti c
19 aese v0.16b, v0.16b
20 ret
21.size _armv8_aes_probe,.-_armv8_aes_probe
22
23.globl _armv8_sha1_probe
24.type _armv8_sha1_probe,%function
25_armv8_sha1_probe:
26 bti c
27 sha1h s0, s0
28 ret
29.size _armv8_sha1_probe,.-_armv8_sha1_probe
30
31.globl _armv8_sha256_probe
32.type _armv8_sha256_probe,%function
33_armv8_sha256_probe:
34 bti c
35 sha256su0 v0.4s, v0.4s
36 ret
37.size _armv8_sha256_probe,.-_armv8_sha256_probe
38
39.globl _armv8_pmull_probe
40.type _armv8_pmull_probe,%function
41_armv8_pmull_probe:
42 bti c
43 pmull v0.1q, v0.1d, v0.1d
44 ret
45.size _armv8_pmull_probe,.-_armv8_pmull_probe
46
47.globl _armv8_sha512_probe
48.type _armv8_sha512_probe,%function
49_armv8_sha512_probe:
50 bti c
51 sha512su0 v0.2d,v0.2d
52 ret
53.size _armv8_sha512_probe,.-_armv8_sha512_probe
diff --git a/src/lib/libcrypto/arch/aarch64/crypto_arch.h b/src/lib/libcrypto/arch/aarch64/crypto_arch.h
index a3dd98d0ce..b0188c498a 100644
--- a/src/lib/libcrypto/arch/aarch64/crypto_arch.h
+++ b/src/lib/libcrypto/arch/aarch64/crypto_arch.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: crypto_arch.h,v 1.1 2024/08/11 13:02:39 jsing Exp $ */ 1/* $OpenBSD: crypto_arch.h,v 1.2 2024/11/08 13:34:24 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2024 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -15,7 +15,22 @@
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */ 16 */
17 17
18#include <stdint.h>
19
18#ifndef HEADER_CRYPTO_ARCH_H 20#ifndef HEADER_CRYPTO_ARCH_H
19#define HEADER_CRYPTO_ARCH_H 21#define HEADER_CRYPTO_ARCH_H
20 22
23#define HAVE_CRYPTO_CPU_CAPS_INIT
24
25#ifndef __ASSEMBLER__
26extern uint64_t crypto_cpu_caps_aarch64;
27#endif
28
29#define CRYPTO_CPU_CAPS_AARCH64_AES (1ULL << 0)
30#define CRYPTO_CPU_CAPS_AARCH64_PMULL (1ULL << 1)
31#define CRYPTO_CPU_CAPS_AARCH64_SHA1 (1ULL << 2)
32#define CRYPTO_CPU_CAPS_AARCH64_SHA2 (1ULL << 3)
33#define CRYPTO_CPU_CAPS_AARCH64_SHA512 (1ULL << 4)
34#define CRYPTO_CPU_CAPS_AARCH64_SHA3 (1ULL << 5)
35
21#endif 36#endif
diff --git a/src/lib/libcrypto/arch/aarch64/crypto_cpu_caps.c b/src/lib/libcrypto/arch/aarch64/crypto_cpu_caps.c
new file mode 100644
index 0000000000..24ebfbdf2b
--- /dev/null
+++ b/src/lib/libcrypto/arch/aarch64/crypto_cpu_caps.c
@@ -0,0 +1,96 @@
1/* $OpenBSD: crypto_cpu_caps.c,v 1.1 2024/11/08 13:34:24 jsing Exp $ */
2/*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/types.h>
19#include <sys/sysctl.h>
20
21#include <machine/cpu.h>
22
23#include <stddef.h>
24#include <stdio.h>
25
26#include "crypto_arch.h"
27
28uint64_t crypto_cpu_caps_aarch64;
29
30static inline uint64_t
31extract_bits(uint64_t val, int start, int end)
32{
33 return (val >> end) & (1ULL << (1 + start - end)) - 1;
34}
35
36static uint64_t
37parse_isar0(uint64_t isar0)
38{
39 uint64_t caps = 0;
40 uint64_t feature;
41
42 /* AES - bits [7:4] */
43 feature = extract_bits(isar0, 7, 4);
44 if (feature >= 1)
45 caps |= CRYPTO_CPU_CAPS_AARCH64_AES;
46 if (feature >= 2)
47 caps |= CRYPTO_CPU_CAPS_AARCH64_PMULL;
48
49 /* SHA1 - bits [11:8] */
50 feature = extract_bits(isar0, 11, 8);
51 if (feature >= 1)
52 caps |= CRYPTO_CPU_CAPS_AARCH64_SHA1;
53
54 /* SHA2 - bits [15:12] */
55 feature = extract_bits(isar0, 15, 12);
56 if (feature >= 1)
57 caps |= CRYPTO_CPU_CAPS_AARCH64_SHA2;
58 if (feature >= 2)
59 caps |= CRYPTO_CPU_CAPS_AARCH64_SHA512;
60
61 /* SHA3 - bits [35:32] */
62 feature = extract_bits(isar0, 35, 32);
63 if (feature >= 1)
64 caps |= CRYPTO_CPU_CAPS_AARCH64_SHA3;
65
66 return caps;
67}
68
69static int
70read_isar0(uint64_t *isar0)
71{
72 uint64_t isar;
73 int mib[2];
74 size_t len;
75
76 mib[0] = CTL_MACHDEP;
77 mib[1] = CPU_ID_AA64ISAR0;
78 len = sizeof(isar);
79 if (sysctl(mib, 2, &isar, &len, NULL, 0) == -1)
80 return 0;
81
82 *isar0 = isar;
83
84 return 1;
85}
86
87void
88crypto_cpu_caps_init(void)
89{
90 uint64_t isar = 0;
91
92 if (!read_isar0(&isar))
93 return;
94
95 crypto_cpu_caps_aarch64 = parse_isar0(isar);
96}