Skip to content

Commit

Permalink
Add "insecure sha compress 256" and "cycle count" GPIOs
Browse files Browse the repository at this point in the history
* Add "insecure sha compress 256", "insecure sha hash digest" and "cycle count" GPIOs (rust feature="pure-prove" only for the insecure sha)
  • Loading branch information
shkoo authored Aug 30, 2022
1 parent 7f09758 commit c7f2f0f
Show file tree
Hide file tree
Showing 20 changed files with 609 additions and 112 deletions.
45 changes: 22 additions & 23 deletions Cargo-host.lock
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ dependencies = [

[[package]]
name = "clap"
version = "3.2.17"
version = "3.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b"
checksum = "b15f2ea93df33549dbe2e8eecd1ca55269d63ae0b3ba1f55db030817d1c2867f"
dependencies = [
"atty",
"bitflags",
Expand All @@ -275,9 +275,9 @@ dependencies = [

[[package]]
name = "clap_derive"
version = "3.2.17"
version = "3.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13547f7012c01ab4a0e8f8967730ada8f9fdf419e8b6c792788f39cf4e46eefa"
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
dependencies = [
"heck",
"proc-macro-error",
Expand Down Expand Up @@ -625,42 +625,42 @@ dependencies = [

[[package]]
name = "futures-channel"
version = "0.3.23"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bfc52cbddcfd745bf1740338492bb0bd83d76c67b445f91c5fb29fae29ecaa1"
checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
dependencies = [
"futures-core",
]

[[package]]
name = "futures-core"
version = "0.3.23"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115"
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"

[[package]]
name = "futures-io"
version = "0.3.23"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5"
checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"

[[package]]
name = "futures-sink"
version = "0.3.23"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765"
checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"

[[package]]
name = "futures-task"
version = "0.3.23"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "842fc63b931f4056a24d59de13fb1272134ce261816e063e634ad0c15cdc5306"
checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"

[[package]]
name = "futures-util"
version = "0.3.23"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577"
checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
dependencies = [
"futures-core",
"futures-io",
Expand Down Expand Up @@ -1558,7 +1558,7 @@ dependencies = [
name = "risc0-make-id"
version = "0.11.1"
dependencies = [
"clap 3.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 3.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"risc0-zkvm",
]

Expand All @@ -1570,7 +1570,7 @@ dependencies = [
"assert_cmd",
"assert_fs",
"bytemuck",
"clap 3.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 3.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger",
"risc0-zkvm",
"risc0-zkvm-methods",
Expand Down Expand Up @@ -1671,7 +1671,6 @@ dependencies = [
name = "risc0-zkvm-platform"
version = "0.11.1"
dependencies = [
"bytemuck",
"compiler_builtins",
"rustc-std-workspace-core",
]
Expand Down Expand Up @@ -1889,9 +1888,9 @@ dependencies = [

[[package]]
name = "socket2"
version = "0.4.4"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
checksum = "10c98bba371b9b22a71a9414e420f92ddeb2369239af08200816169d5e2dd7aa"
dependencies = [
"libc",
"winapi",
Expand Down Expand Up @@ -2002,9 +2001,9 @@ dependencies = [

[[package]]
name = "time"
version = "0.3.13"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45"
checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b"
dependencies = [
"itoa 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc",
Expand Down
26 changes: 24 additions & 2 deletions risc0/zkp/rust/src/core/sha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ pub const DIGEST_WORDS: usize = 8;
/// The size of a word within a [Digest] (32-bits = 4 bytes).
pub const DIGEST_WORD_SIZE: usize = mem::size_of::<u32>();

/// Standard SHA initialization vector .
pub static SHA256_INIT: Digest = Digest::new([
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
]);

/// The result of a SHA-256 hashing function.
// TODO(nils): Remove 'Copy' trait on Digest; these are not small and
// we don't want to copy them around accidentally.
Expand All @@ -44,7 +49,7 @@ pub struct Digest([u32; DIGEST_WORDS]);

impl Digest {
/// Create a new [Digest] from an existing array of words.
pub fn new(data: [u32; DIGEST_WORDS]) -> Digest {
pub const fn new(data: [u32; DIGEST_WORDS]) -> Digest {
Digest(data)
}

Expand Down Expand Up @@ -162,8 +167,25 @@ pub trait Sha: Clone + Debug {
/// length.
fn hash_raw_words(&self, words: &[u32]) -> Self::DigestPtr;

/// Update a SHA digest with zero or more new blocks, zero padded
/// up to the next block boundry. Not all implementations provide
/// this.
fn update(&self, state: &Digest, bytes: &[u8]) -> Self::DigestPtr;

/// Generate a SHA from a pair of [Digests](Digest).
fn hash_pair(&self, a: &Digest, b: &Digest) -> Self::DigestPtr;
fn hash_pair(&self, a: &Digest, b: &Digest) -> Self::DigestPtr {
self.compress(&SHA256_INIT, a, b)
}

/// Execute the sha256 "compress" operation. The block is
/// specified as two half-blocks. Not all implementations provide
/// this.
fn compress(
&self,
state: &Digest,
block_half1: &Digest,
block_half2: &Digest,
) -> Self::DigestPtr;

/// Generate a SHA from a slice of anything that can be
/// represented as plain old data. Pads up to the Sha block
Expand Down
53 changes: 41 additions & 12 deletions risc0/zkp/rust/src/core/sha_cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ use sha2::{
Digest as ShaDigest, Sha256,
};

use super::sha::{Digest, Sha, DIGEST_WORDS};

static INIT_256: [u32; DIGEST_WORDS] = [
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
];
use super::sha::{Digest, Sha, DIGEST_WORDS, SHA256_INIT};

/// A CPU-based [Sha] implementation.
#[derive(Clone)]
Expand All @@ -48,7 +44,7 @@ impl Impl {
size: usize,
stride: usize,
) -> Box<Digest> {
let mut state = INIT_256;
let mut state = *SHA256_INIT.get();
let mut block: GenericArray<u8, U64> = GenericArray::default();

let mut u8s = pods
Expand Down Expand Up @@ -112,7 +108,7 @@ impl Sha for Impl {
"{} should be a multiple of 16, the number of words per SHA block",
words.len()
);
let mut state = INIT_256;
let mut state = *SHA256_INIT.get();
for block in words.chunks(16) {
let block_u8: &[u8] = bytemuck::cast_slice(block);
compress256(
Expand All @@ -125,7 +121,7 @@ impl Sha for Impl {

fn hash_raw_pod_slice<T: bytemuck::Pod>(&self, pod: &[T]) -> Self::DigestPtr {
let u8s: &[u8] = bytemuck::cast_slice(pod);
let mut state = INIT_256;
let mut state = *SHA256_INIT.get();
let mut blocks = u8s.chunks_exact(64);
for block in blocks.by_ref() {
compress256(&mut state, slice::from_ref(GenericArray::from_slice(block)));
Expand All @@ -141,17 +137,50 @@ impl Sha for Impl {
}

// Digest two digest into one
fn hash_pair(&self, a: &Digest, b: &Digest) -> Self::DigestPtr {
let mut state = INIT_256;
fn compress(
&self,
orig_state: &Digest,
block_half1: &Digest,
block_half2: &Digest,
) -> Self::DigestPtr {
let mut state: [u32; DIGEST_WORDS] = *orig_state.get();
let mut block: GenericArray<u8, U64> = GenericArray::default();
for i in 0..8 {
set_word(block.as_mut_slice(), i, a.as_slice()[i]);
set_word(block.as_mut_slice(), 8 + i, b.as_slice()[i]);
set_word(block.as_mut_slice(), i, block_half1.as_slice()[i]);
set_word(block.as_mut_slice(), 8 + i, block_half2.as_slice()[i]);
}
compress256(&mut state, slice::from_ref(&block));
Box::new(Digest::new(state))
}

fn update(&self, orig_state: &Digest, bytes: &[u8]) -> Self::DigestPtr {
let mut state = *orig_state.get();
let mut block: GenericArray<u8, U64> = GenericArray::default();

let mut u8s = bytes.iter().fuse().cloned();
let mut off = 0;
while let Some(b1) = u8s.next() {
let b2 = u8s.next().unwrap_or(0);
let b3 = u8s.next().unwrap_or(0);
let b4 = u8s.next().unwrap_or(0);
set_word(
block.as_mut_slice(),
off,
u32::from_le_bytes([b1, b2, b3, b4]),
);
off += 1;
if off == 16 {
compress256(&mut state, slice::from_ref(&block));
off = 0;
}
}
if off != 0 {
block[off * 4..].fill(0);
compress256(&mut state, slice::from_ref(&block));
}
Box::new(Digest::new(state))
}

// Generate a new digest by mixing two digests together via XOR,
// and stores it back in the pool.
fn mix(&self, pool: &mut Self::DigestPtr, val: &Digest) {
Expand Down
43 changes: 43 additions & 0 deletions risc0/zkvm/platform/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ constexpr size_t kGPIO_SendRecvChannel = 0x01F00014;
constexpr size_t kGPIO_SendRecvSize = 0x01F00018;
constexpr size_t kGPIO_SendRecvAddr = 0x01F0001C;

constexpr size_t kGPIO_CycleCount = 0x01F00020;
constexpr size_t kGPIO_InsecureShaCompress = 0x01F00024;
constexpr size_t kGPIO_InsecureShaHash = 0x01F00028;

// Standard ZKVM channels; must match zkvm/sdk/rust/platform/src/io.rs.

// Request the initial input to the guest.
Expand Down Expand Up @@ -121,6 +125,45 @@ inline const char* volatile* GPIO_Log() {
return reinterpret_cast<const char* volatile*>(kGPIO_Log);
}

// To have the host execute a sha256 "compress" operation, write the
// address of an InsecureShaCompressDescriptor to
// kGPIO_InsecureShaCompress. The output state (64 bytes) is written
// to the guest's INPUT area. WARNING: The host calculates this
// independently and does not include the calculation in the proof, so
// this should not be used when security is a concern.
struct InsecureShaCompressDescriptor {
uint32_t state; // Pointer to input state, 64 bytes
uint32_t block_half1; // Pointer to first half of block
uint32_t block_half2; // Pointer to second half of block
};

inline const InsecureShaCompressDescriptor* volatile* GPIO_InsecureShaCompress() {
return reinterpret_cast<const InsecureShaCompressDescriptor* volatile*>(
kGPIO_InsecureShaCompress);
}

// To have the host zero-pad and hash zero or more blocks,write the
// address of a InsecureShaHashDescriptor to kGPIO_InsecureShaHash.
// The output state (64 bytes) is written to the guest's INPUT area.
// WARNING: The host calculates this independently and does not
// include the calculation in the proof, so this should not be used
// when security is a concern.
struct InsecureShaHashDescriptor {
uint32_t state; // Pointer to input state, 64 bytes
uint32_t start; // Pointer to beginning of data region
uint32_t len; // Number of bytes in the region to be hashed
};

inline const InsecureShaHashDescriptor* volatile* GPIO_InsecureShaHash() {
return reinterpret_cast<const InsecureShaHashDescriptor* volatile*>(kGPIO_InsecureShaHash);
}

// To get the current cycle count of the ZKVM, write a 0 to
// GPIO_CycleCount and read one word from the guest's INPUT area.
inline const uint32_t volatile* GPIO_CycleCount() {
return reinterpret_cast<const uint32_t volatile*>(kGPIO_CycleCount);
}

// TODO(nils) Document GetKey.
struct GetKeyDescriptor {
uint32_t name;
Expand Down
Loading

0 comments on commit c7f2f0f

Please sign in to comment.