Skip to content

Commit

Permalink
mock signature verification
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc committed Oct 31, 2022
1 parent 202e670 commit 20d9235
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 25 deletions.
1 change: 1 addition & 0 deletions bin/full-node/src/run/consensus_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ impl ConsensusService {
heap_pages,
exec_hint: executor::vm::ExecHint::CompileAheadOfTime, // TODO: probably should be decided by the optimisticsync
allow_unresolved_imports: false,
mock_signature_verification_host_functions: false,
})
.unwrap()
},
Expand Down
1 change: 1 addition & 0 deletions src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ impl ChainSpec {
heap_pages,
exec_hint: executor::vm::ExecHint::Oneshot,
allow_unresolved_imports: true,
mock_signature_verification_host_functions: false,
})
.map_err(FromGenesisStorageError::VmInitialization)?;

Expand Down
98 changes: 73 additions & 25 deletions src/executor/host/host_vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,10 +656,19 @@ impl ReadyToRun {
expect_pointer_constant_size!(2, 32),
);
if let Ok(public_key) = public_key {
let signature =
ed25519_zebra::Signature::from(expect_pointer_constant_size!(0, 64));
let signature = expect_pointer_constant_size!(0, 64);
let message = expect_pointer_size!(1);
public_key.verify(&signature, message.as_ref()).is_ok()

if self.inner.mock_signature_verification_host_functions {
is_magic_signature(signature.as_ref())
} else {
public_key
.verify(
&ed25519_zebra::Signature::from(signature),
message.as_ref(),
)
.is_ok()
}
} else {
false
}
Expand All @@ -684,13 +693,17 @@ impl ReadyToRun {
let signature = expect_pointer_constant_size!(0, 64);
let message = expect_pointer_size!(1);

signing_public_key
.verify_simple_preaudit_deprecated(
b"substrate",
message.as_ref(),
&signature,
)
.is_ok()
if self.inner.mock_signature_verification_host_functions {
is_magic_signature(signature.as_ref())
} else {
signing_public_key
.verify_simple_preaudit_deprecated(
b"substrate",
message.as_ref(),
&signature,
)
.is_ok()
}
};

