mirror of https://github.com/openssl/openssl.git
				
				
				
			Add basic RISC-V cpuid and OPENSSL_riscvcap
RISC-V cpuid implementation allows bitmanip extensions Zb[abcs] to be enabled at runtime using OPENSSL_riscvcap environment variable. For example, to specify 64-bit RISC-V with the G,C,Zba,Zbb,Zbc extensions, one could write: OPENSSL_riscvcap="rv64gc_zba_zbb_zbc" Architecture string parsing is still very primitive, but can be expanded in the future. Currently, only bitmanip extensions Zba, Zbb, Zbc and Zbs are supported. Includes implementation of constant-time CRYPTO_memcmp in riscv64 asm, as well as OPENSSL_cleanse. Assembly implementations are written using perlasm. Reviewed-by: Philipp Tomsich <philipp.tomsich@vrull.eu> Signed-off-by: Henry Brausen <henry.brausen@vrull.eu> Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17640)
This commit is contained in:
		
							parent
							
								
									b3504b600c
								
							
						
					
					
						commit
						360f6dcc5a
					
				|  | @ -51,6 +51,8 @@ IF[{- !$disabled{asm} && $config{processor} ne '386' -}] | ||||||
| 
 | 
 | ||||||
|   $CPUIDASM_c64xplus=c64xpluscpuid.s |   $CPUIDASM_c64xplus=c64xpluscpuid.s | ||||||
| 
 | 
 | ||||||
|  |   $CPUIDASM_riscv64=riscvcap.c riscv64cpuid.s | ||||||
|  | 
 | ||||||
|   # Now that we have defined all the arch specific variables, use the |   # Now that we have defined all the arch specific variables, use the | ||||||
|   # appropriate one, and define the appropriate macros |   # appropriate one, and define the appropriate macros | ||||||
|   IF[$CPUIDASM_{- $target{asm_arch} -}] |   IF[$CPUIDASM_{- $target{asm_arch} -}] | ||||||
|  | @ -130,6 +132,7 @@ GENERATE[armv4cpuid.S]=armv4cpuid.pl | ||||||
| INCLUDE[armv4cpuid.o]=. | INCLUDE[armv4cpuid.o]=. | ||||||
| GENERATE[s390xcpuid.S]=s390xcpuid.pl | GENERATE[s390xcpuid.S]=s390xcpuid.pl | ||||||
| INCLUDE[s390xcpuid.o]=. | INCLUDE[s390xcpuid.o]=. | ||||||
|  | GENERATE[riscv64cpuid.s]=riscv64cpuid.pl | ||||||
| 
 | 
 | ||||||
| IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] | IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] | ||||||
|   SHARED_SOURCE[../libcrypto]=dllmain.c |   SHARED_SOURCE[../libcrypto]=dllmain.c | ||||||
|  |  | ||||||
|  | @ -0,0 +1,89 @@ | ||||||
|  | #! /usr/bin/env perl | ||||||
|  | # Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  | # | ||||||
|  | # Licensed under the Apache License 2.0 (the "License").  You may not use | ||||||
|  | # 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 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # $output is the last argument if it looks like a file (it has an extension) | ||||||
|  | # $flavour is the first argument if it doesn't look like a file | ||||||
|  | $output = $#ARGV >= 0 && $ARGV[$#ARGV] =~ m|\.\w+$| ? pop : undef; | ||||||
|  | $flavour = $#ARGV >= 0 && $ARGV[0] !~ m|\.| ? shift : undef; | ||||||
|  | 
 | ||||||
