Using the RISC-V Scalar Cryptography extensions
Compile and emulate RISC-V scalar cryptography extensions with GCC and Qemu.
Introduction
RISC-V is an instruction set provided under a open source license which is more and more used in the embedded device world but not only. Linux kernel and Android support RISC-V processors. The instruction set has a modular design divided between a base part and extensions which allow to integrate to a CPU only the instructions of interest. Each extension is named with a single or several letters. For example, saying that a CPU has instructions set RV64IMC means that has a 64-bit address space with instructions for integer multiplication and division ( the letter M ) and Compressed instructions ( the letter C ).
Among those extensions, the RISC-V Scalar Cryptography extensions accelerate some operations interesting for Symmetric Cryptography. They include instructions to accelerate AES, SM4, SHA-256, SHA-512, SM3 and some bit manipulation instructions available for 32 and 64 bit architectures. It is similar to the AES-NI instructions done by Intel for the x86 architecture. This post focus here on 64 bit architecture but is also applicable for 32-bit CPUs. Scalar Cryptography extensions are ratified since 2021 thus those extensions are stable and will not change in the future. They can be found under the following denominations:
- Zkn: NIST Algorithm Suite, AES and SHA2
- Zks: ShangMi Algorithm Suite, SM3 and SM4
- Zkt: Data independent execution latency extension.
Code
For example, to code an AES encryption in assembly, the two instructions aes64ks1i
and aes64ks2
can be used for the key schedule. If the secret key is in the registers t0
and t1
the first round of the key schedule can be implemented with the following:
|
|
Then for the encryption, the instruction aes64esm
is used to implement the middle round operations without the add round key operation. As well, the instruction aes64es
is used for the final round. A full AES implementation and Makefile is provided in my repository.
Compilation
The Cryptography extensions are supported by GCC since version 12. It should be available in your package manager if you have a recent distribution. LLVM seems to also support those instructions since version 14.0.
To allow GCC to use the Cryptography extensions, the architecture of the target CPU have to be given in a compilation flag. The flag march
should include zkn
to use the AES instructions. The code can be compiled with the following command:
|
|
And it produces a valid ELF executable file:
|
|
It is then possible to disassemble the binary with the objdump
tool:
|
|
Emulation
The Scalar Cryptography extensions are new and there are not a lot of hardware designs available. Some proof-of-concept designs may be found on the RISC-V pages. However, they are supported by Qemu since version 7.1.0 and it allows to emulate the execution of those instructions. Qemu is able to emulate several RISC-V CPUs:
|
|
Here we are interested by the 64-bit architecture but in addition we have to pass the extension option zkn
:
|
|
It gives an emulated execution of our AES encryption implementation.
I found difficult to find how to play with the RISC-V extensions and those instructions even though they are already into standard tool like GCC or Qemu. I hope it will helps people who want to experiment that.