HostVm::ReadyToRun(ReadyToRun {
Expand All @@ -705,13 +718,21 @@ impl ReadyToRun {
let signing_public_key =
schnorrkel::PublicKey::from_bytes(&expect_pointer_constant_size!(2, 32))
.unwrap();
let signature =
schnorrkel::Signature::from_bytes(&expect_pointer_constant_size!(0, 64))
.unwrap();
let signature = expect_pointer_constant_size!(0, 64);

signing_public_key
.verify_simple(b"substrate", expect_pointer_size!(1).as_ref(), &signature)
.is_ok()
if self.inner.mock_signature_verification_host_functions {
is_magic_signature(signature.as_ref())
} else {
let signature = schnorrkel::Signature::from_bytes(&signature).unwrap();

signing_public_key
.verify_simple(
b"substrate",
expect_pointer_size!(1).as_ref(),
&signature,
)
.is_ok()
}
};

HostVm::ReadyToRun(ReadyToRun {
Expand Down Expand Up @@ -759,20 +780,25 @@ impl ReadyToRun {

// signature (64 bytes) + recovery ID (1 byte)
let sig_bytes = expect_pointer_constant_size!(0, 65);
if let Ok(sig) = libsecp256k1::Signature::parse_standard_slice(&sig_bytes[..64])
{
if let Ok(ri) = libsecp256k1::RecoveryId::parse(sig_bytes[64]) {
if let Ok(actual) = libsecp256k1::recover(&message, &sig, &ri) {
expect_pointer_constant_size!(2, 33)[..]
== actual.serialize_compressed()[..]
if self.inner.mock_signature_verification_host_functions {
is_magic_signature(sig_bytes.as_ref())
} else {
if let Ok(sig) =
libsecp256k1::Signature::parse_standard_slice(&sig_bytes[..64])
{
if let Ok(ri) = libsecp256k1::RecoveryId::parse(sig_bytes[64]) {
if let Ok(actual) = libsecp256k1::recover(&message, &sig, &ri) {
expect_pointer_constant_size!(2, 33)[..]
== actual.serialize_compressed()[..]
} else {
false
}
} else {
false
}
} else {
false
}
} else {
false
}
};

Expand Down Expand Up @@ -2113,6 +2139,8 @@ pub struct Inner {

/// Memory allocator in order to answer the calls to `malloc` and `free`.
pub(crate) allocator: allocator::FreeingBumpHeapAllocator,

pub(crate) mock_signature_verification_host_functions: bool,
}

impl Inner {
Expand Down Expand Up @@ -2278,6 +2306,8 @@ impl Inner {
heap_pages: self.heap_pages,
allow_unresolved_imports: self.allow_unresolved_imports,
memory_total_pages: self.memory_total_pages,
mock_signature_verification_host_functions: self
.mock_signature_verification_host_functions,
}
}
}
Expand Down Expand Up @@ -2551,13 +2581,31 @@ impl<'a> allocator::Memory for MemAccess<'a> {
}
}

fn is_magic_signature(signature: &[u8]) -> bool {
signature.starts_with(&[0xde, 0xad, 0xbe, 0xef]) && signature[4..].iter().all(|&b| b == 0xcd)
}

#[cfg(test)]
mod tests {
use super::HostVm;
use super::{is_magic_signature, HostVm};

#[test]
fn is_send() {
fn req<T: Send>() {}
req::<HostVm>();
}

#[test]
fn is_magic_signature_works() {
assert!(is_magic_signature(&[0xde, 0xad, 0xbe, 0xef, 0xcd, 0xcd]));
assert!(is_magic_signature(&[
0xde, 0xad, 0xbe, 0xef, 0xcd, 0xcd, 0xcd, 0xcd
]));
assert!(!is_magic_signature(&[
0xde, 0xad, 0xbe, 0xef, 0xcd, 0xcd, 0xcd, 0x00
]));
assert!(!is_magic_signature(&[
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]));
}
}
15 changes: 15 additions & 0 deletions src/executor/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ pub struct Config<TModule> {
/// a [`Error::UnresolvedFunctionCalled`] error will be generated if the module tries to call
/// an unresolved function.
pub allow_unresolved_imports: bool,

/// Replace the signature verification related host functions with a mock implementation.
/// The mock implementation will return true IF the signature is true OR the signature is
/// magic value `0xdeadbeef` follow by `0xcd` filling the rest of bytes.
/// NOTE: This should only enabled for testing purposes.
pub mock_signature_verification_host_functions: bool,
}

/// Prototype for an [`HostVm`].
Expand Down Expand Up @@ -269,6 +275,12 @@ pub struct HostVmPrototype {
/// Total number of pages of Wasm memory. This is equal to `heap_base / 64k` (rounded up) plus
/// `heap_pages`.
memory_total_pages: HeapPages,

/// Replace the signature verification related host functions with a mock implementation.
/// The mock implementation will return true IF the signature is true OR the signature is
/// magic value `0xdeadbeef` follow by `0xcd`.
/// NOTE: This should only enabled for testing purposes.
mock_signature_verification_host_functions: bool,
}

impl HostVmPrototype {
Expand Down Expand Up @@ -353,6 +365,7 @@ impl HostVmPrototype {
heap_pages,
allow_unresolved_imports,
memory_total_pages,
mock_signature_verification_host_functions: false,
};

// Call `Core_version` if no runtime version is known yet.
Expand Down Expand Up @@ -484,6 +497,8 @@ impl HostVmPrototype {
registered_functions: self.registered_functions,
storage_transaction_depth: 0,
allocator,
mock_signature_verification_host_functions: self
.mock_signature_verification_host_functions,
},
})
}
Expand Down
1 change: 1 addition & 0 deletions src/executor/read_only_runtime_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ impl Inner {
heap_pages: executor::DEFAULT_HEAP_PAGES,
exec_hint: vm::ExecHint::Oneshot,
allow_unresolved_imports: false, // TODO: what is a correct value here?
mock_signature_verification_host_functions: false,
}) {
Ok(w) => w,
Err(_) => {
Expand Down
1 change: 1 addition & 0 deletions src/executor/runtime_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ impl Inner {
heap_pages: executor::DEFAULT_HEAP_PAGES,
exec_hint: vm::ExecHint::Oneshot,
allow_unresolved_imports: false, // TODO: what is a correct value here?
mock_signature_verification_host_functions: false,
}) {
Ok(w) => w,
Err(_) => {
Expand Down
1 change: 1 addition & 0 deletions src/sync/warp_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,7 @@ impl<TSrc, TRq> BuildRuntime<TSrc, TRq> {
heap_pages: decoded_heap_pages,
exec_hint,
allow_unresolved_imports,
mock_signature_verification_host_functions: false,
}) {
Ok(runtime) => runtime,
Err(err) => {
Expand Down
1 change: 1 addition & 0 deletions src/verify/header_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ impl RuntimeCompilation {
heap_pages: self.heap_pages,
exec_hint: vm::ExecHint::CompileAheadOfTime,
allow_unresolved_imports: false,
mock_signature_verification_host_functions: false,
}) {
Ok(vm) => vm,
Err(err) => {
Expand Down

0 comments on commit 20d9235

Please sign in to comment.