#![no_std]
#[cfg(target_os = "zkvm")]
use openvm_platform::alloc::AlignedBuf;
pub const OPCODE: u8 = 0x0b;
pub const SHA2_FUNCT3: u8 = 0b100;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum Sha2BaseFunct7 {
Sha256 = 0x2,
Sha512 = 0x3,
}
#[cfg(target_os = "zkvm")]
#[inline(always)]
#[no_mangle]
pub unsafe extern "C" fn zkvm_sha256_impl(state: *const u8, input: *const u8, output: *mut u8) {
const MIN_ALIGN: usize = 4;
unsafe {
let state_is_aligned = state as usize % MIN_ALIGN == 0;
let input_is_aligned = input as usize % MIN_ALIGN == 0;
let output_is_aligned = output as usize % MIN_ALIGN == 0;
let aligned_state;
let state_ptr = if state_is_aligned {
state
} else {
aligned_state = AlignedBuf::new(state, 32, MIN_ALIGN);
aligned_state.ptr as *const u8
};
let aligned_input;
let input_ptr = if input_is_aligned {
input
} else {
aligned_input = AlignedBuf::new(input, 64, MIN_ALIGN);
aligned_input.ptr as *const u8
};
let aligned_output;
let output_ptr = if output_is_aligned {
output
} else {
aligned_output = AlignedBuf::uninit(32, MIN_ALIGN);
aligned_output.ptr
};
__native_sha256_compress(state_ptr, input_ptr, output_ptr);
if !output_is_aligned {
core::ptr::copy_nonoverlapping(output_ptr, output, 32);
}
}
}
#[cfg(target_os = "zkvm")]
#[inline(always)]
#[no_mangle]
pub unsafe extern "C" fn zkvm_sha512_impl(state: *const u8, input: *const u8, output: *mut u8) {
const MIN_ALIGN: usize = 4;
unsafe {
let state_is_aligned = state as usize % MIN_ALIGN == 0;
let input_is_aligned = input as usize % MIN_ALIGN == 0;
let output_is_aligned = output as usize % MIN_ALIGN == 0;
let aligned_state;
let state_ptr = if state_is_aligned {
state
} else {
aligned_state = AlignedBuf::new(state, 64, MIN_ALIGN);
aligned_state.ptr as *const u8
};
let aligned_input;
let input_ptr = if input_is_aligned {
input
} else {
aligned_input = AlignedBuf::new(input, 128, MIN_ALIGN);
aligned_input.ptr as *const u8
};
let aligned_output;
let output_ptr = if output_is_aligned {
output
} else {
aligned_output = AlignedBuf::uninit(64, MIN_ALIGN);
aligned_output.ptr
};
__native_sha512_compress(state_ptr, input_ptr, output_ptr);
if !output_is_aligned {
core::ptr::copy_nonoverlapping(output_ptr, output, 64);
}
}
}
#[cfg(target_os = "zkvm")]
#[inline(always)]
fn __native_sha256_compress(prev_state: *const u8, input: *const u8, output: *mut u8) {
openvm_platform::custom_insn_r!(opcode = OPCODE, funct3 = SHA2_FUNCT3, funct7 = Sha2BaseFunct7::Sha256 as u8, rd = In output, rs1 = In prev_state, rs2 = In input);
}
#[cfg(target_os = "zkvm")]
#[inline(always)]
fn __native_sha512_compress(prev_state: *const u8, input: *const u8, output: *mut u8) {
openvm_platform::custom_insn_r!(opcode = OPCODE, funct3 = SHA2_FUNCT3, funct7 = Sha2BaseFunct7::Sha512 as u8, rd = In output, rs1 = In prev_state, rs2 = In input);
}