Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support RISCV64 vector extension. #6

Merged
merged 1 commit into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
rustflags = ["-C", "target-feature=+neon,+aes"]

[target.'cfg(target_arch="riscv64")']
rustflags = ["-C", "target-feature=+zkne"]
rustflags = ["-C", "target-feature=+v,+zvkn"]

[target.'cfg(target_arch="x86_64")']
rustflags = ["-C", "target-feature=+sse2,+aes"]
14 changes: 4 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,14 @@ jobs:
- name: Linux x86_64
os: ubuntu-24.04
target: x86_64-unknown-linux-gnu
channel: stable

- name: Linux riscv64gc
os: ubuntu-24.04
target: riscv64gc-unknown-linux-gnu
channel: nightly

- name: MacOS aarch64
os: macos-latest
target: aarch64-apple-darwin
channel: stable

name: Clippy ${{ matrix.name }}
runs-on: ${{ matrix.os }}
Expand All @@ -40,8 +37,8 @@ jobs:

- name: Install toolchain
run: |
rustup toolchain install ${{ matrix.channel }} --no-self-update --profile=minimal --component clippy --target ${{ matrix.target }}
rustup override set ${{ matrix.channel }}
rustup toolchain install stable --no-self-update --profile=minimal --component clippy --target ${{ matrix.target }}
rustup override set stable
cargo -V

- name: Caching
Expand Down Expand Up @@ -139,16 +136,13 @@ jobs:
- name: aarch64
arch: aarch64
target: aarch64-unknown-linux-gnu
channel: stable
cpu: a64fx
- name: riscv64
arch: riscv64
target: riscv64gc-unknown-linux-gnu
channel: nightly
- name: x86_64
arch: x86-64
target: x86_64-unknown-linux-gnu
channel: stable

name: Validate ${{ matrix.name }}
runs-on: ubuntu-24.04
Expand All @@ -165,8 +159,8 @@ jobs:

- name: Install toolchain
run: |
rustup toolchain install ${{ matrix.channel }} --no-self-update --profile=minimal --target ${{ matrix.target }}
rustup override set ${{ matrix.channel }}
rustup toolchain install stable --no-self-update --profile=minimal --target ${{ matrix.target }}
rustup override set stable
cargo -V

- name: Caching
Expand Down
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ default = ["std", "tls", "getrandom", "rand_core"]
std = []
# Activates the thread local functionality.
tls = ["std"]
# Enables support for experimental RISC-V vector cryptography extension. Please read the README.md.
experimental_riscv = []

### The following features are only used internally and are unstable ###
# Forces the compiler to always use the fallback (never using the hardware AES directly).
Expand Down
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,29 @@ We provide a software implementation of AES in case there is no hardware acceler
accelerated versions for the following architectures:

- aarch64: Support since Cortex-A53 (2012).
- riscv64: Must support the scalar based cryptography extension (zk).
- riscv64: Experimental using the vector crypto extension.
- x86_64: Support since Intel's Westmere (2010) and AMD's Bulldozer (2011).

riscv64 needs nightly Rust, since the AES intrinsics are not marked as stable yet.
## Experimental RISC-V support

There are two AES extensions for RISC-V, the scalar (zkn) and the vector crypto extensions (zvkn). Currently, there
are no hardware based CPUs that support either of them. It's also not clear which platform will favor which. Since
this crate mainly targets application class architectures (opposed to embedded), we think that providing a vector
crypto implementation is the safest bet. Since there are no intrinsics for the vector crypto extension, we provide
a handwritten ASM implementation. Since there is currently no way to discover the support for the vector crypto
extension (August 2024), you need to select the needed target features and an experimental create feature at compile
time. The generated executable will only run on systems with a vector crypto extension.

Activate the target features vor the vector extension and the vector crypto extension. This can be done for example
inside the `.cargo/config.toml`:

```toml
[target.'cfg(target_arch="riscv64")']
rustflags = ["-C", "target-feature=+v,+zvkn"]
```

You also need to select the `experimental_riscv` create feature. This feature is experimental and will
most likely become absolute in the future (once intrinsics and runtime discovery are available).

## Optimal Performance

Expand All @@ -83,7 +102,7 @@ much better performance. The runtime detection is not supported in `no_std`.
Use the following target features for optimal performance:

- aarch64: "aes" (using the cryptographic extension)
- riscv64: "zkne" (using the scalar based cryptography extension)
- riscv64: "v" and "zvkn" (using the vector and vector crypto extension)
- x86_64: "aes" (using AES-NI)

Example in `.cargo/config.toml`:
Expand All @@ -93,7 +112,7 @@ Example in `.cargo/config.toml`:
rustflags = ["-C", "target-feature=+aes"]

[target.'cfg(target_arch="riscv64")']
rustflags = ["-C", "target-feature=+zkne"]
rustflags = ["-C", "target-feature=+v,+zvkn"]

[target.'cfg(target_arch="x86_64")']
rustflags = ["-C", "target-feature=+aes"]
Expand Down
4 changes: 2 additions & 2 deletions scripts/run_verification.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ case $ARCH in
qemu-aarch64 -cpu cortex-a53 -L /usr/aarch64-linux-gnu ../target/aarch64-unknown-linux-gnu/release/verification
;;
"riscv64")
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER=riscv64-linux-gnu-gcc cargo +nightly build --release --target=riscv64gc-unknown-linux-gnu
qemu-riscv64 -cpu rv64,zk=true -L /usr/riscv64-linux-gnu ../target/riscv64gc-unknown-linux-gnu/release/verification
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER=riscv64-linux-gnu-gcc cargo build --release --target=riscv64gc-unknown-linux-gnu --no-default-features --features=experimental_riscv
qemu-riscv64 -cpu rv64,v=true,vlen=128,zvkn=true -L /usr/riscv64-linux-gnu ../target/riscv64gc-unknown-linux-gnu/release/verification
;;
"x86_64")
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=x86_64-linux-gnu-gcc cargo build --release --target=x86_64-unknown-linux-gnu
Expand Down
35 changes: 5 additions & 30 deletions src/fallback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@
//! - Fixed: Always uses the software AES implementation.
#[cfg(all(
any(
not(all(
feature = "std",
any(
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "x86_64",
)
)),
not(all(feature = "std", any(target_arch = "aarch64", target_arch = "x86_64",))),
feature = "force_no_runtime_detection"
),
not(feature = "verification")
Expand All @@ -21,14 +14,7 @@ mod fixed;

#[cfg(all(
not(any(
not(all(
feature = "std",
any(
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "x86_64",
)
)),
not(all(feature = "std", any(target_arch = "aarch64", target_arch = "x86_64",))),
feature = "force_no_runtime_detection"
)),
not(feature = "verification")
Expand All @@ -37,28 +23,17 @@ mod runtime;

pub(crate) mod software;

#[cfg(all(
#[cfg(all(
feature = "std",
any(
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "x86_64",
),
any(target_arch = "aarch64", target_arch = "x86_64",),
not(feature = "force_no_runtime_detection"),
not(feature = "verification")
))]
pub use runtime::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64};

#[cfg(all(
any(
not(all(
feature = "std",
any(
target_arch = "aarch64",
target_arch = "riscv64",
target_arch = "x86_64",
)
)),
not(all(feature = "std", any(target_arch = "aarch64", target_arch = "x86_64",))),
feature = "force_no_runtime_detection"
),
not(feature = "verification")
Expand Down
8 changes: 1 addition & 7 deletions src/fallback/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ pub(crate) fn has_hardware_acceleration() -> bool {
{
return true;
}
#[cfg(target_arch = "riscv64")]
if std::arch::is_riscv_feature_detected!("zkne") {
return true;
}

false
}
Expand Down Expand Up @@ -265,9 +261,7 @@ impl Aes256Ctr64 {
// Safety: We checked that the hardware acceleration is available.
unsafe { this.next_impl() }
}
Aes256Ctr64Inner::Software(this) => {
this.borrow_mut().next_impl()
},
Aes256Ctr64Inner::Software(this) => this.borrow_mut().next_impl(),
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/hardware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ pub use x86_64::{Aes128Ctr128, Aes128Ctr64, Aes256Ctr128, Aes256Ctr64};
target_feature = "sse2",
target_feature = "aes",
),
all(
target_arch = "riscv64", target_feature = "zkne"
),
all(target_arch = "riscv64", feature = "experimental_riscv"),
all(
target_arch = "aarch64",
target_feature = "neon",
Expand Down
Loading