mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'riscv-for-linus-6.9-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V updates from Palmer Dabbelt:
- Support for various vector-accelerated crypto routines
- Hibernation is now enabled for portable kernel builds
- mmap_rnd_bits_max is larger on systems with larger VAs
- Support for fast GUP
- Support for membarrier-based instruction cache synchronization
- Support for the Andes hart-level interrupt controller and PMU
- Some cleanups around unaligned access speed probing and Kconfig
settings
- Support for ACPI LPI and CPPC
- Various cleanus related to barriers
- A handful of fixes
* tag 'riscv-for-linus-6.9-mw2' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: (66 commits)
riscv: Fix syscall wrapper for >word-size arguments
crypto: riscv - add vector crypto accelerated AES-CBC-CTS
crypto: riscv - parallelize AES-CBC decryption
riscv: Only flush the mm icache when setting an exec pte
riscv: Use kcalloc() instead of kzalloc()
riscv/barrier: Add missing space after ','
riscv/barrier: Consolidate fence definitions
riscv/barrier: Define RISCV_FULL_BARRIER
riscv/barrier: Define __{mb,rmb,wmb}
RISC-V: defconfig: Enable CONFIG_ACPI_CPPC_CPUFREQ
cpufreq: Move CPPC configs to common Kconfig and add RISC-V
ACPI: RISC-V: Add CPPC driver
ACPI: Enable ACPI_PROCESSOR for RISC-V
ACPI: RISC-V: Add LPI driver
cpuidle: RISC-V: Move few functions to arch/riscv
riscv: Introduce set_compat_task() in asm/compat.h
riscv: Introduce is_compat_thread() into compat.h
riscv: add compile-time test into is_compat_task()
riscv: Replace direct thread flag check with is_compat_task()
riscv: Improve arch_get_mmap_end() macro
...
This commit is contained in:
@@ -144,14 +144,8 @@ passing 0 into the hint address parameter of mmap. On CPUs with an address space
|
||||
smaller than sv48, the CPU maximum supported address space will be the default.
|
||||
|
||||
Software can "opt-in" to receiving VAs from another VA space by providing
|
||||
a hint address to mmap. A hint address passed to mmap will cause the largest
|
||||
address space that fits entirely into the hint to be used, unless there is no
|
||||
space left in the address space. If there is no space available in the requested
|
||||
address space, an address in the next smallest available address space will be
|
||||
returned.
|
||||
|
||||
For example, in order to obtain 48-bit VA space, a hint address greater than
|
||||
:code:`1 << 47` must be provided. Note that this is 47 due to sv48 userspace
|
||||
ending at :code:`1 << 47` and the addresses beyond this are reserved for the
|
||||
kernel. Similarly, to obtain 57-bit VA space addresses, a hint address greater
|
||||
than or equal to :code:`1 << 56` must be provided.
|
||||
a hint address to mmap. When a hint address is passed to mmap, the returned
|
||||
address will never use more bits than the hint address. For example, if a hint
|
||||
address of `1 << 40` is passed to mmap, a valid returned address will never use
|
||||
bits 41 through 63. If no mappable addresses are available in that range, mmap
|
||||
will return `MAP_FAILED`.
|
||||
|
||||
@@ -110,7 +110,11 @@ properties:
|
||||
const: 1
|
||||
|
||||
compatible:
|
||||
const: riscv,cpu-intc
|
||||
oneOf:
|
||||
- items:
|
||||
- const: andestech,cpu-intc
|
||||
- const: riscv,cpu-intc
|
||||
- const: riscv,cpu-intc
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
|
||||
@@ -477,5 +477,12 @@ properties:
|
||||
latency, as ratified in commit 56ed795 ("Update
|
||||
riscv-crypto-spec-vector.adoc") of riscv-crypto.
|
||||
|
||||
- const: xandespmu
|
||||
description:
|
||||
The Andes Technology performance monitor extension for counter overflow
|
||||
and privilege mode filtering. For more details, see Counter Related
|
||||
Registers in the AX45MP datasheet.
|
||||
https://www.andestech.com/wp-content/uploads/AX45MP-1C-Rev.-5.0.0-Datasheet.pdf
|
||||
|
||||
additionalProperties: true
|
||||
...
|
||||
|
||||
@@ -10,6 +10,22 @@
|
||||
# Rely on implicit context synchronization as a result of exception return
|
||||
# when returning from IPI handler, and when returning to user-space.
|
||||
#
|
||||
# * riscv
|
||||
#
|
||||
# riscv uses xRET as return from interrupt and to return to user-space.
|
||||
#
|
||||
# Given that xRET is not core serializing, we rely on FENCE.I for providing
|
||||
# core serialization:
|
||||
#
|
||||
# - by calling sync_core_before_usermode() on return from interrupt (cf.
|
||||
# ipi_sync_core()),
|
||||
#
|
||||
# - via switch_mm() and sync_core_before_usermode() (respectively, for
|
||||
# uthread->uthread and kthread->uthread transitions) before returning
|
||||
# to user-space.
|
||||
#
|
||||
# The serialization in switch_mm() is activated by prepare_sync_core_cmd().
|
||||
#
|
||||
# * x86
|
||||
#
|
||||
# x86-32 uses IRET as return from interrupt, which takes care of the IPI.
|
||||
@@ -43,7 +59,7 @@
|
||||
| openrisc: | TODO |
|
||||
| parisc: | TODO |
|
||||
| powerpc: | ok |
|
||||
| riscv: | TODO |
|
||||
| riscv: | ok |
|
||||
| s390: | ok |
|
||||
| sh: | TODO |
|
||||
| sparc: | TODO |
|
||||
|
||||
@@ -7,6 +7,7 @@ Scheduler
|
||||
|
||||
|
||||
completion
|
||||
membarrier
|
||||
sched-arch
|
||||
sched-bwc
|
||||
sched-deadline
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
========================
|
||||
membarrier() System Call
|
||||
========================
|
||||
|
||||
MEMBARRIER_CMD_{PRIVATE,GLOBAL}_EXPEDITED - Architecture requirements
|
||||
=====================================================================
|
||||
|
||||
Memory barriers before updating rq->curr
|
||||
----------------------------------------
|
||||
|
||||
The commands MEMBARRIER_CMD_PRIVATE_EXPEDITED and MEMBARRIER_CMD_GLOBAL_EXPEDITED
|
||||
require each architecture to have a full memory barrier after coming from
|
||||
user-space, before updating rq->curr. This barrier is implied by the sequence
|
||||
rq_lock(); smp_mb__after_spinlock() in __schedule(). The barrier matches a full
|
||||
barrier in the proximity of the membarrier system call exit, cf.
|
||||
membarrier_{private,global}_expedited().
|
||||
|
||||
Memory barriers after updating rq->curr
|
||||
---------------------------------------
|
||||
|
||||
The commands MEMBARRIER_CMD_PRIVATE_EXPEDITED and MEMBARRIER_CMD_GLOBAL_EXPEDITED
|
||||
require each architecture to have a full memory barrier after updating rq->curr,
|
||||
before returning to user-space. The schemes providing this barrier on the various
|
||||
architectures are as follows.
|
||||
|
||||
- alpha, arc, arm, hexagon, mips rely on the full barrier implied by
|
||||
spin_unlock() in finish_lock_switch().
|
||||
|
||||
- arm64 relies on the full barrier implied by switch_to().
|
||||
|
||||
- powerpc, riscv, s390, sparc, x86 rely on the full barrier implied by
|
||||
switch_mm(), if mm is not NULL; they rely on the full barrier implied
|
||||
by mmdrop(), otherwise. On powerpc and riscv, switch_mm() relies on
|
||||
membarrier_arch_switch_mm().
|
||||
|
||||
The barrier matches a full barrier in the proximity of the membarrier system call
|
||||
entry, cf. membarrier_{private,global}_expedited().
|
||||
+3
-1
@@ -14134,7 +14134,9 @@ M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
|
||||
M: "Paul E. McKenney" <paulmck@kernel.org>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
F: arch/powerpc/include/asm/membarrier.h
|
||||
F: Documentation/scheduler/membarrier.rst
|
||||
F: arch/*/include/asm/membarrier.h
|
||||
F: arch/*/include/asm/sync_core.h
|
||||
F: include/uapi/linux/membarrier.h
|
||||
F: kernel/sched/membarrier.c
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
obj-y += kernel/ mm/ net/
|
||||
obj-$(CONFIG_BUILTIN_DTB) += boot/dts/
|
||||
obj-$(CONFIG_CRYPTO) += crypto/
|
||||
obj-y += errata/
|
||||
obj-$(CONFIG_KVM) += kvm/
|
||||
|
||||
|
||||
+64
-16
@@ -27,14 +27,18 @@ config RISCV
|
||||
select ARCH_HAS_GCOV_PROFILE_ALL
|
||||
select ARCH_HAS_GIGANTIC_PAGE
|
||||
select ARCH_HAS_KCOV
|
||||
select ARCH_HAS_MEMBARRIER_CALLBACKS
|
||||
select ARCH_HAS_MEMBARRIER_SYNC_CORE
|
||||
select ARCH_HAS_MMIOWB
|
||||
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
|
||||
select ARCH_HAS_PMEM_API
|
||||
select ARCH_HAS_PREPARE_SYNC_CORE_CMD
|
||||
select ARCH_HAS_PTE_SPECIAL
|
||||
select ARCH_HAS_SET_DIRECT_MAP if MMU
|
||||
select ARCH_HAS_SET_MEMORY if MMU
|
||||
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
|
||||
select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
|
||||
select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
|
||||
select ARCH_HAS_SYSCALL_WRAPPER
|
||||
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select ARCH_HAS_UBSAN
|
||||
@@ -47,6 +51,9 @@ config RISCV
|
||||
select ARCH_SUPPORTS_CFI_CLANG
|
||||
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if MMU
|
||||
select ARCH_SUPPORTS_HUGETLBFS if MMU
|
||||
# LLD >= 14: https://github.com/llvm/llvm-project/issues/50505
|
||||
select ARCH_SUPPORTS_LTO_CLANG if LLD_VERSION >= 140000
|
||||
select ARCH_SUPPORTS_LTO_CLANG_THIN if LLD_VERSION >= 140000
|
||||
select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU
|
||||
select ARCH_SUPPORTS_PER_VMA_LOCK if MMU
|
||||
select ARCH_SUPPORTS_SHADOW_CALL_STACK if HAVE_SHADOW_CALL_STACK
|
||||
@@ -106,6 +113,7 @@ config RISCV
|
||||
select HAVE_ARCH_KGDB_QXFER_PKT
|
||||
select HAVE_ARCH_MMAP_RND_BITS if MMU
|
||||
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
|
||||
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
|
||||
select HAVE_ARCH_SECCOMP_FILTER
|
||||
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
|
||||
select HAVE_ARCH_TRACEHOOK
|
||||
@@ -124,6 +132,7 @@ config RISCV
|
||||
select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION
|
||||
select HAVE_EBPF_JIT if MMU
|
||||
select HAVE_FAST_GUP if MMU
|
||||
select HAVE_FUNCTION_ARG_ACCESS_API
|
||||
select HAVE_FUNCTION_ERROR_INJECTION
|
||||
select HAVE_GCC_PLUGINS
|
||||
@@ -155,6 +164,7 @@ config RISCV
|
||||
select IRQ_FORCED_THREADING
|
||||
select KASAN_VMALLOC if KASAN
|
||||
select LOCK_MM_AND_FIND_VMA
|
||||
select MMU_GATHER_RCU_TABLE_FREE if SMP && MMU
|
||||
select MODULES_USE_ELF_RELA if MODULES
|
||||
select MODULE_SECTIONS if MODULES
|
||||
select OF
|
||||
@@ -576,6 +586,13 @@ config TOOLCHAIN_HAS_ZBB
|
||||
depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900
|
||||
depends on AS_HAS_OPTION_ARCH
|
||||
|
||||
# This symbol indicates that the toolchain supports all v1.0 vector crypto
|
||||
# extensions, including Zvk*, Zvbb, and Zvbc. LLVM added all of these at once.
|
||||
# binutils added all except Zvkb, then added Zvkb. So we just check for Zvkb.
|
||||
config TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
def_bool $(as-instr, .option arch$(comma) +v$(comma) +zvkb)
|
||||
depends on AS_HAS_OPTION_ARCH
|
||||
|
||||
config RISCV_ISA_ZBB
|
||||
bool "Zbb extension support for bit manipulation instructions"
|
||||
depends on TOOLCHAIN_HAS_ZBB
|
||||
@@ -686,27 +703,61 @@ config THREAD_SIZE_ORDER
|
||||
affects irq stack size, which is equal to thread stack size.
|
||||
|
||||
config RISCV_MISALIGNED
|
||||
bool "Support misaligned load/store traps for kernel and userspace"
|
||||
bool
|
||||
select SYSCTL_ARCH_UNALIGN_ALLOW
|
||||
default y
|
||||
help
|
||||
Say Y here if you want the kernel to embed support for misaligned
|
||||
load/store for both kernel and userspace. When disable, misaligned
|
||||
accesses will generate SIGBUS in userspace and panic in kernel.
|
||||
Embed support for emulating misaligned loads and stores.
|
||||
|
||||
choice
|
||||
prompt "Unaligned Accesses Support"
|
||||
default RISCV_PROBE_UNALIGNED_ACCESS
|
||||
help
|
||||
This determines the level of support for unaligned accesses. This
|
||||
information is used by the kernel to perform optimizations. It is also
|
||||
exposed to user space via the hwprobe syscall. The hardware will be
|
||||
probed at boot by default.
|
||||
|
||||
config RISCV_PROBE_UNALIGNED_ACCESS
|
||||
bool "Probe for hardware unaligned access support"
|
||||
select RISCV_MISALIGNED
|
||||
help
|
||||
During boot, the kernel will run a series of tests to determine the
|
||||
speed of unaligned accesses. This probing will dynamically determine
|
||||
the speed of unaligned accesses on the underlying system. If unaligned
|
||||
memory accesses trap into the kernel as they are not supported by the
|
||||
system, the kernel will emulate the unaligned accesses to preserve the
|
||||
UABI.
|
||||
|
||||
config RISCV_EMULATED_UNALIGNED_ACCESS
|
||||
bool "Emulate unaligned access where system support is missing"
|
||||
select RISCV_MISALIGNED
|
||||
help
|
||||
If unaligned memory accesses trap into the kernel as they are not
|
||||
supported by the system, the kernel will emulate the unaligned
|
||||
accesses to preserve the UABI. When the underlying system does support
|
||||
unaligned accesses, the unaligned accesses are assumed to be slow.
|
||||
|
||||
config RISCV_SLOW_UNALIGNED_ACCESS
|
||||
bool "Assume the system supports slow unaligned memory accesses"
|
||||
depends on NONPORTABLE
|
||||
help
|
||||
Assume that the system supports slow unaligned memory accesses. The
|
||||
kernel and userspace programs may not be able to run at all on systems
|
||||
that do not support unaligned memory accesses.
|
||||
|
||||
config RISCV_EFFICIENT_UNALIGNED_ACCESS
|
||||
bool "Assume the CPU supports fast unaligned memory accesses"
|
||||
bool "Assume the system supports fast unaligned memory accesses"
|
||||
depends on NONPORTABLE
|
||||
select DCACHE_WORD_ACCESS if MMU
|
||||
select HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
help
|
||||
Say Y here if you want the kernel to assume that the CPU supports
|
||||
efficient unaligned memory accesses. When enabled, this option
|
||||
improves the performance of the kernel on such CPUs. However, the
|
||||
kernel will run much more slowly, or will not be able to run at all,
|
||||
on CPUs that do not support efficient unaligned memory accesses.
|
||||
Assume that the system supports fast unaligned memory accesses. When
|
||||
enabled, this option improves the performance of the kernel on such
|
||||
systems. However, the kernel and userspace programs will run much more
|
||||
slowly, or will not be able to run at all, on systems that do not
|
||||
support efficient unaligned memory accesses.
|
||||
|
||||
If unsure what to do here, say N.
|
||||
endchoice
|
||||
|
||||
endmenu # "Platform type"
|
||||
|
||||
@@ -1011,11 +1062,8 @@ menu "Power management options"
|
||||
|
||||
source "kernel/power/Kconfig"
|
||||
|
||||
# Hibernation is only possible on systems where the SBI implementation has
|
||||
# marked its reserved memory as not accessible from, or does not run
|
||||
# from the same memory as, Linux
|
||||
config ARCH_HIBERNATION_POSSIBLE
|
||||
def_bool NONPORTABLE
|
||||
def_bool y
|
||||
|
||||
config ARCH_HIBERNATION_HEADER
|
||||
def_bool HIBERNATION
|
||||
|
||||
@@ -50,6 +50,11 @@ ifndef CONFIG_AS_IS_LLVM
|
||||
KBUILD_CFLAGS += -Wa,-mno-relax
|
||||
KBUILD_AFLAGS += -Wa,-mno-relax
|
||||
endif
|
||||
# LLVM has an issue with target-features and LTO: https://github.com/llvm/llvm-project/issues/59350
|
||||
# Ensure it is aware of linker relaxation with LTO, otherwise relocations may
|
||||
# be incorrect: https://github.com/llvm/llvm-project/issues/65090
|
||||
else ifeq ($(CONFIG_LTO_CLANG),y)
|
||||
KBUILD_LDFLAGS += -mllvm -mattr=+c -mllvm -mattr=+relax
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_SHADOW_CALL_STACK),y)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
riscv,isa-base = "rv64i";
|
||||
riscv,isa-extensions = "i", "m", "a", "f", "d", "c",
|
||||
"zicntr", "zicsr", "zifencei",
|
||||
"zihpm";
|
||||
"zihpm", "xandespmu";
|
||||
mmu-type = "riscv,sv39";
|
||||
i-cache-size = <0x8000>;
|
||||
i-cache-line-size = <0x40>;
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
cpu0_intc: interrupt-controller {
|
||||
#interrupt-cells = <1>;
|
||||
compatible = "riscv,cpu-intc";
|
||||
compatible = "andestech,cpu-intc", "riscv,cpu-intc";
|
||||
interrupt-controller;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,6 +44,7 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y
|
||||
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
|
||||
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
|
||||
CONFIG_CPUFREQ_DT=y
|
||||
CONFIG_ACPI_CPPC_CPUFREQ=m
|
||||
CONFIG_VIRTUALIZATION=y
|
||||
CONFIG_KVM=m
|
||||
CONFIG_ACPI=y
|
||||
@@ -215,6 +216,7 @@ CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_PLTFM=y
|
||||
CONFIG_MMC_SDHCI_CADENCE=y
|
||||
CONFIG_MMC_SDHCI_OF_DWCMSHC=y
|
||||
CONFIG_MMC_SPI=y
|
||||
CONFIG_MMC_DW=y
|
||||
CONFIG_MMC_DW_STARFIVE=y
|
||||
@@ -224,6 +226,7 @@ CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_SUN6I=y
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_DMA_SUN6I=m
|
||||
CONFIG_DW_AXI_DMAC=y
|
||||
CONFIG_RZ_DMAC=y
|
||||
CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO_BALLOON=y
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
menu "Accelerated Cryptographic Algorithms for CPU (riscv)"
|
||||
|
||||
config CRYPTO_AES_RISCV64
|
||||
tristate "Ciphers: AES, modes: ECB, CBC, CTS, CTR, XTS"
|
||||
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_LIB_AES
|
||||
select CRYPTO_SKCIPHER
|
||||
help
|
||||
Block cipher: AES cipher algorithms
|
||||
Length-preserving ciphers: AES with ECB, CBC, CTS, CTR, XTS
|
||||
|
||||
Architecture: riscv64 using:
|
||||
- Zvkned vector crypto extension
|
||||
- Zvbb vector extension (XTS)
|
||||
- Zvkb vector crypto extension (CTR)
|
||||
- Zvkg vector crypto extension (XTS)
|
||||
|
||||
config CRYPTO_CHACHA_RISCV64
|
||||
tristate "Ciphers: ChaCha"
|
||||
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
select CRYPTO_SKCIPHER
|
||||
select CRYPTO_LIB_CHACHA_GENERIC
|
||||
help
|
||||
Length-preserving ciphers: ChaCha20 stream cipher algorithm
|
||||
|
||||
Architecture: riscv64 using:
|
||||
- Zvkb vector crypto extension
|
||||
|
||||
config CRYPTO_GHASH_RISCV64
|
||||
tristate "Hash functions: GHASH"
|
||||
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
select CRYPTO_GCM
|
||||
help
|
||||
GCM GHASH function (NIST SP 800-38D)
|
||||
|
||||
Architecture: riscv64 using:
|
||||
- Zvkg vector crypto extension
|
||||
|
||||
config CRYPTO_SHA256_RISCV64
|
||||
tristate "Hash functions: SHA-224 and SHA-256"
|
||||
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
select CRYPTO_SHA256
|
||||
help
|
||||
SHA-224 and SHA-256 secure hash algorithm (FIPS 180)
|
||||
|
||||
Architecture: riscv64 using:
|
||||
- Zvknha or Zvknhb vector crypto extensions
|
||||
- Zvkb vector crypto extension
|
||||
|
||||
config CRYPTO_SHA512_RISCV64
|
||||
tristate "Hash functions: SHA-384 and SHA-512"
|
||||
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
select CRYPTO_SHA512
|
||||
help
|
||||
SHA-384 and SHA-512 secure hash algorithm (FIPS 180)
|
||||
|
||||
Architecture: riscv64 using:
|
||||
- Zvknhb vector crypto extension
|
||||
- Zvkb vector crypto extension
|
||||
|
||||
config CRYPTO_SM3_RISCV64
|
||||
tristate "Hash functions: SM3 (ShangMi 3)"
|
||||
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
select CRYPTO_HASH
|
||||
select CRYPTO_SM3
|
||||
help
|
||||
SM3 (ShangMi 3) secure hash function (OSCCA GM/T 0004-2012)
|
||||
|
||||
Architecture: riscv64 using:
|
||||
- Zvksh vector crypto extension
|
||||
- Zvkb vector crypto extension
|
||||
|
||||
config CRYPTO_SM4_RISCV64
|
||||
tristate "Ciphers: SM4 (ShangMi 4)"
|
||||
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
|
||||
select CRYPTO_ALGAPI
|
||||
select CRYPTO_SM4
|
||||
help
|
||||
SM4 block cipher algorithm (OSCCA GB/T 32907-2016,
|
||||
ISO/IEC 18033-3:2010/Amd 1:2021)
|
||||
|
||||
SM4 (GBT.32907-2016) is a cryptographic standard issued by the
|
||||
Organization of State Commercial Administration of China (OSCCA)
|
||||
as an authorized cryptographic algorithm for use within China.
|
||||
|
||||
Architecture: riscv64 using:
|
||||
- Zvksed vector crypto extension
|
||||
- Zvkb vector crypto extension
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,23 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_RISCV64) += aes-riscv64.o
|
||||
aes-riscv64-y := aes-riscv64-glue.o aes-riscv64-zvkned.o \
|
||||
aes-riscv64-zvkned-zvbb-zvkg.o aes-riscv64-zvkned-zvkb.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_CHACHA_RISCV64) += chacha-riscv64.o
|
||||
chacha-riscv64-y := chacha-riscv64-glue.o chacha-riscv64-zvkb.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_GHASH_RISCV64) += ghash-riscv64.o
|
||||
ghash-riscv64-y := ghash-riscv64-glue.o ghash-riscv64-zvkg.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SHA256_RISCV64) += sha256-riscv64.o
|
||||
sha256-riscv64-y := sha256-riscv64-glue.o sha256-riscv64-zvknha_or_zvknhb-zvkb.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SHA512_RISCV64) += sha512-riscv64.o
|
||||
sha512-riscv64-y := sha512-riscv64-glue.o sha512-riscv64-zvknhb-zvkb.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SM3_RISCV64) += sm3-riscv64.o
|
||||
sm3-riscv64-y := sm3-riscv64-glue.o sm3-riscv64-zvksh-zvkb.o
|
||||
|
||||
obj-$(CONFIG_CRYPTO_SM4_RISCV64) += sm4-riscv64.o
|
||||
sm4-riscv64-y := sm4-riscv64-glue.o sm4-riscv64-zvksed-zvkb.o
|
||||
@@ -0,0 +1,156 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause */
|
||||
//
|
||||
// This file is dual-licensed, meaning that you can use it under your
|
||||
// choice of either of the following two licenses:
|
||||
//
|
||||
// Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License 2.0 (the "License"). You can obtain
|
||||
// a copy in the file LICENSE in the source distribution or at
|
||||
// https://www.openssl.org/source/license.html
|
||||
//
|
||||
// or
|
||||
//
|
||||
// Copyright (c) 2023, Christoph Müllner <christoph.muellner@vrull.eu>
|
||||
// Copyright (c) 2023, Phoebe Chen <phoebe.chen@sifive.com>
|
||||
// Copyright (c) 2023, Jerry Shih <jerry.shih@sifive.com>
|
||||
// Copyright 2024 Google LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This file contains macros that are shared by the other aes-*.S files. The
|
||||
// generated code of these macros depends on the following RISC-V extensions:
|
||||
// - RV64I
|
||||
// - RISC-V Vector ('V') with VLEN >= 128
|
||||
// - RISC-V Vector AES block cipher extension ('Zvkned')
|
||||
|
||||
// Loads the AES round keys from \keyp into vector registers and jumps to code
|
||||
// specific to the length of the key. Specifically:
|
||||
// - If AES-128, loads round keys into v1-v11 and jumps to \label128.
|
||||
// - If AES-192, loads round keys into v1-v13 and jumps to \label192.
|
||||
// - If AES-256, loads round keys into v1-v15 and continues onwards.
|
||||
//
|
||||
// Also sets vl=4 and vtype=e32,m1,ta,ma. Clobbers t0 and t1.
|
||||
.macro aes_begin keyp, label128, label192
|
||||
lwu t0, 480(\keyp) // t0 = key length in bytes
|
||||
li t1, 24 // t1 = key length for AES-192
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vle32.v v1, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v2, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v3, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v4, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v5, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v6, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v7, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v8, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v9, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v10, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v11, (\keyp)
|
||||
blt t0, t1, \label128 // If AES-128, goto label128.
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v12, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v13, (\keyp)
|
||||
beq t0, t1, \label192 // If AES-192, goto label192.
|
||||
// Else, it's AES-256.
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v14, (\keyp)
|
||||
addi \keyp, \keyp, 16
|
||||
vle32.v v15, (\keyp)
|
||||
.endm
|
||||
|
||||
// Encrypts \data using zvkned instructions, using the round keys loaded into
|
||||
// v1-v11 (for AES-128), v1-v13 (for AES-192), or v1-v15 (for AES-256). \keylen
|
||||
// is the AES key length in bits. vl and vtype must already be set
|
||||
// appropriately. Note that if vl > 4, multiple blocks are encrypted.
|
||||
.macro aes_encrypt data, keylen
|
||||
vaesz.vs \data, v1
|
||||
vaesem.vs \data, v2
|
||||
vaesem.vs \data, v3
|
||||
vaesem.vs \data, v4
|
||||
vaesem.vs \data, v5
|
||||
vaesem.vs \data, v6
|
||||
vaesem.vs \data, v7
|
||||
vaesem.vs \data, v8
|
||||
vaesem.vs \data, v9
|
||||
vaesem.vs \data, v10
|
||||
.if \keylen == 128
|
||||
vaesef.vs \data, v11
|
||||
.elseif \keylen == 192
|
||||
vaesem.vs \data, v11
|
||||
vaesem.vs \data, v12
|
||||
vaesef.vs \data, v13
|
||||
.else
|
||||
vaesem.vs \data, v11
|
||||
vaesem.vs \data, v12
|
||||
vaesem.vs \data, v13
|
||||
vaesem.vs \data, v14
|
||||
vaesef.vs \data, v15
|
||||
.endif
|
||||
.endm
|
||||
|
||||
// Same as aes_encrypt, but decrypts instead of encrypts.
|
||||
.macro aes_decrypt data, keylen
|
||||
.if \keylen == 128
|
||||
vaesz.vs \data, v11
|
||||
.elseif \keylen == 192
|
||||
vaesz.vs \data, v13
|
||||
vaesdm.vs \data, v12
|
||||
vaesdm.vs \data, v11
|
||||
.else
|
||||
vaesz.vs \data, v15
|
||||
vaesdm.vs \data, v14
|
||||
vaesdm.vs \data, v13
|
||||
vaesdm.vs \data, v12
|
||||
vaesdm.vs \data, v11
|
||||
.endif
|
||||
vaesdm.vs \data, v10
|
||||
vaesdm.vs \data, v9
|
||||
vaesdm.vs \data, v8
|
||||
vaesdm.vs \data, v7
|
||||
vaesdm.vs \data, v6
|
||||
vaesdm.vs \data, v5
|
||||
vaesdm.vs \data, v4
|
||||
vaesdm.vs \data, v3
|
||||
vaesdm.vs \data, v2
|
||||
vaesdf.vs \data, v1
|
||||
.endm
|
||||
|
||||
// Expands to aes_encrypt or aes_decrypt according to \enc, which is 1 or 0.
|
||||
.macro aes_crypt data, enc, keylen
|
||||
.if \enc
|
||||
aes_encrypt \data, \keylen
|
||||
.else
|
||||
aes_decrypt \data, \keylen
|
||||
.endif
|
||||
.endm
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,312 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause */
|
||||
//
|
||||
// This file is dual-licensed, meaning that you can use it under your
|
||||
// choice of either of the following two licenses:
|
||||
//
|
||||
// Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License 2.0 (the "License"). You can obtain
|
||||
// a copy in the file LICENSE in the source distribution or at
|
||||
// https://www.openssl.org/source/license.html
|
||||
//
|
||||
// or
|
||||
//
|
||||
// Copyright (c) 2023, Jerry Shih <jerry.shih@sifive.com>
|
||||
// Copyright 2024 Google LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The generated code of this file depends on the following RISC-V extensions:
|
||||
// - RV64I
|
||||
// - RISC-V Vector ('V') with VLEN >= 128 && VLEN < 2048
|
||||
// - RISC-V Vector AES block cipher extension ('Zvkned')
|
||||
// - RISC-V Vector Bit-manipulation extension ('Zvbb')
|
||||
// - RISC-V Vector GCM/GMAC extension ('Zvkg')
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.text
|
||||
.option arch, +zvkned, +zvbb, +zvkg
|
||||
|
||||
#include "aes-macros.S"
|
||||
|
||||
#define KEYP a0
|
||||
#define INP a1
|
||||
#define OUTP a2
|
||||
#define LEN a3
|
||||
#define TWEAKP a4
|
||||
|
||||
#define LEN32 a5
|
||||
#define TAIL_LEN a6
|
||||
#define VL a7
|
||||
#define VLMAX t4
|
||||
|
||||
// v1-v15 contain the AES round keys, but they are used for temporaries before
|
||||
// the AES round keys have been loaded.
|
||||
#define TWEAKS v16 // LMUL=4 (most of the time)
|
||||
#define TWEAKS_BREV v20 // LMUL=4 (most of the time)
|
||||
#define MULTS_BREV v24 // LMUL=4 (most of the time)
|
||||
#define TMP0 v28
|
||||
#define TMP1 v29
|
||||
#define TMP2 v30
|
||||
#define TMP3 v31
|
||||
|
||||
// xts_init initializes the following values:
|
||||
//
|
||||
// TWEAKS: N 128-bit tweaks T*(x^i) for i in 0..(N - 1)
|
||||
// TWEAKS_BREV: same as TWEAKS, but bit-reversed
|
||||
// MULTS_BREV: N 128-bit values x^N, bit-reversed. Only if N > 1.
|
||||
//
|
||||
// N is the maximum number of blocks that will be processed per loop iteration,
|
||||
// computed using vsetvli.
|
||||
//
|
||||
// The field convention used by XTS is the same as that of GHASH, but with the
|
||||
// bits reversed within each byte. The zvkg extension provides the vgmul
|
||||
// instruction which does multiplication in this field. Therefore, for tweak
|
||||
// computation we use vgmul to do multiplications in parallel, instead of
|
||||
// serially multiplying by x using shifting+xoring. Note that for this to work,
|
||||
// the inputs and outputs to vgmul must be bit-reversed (we do it with vbrev8).
|
||||
.macro xts_init
|
||||
|
||||
// Load the first tweak T.
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vle32.v TWEAKS, (TWEAKP)
|
||||
|
||||
// If there's only one block (or no blocks at all), then skip the tweak
|
||||
// sequence computation because (at most) T itself is needed.
|
||||
li t0, 16
|
||||
ble LEN, t0, .Linit_single_block\@
|
||||
|
||||
// Save a copy of T bit-reversed in v12.
|
||||
vbrev8.v v12, TWEAKS
|
||||
|
||||
//
|
||||
// Generate x^i for i in 0..(N - 1), i.e. 128-bit values 1 << i assuming
|
||||
// that N <= 128. Though, this code actually requires N < 64 (or
|
||||
// equivalently VLEN < 2048) due to the use of 64-bit intermediate
|
||||
// values here and in the x^N computation later.
|
||||
//
|
||||
vsetvli VL, LEN32, e32, m4, ta, ma
|
||||
srli t0, VL, 2 // t0 = N (num blocks)
|
||||
// Generate two sequences, each with N 32-bit values:
|
||||
// v0=[1, 1, 1, ...] and v1=[0, 1, 2, ...].
|
||||
vsetvli zero, t0, e32, m1, ta, ma
|
||||
vmv.v.i v0, 1
|
||||
vid.v v1
|
||||
// Use vzext to zero-extend the sequences to 64 bits. Reinterpret them
|
||||
// as two sequences, each with 2*N 32-bit values:
|
||||
// v2=[1, 0, 1, 0, 1, 0, ...] and v4=[0, 0, 1, 0, 2, 0, ...].
|
||||
vsetvli zero, t0, e64, m2, ta, ma
|
||||
vzext.vf2 v2, v0
|
||||
vzext.vf2 v4, v1
|
||||
slli t1, t0, 1 // t1 = 2*N
|
||||
vsetvli zero, t1, e32, m2, ta, ma
|
||||
// Use vwsll to compute [1<<0, 0<<0, 1<<1, 0<<0, 1<<2, 0<<0, ...],
|
||||
// widening to 64 bits per element. When reinterpreted as N 128-bit
|
||||
// values, this is the needed sequence of 128-bit values 1 << i (x^i).
|
||||
vwsll.vv v8, v2, v4
|
||||
|
||||
// Copy the bit-reversed T to all N elements of TWEAKS_BREV, then
|
||||
// multiply by x^i. This gives the sequence T*(x^i), bit-reversed.
|
||||
vsetvli zero, LEN32, e32, m4, ta, ma
|
||||
vmv.v.i TWEAKS_BREV, 0
|
||||
vaesz.vs TWEAKS_BREV, v12
|
||||
vbrev8.v v8, v8
|
||||
vgmul.vv TWEAKS_BREV, v8
|
||||
|
||||
// Save a copy of the sequence T*(x^i) with the bit reversal undone.
|
||||
vbrev8.v TWEAKS, TWEAKS_BREV
|
||||
|
||||
// Generate N copies of x^N, i.e. 128-bit values 1 << N, bit-reversed.
|
||||
li t1, 1
|
||||
sll t1, t1, t0 // t1 = 1 << N
|
||||
vsetivli zero, 2, e64, m1, ta, ma
|
||||
vmv.v.i v0, 0
|
||||
vsetivli zero, 1, e64, m1, tu, ma
|
||||
vmv.v.x v0, t1
|
||||
vbrev8.v v0, v0
|
||||
vsetvli zero, LEN32, e32, m4, ta, ma
|
||||
vmv.v.i MULTS_BREV, 0
|
||||
vaesz.vs MULTS_BREV, v0
|
||||
|
||||
j .Linit_done\@
|
||||
|
||||
.Linit_single_block\@:
|
||||
vbrev8.v TWEAKS_BREV, TWEAKS
|
||||
.Linit_done\@:
|
||||
.endm
|
||||
|
||||
// Set the first 128 bits of MULTS_BREV to 0x40, i.e. 'x' bit-reversed. This is
|
||||
// the multiplier required to advance the tweak by one.
|
||||
.macro load_x
|
||||
li t0, 0x40
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vmv.v.i MULTS_BREV, 0
|
||||
vsetivli zero, 1, e8, m1, tu, ma
|
||||
vmv.v.x MULTS_BREV, t0
|
||||
.endm
|
||||
|
||||
.macro __aes_xts_crypt enc, keylen
|
||||
// With 16 < len <= 31, there's no main loop, just ciphertext stealing.
|
||||
beqz LEN32, .Lcts_without_main_loop\@
|
||||
|
||||
vsetvli VLMAX, zero, e32, m4, ta, ma
|
||||
1:
|
||||
vsetvli VL, LEN32, e32, m4, ta, ma
|
||||
2:
|
||||
// Encrypt or decrypt VL/4 blocks.
|
||||
vle32.v TMP0, (INP)
|
||||
vxor.vv TMP0, TMP0, TWEAKS
|
||||
aes_crypt TMP0, \enc, \keylen
|
||||
vxor.vv TMP0, TMP0, TWEAKS
|
||||
vse32.v TMP0, (OUTP)
|
||||
|
||||
// Update the pointers and the remaining length.
|
||||
slli t0, VL, 2
|
||||
add INP, INP, t0
|
||||
add OUTP, OUTP, t0
|
||||
sub LEN32, LEN32, VL
|
||||
|
||||
// Check whether more blocks remain.
|
||||
beqz LEN32, .Lmain_loop_done\@
|
||||
|
||||
// Compute the next sequence of tweaks by multiplying the previous
|
||||
// sequence by x^N. Store the result in both bit-reversed order and
|
||||
// regular order (i.e. with the bit reversal undone).
|
||||
vgmul.vv TWEAKS_BREV, MULTS_BREV
|
||||
vbrev8.v TWEAKS, TWEAKS_BREV
|
||||
|
||||
// Since we compute the tweak multipliers x^N in advance, we require
|
||||
// that each iteration process the same length except possibly the last.
|
||||
// This conflicts slightly with the behavior allowed by RISC-V Vector
|
||||
// Extension, where CPUs can select a lower length for both of the last
|
||||
// two iterations. E.g., vl might take the sequence of values
|
||||
// [16, 16, 16, 12, 12], whereas we need [16, 16, 16, 16, 8] so that we
|
||||
// can use x^4 again instead of computing x^3. Therefore, we explicitly
|
||||
// keep the vl at VLMAX if there is at least VLMAX remaining.
|
||||
bge LEN32, VLMAX, 2b
|
||||
j 1b
|
||||
|
||||
.Lmain_loop_done\@:
|
||||
load_x
|
||||
|
||||
// Compute the next tweak.
|
||||
addi t0, VL, -4
|
||||
vsetivli zero, 4, e32, m4, ta, ma
|
||||
vslidedown.vx TWEAKS_BREV, TWEAKS_BREV, t0 // Extract last tweak
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vgmul.vv TWEAKS_BREV, MULTS_BREV // Advance to next tweak
|
||||
|
||||
bnez TAIL_LEN, .Lcts\@
|
||||
|
||||
// Update *TWEAKP to contain the next tweak.
|
||||
vbrev8.v TWEAKS, TWEAKS_BREV
|
||||
vse32.v TWEAKS, (TWEAKP)
|
||||
ret
|
||||
|
||||
.Lcts_without_main_loop\@:
|
||||
load_x
|
||||
.Lcts\@:
|
||||
// TWEAKS_BREV now contains the next tweak. Compute the one after that.
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vmv.v.v TMP0, TWEAKS_BREV
|
||||
vgmul.vv TMP0, MULTS_BREV
|
||||
// Undo the bit reversal of the next two tweaks and store them in TMP1
|
||||
// and TMP2, such that TMP1 is the first needed and TMP2 the second.
|
||||
.if \enc
|
||||
vbrev8.v TMP1, TWEAKS_BREV
|
||||
vbrev8.v TMP2, TMP0
|
||||
.else
|
||||
vbrev8.v TMP1, TMP0
|
||||
vbrev8.v TMP2, TWEAKS_BREV
|
||||
.endif
|
||||
|
||||
// Encrypt/decrypt the last full block.
|
||||
vle32.v TMP0, (INP)
|
||||
vxor.vv TMP0, TMP0, TMP1
|
||||
aes_crypt TMP0, \enc, \keylen
|
||||
vxor.vv TMP0, TMP0, TMP1
|
||||
|
||||
// Swap the first TAIL_LEN bytes of the above result with the tail.
|
||||
// Note that to support in-place encryption/decryption, the load from
|
||||
// the input tail must happen before the store to the output tail.
|
||||
addi t0, INP, 16
|
||||
addi t1, OUTP, 16
|
||||
vmv.v.v TMP3, TMP0
|
||||
vsetvli zero, TAIL_LEN, e8, m1, tu, ma
|
||||
vle8.v TMP0, (t0)
|
||||
vse8.v TMP3, (t1)
|
||||
|
||||
// Encrypt/decrypt again and store the last full block.
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vxor.vv TMP0, TMP0, TMP2
|
||||
aes_crypt TMP0, \enc, \keylen
|
||||
vxor.vv TMP0, TMP0, TMP2
|
||||
vse32.v TMP0, (OUTP)
|
||||
|
||||
ret
|
||||
.endm
|
||||
|
||||
.macro aes_xts_crypt enc
|
||||
|
||||
// Check whether the length is a multiple of the AES block size.
|
||||
andi TAIL_LEN, LEN, 15
|
||||
beqz TAIL_LEN, 1f
|
||||
|
||||
// The length isn't a multiple of the AES block size, so ciphertext
|
||||
// stealing will be required. Ciphertext stealing involves special
|
||||
// handling of the partial block and the last full block, so subtract
|
||||
// the length of both from the length to be processed in the main loop.
|
||||
sub LEN, LEN, TAIL_LEN
|
||||
addi LEN, LEN, -16
|
||||
1:
|
||||
srli LEN32, LEN, 2
|
||||
// LEN and LEN32 now contain the total length of the blocks that will be
|
||||
// processed in the main loop, in bytes and 32-bit words respectively.
|
||||
|
||||
xts_init
|
||||
aes_begin KEYP, 128f, 192f
|
||||
__aes_xts_crypt \enc, 256
|
||||
128:
|
||||
__aes_xts_crypt \enc, 128
|
||||
192:
|
||||
__aes_xts_crypt \enc, 192
|
||||
.endm
|
||||
|
||||
// void aes_xts_encrypt_zvkned_zvbb_zvkg(const struct crypto_aes_ctx *key,
|
||||
// const u8 *in, u8 *out, size_t len,
|
||||
// u8 tweak[16]);
|
||||
//
|
||||
// |key| is the data key. |tweak| contains the next tweak; the encryption of
|
||||
// the original IV with the tweak key was already done. This function supports
|
||||
// incremental computation, but |len| must always be >= 16 (AES_BLOCK_SIZE), and
|
||||
// |len| must be a multiple of 16 except on the last call. If |len| is a
|
||||
// multiple of 16, then this function updates |tweak| to contain the next tweak.
|
||||
SYM_FUNC_START(aes_xts_encrypt_zvkned_zvbb_zvkg)
|
||||
aes_xts_crypt 1
|
||||
SYM_FUNC_END(aes_xts_encrypt_zvkned_zvbb_zvkg)
|
||||
|
||||
// Same prototype and calling convention as the encryption function
|
||||
SYM_FUNC_START(aes_xts_decrypt_zvkned_zvbb_zvkg)
|
||||
aes_xts_crypt 0
|
||||
SYM_FUNC_END(aes_xts_decrypt_zvkned_zvbb_zvkg)
|
||||
@@ -0,0 +1,146 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause */
|
||||
//
|
||||
// This file is dual-licensed, meaning that you can use it under your
|
||||
// choice of either of the following two licenses:
|
||||
//
|
||||
// Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License 2.0 (the "License"). You can obtain
|
||||
// a copy in the file LICENSE in the source distribution or at
|
||||
// https://www.openssl.org/source/license.html
|
||||
//
|
||||
// or
|
||||
//
|
||||
// Copyright (c) 2023, Jerry Shih <jerry.shih@sifive.com>
|
||||
// Copyright 2024 Google LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The generated code of this file depends on the following RISC-V extensions:
|
||||
// - RV64I
|
||||
// - RISC-V Vector ('V') with VLEN >= 128
|
||||
// - RISC-V Vector AES block cipher extension ('Zvkned')
|
||||
// - RISC-V Vector Cryptography Bit-manipulation extension ('Zvkb')
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.text
|
||||
.option arch, +zvkned, +zvkb
|
||||
|
||||
#include "aes-macros.S"
|
||||
|
||||
#define KEYP a0
|
||||
#define INP a1
|
||||
#define OUTP a2
|
||||
#define LEN a3
|
||||
#define IVP a4
|
||||
|
||||
#define LEN32 a5
|
||||
#define VL_E32 a6
|
||||
#define VL_BLOCKS a7
|
||||
|
||||
.macro aes_ctr32_crypt keylen
|
||||
// LEN32 = number of blocks, rounded up, in 32-bit words.
|
||||
addi t0, LEN, 15
|
||||
srli t0, t0, 4
|
||||
slli LEN32, t0, 2
|
||||
|
||||
// Create a mask that selects the last 32-bit word of each 128-bit
|
||||
// block. This is the word that contains the (big-endian) counter.
|
||||
li t0, 0x88
|
||||
vsetvli t1, zero, e8, m1, ta, ma
|
||||
vmv.v.x v0, t0
|
||||
|
||||
// Load the IV into v31. The last 32-bit word contains the counter.
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vle32.v v31, (IVP)
|
||||
|
||||
// Convert the big-endian counter into little-endian.
|
||||
vsetivli zero, 4, e32, m1, ta, mu
|
||||
vrev8.v v31, v31, v0.t
|
||||
|
||||
// Splat the IV to v16 (with LMUL=4). The number of copies is the
|
||||
// maximum number of blocks that will be processed per iteration.
|
||||
vsetvli zero, LEN32, e32, m4, ta, ma
|
||||
vmv.v.i v16, 0
|
||||
vaesz.vs v16, v31
|
||||
|
||||
// v20 = [x, x, x, 0, x, x, x, 1, ...]
|
||||
viota.m v20, v0, v0.t
|
||||
// v16 = [IV0, IV1, IV2, counter+0, IV0, IV1, IV2, counter+1, ...]
|
||||
vsetvli VL_E32, LEN32, e32, m4, ta, mu
|
||||
vadd.vv v16, v16, v20, v0.t
|
||||
|
||||
j 2f
|
||||
1:
|
||||
// Set the number of blocks to process in this iteration. vl=VL_E32 is
|
||||
// the length in 32-bit words, i.e. 4 times the number of blocks.
|
||||
vsetvli VL_E32, LEN32, e32, m4, ta, mu
|
||||
|
||||
// Increment the counters by the number of blocks processed in the
|
||||
// previous iteration.
|
||||
vadd.vx v16, v16, VL_BLOCKS, v0.t
|
||||
2:
|
||||
// Prepare the AES inputs into v24.
|
||||
vmv.v.v v24, v16
|
||||
vrev8.v v24, v24, v0.t // Convert counters back to big-endian.
|
||||
|
||||
// Encrypt the AES inputs to create the next portion of the keystream.
|
||||
aes_encrypt v24, \keylen
|
||||
|
||||
// XOR the data with the keystream.
|
||||
vsetvli t0, LEN, e8, m4, ta, ma
|
||||
vle8.v v20, (INP)
|
||||
vxor.vv v20, v20, v24
|
||||
vse8.v v20, (OUTP)
|
||||
|
||||
// Advance the pointers and update the remaining length.
|
||||
add INP, INP, t0
|
||||
add OUTP, OUTP, t0
|
||||
sub LEN, LEN, t0
|
||||
sub LEN32, LEN32, VL_E32
|
||||
srli VL_BLOCKS, VL_E32, 2
|
||||
|
||||
// Repeat if more data remains.
|
||||
bnez LEN, 1b
|
||||
|
||||
// Update *IVP to contain the next counter.
|
||||
vsetivli zero, 4, e32, m1, ta, mu
|
||||
vadd.vx v16, v16, VL_BLOCKS, v0.t
|
||||
vrev8.v v16, v16, v0.t // Convert counters back to big-endian.
|
||||
vse32.v v16, (IVP)
|
||||
|
||||
ret
|
||||
.endm
|
||||
|
||||
// void aes_ctr32_crypt_zvkned_zvkb(const struct crypto_aes_ctx *key,
|
||||
// const u8 *in, u8 *out, size_t len,
|
||||
// u8 iv[16]);
|
||||
SYM_FUNC_START(aes_ctr32_crypt_zvkned_zvkb)
|
||||
aes_begin KEYP, 128f, 192f
|
||||
aes_ctr32_crypt 256
|
||||
128:
|
||||
aes_ctr32_crypt 128
|
||||
192:
|
||||
aes_ctr32_crypt 192
|
||||
SYM_FUNC_END(aes_ctr32_crypt_zvkned_zvkb)
|
||||
@@ -0,0 +1,339 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause */
|
||||
//
|
||||
// This file is dual-licensed, meaning that you can use it under your
|
||||
// choice of either of the following two licenses:
|
||||
//
|
||||
// Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License 2.0 (the "License"). You can obtain
|
||||
// a copy in the file LICENSE in the source distribution or at
|
||||
// https://www.openssl.org/source/license.html
|
||||
//
|
||||
// or
|
||||
//
|
||||
// Copyright (c) 2023, Christoph Müllner <christoph.muellner@vrull.eu>
|
||||
// Copyright (c) 2023, Phoebe Chen <phoebe.chen@sifive.com>
|
||||
// Copyright (c) 2023, Jerry Shih <jerry.shih@sifive.com>
|
||||
// Copyright 2024 Google LLC
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// The generated code of this file depends on the following RISC-V extensions:
|
||||
// - RV64I
|
||||
// - RISC-V Vector ('V') with VLEN >= 128
|
||||
// - RISC-V Vector AES block cipher extension ('Zvkned')
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.text
|
||||
.option arch, +zvkned
|
||||
|
||||
#include "aes-macros.S"
|
||||
|
||||
#define KEYP a0
|
||||
#define INP a1
|
||||
#define OUTP a2
|
||||
#define LEN a3
|
||||
#define IVP a4
|
||||
|
||||
.macro __aes_crypt_zvkned enc, keylen
|
||||
vle32.v v16, (INP)
|
||||
aes_crypt v16, \enc, \keylen
|
||||
vse32.v v16, (OUTP)
|
||||
ret
|
||||
.endm
|
||||
|
||||
.macro aes_crypt_zvkned enc
|
||||
aes_begin KEYP, 128f, 192f
|
||||
__aes_crypt_zvkned \enc, 256
|
||||
128:
|
||||
__aes_crypt_zvkned \enc, 128
|
||||
192:
|
||||
__aes_crypt_zvkned \enc, 192
|
||||
.endm
|
||||
|
||||
// void aes_encrypt_zvkned(const struct crypto_aes_ctx *key,
|
||||
// const u8 in[16], u8 out[16]);
|
||||
SYM_FUNC_START(aes_encrypt_zvkned)
|
||||
aes_crypt_zvkned 1
|
||||
SYM_FUNC_END(aes_encrypt_zvkned)
|
||||
|
||||
// Same prototype and calling convention as the encryption function
|
||||
SYM_FUNC_START(aes_decrypt_zvkned)
|
||||
aes_crypt_zvkned 0
|
||||
SYM_FUNC_END(aes_decrypt_zvkned)
|
||||
|
||||
.macro __aes_ecb_crypt enc, keylen
|
||||
srli t0, LEN, 2
|
||||
// t0 is the remaining length in 32-bit words. It's a multiple of 4.
|
||||
1:
|
||||
vsetvli t1, t0, e32, m8, ta, ma
|
||||
sub t0, t0, t1 // Subtract number of words processed
|
||||
slli t1, t1, 2 // Words to bytes
|
||||
vle32.v v16, (INP)
|
||||
aes_crypt v16, \enc, \keylen
|
||||
vse32.v v16, (OUTP)
|
||||
add INP, INP, t1
|
||||
add OUTP, OUTP, t1
|
||||
bnez t0, 1b
|
||||
|
||||
ret
|
||||
.endm
|
||||
|
||||
.macro aes_ecb_crypt enc
|
||||
aes_begin KEYP, 128f, 192f
|
||||
__aes_ecb_crypt \enc, 256
|
||||
128:
|
||||
__aes_ecb_crypt \enc, 128
|
||||
192:
|
||||
__aes_ecb_crypt \enc, 192
|
||||
.endm
|
||||
|
||||
// void aes_ecb_encrypt_zvkned(const struct crypto_aes_ctx *key,
|
||||
// const u8 *in, u8 *out, size_t len);
|
||||
//
|
||||
// |len| must be nonzero and a multiple of 16 (AES_BLOCK_SIZE).
|
||||
SYM_FUNC_START(aes_ecb_encrypt_zvkned)
|
||||
aes_ecb_crypt 1
|
||||
SYM_FUNC_END(aes_ecb_encrypt_zvkned)
|
||||
|
||||
// Same prototype and calling convention as the encryption function
|
||||
SYM_FUNC_START(aes_ecb_decrypt_zvkned)
|
||||
aes_ecb_crypt 0
|
||||
SYM_FUNC_END(aes_ecb_decrypt_zvkned)
|
||||
|
||||
.macro aes_cbc_encrypt keylen
|
||||
vle32.v v16, (IVP) // Load IV
|
||||
1:
|
||||
vle32.v v17, (INP) // Load plaintext block
|
||||
vxor.vv v16, v16, v17 // XOR with IV or prev ciphertext block
|
||||
aes_encrypt v16, \keylen // Encrypt
|
||||
vse32.v v16, (OUTP) // Store ciphertext block
|
||||
addi INP, INP, 16
|
||||
addi OUTP, OUTP, 16
|
||||
addi LEN, LEN, -16
|
||||
bnez LEN, 1b
|
||||
|
||||
vse32.v v16, (IVP) // Store next IV
|
||||
ret
|
||||
.endm
|
||||
|
||||
.macro aes_cbc_decrypt keylen
|
||||
srli LEN, LEN, 2 // Convert LEN from bytes to words
|
||||
vle32.v v16, (IVP) // Load IV
|
||||
1:
|
||||
vsetvli t0, LEN, e32, m4, ta, ma
|
||||
vle32.v v20, (INP) // Load ciphertext blocks
|
||||
vslideup.vi v16, v20, 4 // Setup prev ciphertext blocks
|
||||
addi t1, t0, -4
|
||||
vslidedown.vx v24, v20, t1 // Save last ciphertext block
|
||||
aes_decrypt v20, \keylen // Decrypt the blocks
|
||||
vxor.vv v20, v20, v16 // XOR with prev ciphertext blocks
|
||||
vse32.v v20, (OUTP) // Store plaintext blocks
|
||||
vmv.v.v v16, v24 // Next "IV" is last ciphertext block
|
||||
slli t1, t0, 2 // Words to bytes
|
||||
add INP, INP, t1
|
||||
add OUTP, OUTP, t1
|
||||
sub LEN, LEN, t0
|
||||
bnez LEN, 1b
|
||||
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
vse32.v v16, (IVP) // Store next IV
|
||||
ret
|
||||
.endm
|
||||
|
||||
// void aes_cbc_encrypt_zvkned(const struct crypto_aes_ctx *key,
|
||||
// const u8 *in, u8 *out, size_t len, u8 iv[16]);
|
||||
//
|
||||
// |len| must be nonzero and a multiple of 16 (AES_BLOCK_SIZE).
|
||||
SYM_FUNC_START(aes_cbc_encrypt_zvkned)
|
||||
aes_begin KEYP, 128f, 192f
|
||||
aes_cbc_encrypt 256
|
||||
128:
|
||||
aes_cbc_encrypt 128
|
||||
192:
|
||||
aes_cbc_encrypt 192
|
||||
SYM_FUNC_END(aes_cbc_encrypt_zvkned)
|
||||
|
||||
// Same prototype and calling convention as the encryption function
|
||||
SYM_FUNC_START(aes_cbc_decrypt_zvkned)
|
||||
aes_begin KEYP, 128f, 192f
|
||||
aes_cbc_decrypt 256
|
||||
128:
|
||||
aes_cbc_decrypt 128
|
||||
192:
|
||||
aes_cbc_decrypt 192
|
||||
SYM_FUNC_END(aes_cbc_decrypt_zvkned)
|
||||
|
||||
.macro aes_cbc_cts_encrypt keylen
|
||||
|
||||
// CBC-encrypt all blocks except the last. But don't store the
|
||||
// second-to-last block to the output buffer yet, since it will be
|
||||
// handled specially in the ciphertext stealing step. Exception: if the
|
||||
// message is single-block, still encrypt the last (and only) block.
|
||||
li t0, 16
|
||||
j 2f
|
||||
1:
|
||||
vse32.v v16, (OUTP) // Store ciphertext block
|
||||
addi OUTP, OUTP, 16
|
||||
2:
|
||||
vle32.v v17, (INP) // Load plaintext block
|
||||
vxor.vv v16, v16, v17 // XOR with IV or prev ciphertext block
|
||||
aes_encrypt v16, \keylen // Encrypt
|
||||
addi INP, INP, 16
|
||||
addi LEN, LEN, -16
|
||||
bgt LEN, t0, 1b // Repeat if more than one block remains
|
||||
|
||||
// Special case: if the message is a single block, just do CBC.
|
||||
beqz LEN, .Lcts_encrypt_done\@
|
||||
|
||||
// Encrypt the last two blocks using ciphertext stealing as follows:
|
||||
// C[n-1] = Encrypt(Encrypt(P[n-1] ^ C[n-2]) ^ P[n])
|
||||
// C[n] = Encrypt(P[n-1] ^ C[n-2])[0..LEN]
|
||||
//
|
||||
// C[i] denotes the i'th ciphertext block, and likewise P[i] the i'th
|
||||
// plaintext block. Block n, the last block, may be partial; its length
|
||||
// is 1 <= LEN <= 16. If there are only 2 blocks, C[n-2] means the IV.
|
||||
//
|
||||
// v16 already contains Encrypt(P[n-1] ^ C[n-2]).
|
||||
// INP points to P[n]. OUTP points to where C[n-1] should go.
|
||||
// To support in-place encryption, load P[n] before storing C[n].
|
||||
addi t0, OUTP, 16 // Get pointer to where C[n] should go
|
||||
vsetvli zero, LEN, e8, m1, tu, ma
|
||||
vle8.v v17, (INP) // Load P[n]
|
||||
vse8.v v16, (t0) // Store C[n]
|
||||
vxor.vv v16, v16, v17 // v16 = Encrypt(P[n-1] ^ C[n-2]) ^ P[n]
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
aes_encrypt v16, \keylen
|
||||
.Lcts_encrypt_done\@:
|
||||
vse32.v v16, (OUTP) // Store C[n-1] (or C[n] in single-block case)
|
||||
ret
|
||||
.endm
|
||||
|
||||
#define LEN32 t4 // Length of remaining full blocks in 32-bit words
|
||||
#define LEN_MOD16 t5 // Length of message in bytes mod 16
|
||||
|
||||
.macro aes_cbc_cts_decrypt keylen
|
||||
andi LEN32, LEN, ~15
|
||||
srli LEN32, LEN32, 2
|
||||
andi LEN_MOD16, LEN, 15
|
||||
|
||||
// Save C[n-2] in v28 so that it's available later during the ciphertext
|
||||
// stealing step. If there are fewer than three blocks, C[n-2] means
|
||||
// the IV, otherwise it means the third-to-last ciphertext block.
|
||||
vmv.v.v v28, v16 // IV
|
||||
add t0, LEN, -33
|
||||
bltz t0, .Lcts_decrypt_loop\@
|
||||
andi t0, t0, ~15
|
||||
add t0, t0, INP
|
||||
vle32.v v28, (t0)
|
||||
|
||||
// CBC-decrypt all full blocks. For the last full block, or the last 2
|
||||
// full blocks if the message is block-aligned, this doesn't write the
|
||||
// correct output blocks (unless the message is only a single block),
|
||||
// because it XORs the wrong values with the raw AES plaintexts. But we
|
||||
// fix this after this loop without redoing the AES decryptions. This
|
||||
// approach allows more of the AES decryptions to be parallelized.
|
||||
.Lcts_decrypt_loop\@:
|
||||
vsetvli t0, LEN32, e32, m4, ta, ma
|
||||
addi t1, t0, -4
|
||||
vle32.v v20, (INP) // Load next set of ciphertext blocks
|
||||
vmv.v.v v24, v16 // Get IV or last ciphertext block of prev set
|
||||
vslideup.vi v24, v20, 4 // Setup prev ciphertext blocks
|
||||
vslidedown.vx v16, v20, t1 // Save last ciphertext block of this set
|
||||
aes_decrypt v20, \keylen // Decrypt this set of blocks
|
||||
vxor.vv v24, v24, v20 // XOR prev ciphertext blocks with decrypted blocks
|
||||
vse32.v v24, (OUTP) // Store this set of plaintext blocks
|
||||
sub LEN32, LEN32, t0
|
||||
slli t0, t0, 2 // Words to bytes
|
||||
add INP, INP, t0
|
||||
add OUTP, OUTP, t0
|
||||
bnez LEN32, .Lcts_decrypt_loop\@
|
||||
|
||||
vsetivli zero, 4, e32, m4, ta, ma
|
||||
vslidedown.vx v20, v20, t1 // Extract raw plaintext of last full block
|
||||
addi t0, OUTP, -16 // Get pointer to last full plaintext block
|
||||
bnez LEN_MOD16, .Lcts_decrypt_non_block_aligned\@
|
||||
|
||||
// Special case: if the message is a single block, just do CBC.
|
||||
li t1, 16
|
||||
beq LEN, t1, .Lcts_decrypt_done\@
|
||||
|
||||
// Block-aligned message. Just fix up the last 2 blocks. We need:
|
||||
//
|
||||
// P[n-1] = Decrypt(C[n]) ^ C[n-2]
|
||||
// P[n] = Decrypt(C[n-1]) ^ C[n]
|
||||
//
|
||||
// We have C[n] in v16, Decrypt(C[n]) in v20, and C[n-2] in v28.
|
||||
// Together with Decrypt(C[n-1]) ^ C[n-2] from the output buffer, this
|
||||
// is everything needed to fix the output without re-decrypting blocks.
|
||||
addi t1, OUTP, -32 // Get pointer to where P[n-1] should go
|
||||
vxor.vv v20, v20, v28 // Decrypt(C[n]) ^ C[n-2] == P[n-1]
|
||||
vle32.v v24, (t1) // Decrypt(C[n-1]) ^ C[n-2]
|
||||
vse32.v v20, (t1) // Store P[n-1]
|
||||
vxor.vv v20, v24, v16 // Decrypt(C[n-1]) ^ C[n-2] ^ C[n] == P[n] ^ C[n-2]
|
||||
j .Lcts_decrypt_finish\@
|
||||
|
||||
.Lcts_decrypt_non_block_aligned\@:
|
||||
// Decrypt the last two blocks using ciphertext stealing as follows:
|
||||
//
|
||||
// P[n-1] = Decrypt(C[n] || Decrypt(C[n-1])[LEN_MOD16..16]) ^ C[n-2]
|
||||
// P[n] = (Decrypt(C[n-1]) ^ C[n])[0..LEN_MOD16]
|
||||
//
|
||||
// We already have Decrypt(C[n-1]) in v20 and C[n-2] in v28.
|
||||
vmv.v.v v16, v20 // v16 = Decrypt(C[n-1])
|
||||
vsetvli zero, LEN_MOD16, e8, m1, tu, ma
|
||||
vle8.v v20, (INP) // v20 = C[n] || Decrypt(C[n-1])[LEN_MOD16..16]
|
||||
vxor.vv v16, v16, v20 // v16 = Decrypt(C[n-1]) ^ C[n]
|
||||
vse8.v v16, (OUTP) // Store P[n]
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
aes_decrypt v20, \keylen // v20 = Decrypt(C[n] || Decrypt(C[n-1])[LEN_MOD16..16])
|
||||
.Lcts_decrypt_finish\@:
|
||||
vxor.vv v20, v20, v28 // XOR with C[n-2]
|
||||
vse32.v v20, (t0) // Store last full plaintext block
|
||||
.Lcts_decrypt_done\@:
|
||||
ret
|
||||
.endm
|
||||
|
||||
.macro aes_cbc_cts_crypt keylen
|
||||
vle32.v v16, (IVP) // Load IV
|
||||
beqz a5, .Lcts_decrypt\@
|
||||
aes_cbc_cts_encrypt \keylen
|
||||
.Lcts_decrypt\@:
|
||||
aes_cbc_cts_decrypt \keylen
|
||||
.endm
|
||||
|
||||
// void aes_cbc_cts_crypt_zvkned(const struct crypto_aes_ctx *key,
|
||||
// const u8 *in, u8 *out, size_t len,
|
||||
// const u8 iv[16], bool enc);
|
||||
//
|
||||
// Encrypts or decrypts a message with the CS3 variant of AES-CBC-CTS.
|
||||
// This is the variant that unconditionally swaps the last two blocks.
|
||||
SYM_FUNC_START(aes_cbc_cts_crypt_zvkned)
|
||||
aes_begin KEYP, 128f, 192f
|
||||
aes_cbc_cts_crypt 256
|
||||
128:
|
||||
aes_cbc_cts_crypt 128
|
||||
192:
|
||||
aes_cbc_cts_crypt 192
|
||||
SYM_FUNC_END(aes_cbc_cts_crypt_zvkned)
|
||||
@@ -0,0 +1,101 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* ChaCha20 using the RISC-V vector crypto extensions
|
||||
*
|
||||
* Copyright (C) 2023 SiFive, Inc.
|
||||
* Author: Jerry Shih <jerry.shih@sifive.com>
|
||||
*/
|
||||
|
||||
#include <asm/simd.h>
|
||||
#include <asm/vector.h>
|
||||
#include <crypto/internal/chacha.h>
|
||||
#include <crypto/internal/skcipher.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
asmlinkage void chacha20_zvkb(const u32 key[8], const u8 *in, u8 *out,
|
||||
size_t len, const u32 iv[4]);
|
||||
|
||||
static int riscv64_chacha20_crypt(struct skcipher_request *req)
|
||||
{
|
||||
u32 iv[CHACHA_IV_SIZE / sizeof(u32)];
|
||||
u8 block_buffer[CHACHA_BLOCK_SIZE];
|
||||
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
|
||||
const struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
|
||||
struct skcipher_walk walk;
|
||||
unsigned int nbytes;
|
||||
unsigned int tail_bytes;
|
||||
int err;
|
||||
|
||||
iv[0] = get_unaligned_le32(req->iv);
|
||||
iv[1] = get_unaligned_le32(req->iv + 4);
|
||||
iv[2] = get_unaligned_le32(req->iv + 8);
|
||||
iv[3] = get_unaligned_le32(req->iv + 12);
|
||||
|
||||
err = skcipher_walk_virt(&walk, req, false);
|
||||
while (walk.nbytes) {
|
||||
nbytes = walk.nbytes & ~(CHACHA_BLOCK_SIZE - 1);
|
||||
tail_bytes = walk.nbytes & (CHACHA_BLOCK_SIZE - 1);
|
||||
kernel_vector_begin();
|
||||
if (nbytes) {
|
||||
chacha20_zvkb(ctx->key, walk.src.virt.addr,
|
||||
walk.dst.virt.addr, nbytes, iv);
|
||||
iv[0] += nbytes / CHACHA_BLOCK_SIZE;
|
||||
}
|
||||
if (walk.nbytes == walk.total && tail_bytes > 0) {
|
||||
memcpy(block_buffer, walk.src.virt.addr + nbytes,
|
||||
tail_bytes);
|
||||
chacha20_zvkb(ctx->key, block_buffer, block_buffer,
|
||||
CHACHA_BLOCK_SIZE, iv);
|
||||
memcpy(walk.dst.virt.addr + nbytes, block_buffer,
|
||||
tail_bytes);
|
||||
tail_bytes = 0;
|
||||
}
|
||||
kernel_vector_end();
|
||||
|
||||
err = skcipher_walk_done(&walk, tail_bytes);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct skcipher_alg riscv64_chacha_alg = {
|
||||
.setkey = chacha20_setkey,
|
||||
.encrypt = riscv64_chacha20_crypt,
|
||||
.decrypt = riscv64_chacha20_crypt,
|
||||
.min_keysize = CHACHA_KEY_SIZE,
|
||||
.max_keysize = CHACHA_KEY_SIZE,
|
||||
.ivsize = CHACHA_IV_SIZE,
|
||||
.chunksize = CHACHA_BLOCK_SIZE,
|
||||
.walksize = 4 * CHACHA_BLOCK_SIZE,
|
||||
.base = {
|
||||
.cra_blocksize = 1,
|
||||
.cra_ctxsize = sizeof(struct chacha_ctx),
|
||||
.cra_priority = 300,
|
||||
.cra_name = "chacha20",
|
||||
.cra_driver_name = "chacha20-riscv64-zvkb",
|
||||
.cra_module = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init riscv64_chacha_mod_init(void)
|
||||
{
|
||||
if (riscv_isa_extension_available(NULL, ZVKB) &&
|
||||
riscv_vector_vlen() >= 128)
|
||||
return crypto_register_skcipher(&riscv64_chacha_alg);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void __exit riscv64_chacha_mod_exit(void)
|
||||
{
|
||||
crypto_unregister_skcipher(&riscv64_chacha_alg);
|
||||
}
|
||||
|
||||
module_init(riscv64_chacha_mod_init);
|
||||
module_exit(riscv64_chacha_mod_exit);
|
||||
|
||||
MODULE_DESCRIPTION("ChaCha20 (RISC-V accelerated)");
|
||||
MODULE_AUTHOR("Jerry Shih <jerry.shih@sifive.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_CRYPTO("chacha20");
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user