| 
									
										
										
										
											2016-05-18 02:51:26 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2018-02-13 20:51:29 +08:00
										 |  |  |  * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2016-05-18 02:51:26 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-06 21:03:01 +08:00
										 |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							| 
									
										
										
										
											2016-05-18 02:51:26 +08:00
										 |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <setjmp.h>
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							| 
									
										
										
										
											2015-04-02 16:17:42 +08:00
										 |  |  | #include <openssl/crypto.h>
 | 
					
						
							| 
									
										
										
										
											2017-11-20 00:40:56 +08:00
										 |  |  | #include "internal/cryptlib.h"
 | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "arm_arch.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | unsigned int OPENSSL_armcap_P = 0; | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-08 05:48:22 +08:00
										 |  |  | #if __ARM_MAX_ARCH__<7
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | void OPENSSL_cpuid_setup(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 00:40:56 +08:00
										 |  |  | uint32_t OPENSSL_rdtsc(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-11-08 05:48:22 +08:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | static sigset_t all_masked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static sigjmp_buf ill_jmp; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | static void ill_handler(int sig) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     siglongjmp(ill_jmp, sig); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Following subroutines could have been inlined, but it's not all | 
					
						
							|  |  |  |  * ARM compilers support inline assembler... | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void _armv7_neon_probe(void); | 
					
						
							| 
									
										
										
										
											2014-05-04 16:55:49 +08:00
										 |  |  | void _armv8_aes_probe(void); | 
					
						
							|  |  |  | void _armv8_sha1_probe(void); | 
					
						
							|  |  |  | void _armv8_sha256_probe(void); | 
					
						
							|  |  |  | void _armv8_pmull_probe(void); | 
					
						
							| 
									
										
										
										
											2018-02-11 19:29:06 +08:00
										 |  |  | # ifdef __aarch64__
 | 
					
						
							|  |  |  | void _armv8_sha512_probe(void); | 
					
						
							|  |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2017-11-20 00:40:56 +08:00
										 |  |  | uint32_t _armv7_tick(void); | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 00:40:56 +08:00
										 |  |  | uint32_t OPENSSL_rdtsc(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (OPENSSL_armcap_P & ARMV7_TICK) | 
					
						
							|  |  |  |         return _armv7_tick(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-05 18:25:10 +08:00
										 |  |  | # if defined(__GNUC__) && __GNUC__>=2
 | 
					
						
							|  |  |  | void OPENSSL_cpuid_setup(void) __attribute__ ((constructor)); | 
					
						
							|  |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2019-01-16 13:31:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | # if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
 | 
					
						
							|  |  |  | #  if __GLIBC_PREREQ(2, 16)
 | 
					
						
							|  |  |  | #   include <sys/auxv.h>
 | 
					
						
							|  |  |  | #   define OSSL_IMPLEMENT_GETAUXVAL
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2014-06-01 23:21:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2017-08-04 13:10:41 +08:00
										 |  |  |  * ARM puts the feature bits for Crypto Extensions in AT_HWCAP2, whereas | 
					
						
							| 
									
										
										
										
											2014-06-01 23:21:06 +08:00
										 |  |  |  * AArch64 used AT_HWCAP. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # if defined(__arm__) || defined (__arm)
 | 
					
						
							|  |  |  | #  define HWCAP                  16
 | 
					
						
							|  |  |  |                                   /* AT_HWCAP */ | 
					
						
							|  |  |  | #  define HWCAP_NEON             (1 << 12)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  define HWCAP_CE               26
 | 
					
						
							|  |  |  |                                   /* AT_HWCAP2 */ | 
					
						
							|  |  |  | #  define HWCAP_CE_AES           (1 << 0)
 | 
					
						
							|  |  |  | #  define HWCAP_CE_PMULL         (1 << 1)
 | 
					
						
							|  |  |  | #  define HWCAP_CE_SHA1          (1 << 2)
 | 
					
						
							|  |  |  | #  define HWCAP_CE_SHA256        (1 << 3)
 | 
					
						
							|  |  |  | # elif defined(__aarch64__)
 | 
					
						
							|  |  |  | #  define HWCAP                  16
 | 
					
						
							|  |  |  |                                   /* AT_HWCAP */ | 
					
						
							|  |  |  | #  define HWCAP_NEON             (1 << 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  define HWCAP_CE               HWCAP
 | 
					
						
							|  |  |  | #  define HWCAP_CE_AES           (1 << 3)
 | 
					
						
							|  |  |  | #  define HWCAP_CE_PMULL         (1 << 4)
 | 
					
						
							|  |  |  | #  define HWCAP_CE_SHA1          (1 << 5)
 | 
					
						
							|  |  |  | #  define HWCAP_CE_SHA256        (1 << 6)
 | 
					
						
							| 
									
										
										
										
											2018-02-11 19:29:06 +08:00
										 |  |  | #  define HWCAP_CE_SHA512        (1 << 21)
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | # endif
 | 
					
						
							| 
									
										
										
										
											2014-06-01 23:21:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-18 01:40:29 +08:00
										 |  |  | void OPENSSL_cpuid_setup(void) | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-06-11 21:38:05 +08:00
										 |  |  |     const char *e; | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     struct sigaction ill_oact, ill_act; | 
					
						
							|  |  |  |     sigset_t oset; | 
					
						
							|  |  |  |     static int trigger = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (trigger) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     trigger = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((e = getenv("OPENSSL_armcap"))) { | 
					
						
							|  |  |  |         OPENSSL_armcap_P = (unsigned int)strtoul(e, NULL, 0); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 19:01:09 +08:00
										 |  |  | # if defined(__APPLE__) && !defined(__aarch64__)
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Capability probing by catching SIGILL appears to be problematic | 
					
						
							|  |  |  |      * on iOS. But since Apple universe is "monocultural", it's actually | 
					
						
							|  |  |  |      * possible to simply set pre-defined processor capability mask. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     if (1) { | 
					
						
							|  |  |  |         OPENSSL_armcap_P = ARMV7_NEON; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * One could do same even for __aarch64__ iOS builds. It's not done | 
					
						
							|  |  |  |      * exclusively for reasons of keeping code unified across platforms. | 
					
						
							|  |  |  |      * Unified code works because it never triggers SIGILL on Apple | 
					
						
							|  |  |  |      * devices... | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-16 13:31:15 +08:00
										 |  |  |     OPENSSL_armcap_P = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # ifdef OSSL_IMPLEMENT_GETAUXVAL
 | 
					
						
							|  |  |  |     if (getauxval(HWCAP) & HWCAP_NEON) { | 
					
						
							|  |  |  |         unsigned long hwcap = getauxval(HWCAP_CE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         OPENSSL_armcap_P |= ARMV7_NEON; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (hwcap & HWCAP_CE_AES) | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_AES; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (hwcap & HWCAP_CE_PMULL) | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_PMULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (hwcap & HWCAP_CE_SHA1) | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_SHA1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (hwcap & HWCAP_CE_SHA256) | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_SHA256; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #  ifdef __aarch64__
 | 
					
						
							|  |  |  |         if (hwcap & HWCAP_CE_SHA512) | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_SHA512; | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | # endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     sigfillset(&all_masked); | 
					
						
							|  |  |  |     sigdelset(&all_masked, SIGILL); | 
					
						
							|  |  |  |     sigdelset(&all_masked, SIGTRAP); | 
					
						
							|  |  |  |     sigdelset(&all_masked, SIGFPE); | 
					
						
							|  |  |  |     sigdelset(&all_masked, SIGBUS); | 
					
						
							|  |  |  |     sigdelset(&all_masked, SIGSEGV); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memset(&ill_act, 0, sizeof(ill_act)); | 
					
						
							|  |  |  |     ill_act.sa_handler = ill_handler; | 
					
						
							|  |  |  |     ill_act.sa_mask = all_masked; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); | 
					
						
							|  |  |  |     sigaction(SIGILL, &ill_act, &ill_oact); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-16 13:31:15 +08:00
										 |  |  |     /* If we used getauxval, we already have all the values */ | 
					
						
							|  |  |  | # ifndef OSSL_IMPLEMENT_GETAUXVAL
 | 
					
						
							|  |  |  |     if (sigsetjmp(ill_jmp, 1) == 0) { | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |         _armv7_neon_probe(); | 
					
						
							|  |  |  |         OPENSSL_armcap_P |= ARMV7_NEON; | 
					
						
							|  |  |  |         if (sigsetjmp(ill_jmp, 1) == 0) { | 
					
						
							|  |  |  |             _armv8_pmull_probe(); | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; | 
					
						
							|  |  |  |         } else if (sigsetjmp(ill_jmp, 1) == 0) { | 
					
						
							|  |  |  |             _armv8_aes_probe(); | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_AES; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (sigsetjmp(ill_jmp, 1) == 0) { | 
					
						
							|  |  |  |             _armv8_sha1_probe(); | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_SHA1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (sigsetjmp(ill_jmp, 1) == 0) { | 
					
						
							|  |  |  |             _armv8_sha256_probe(); | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_SHA256; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-01-16 13:31:15 +08:00
										 |  |  | #  if defined(__aarch64__) && !defined(__APPLE__)
 | 
					
						
							| 
									
										
										
										
											2018-02-11 19:29:06 +08:00
										 |  |  |         if (sigsetjmp(ill_jmp, 1) == 0) { | 
					
						
							|  |  |  |             _armv8_sha512_probe(); | 
					
						
							|  |  |  |             OPENSSL_armcap_P |= ARMV8_SHA512; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-01-16 13:31:15 +08:00
										 |  |  | #  endif
 | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-01-16 13:31:15 +08:00
										 |  |  | # endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Things that getauxval didn't tell us */ | 
					
						
							| 
									
										
										
										
											2015-01-22 11:40:55 +08:00
										 |  |  |     if (sigsetjmp(ill_jmp, 1) == 0) { | 
					
						
							|  |  |  |         _armv7_tick(); | 
					
						
							|  |  |  |         OPENSSL_armcap_P |= ARMV7_TICK; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sigaction(SIGILL, &ill_oact, NULL); | 
					
						
							|  |  |  |     sigprocmask(SIG_SETMASK, &oset, NULL); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-11-08 05:48:22 +08:00
										 |  |  | #endif
 |