xref: /openbsd-src/lib/libcrypto/arch/aarch64/crypto_cpu_caps.c (revision 504020dca5ad63d843f2810f0f74b6715810d111)
1 /* $OpenBSD: crypto_cpu_caps.c,v 1.2 2024/11/12 13:52:31 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 
28 /* Machine dependent CPU capabilities. */
29 uint64_t crypto_cpu_caps_aarch64;
30 
31 static inline uint64_t
32 extract_bits(uint64_t val, int start, int end)
33 {
34 	return (val >> end) & (1ULL << (1 + start - end)) - 1;
35 }
36 
37 static uint64_t
38 parse_isar0(uint64_t isar0)
39 {
40 	uint64_t caps = 0;
41 	uint64_t feature;
42 
43 	/* AES - bits [7:4] */
44 	feature = extract_bits(isar0, 7, 4);
45 	if (feature >= 1)
46 		caps |= CRYPTO_CPU_CAPS_AARCH64_AES;
47 	if (feature >= 2)
48 		caps |= CRYPTO_CPU_CAPS_AARCH64_PMULL;
49 
50 	/* SHA1 - bits [11:8] */
51 	feature = extract_bits(isar0, 11, 8);
52 	if (feature >= 1)
53 		caps |= CRYPTO_CPU_CAPS_AARCH64_SHA1;
54 
55 	/* SHA2 - bits [15:12] */
56 	feature = extract_bits(isar0, 15, 12);
57 	if (feature >= 1)
58 		caps |= CRYPTO_CPU_CAPS_AARCH64_SHA2;
59 	if (feature >= 2)
60 		caps |= CRYPTO_CPU_CAPS_AARCH64_SHA512;
61 
62 	/* SHA3 - bits [35:32] */
63 	feature = extract_bits(isar0, 35, 32);
64 	if (feature >= 1)
65 		caps |= CRYPTO_CPU_CAPS_AARCH64_SHA3;
66 
67 	return caps;
68 }
69 
70 static int
71 read_isar0(uint64_t *isar0)
72 {
73 	uint64_t isar;
74 	int mib[2];
75 	size_t len;
76 
77 	mib[0] = CTL_MACHDEP;
78 	mib[1] = CPU_ID_AA64ISAR0;
79 	len = sizeof(isar);
80 	if (sysctl(mib, 2, &isar, &len, NULL, 0) == -1)
81 		return 0;
82 
83 	*isar0 = isar;
84 
85 	return 1;
86 }
87 
88 void
89 crypto_cpu_caps_init(void)
90 {
91 	uint64_t isar = 0;
92 
93 	if (!read_isar0(&isar))
94 		return;
95 
96 	crypto_cpu_caps_aarch64 = parse_isar0(isar);
97 }
98