Skip to content

Commit

Permalink
Add compact versions
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Aug 21, 2024
1 parent b263635 commit 14158e9
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 12 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/sha2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ jobs:
- run: cross test --package sha2 --target riscv64gc-unknown-linux-gnu
env:
RUSTFLAGS: '-Dwarnings --cfg sha2_backend="riscv-zknh" -C target-feature=+zknh'
- run: cross test --package sha2 --target riscv64gc-unknown-linux-gnu
env:
RUSTFLAGS: '-Dwarnings --cfg sha2_backend="riscv-zknh-compact" -C target-feature=+zknh'

riscv32-zknh:
runs-on: ubuntu-latest
Expand All @@ -175,6 +178,9 @@ jobs:
- run: cargo build --target riscv32gc-unknown-linux-gnu -Z build-std
env:
RUSTFLAGS: '-Dwarnings --cfg sha2_backend="riscv-zknh" -C target-feature=+zknh'
- run: cargo build --target riscv32gc-unknown-linux-gnu -Z build-std
env:
RUSTFLAGS: '-Dwarnings --cfg sha2_backend="riscv-zknh-compact" -C target-feature=+zknh'

minimal-versions:
uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
Expand Down
6 changes: 3 additions & 3 deletions sha2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ base16ct = { version = "0.2", features = ["alloc"] }
[features]
default = ["oid", "std"]
std = ["digest/std"]
oid = ["digest/oid"] # Enable OID support
oid = ["digest/oid"] # Enable OID support
zeroize = ["digest/zeroize"]
force-soft = [] # Force software implementation
force-soft = [] # Force software implementation

[lints.rust.unexpected_cfgs]
level = "warn"
check-cfg = ['cfg(sha2_backend, values("riscv-zknh"))']
check-cfg = ['cfg(sha2_backend, values("riscv-zknh", "riscv-zknh-compact"))']

[package.metadata.docs.rs]
all-features = true
Expand Down
5 changes: 4 additions & 1 deletion sha2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs, rust_2018_idioms)]
#![cfg_attr(sha2_backend = "riscv-zknh", feature(riscv_ext_intrinsics))]
#![cfg_attr(
any(sha2_backend = "riscv-zknh", sha2_backend = "riscv-zknh-compact"),
feature(riscv_ext_intrinsics)
)]

pub use digest::{self, Digest};

Expand Down
6 changes: 6 additions & 0 deletions sha2/src/sha256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ cfg_if::cfg_if! {
))] {
mod riscv_zknh;
use riscv_zknh::compress;
} else if #[cfg(all(
any(target_arch = "riscv32", target_arch = "riscv64"),
sha2_backend = "riscv-zknh-compact"
))] {
mod riscv_zknh_compact;
use riscv_zknh_compact::compress;
} else if #[cfg(target_arch = "aarch64")] {
mod soft;
mod aarch64;
Expand Down
17 changes: 9 additions & 8 deletions sha2/src/sha256/riscv_zknh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ fn maj(x: u32, y: u32, z: u32) -> u32 {
}

fn round<const R: usize>(state: &mut [u32; 8], block: &[u32; 16]) {
let a = (K32.len() - R) % 8;
let b = (K32.len() - R + 1) % 8;
let c = (K32.len() - R + 2) % 8;
let d = (K32.len() - R + 3) % 8;
let e = (K32.len() - R + 4) % 8;
let f = (K32.len() - R + 5) % 8;
let g = (K32.len() - R + 6) % 8;
let h = (K32.len() - R + 7) % 8;
let n = K32.len() - R;
let a = n % 8;
let b = (n + 1) % 8;
let c = (n + 2) % 8;
let d = (n + 3) % 8;
let e = (n + 4) % 8;
let f = (n + 5) % 8;
let g = (n + 6) % 8;
let h = (n + 7) % 8;

state[h] = state[h]
.wrapping_add(unsafe { sha256sum1(state[e]) })
Expand Down
79 changes: 79 additions & 0 deletions sha2/src/sha256/riscv_zknh_compact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use crate::consts::K32;

#[cfg(target_arch = "riscv32")]
use core::arch::riscv32::*;
#[cfg(target_arch = "riscv64")]
use core::arch::riscv64::*;

#[cfg(not(target_feature = "zknh"))]
compile_error!("riscv-zknh backend requires enabled zknh target feature");

#[inline(always)]
fn ch(x: u32, y: u32, z: u32) -> u32 {
(x & y) ^ (!x & z)
}

#[inline(always)]
fn maj(x: u32, y: u32, z: u32) -> u32 {
(x & y) ^ (x & z) ^ (y & z)
}

#[inline(always)]
fn round(state: &mut [u32; 8], block: &[u32; 16], r: usize) {
let n = K32.len() - r;
let a = (n + 0) % 8;
let b = (n + 1) % 8;
let c = (n + 2) % 8;
let d = (n + 3) % 8;
let e = (n + 4) % 8;
let f = (n + 5) % 8;
let g = (n + 6) % 8;
let h = (n + 7) % 8;

state[h] = state[h]
.wrapping_add(unsafe { sha256sum1(state[e]) })
.wrapping_add(ch(state[e], state[f], state[g]))
.wrapping_add(K32[r])
.wrapping_add(block[r % 16]);
state[d] = state[d].wrapping_add(state[h]);
state[h] = state[h]
.wrapping_add(unsafe { sha256sum0(state[a]) })
.wrapping_add(maj(state[a], state[b], state[c]))
}

#[inline(always)]
fn round_schedule(state: &mut [u32; 8], block: &mut [u32; 16], r: usize) {
round(state, block, r);

block[r % 16] = block[r % 16]
.wrapping_add(unsafe { sha256sig1(block[(r + 14) % 16]) })
.wrapping_add(block[(r + 9) % 16])
.wrapping_add(unsafe { sha256sig0(block[(r + 1) % 16]) });
}

#[inline(always)]
fn compress_block(state: &mut [u32; 8], mut block: [u32; 16]) {
let s = &mut state.clone();
let b = &mut block;

for i in 0..48 {
round_schedule(s, b, i);
}
for i in 48..64 {
round(s, b, i);
}

for i in 0..8 {
state[i] = state[i].wrapping_add(s[i]);
}
}

pub fn compress(state: &mut [u32; 8], blocks: &[[u8; 64]]) {
for block_u8 in blocks {
let mut block = [0u32; 16];
for (dst, src) in block.iter_mut().zip(block_u8.chunks_exact(4)) {
*dst = u32::from_be_bytes(src.try_into().unwrap());
}
compress_block(state, block);
}
}
6 changes: 6 additions & 0 deletions sha2/src/sha512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ cfg_if::cfg_if! {
))] {
mod riscv_zknh;
use riscv_zknh::compress;
} else if #[cfg(all(
any(target_arch = "riscv32", target_arch = "riscv64"),
sha2_backend = "riscv-zknh-compact"
))] {
mod riscv_zknh_compact;
use riscv_zknh_compact::compress;
} else if #[cfg(target_arch = "aarch64")] {
mod soft;
mod aarch64;
Expand Down
107 changes: 107 additions & 0 deletions sha2/src/sha512/riscv_zknh_compact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use crate::consts::K64;

