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