Skip to content

Commit

Permalink
sha2: move opaque_load to the utils module (#618)
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov authored Aug 27, 2024
1 parent b2312fa commit 9a2bb25
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 76 deletions.
29 changes: 1 addition & 28 deletions sha2/src/sha256/riscv_zknh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,6 @@ fn maj(x: u32, y: u32, z: u32) -> u32 {
(x & y) ^ (x & z) ^ (y & z)
}

/// This function returns `k[R]`, but prevents compiler from inlining the indexed value
pub(super) fn opaque_load<const R: usize>(k: &[u32]) -> u32 {
assert!(R < k.len());
let dst;
#[cfg(target_arch = "riscv64")]
unsafe {
core::arch::asm!(
"lwu {dst}, 4*{R}({k})",
R = const R,
k = in(reg) k.as_ptr(),
dst = out(reg) dst,
options(pure, readonly, nostack, preserves_flags),
);
}
#[cfg(target_arch = "riscv32")]
unsafe {
core::arch::asm!(
"lw {dst}, 4*{R}({k})",
R = const R,
k = in(reg) k.as_ptr(),
dst = out(reg) dst,
options(pure, readonly, nostack, preserves_flags),
);
}
dst
}

fn round<const R: usize>(state: &mut [u32; 8], block: &[u32; 16], k: &[u32]) {
let n = K32.len() - R;
#[allow(clippy::identity_op)]
Expand All @@ -63,7 +36,7 @@ fn round<const R: usize>(state: &mut [u32; 8], block: &[u32; 16], k: &[u32]) {
state[h] = state[h]
.wrapping_add(unsafe { sha256sum1(state[e]) })
.wrapping_add(ch(state[e], state[f], state[g]))
.wrapping_add(opaque_load::<R>(k))
.wrapping_add(super::riscv_zknh_utils::opaque_load::<R>(k))
.wrapping_add(block[R]);
state[d] = state[d].wrapping_add(state[h]);
state[h] = state[h]
Expand Down
45 changes: 31 additions & 14 deletions sha2/src/sha256/riscv_zknh_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ fn load_aligned_block(block: &[u8; 64]) -> [u32; 16] {
res
}

/// Use LW instruction on RV32 and LWU on RV64
#[cfg(target_arch = "riscv32")]
macro_rules! lw {
($r:literal) => {
concat!("lw ", $r)
};
}
#[cfg(target_arch = "riscv64")]
macro_rules! lw {
($r:literal) => {
concat!("lwu ", $r)
};
}

#[inline(always)]
fn load_unaligned_block(block: &[u8; 64]) -> [u32; 16] {
let offset = (block.as_ptr() as usize) % align_of::<u32>();
Expand All @@ -32,20 +46,6 @@ fn load_unaligned_block(block: &[u8; 64]) -> [u32; 16] {
let mut left: u32;
let mut res = [0u32; 16];

/// Use LW instruction on RV32 and LWU on RV64
#[cfg(target_arch = "riscv32")]
macro_rules! lw {
($r:literal) => {
concat!("lw ", $r)
};
}
#[cfg(target_arch = "riscv64")]
macro_rules! lw {
($r:literal) => {
concat!("lwu ", $r)
};
}

unsafe {
asm!(
lw!("{left}, 0({bp})"), // left = unsafe { ptr::read(bp) };
Expand Down Expand Up @@ -78,3 +78,20 @@ fn load_unaligned_block(block: &[u8; 64]) -> [u32; 16] {

res
}

/// This function returns `k[R]`, but prevents compiler from inlining the indexed value
#[cfg(sha2_backend = "riscv-zknh")]
pub(super) fn opaque_load<const R: usize>(k: &[u32]) -> u32 {
assert!(R < k.len());
let dst;
unsafe {
core::arch::asm!(
lw!("{dst}, 4*{R}({k})"),
R = const R,
k = in(reg) k.as_ptr(),
dst = out(reg) dst,
options(pure, readonly, nostack, preserves_flags),
);
}
dst
}
35 changes: 1 addition & 34 deletions sha2/src/sha512/riscv_zknh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,39 +49,6 @@ fn maj(x: u64, y: u64, z: u64) -> u64 {
(x & y) ^ (x & z) ^ (y & z)
}

/// This function returns `k[R]`, but prevents compiler from inlining the indexed value
pub(super) fn opaque_load<const R: usize>(k: &[u64]) -> u64 {
use core::arch::asm;
assert!(R < k.len());
#[cfg(target_arch = "riscv64")]
unsafe {
let dst;
asm!(
"ld {dst}, {N}({k})",
N = const 8 * R,
k = in(reg) k.as_ptr(),
dst = out(reg) dst,
options(pure, readonly, nostack, preserves_flags),
);
dst
}
#[cfg(target_arch = "riscv32")]
unsafe {
let [hi, lo]: [u32; 2];
asm!(
"lw {lo}, {N1}({k})",
"lw {hi}, {N2}({k})",
N1 = const 8 * R,
N2 = const 8 * R + 4,
k = in(reg) k.as_ptr(),
lo = out(reg) lo,
hi = out(reg) hi,
options(pure, readonly, nostack, preserves_flags),
);
((hi as u64) << 32) | (lo as u64)
}
}

fn round<const R: usize>(state: &mut [u64; 8], block: &[u64; 16], k: &[u64]) {
let n = K64.len() - R;
#[allow(clippy::identity_op)]
Expand All @@ -97,7 +64,7 @@ fn round<const R: usize>(state: &mut [u64; 8], block: &[u64; 16], k: &[u64]) {
state[h] = state[h]
.wrapping_add(unsafe { sha512sum1(state[e]) })
.wrapping_add(ch(state[e], state[f], state[g]))
.wrapping_add(opaque_load::<R>(k))
.wrapping_add(super::riscv_zknh_utils::opaque_load::<R>(k))
.wrapping_add(block[R]);
state[d] = state[d].wrapping_add(state[h]);
state[h] = state[h]
Expand Down
32 changes: 32 additions & 0 deletions sha2/src/sha512/riscv_zknh_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,35 @@ fn load_unaligned_block(block: &[u8; 128]) -> [u64; 16] {

res
}

/// This function returns `k[R]`, but prevents compiler from inlining the indexed value
#[cfg(sha2_backend = "riscv-zknh")]
pub(super) fn opaque_load<const R: usize>(k: &[u64]) -> u64 {
assert!(R < k.len());
#[cfg(target_arch = "riscv64")]
unsafe {
let dst;
asm!(
"ld {dst}, 8 * {R}({k})",
R = const R,
k = in(reg) k.as_ptr(),
dst = out(reg) dst,
options(pure, readonly, nostack, preserves_flags),
);
dst
}
#[cfg(target_arch = "riscv32")]
unsafe {
let [hi, lo]: [u32; 2];
asm!(
"lw {lo}, 8 * {R}({k})",
"lw {hi}, 8 * {R} + 4({k})",
R = const R,
k = in(reg) k.as_ptr(),
lo = out(reg) lo,
hi = out(reg) hi,
options(pure, readonly, nostack, preserves_flags),
);
((hi as u64) << 32) | (lo as u64)
}
}

0 comments on commit 9a2bb25

Please sign in to comment.