#[cfg(target_arch = "riscv32")]
use core::arch::riscv32::*;
#[cfg(target_arch = "riscv64")]
use core::arch::riscv64::*;

#[cfg(not(target_feature = "zknh"))]
compile_error!("riscv-zknh backend requires enabled zknh target feature");

#[cfg(target_arch = "riscv32")]
unsafe fn sha512sum0(x: u64) -> u64 {
let a = sha512sum0r((x >> 32) as u32, x as u32);
let b = sha512sum0r(x as u32, (x >> 32) as u32);
((a as u64) << 32) | (b as u64)
}

#[cfg(target_arch = "riscv32")]
unsafe fn sha512sum1(x: u64) -> u64 {
let a = sha512sum1r((x >> 32) as u32, x as u32);
let b = sha512sum1r(x as u32, (x >> 32) as u32);
((a as u64) << 32) | (b as u64)
}

#[cfg(target_arch = "riscv32")]
unsafe fn sha512sig0(x: u64) -> u64 {
let a = sha512sig0h((x >> 32) as u32, x as u32);
let b = sha512sig0l(x as u32, (x >> 32) as u32);
((a as u64) << 32) | (b as u64)
}

#[cfg(target_arch = "riscv32")]
unsafe fn sha512sig1(x: u64) -> u64 {
let a = sha512sig1h((x >> 32) as u32, x as u32);
let b = sha512sig1l(x as u32, (x >> 32) as u32);
((a as u64) << 32) | (b as u64)
}

#[inline(always)]
fn ch(x: u64, y: u64, z: u64) -> u64 {
(x & y) ^ (!x & z)
}

#[inline(always)]
fn maj(x: u64, y: u64, z: u64) -> u64 {
(x & y) ^ (x & z) ^ (y & z)
}

#[inline(always)]
fn round(state: &mut [u64; 8], block: &[u64; 16], r: usize) {
let n = K64.len() - r;
let a = (n + 0) % 8;
let b = (n + 1) % 8;
let c = (n + 2) % 8;
let d = (n + 3) % 8;
let e = (n + 4) % 8;
let f = (n + 5) % 8;
let g = (n + 6) % 8;
let h = (n + 7) % 8;

state[h] = state[h]
.wrapping_add(unsafe { sha512sum1(state[e]) })
.wrapping_add(ch(state[e], state[f], state[g]))
.wrapping_add(K64[r])
.wrapping_add(block[r % 16]);
state[d] = state[d].wrapping_add(state[h]);
state[h] = state[h]
.wrapping_add(unsafe { sha512sum0(state[a]) })
.wrapping_add(maj(state[a], state[b], state[c]))
}

#[inline(always)]
fn round_schedule(state: &mut [u64; 8], block: &mut [u64; 16], r: usize) {
round(state, block, r);

block[r % 16] = block[r % 16]
.wrapping_add(unsafe { sha512sig1(block[(r + 14) % 16]) })
.wrapping_add(block[(r + 9) % 16])
.wrapping_add(unsafe { sha512sig0(block[(r + 1) % 16]) });
}

#[inline(always)]
fn compress_block(state: &mut [u64; 8], mut block: [u64; 16]) {
let s = &mut state.clone();
let b = &mut block;

for i in 0..64 {
round_schedule(s, b, i);
}
for i in 64..80 {
round(s, b, i);
}

for i in 0..8 {
state[i] = state[i].wrapping_add(s[i]);
}
}

pub fn compress(state: &mut [u64; 8], blocks: &[[u8; 128]]) {
for block_u8 in blocks {
let mut block = [0u64; 16];
for (dst, src) in block.iter_mut().zip(block_u8.chunks_exact(8)) {
*dst = u64::from_be_bytes(src.try_into().unwrap());
}
compress_block(state, block);
}
}

0 comments on commit 14158e9

Please sign in to comment.