#include <sys/types.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
#include <stddef.h>
#include <stdio.h>
#include "crypto_arch.h"
uint64_t crypto_cpu_caps_aarch64;
static inline uint64_t
extract_bits(uint64_t val, int start, int end)
{
return (val >> end) & (1ULL << (1 + start - end)) - 1;
}
static uint64_t
parse_isar0(uint64_t isar0)
{
uint64_t caps = 0;
uint64_t feature;
feature = extract_bits(isar0, 7, 4);
if (feature >= 1)
caps |= CRYPTO_CPU_CAPS_AARCH64_AES;
if (feature >= 2)
caps |= CRYPTO_CPU_CAPS_AARCH64_PMULL;
feature = extract_bits(isar0, 11, 8);
if (feature >= 1)
caps |= CRYPTO_CPU_CAPS_AARCH64_SHA1;
feature = extract_bits(isar0, 15, 12);
if (feature >= 1)
caps |= CRYPTO_CPU_CAPS_AARCH64_SHA2;
if (feature >= 2)
caps |= CRYPTO_CPU_CAPS_AARCH64_SHA512;
feature = extract_bits(isar0, 35, 32);
if (feature >= 1)
caps |= CRYPTO_CPU_CAPS_AARCH64_SHA3;
return caps;
}
static int
read_isar0(uint64_t *isar0)
{
uint64_t isar;
int mib[2];
size_t len;
mib[0] = CTL_MACHDEP;
mib[1] = CPU_ID_AA64ISAR0;
len = sizeof(isar);
if (sysctl(mib, 2, &isar, &len, NULL, 0) == -1)
return 0;
*isar0 = isar;
return 1;
}
void
crypto_cpu_caps_init(void)
{
uint64_t isar = 0;
if (!read_isar0(&isar))
return;
crypto_cpu_caps_aarch64 = parse_isar0(isar);
}