Home | History | Annotate | Download | only in crypto
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <setjmp.h>
      5 #include <signal.h>
      6 #include <crypto.h>
      7 
      8 #include "arm_arch.h"
      9 
     10 unsigned int OPENSSL_armcap_P;
     11 
     12 static sigset_t all_masked;
     13 
     14 static sigjmp_buf ill_jmp;
     15 static void ill_handler (int sig) { siglongjmp(ill_jmp,sig); }
     16 
     17 /*
     18  * Following subroutines could have been inlined, but it's not all
     19  * ARM compilers support inline assembler...
     20  */
     21 void _armv7_neon_probe(void);
     22 void _armv8_aes_probe(void);
     23 void _armv8_sha1_probe(void);
     24 void _armv8_sha256_probe(void);
     25 void _armv8_pmull_probe(void);
     26 unsigned long _armv7_tick(void);
     27 
     28 unsigned long OPENSSL_rdtsc(void)
     29 	{
     30 	if (OPENSSL_armcap_P & ARMV7_TICK)
     31 		return _armv7_tick();
     32 	else
     33 		return 0;
     34 	}
     35 
     36 /*
     37  * Use a weak reference to getauxval() so we can use it if it is available but
     38  * don't break the build if it is not.
     39  */
     40 #if defined(__GNUC__) && __GNUC__>=2
     41 void OPENSSL_cpuid_setup(void) __attribute__((constructor));
     42 extern unsigned long getauxval(unsigned long type) __attribute__((weak));
     43 #else
     44 static unsigned long (*getauxval)(unsigned long) = NULL;
     45 #endif
     46 
     47 /*
     48  * ARM puts the the feature bits for Crypto Extensions in AT_HWCAP2, whereas
     49  * AArch64 used AT_HWCAP.
     50  */
     51 #if defined(__arm__) || defined (__arm)
     52 # define HWCAP			16	/* AT_HWCAP */
     53 # define HWCAP_NEON		(1 << 12)
     54 
     55 # define HWCAP_CE		26	/* AT_HWCAP2 */
     56 # define HWCAP_CE_AES		(1 << 0)
     57 # define HWCAP_CE_PMULL		(1 << 1)
     58 # define HWCAP_CE_SHA1		(1 << 2)
     59 # define HWCAP_CE_SHA256	(1 << 3)
     60 #elif defined(__aarch64__)
     61 # define HWCAP			16	/* AT_HWCAP */
     62 # define HWCAP_NEON		(1 << 1)
     63 
     64 # define HWCAP_CE		HWCAP
     65 # define HWCAP_CE_AES		(1 << 3)
     66 # define HWCAP_CE_PMULL		(1 << 4)
     67 # define HWCAP_CE_SHA1		(1 << 5)
     68 # define HWCAP_CE_SHA256	(1 << 6)
     69 #endif
     70 
     71 void OPENSSL_cpuid_setup(void)
     72 	{
     73 	char *e;
     74 	struct sigaction	ill_oact,ill_act;
     75 	sigset_t		oset;
     76 	static int trigger=0;
     77 
     78 	if (trigger) return;
     79 	trigger=1;
     80 
     81 	if ((e=getenv("OPENSSL_armcap")))
     82 		{
     83 		OPENSSL_armcap_P=(unsigned int)strtoul(e,NULL,0);
     84 		return;
     85 		}
     86 
     87 	sigfillset(&all_masked);
     88 	sigdelset(&all_masked,SIGILL);
     89 	sigdelset(&all_masked,SIGTRAP);
     90 	sigdelset(&all_masked,SIGFPE);
     91 	sigdelset(&all_masked,SIGBUS);
     92 	sigdelset(&all_masked,SIGSEGV);
     93 
     94 	OPENSSL_armcap_P = 0;
     95 
     96 	memset(&ill_act,0,sizeof(ill_act));
     97 	ill_act.sa_handler = ill_handler;
     98 	ill_act.sa_mask    = all_masked;
     99 
    100 	sigprocmask(SIG_SETMASK,&ill_act.sa_mask,&oset);
    101 	sigaction(SIGILL,&ill_act,&ill_oact);
    102 
    103 	if (getauxval != NULL)
    104 		{
    105 		if (getauxval(HWCAP) & HWCAP_NEON)
    106 			{
    107 			unsigned long hwcap = getauxval(HWCAP_CE);
    108 
    109 			OPENSSL_armcap_P |= ARMV7_NEON;
    110 
    111 			if (hwcap & HWCAP_CE_AES)
    112 				OPENSSL_armcap_P |= ARMV8_AES;
    113 
    114 			if (hwcap & HWCAP_CE_PMULL)
    115 				OPENSSL_armcap_P |= ARMV8_PMULL;
    116 
    117 			if (hwcap & HWCAP_CE_SHA1)
    118 				OPENSSL_armcap_P |= ARMV8_SHA1;
    119 
    120 			if (hwcap & HWCAP_CE_SHA256)
    121 				OPENSSL_armcap_P |= ARMV8_SHA256;
    122 			}
    123 		}
    124 	else if (sigsetjmp(ill_jmp,1) == 0)
    125 		{
    126 		_armv7_neon_probe();
    127 		OPENSSL_armcap_P |= ARMV7_NEON;
    128 		if (sigsetjmp(ill_jmp,1) == 0)
    129 			{
    130 			_armv8_pmull_probe();
    131 			OPENSSL_armcap_P |= ARMV8_PMULL|ARMV8_AES;
    132 			}
    133 		else if (sigsetjmp(ill_jmp,1) == 0)
    134 			{
    135 			_armv8_aes_probe();
    136 			OPENSSL_armcap_P |= ARMV8_AES;
    137 			}
    138 		if (sigsetjmp(ill_jmp,1) == 0)
    139 			{
    140 			_armv8_sha1_probe();
    141 			OPENSSL_armcap_P |= ARMV8_SHA1;
    142 			}
    143 		if (sigsetjmp(ill_jmp,1) == 0)
    144 			{
    145 			_armv8_sha256_probe();
    146 			OPENSSL_armcap_P |= ARMV8_SHA256;
    147 			}
    148 		}
    149 	if (sigsetjmp(ill_jmp,1) == 0)
    150 		{
    151 		_armv7_tick();
    152 		OPENSSL_armcap_P |= ARMV7_TICK;
    153 		}
    154 
    155 	sigaction (SIGILL,&ill_oact,NULL);
    156 	sigprocmask(SIG_SETMASK,&oset,NULL);
    157 	}
    158