Skip to content

Commit

Permalink
Keccak endianness (BE -> LE) (#2318)
Browse files Browse the repository at this point in the history
Changes the endianness of the Keccak machine (only Keccakf32Memory for
now) from BE to LE. As a result, the sponge construction can now avoid
the step that required inverting the u32 of each u64 word and, directly
use full u64 directly.
  • Loading branch information
gzanitti authored Jan 10, 2025
1 parent 3d5bce0 commit d5f39d7
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 144 deletions.
11 changes: 5 additions & 6 deletions riscv-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2585,13 +2585,12 @@ impl<F: FieldElement> Executor<'_, '_, F> {
set_col!(tmp2_col, output_ptr);

let mut state = [0u64; 25];
// Note: lo/hi positions are swapped (lo at +4 offset, hi at +0) to match
// the Keccak machine specification's memory layout

for (i, state_i) in state.iter_mut().enumerate() {
let lo = self
let hi = self
.proc
.get_mem(input_ptr.u() + 8 * i as u32 + 4, self.step, lid);
let hi = self
let lo = self
.proc
.get_mem(input_ptr.u() + 8 * i as u32, self.step, lid);
*state_i = ((hi as u64) << 32) | lo as u64;
Expand All @@ -2604,9 +2603,9 @@ impl<F: FieldElement> Executor<'_, '_, F> {
let hi = (val >> 32) as u32;

self.proc
.set_mem(output_ptr.u() + i as u32 * 8 + 4, lo, self.step + 1, lid);
.set_mem(output_ptr.u() + i as u32 * 8, lo, self.step + 1, lid);
self.proc
.set_mem(output_ptr.u() + i as u32 * 8, hi, self.step + 1, lid);
.set_mem(output_ptr.u() + i as u32 * 8 + 4, hi, self.step + 1, lid);
}

//let lid = self.instr_link_id(instr, "main_keccakf", 0);
Expand Down
34 changes: 14 additions & 20 deletions riscv-runtime/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,43 +40,38 @@ pub fn poseidon2_gl(data: &[Goldilocks; 8]) -> [Goldilocks; 8] {

/// Calls the keccakf machine.
/// Return value is placed in the output array.
pub fn keccakf(input: &[u32; 50], output: &mut [u32; 50]) {
pub fn keccakf(input: &[u64; 25], output: &mut [u64; 25]) {
unsafe {
// Syscall inputs: memory pointer to input array and memory pointer to output array.
ecall!(Syscall::KeccakF, in("a0") input, in("a1") output);
}
}

pub struct Keccak {
state: [u32; 50],
state: [u64; 25],
next_word: usize,
input_buffer: u32,
input_buffer: u64,
next_byte: usize,
}

impl Keccak {
const RATE: usize = 34; // Rate in u32 words
const RATE: usize = 17; // Rate in u64 words

pub fn v256() -> Self {
Self {
state: [0u32; 50],
state: [0u64; 25],
next_word: 0,
input_buffer: 0,
next_byte: 0,
}
}

fn xor_word_to_state(&mut self, word: u32) {
let word_pair = self.next_word & !1;
if (self.next_word & 1) == 0 {
self.state[word_pair + 1] ^= word;
} else {
self.state[word_pair] ^= word;
}
fn xor_word_to_state(&mut self, word: u64) {
self.state[self.next_word] ^= word;
self.next_word += 1;

if self.next_word == Self::RATE {
let mut state_out = [0u32; 50];
let mut state_out = [0u64; 25];
keccakf(&self.state, &mut state_out);
self.state = state_out;
self.next_word = 0;
Expand All @@ -85,15 +80,15 @@ impl Keccak {

pub fn update(&mut self, data: &[u8]) {
unsafe {
let (prefix, words, suffix) = data.align_to::<u32>();
let (prefix, words, suffix) = data.align_to::<u64>();

self.update_unaligned(prefix);
for &word in words {
if self.next_byte == 0 {
self.xor_word_to_state(word);
} else {
self.xor_word_to_state(self.input_buffer | (word << (8 * self.next_byte)));
self.input_buffer = word >> (32 - 8 * self.next_byte);
self.input_buffer = word >> (64 - 8 * self.next_byte);
}
}
self.update_unaligned(suffix);
Expand All @@ -102,9 +97,9 @@ impl Keccak {

fn update_unaligned(&mut self, bytes: &[u8]) {
for &byte in bytes {
self.input_buffer |= (byte as u32) << (8 * self.next_byte);
self.input_buffer |= (byte as u64) << (8 * self.next_byte);
self.next_byte += 1;
if self.next_byte == 4 {
if self.next_byte == 8 {
self.xor_word_to_state(self.input_buffer);
self.input_buffer = 0;
self.next_byte = 0;
Expand All @@ -123,11 +118,10 @@ impl Keccak {
while self.next_word < Self::RATE - 1 {
self.xor_word_to_state(0);
}
self.xor_word_to_state(0x80000000);
self.xor_word_to_state(0x8000000000000000);

for i in 0..4 {
output[i * 8..(i * 8 + 4)].copy_from_slice(&self.state[i * 2 + 1].to_le_bytes());
output[(i * 8 + 4)..(i * 8 + 8)].copy_from_slice(&self.state[i * 2].to_le_bytes());
output[i * 8..(i + 1) * 8].copy_from_slice(&self.state[i].to_ne_bytes());
}
}
}
Loading

0 comments on commit d5f39d7

Please sign in to comment.