|  | $output and open STDOUT,">$output"; | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  | my ($in_a,$in_b,$len,$x,$temp1,$temp2) = ('a0','a1','a2','t0','t1','t2'); | ||||||
|  | $code.=<<___; | ||||||
|  | ################################################################################ | ||||||
|  | # int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len) | ||||||
|  | ################################################################################ | ||||||
|  | .text | ||||||
|  | .balign 16 | ||||||
|  | .globl CRYPTO_memcmp | ||||||
|  | .type   CRYPTO_memcmp,\@function | ||||||
|  | CRYPTO_memcmp: | ||||||
|  |     li      $x,0 | ||||||
|  |     beqz    $len,2f   # len == 0 | ||||||
|  | 1: | ||||||
|  |     lbu     $temp1,0($in_a) | ||||||
|  |     lbu     $temp2,0($in_b) | ||||||
|  |     addi    $in_a,$in_a,1 | ||||||
|  |     addi    $in_b,$in_b,1 | ||||||
|  |     addi    $len,$len,-1 | ||||||
|  |     xor     $temp1,$temp1,$temp2 | ||||||
|  |     or      $x,$x,$temp1 | ||||||
|  |     bgtz    $len,1b | ||||||
|  | 2: | ||||||
|  |     mv      a0,$x | ||||||
|  |     ret | ||||||
|  | ___ | ||||||
|  | } | ||||||
|  | { | ||||||
|  | my ($ptr,$len,$temp1,$temp2) = ('a0','a1','t0','t1'); | ||||||
|  | $code.=<<___; | ||||||
|  | ################################################################################ | ||||||
|  | # void OPENSSL_cleanse(void *ptr, size_t len) | ||||||
|  | ################################################################################ | ||||||
|  | .text | ||||||
|  | .balign 16 | ||||||
|  | .globl OPENSSL_cleanse | ||||||
|  | .type   OPENSSL_cleanse,\@function | ||||||
|  | OPENSSL_cleanse: | ||||||
|  |     beqz    $len,2f         # len == 0, return | ||||||
|  |     srli    $temp1,$len,4 | ||||||
|  |     bnez    $temp1,3f       # len > 15 | ||||||
|  | 
 | ||||||
|  | 1:  # Store <= 15 individual bytes | ||||||
|  |     sb      x0,0($ptr) | ||||||
|  |     addi    $ptr,$ptr,1 | ||||||
|  |     addi    $len,$len,-1 | ||||||
|  |     bnez    $len,1b | ||||||
|  | 2: | ||||||
|  |     ret | ||||||
|  | 
 | ||||||
|  | 3:  # Store individual bytes until we are aligned | ||||||
|  |     andi    $temp1,$ptr,0x7 | ||||||
|  |     beqz    $temp1,4f | ||||||
|  |     sb      x0,0($ptr) | ||||||
|  |     addi    $ptr,$ptr,1 | ||||||
|  |     addi    $len,$len,-1 | ||||||
|  |     j       3b | ||||||
|  | 
 | ||||||
|  | 4:  # Store aligned dwords | ||||||
|  |     li      $temp2,8 | ||||||
|  | 4: | ||||||
|  |     sd      x0,0($ptr) | ||||||
|  |     addi    $ptr,$ptr,8 | ||||||
|  |     addi    $len,$len,-8 | ||||||
|  |     bge     $len,$temp2,4b  # if len>=8 loop | ||||||
|  |     bnez    $len,1b         # if len<8 and len != 0, store remaining bytes | ||||||
|  |     ret | ||||||
|  | ___ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | print $code; | ||||||
|  | close STDOUT or die "error closing STDOUT: $!"; | ||||||
|  | @ -0,0 +1,86 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | ||||||
|  |  * 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
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <openssl/crypto.h> | ||||||
|  | #include "internal/cryptlib.h" | ||||||
|  | 
 | ||||||
|  | #define OPENSSL_RISCVCAP_IMPL | ||||||
|  | #include "crypto/riscv_arch.h" | ||||||
|  | 
 | ||||||
|  | static void parse_env(const char *envstr); | ||||||
|  | static void strtoupper(char *str); | ||||||
|  | 
 | ||||||
|  | uint32_t OPENSSL_rdtsc(void) | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt) | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max) | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void strtoupper(char *str) | ||||||
|  | { | ||||||
|  |     for (char *x = str; *x; ++x) | ||||||
|  |         *x = toupper(*x); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* parse_env() parses a RISC-V architecture string. An example of such a string
 | ||||||
|  |  * is "rv64gc_zba_zbb_zbc_zbs". Currently, the rv64gc part is ignored | ||||||
|  |  * and we simply search for "_[extension]" in the arch string to see if we | ||||||
|  |  * should enable a given extension. | ||||||
|  |  */ | ||||||
|  | #define BUFLEN 256 | ||||||
|  | static void parse_env(const char *envstr) | ||||||
|  | { | ||||||
|  |     char envstrupper[BUFLEN]; | ||||||
|  |     char buf[BUFLEN]; | ||||||
|  | 
 | ||||||
|  |     /* Convert env str to all uppercase */ | ||||||
|  |     OPENSSL_strlcpy(envstrupper, envstr, sizeof(envstrupper)); | ||||||
|  |     strtoupper(envstrupper); | ||||||
|  | 
 | ||||||
|  |     for (size_t i = 0; i < kRISCVNumCaps; ++i) { | ||||||
|  |         /* Prefix capability with underscore in preparation for search */ | ||||||
|  |         BIO_snprintf(buf, BUFLEN, "_%s", RISCV_capabilities[i].name); | ||||||
|  |         if (strstr(envstrupper, buf) != NULL) { | ||||||
|  |             /* Match, set relevant bit in OPENSSL_riscvcap_P[] */ | ||||||
|  |             OPENSSL_riscvcap_P[RISCV_capabilities[i].index] |= | ||||||
|  |                 (1 << RISCV_capabilities[i].bit_offset); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | # if defined(__GNUC__) && __GNUC__>=2 | ||||||
|  | __attribute__ ((constructor)) | ||||||
|  | # endif | ||||||
|  | void OPENSSL_cpuid_setup(void) | ||||||
|  | { | ||||||
|  |     char *e; | ||||||
|  |     static int trigger = 0; | ||||||
|  | 
 | ||||||
|  |     if (trigger != 0) | ||||||
|  |         return; | ||||||
|  |     trigger = 1; | ||||||
|  | 
 | ||||||
|  |     if ((e = getenv("OPENSSL_riscvcap"))) { | ||||||
|  |         parse_env(e); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -74,7 +74,7 @@ See L<SSL_CTX_load_verify_locations(3)>. | ||||||
| 
 | 
 | ||||||
| Additional arguments for the L<tsget(1)> command. | Additional arguments for the L<tsget(1)> command. | ||||||
| 
 | 
 | ||||||
| =item B<OPENSSL_ia32cap>, B<OPENSSL_sparcv9cap>, B<OPENSSL_ppccap>, B<OPENSSL_armcap>, B<OPENSSL_s390xcap> | =item B<OPENSSL_ia32cap>, B<OPENSSL_sparcv9cap>, B<OPENSSL_ppccap>, B<OPENSSL_armcap>, B<OPENSSL_s390xcap>, B<OPENSSL_riscvcap> | ||||||
| 
 | 
 | ||||||
| OpenSSL supports a number of different algorithm implementations for | OpenSSL supports a number of different algorithm implementations for | ||||||
| various machines and, by default, it determines which to use based on the | various machines and, by default, it determines which to use based on the | ||||||
|  | @ -91,7 +91,7 @@ See L<OSSL_HTTP_parse_url(3)>. | ||||||
| 
 | 
 | ||||||
| =head1 COPYRIGHT | =head1 COPYRIGHT | ||||||
| 
 | 
 | ||||||
| Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. | Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. | ||||||
| 
 | 
 | ||||||
| Licensed under the Apache License 2.0 (the "License").  You may not use | Licensed under the Apache License 2.0 (the "License").  You may not use | ||||||
| this file except in compliance with the License.  You can obtain a copy | this file except in compliance with the License.  You can obtain a copy | ||||||
|  |  | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | ||||||
|  |  * 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 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | /* X Macro Definitions for Specification of RISC-V Arch Capabilities */ | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * Each RISC-V capability ends up encoded as a single set bit in an array of | ||||||
|  |  * words. When specifying a new capability, write a new RISCV_DEFINE_CAP | ||||||
|  |  * statement, with an argument as the extension name in all-caps, | ||||||
|  |  * second argument as the index in the array where the capability will be stored | ||||||
|  |  * and third argument as the index of the bit to be used to encode the | ||||||
|  |  * capability. | ||||||
|  |  * RISCV_DEFINE_CAP(EXTENSION NAME, array index, bit index) */ | ||||||
|  | 
 | ||||||
|  | RISCV_DEFINE_CAP(ZBA, 0, 0) | ||||||
|  | RISCV_DEFINE_CAP(ZBB, 0, 1) | ||||||
|  | RISCV_DEFINE_CAP(ZBC, 0, 2) | ||||||
|  | RISCV_DEFINE_CAP(ZBS, 0, 3) | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  |  * In the future ... | ||||||
|  |  * RISCV_DEFINE_CAP(ZFOO, 0, 31) | ||||||
|  |  * RISCV_DEFINE_CAP(ZBAR, 1, 0) | ||||||
|  |  * ... and so on. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #undef RISCV_DEFINE_CAP | ||||||
|  | @ -0,0 +1,59 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. | ||||||
|  |  * | ||||||
|  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | ||||||
|  |  * 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
 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef OSSL_CRYPTO_RISCV_ARCH_H | ||||||
|  | # define OSSL_CRYPTO_RISCV_ARCH_H | ||||||
|  | 
 | ||||||
|  | # include <ctype.h> | ||||||
|  | # include <stdint.h> | ||||||
|  | 
 | ||||||
|  | # define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 | ||||||
|  | extern uint32_t OPENSSL_riscvcap_P[ (( | ||||||
|  | # include "riscv_arch.def" | ||||||
|  | ) + sizeof(uint32_t) - 1) / sizeof(uint32_t) ]; | ||||||
|  | 
 | ||||||
|  | # ifdef OPENSSL_RISCVCAP_IMPL | ||||||
|  | #  define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 | ||||||
|  | uint32_t OPENSSL_riscvcap_P[ (( | ||||||
|  | #  include "riscv_arch.def" | ||||||
|  | ) + sizeof(uint32_t) - 1) / sizeof(uint32_t) ]; | ||||||
|  | # endif | ||||||
|  | 
 | ||||||
|  | # define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX)                   \ | ||||||
|  |     static inline int RISCV_HAS_##NAME(void)                        \ | ||||||
|  |     {                                                               \ | ||||||
|  |         return (OPENSSL_riscvcap_P[INDEX] & (1 << BIT_INDEX)) != 0; \ | ||||||
|  |     } | ||||||
|  | # include "riscv_arch.def" | ||||||
|  | 
 | ||||||
|  | struct RISCV_capability_s { | ||||||
|  |     const char *name; | ||||||
|  |     size_t index; | ||||||
|  |     size_t bit_offset; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | # define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 | ||||||
|  | extern const struct RISCV_capability_s RISCV_capabilities[ | ||||||
|  | # include "riscv_arch.def" | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | # ifdef OPENSSL_RISCVCAP_IMPL | ||||||
|  | #  define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) \ | ||||||
|  |     { #NAME, INDEX, BIT_INDEX }, | ||||||
|  | const struct RISCV_capability_s RISCV_capabilities[] = { | ||||||
|  | #  include "riscv_arch.def" | ||||||
|  | }; | ||||||
|  | # endif | ||||||
|  | 
 | ||||||
|  | # define RISCV_DEFINE_CAP(NAME, INDEX, BIT_INDEX) +1 | ||||||
|  | static const size_t kRISCVNumCaps = | ||||||
|  | # include "riscv_arch.def" | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
		Loading…
	
		Reference in New Issue