summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorHenry Brausen <henry.brausen@vrull.eu>2022-01-28 01:28:52 -0700
committerTomas Mraz <tomas@openssl.org>2022-11-21 10:49:52 +0100
commit8448432a3be6cd5eb2576594c742e3d54d92f78a (patch)
tree59b96ecce2d8dbf89a1ec07af702a6e7757a8505 /crypto
parentb60603c5e3ac6396306bbaafd829f8340d22e1a0 (diff)
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) (cherry picked from commit 360f6dcc5aa1a86ec3ff9a94612b88e3d960ee2e)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/build.info3
-rw-r--r--crypto/riscv64cpuid.pl89
-rw-r--r--crypto/riscvcap.c86
3 files changed, 178 insertions, 0 deletions
diff --git a/crypto/build.info b/crypto/build.info
index a45bf8deef..f568234081 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -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
diff --git a/crypto/riscv64cpuid.pl b/crypto/riscv64cpuid.pl
new file mode 100644
index 0000000000..675e9b6111
--- /dev/null
+++ b/crypto/riscv64cpuid.pl
@@ -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: $!";
diff --git a/crypto/riscvcap.c b/crypto/riscvcap.c
new file mode 100644
index 0000000000..1cbfb4a574
--- /dev/null
+++ b/crypto/riscvcap.c
@@ -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;
+ }
+}