131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <stdio.h>
231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <stdlib.h>
331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <string.h>
431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <setjmp.h>
531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <signal.h>
631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include <crypto.h>
731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#include "arm_arch.h"
931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootunsigned int OPENSSL_armcap_P;
1131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootstatic sigset_t all_masked;
1331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootstatic sigjmp_buf ill_jmp;
1531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootstatic void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
1631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root/*
1831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root * Following subroutines could have been inlined, but it's not all
1931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root * ARM compilers support inline assembler...
2031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root */
2131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootvoid _armv7_neon_probe(void);
223f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid _armv8_aes_probe(void);
233f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid _armv8_sha1_probe(void);
243f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid _armv8_sha256_probe(void);
253f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid _armv8_pmull_probe(void);
263f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootunsigned long _armv7_tick(void);
2731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
283f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootunsigned long OPENSSL_rdtsc(void)
2931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	{
3031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if (OPENSSL_armcap_P & ARMV7_TICK)
3131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		return _armv7_tick();
3231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	else
3331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		return 0;
3431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	}
3531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
363f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root/*
373f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root * Use a weak reference to getauxval() so we can use it if it is available but
383f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root * don't break the build if it is not.
393f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root */
4031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#if defined(__GNUC__) && __GNUC__>=2
4131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootvoid OPENSSL_cpuid_setup(void) __attribute__((constructor));
423f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootextern unsigned long getauxval(unsigned long type) __attribute__((weak));
433f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#else
443f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootstatic unsigned long (*getauxval)(unsigned long) = NULL;
4531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root#endif
463f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
473f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root/*
483f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root * ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas
493f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root * AArch64 used AT_HWCAP.
503f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root */
513f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#if defined(__arm__) || defined (__arm)
523f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP			16	/* AT_HWCAP */
533f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_NEON		(1 << 12)
543f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
553f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE		26	/* AT_HWCAP2 */
563f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_AES		(1 << 0)
573f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_PMULL		(1 << 1)
583f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_SHA1		(1 << 2)
593f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_SHA256	(1 << 3)
603f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#elif defined(__aarch64__)
613f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP			16	/* AT_HWCAP */
623f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_NEON		(1 << 1)
633f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
643f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE		HWCAP
653f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_AES		(1 << 3)
663f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_PMULL		(1 << 4)
673f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_SHA1		(1 << 5)
683f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# define HWCAP_CE_SHA256	(1 << 6)
693f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#endif
703f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
7131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Rootvoid OPENSSL_cpuid_setup(void)
7231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	{
7331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	char *e;
7431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	struct sigaction	ill_oact,ill_act;
7531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigset_t		oset;
7631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	static int trigger=0;
7731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
7831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if (trigger) return;
7931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	trigger=1;
8031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
8131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if ((e=getenv("OPENSSL_armcap")))
8231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		{
833f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		OPENSSL_armcap_P=(unsigned int)strtoul(e,NULL,0);
8431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		return;
8531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		}
8631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
8731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigfillset(&all_masked);
8831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGILL);
8931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGTRAP);
9031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGFPE);
9131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGBUS);
9231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigdelset(&all_masked,SIGSEGV);
9331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
9431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	OPENSSL_armcap_P = 0;
9531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
9631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	memset(&ill_act,0,sizeof(ill_act));
9731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	ill_act.sa_handler = ill_handler;
9831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	ill_act.sa_mask    = all_masked;
9931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
10031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
10131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigaction(SIGILL,&ill_act,&ill_oact);
10231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
1033f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root	if (getauxval != NULL)
1043f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		{
1053f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		if (getauxval(HWCAP) & HWCAP_NEON)
1063f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			{
1073f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			unsigned long hwcap = getauxval(HWCAP_CE);
1083f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
1093f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			OPENSSL_armcap_P |= ARMV7_NEON;
1103f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
1113f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			if (hwcap & HWCAP_CE_AES)
1123f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root				OPENSSL_armcap_P |= ARMV8_AES;
1133f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
1143f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			if (hwcap & HWCAP_CE_PMULL)
1153f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root				OPENSSL_armcap_P |= ARMV8_PMULL;
1163f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
1173f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			if (hwcap & HWCAP_CE_SHA1)
1183f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root				OPENSSL_armcap_P |= ARMV8_SHA1;
1193f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root
1203f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			if (hwcap & HWCAP_CE_SHA256)
1213f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root				OPENSSL_armcap_P |= ARMV8_SHA256;
1223f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			}
1233f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		}
1243f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root	else if (sigsetjmp(ill_jmp,1) == 0)
12531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		{
12631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		_armv7_neon_probe();
12731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		OPENSSL_armcap_P |= ARMV7_NEON;
1283f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		if (sigsetjmp(ill_jmp,1) == 0)
1293f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			{
1303f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			_armv8_pmull_probe();
1313f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			OPENSSL_armcap_P |= ARMV8_PMULL|ARMV8_AES;
1323f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			}
1333f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		else if (sigsetjmp(ill_jmp,1) == 0)
1343f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			{
1353f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			_armv8_aes_probe();
1363f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			OPENSSL_armcap_P |= ARMV8_AES;
1373f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			}
1383f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		if (sigsetjmp(ill_jmp,1) == 0)
1393f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			{
1403f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			_armv8_sha1_probe();
1413f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			OPENSSL_armcap_P |= ARMV8_SHA1;
1423f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			}
1433f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		if (sigsetjmp(ill_jmp,1) == 0)
1443f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			{
1453f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			_armv8_sha256_probe();
1463f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			OPENSSL_armcap_P |= ARMV8_SHA256;
1473f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root			}
14831cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		}
14931cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	if (sigsetjmp(ill_jmp,1) == 0)
15031cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		{
15131cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		_armv7_tick();
15231cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		OPENSSL_armcap_P |= ARMV7_TICK;
15331cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root		}
15431cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root
15531cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigaction (SIGILL,&ill_oact,NULL);
15631cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	sigprocmask(SIG_SETMASK,&oset,NULL);
15731cf9ecd5035e6b5e8640ec5cc0c3f022e7f6895Kenny Root	}
158