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_riscv64=riscvcap.c riscv64cpuid.s | ||||
| 
 | ||||
|   # Now that we have defined all the arch specific variables, use the | ||||
|   # appropriate one, and define the appropriate macros | ||||
|   IF[$CPUIDASM_{- $target{asm_arch} -}] | ||||
|  | @ -130,6 +132,7 @@ GENERATE[armv4cpuid.S]=armv4cpuid.pl | |||
| INCLUDE[armv4cpuid.o]=. | ||||
| GENERATE[s390xcpuid.S]=s390xcpuid.pl | ||||
| INCLUDE[s390xcpuid.o]=. | ||||
| GENERATE[riscv64cpuid.s]=riscv64cpuid.pl | ||||
| 
 | ||||
| IF[{- $config{target} =~ /^(?:Cygwin|mingw|VC-|BC-)/ -}] | ||||
|   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. | ||||
| 
 | ||||
| =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 | ||||
| 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 | ||||
| 
 | ||||
| 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 | ||||
| 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