diff --git a/unix/utils/arm_arch_queries.c b/unix/utils/arm_arch_queries.c index cc3e4125..d6dc97bc 100644 --- a/unix/utils/arm_arch_queries.c +++ b/unix/utils/arm_arch_queries.c @@ -17,10 +17,11 @@ bool platform_aes_neon_available(void) #elif defined HWCAP2_AES return getauxval(AT_HWCAP2) & HWCAP2_AES; #elif defined __APPLE__ - /* M1 macOS defines no optional sysctl flag indicating presence of - * the AES extension, which I assume to be because it's always - * present */ - return true; + SysctlResult res = test_sysctl_flag("hw.optional.arm.FEAT_AES"); + /* Older M1 macOS didn't provide this flag, but as far as I know + * implemented the crypto extension anyway, so treat 'feature + * missing' as 'implemented' */ + return res != SYSCTL_OFF; #else return false; #endif @@ -33,8 +34,9 @@ bool platform_sha256_neon_available(void) #elif defined HWCAP2_SHA2 return getauxval(AT_HWCAP2) & HWCAP2_SHA2; #elif defined __APPLE__ - /* Assume always present on M1 macOS, similarly to AES */ - return true; + SysctlResult res = test_sysctl_flag("hw.optional.arm.FEAT_SHA256"); + /* As above, treat 'missing' as enabled */ + return res != SYSCTL_OFF; #else return false; #endif @@ -47,8 +49,9 @@ bool platform_sha1_neon_available(void) #elif defined HWCAP2_SHA1 return getauxval(AT_HWCAP2) & HWCAP2_SHA1; #elif defined __APPLE__ - /* Assume always present on M1 macOS, similarly to AES */ - return true; + SysctlResult res = test_sysctl_flag("hw.optional.arm.FEAT_SHA1"); + /* As above, treat 'missing' as enabled */ + return res != SYSCTL_OFF; #else return false; #endif @@ -61,7 +64,14 @@ bool platform_sha512_neon_available(void) #elif defined HWCAP2_SHA512 return getauxval(AT_HWCAP2) & HWCAP2_SHA512; #elif defined __APPLE__ - return test_sysctl_flag("hw.optional.armv8_2_sha512"); + /* There are two sysctl flags for this, apparently invented at + * different times. Try both, falling back to the older one. */ + SysctlResult res = test_sysctl_flag("hw.optional.arm.FEAT_SHA512"); + if (res != SYSCTL_MISSING) + return res == SYSCTL_ON; + + res = test_sysctl_flag("hw.optional.armv8_2_sha512"); + return res == SYSCTL_ON; #else return false; #endif diff --git a/unix/utils/arm_arch_queries.h b/unix/utils/arm_arch_queries.h index bd055687..fa46c622 100644 --- a/unix/utils/arm_arch_queries.h +++ b/unix/utils/arm_arch_queries.h @@ -49,15 +49,19 @@ static inline u_long getauxval(int which) { return 0; } #endif /* defined __arm__ || defined __aarch64__ */ #if defined __APPLE__ -static inline bool test_sysctl_flag(const char *flagname) +typedef enum { SYSCTL_MISSING, SYSCTL_OFF, SYSCTL_ON } SysctlResult; + +static inline SysctlResult test_sysctl_flag(const char *flagname) { #if HAVE_SYSCTLBYNAME int value; size_t size = sizeof(value); - return (sysctlbyname(flagname, &value, &size, NULL, 0) == 0 && - size == sizeof(value) && value != 0); + if (sysctlbyname(flagname, &value, &size, NULL, 0) == 0 && + size == sizeof(value)) { + return value != 0 ? SYSCTL_ON : SYSCTL_OFF; + } #else /* HAVE_SYSCTLBYNAME */ - return false; + return SYSCTL_MISSING; #endif /* HAVE_SYSCTLBYNAME */ } #endif /* defined __APPLE__ */