diff --git a/Cargo.toml b/Cargo.toml index 2c8a65f4..f7d7080d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ path = "src/lib.rs" [features] bitcoinconsenus = ["bitcoinconsensus"] +fuzztarget = ["secp256k1/fuzztarget"] [dependencies] bitcoin-bech32 = "0.5.1" diff --git a/src/blockdata/script.rs b/src/blockdata/script.rs index 585521de..88be676d 100644 --- a/src/blockdata/script.rs +++ b/src/blockdata/script.rs @@ -28,7 +28,6 @@ use std::default::Default; use std::{error, fmt}; use crypto::digest::Digest; -use crypto::sha2::Sha256; use serde; use blockdata::opcodes; @@ -39,6 +38,9 @@ use util::hash::Hash160; #[cfg(feature="bitcoinconsensus")] use std::convert; #[cfg(feature="bitcoinconsensus")] use util::hash::Sha256dHash; +#[cfg(feature="fuzztarget")] use util::sha2::Sha256; +#[cfg(not(feature="fuzztarget"))] use crypto::sha2::Sha256; + #[derive(Clone, PartialEq, Eq, Hash)] /// A Bitcoin script pub struct Script(Box<[u8]>); diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 7834c7e2..ff785dcb 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -28,14 +28,15 @@ use crypto::digest::Digest; use crypto::hmac::Hmac; use crypto::mac::Mac; use crypto::ripemd160::Ripemd160; -use crypto::sha2::Sha256; -use crypto::sha2::Sha512; use secp256k1::key::{PublicKey, SecretKey}; use secp256k1::{self, Secp256k1}; use network::constants::Network; use util::base58; +#[cfg(feature="fuzztarget")] use util::sha2::{Sha256, Sha512}; +#[cfg(not(feature="fuzztarget"))] use crypto::sha2::{Sha256, Sha512}; + /// A chain code pub struct ChainCode([u8; 32]); impl_array_newtype!(ChainCode, u8, 32); diff --git a/src/util/contracthash.rs b/src/util/contracthash.rs index 666aa546..1a13fff0 100644 --- a/src/util/contracthash.rs +++ b/src/util/contracthash.rs @@ -20,7 +20,7 @@ use secp256k1::{self, Secp256k1}; use secp256k1::key::{PublicKey, SecretKey}; use blockdata::{opcodes, script}; -use crypto::{hmac, sha2}; +use crypto::hmac; use crypto::mac::Mac; use std::{error, fmt}; @@ -28,6 +28,9 @@ use std::{error, fmt}; use network::constants::Network; use util::{address, hash}; +#[cfg(feature="fuzztarget")] use util::sha2; +#[cfg(not(feature="fuzztarget"))] use crypto::sha2; + /// Encoding of "pubkey here" in script; from bitcoin core `src/script/script.h` static PUBKEY: u8 = 0xFE; diff --git a/src/util/hash.rs b/src/util/hash.rs index ccde8a22..9f1d6743 100644 --- a/src/util/hash.rs +++ b/src/util/hash.rs @@ -26,13 +26,15 @@ use serde; use byteorder::{LittleEndian, WriteBytesExt}; use crypto::digest::Digest; -use crypto::sha2::Sha256; use crypto::ripemd160::Ripemd160; use network::encodable::{ConsensusDecodable, ConsensusEncodable}; use network::serialize::{SimpleEncoder, RawEncoder, BitcoinHash}; use util::uint::Uint256; +#[cfg(feature="fuzztarget")] use util::sha2::Sha256; +#[cfg(not(feature="fuzztarget"))] use crypto::sha2::Sha256; + /// Hex deserialization error #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum HexError { diff --git a/src/util/mod.rs b/src/util/mod.rs index 77e91cce..58f7c79f 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -28,6 +28,9 @@ pub mod iter; pub mod misc; pub mod uint; +#[cfg(feature = "fuzztarget")] +pub mod sha2; + use std::{error, fmt, io}; use bitcoin_bech32; diff --git a/src/util/sha2.rs b/src/util/sha2.rs new file mode 100644 index 00000000..7c819ffb --- /dev/null +++ b/src/util/sha2.rs @@ -0,0 +1,64 @@ +//! fuzztarget-only Sha2 context with a dummy Sha256 and Sha512 hashers. + +use crypto::digest::Digest; +use crypto::sha2; + +#[derive(Clone, Copy)] +/// Dummy Sha256 that hashes the input, but only returns the first byte of output, masking the +/// rest to 0s. +pub struct Sha256 { + state: sha2::Sha256, +} + +impl Sha256 { + /// Constructs a new dummy Sha256 context + pub fn new() -> Sha256 { + Sha256 { + state: sha2::Sha256::new(), + } + } +} + +impl Digest for Sha256 { + fn result(&mut self, data: &mut [u8]) { + self.state.result(data); + for i in 1..32 { + data[i] = 0; + } + } + + fn input(&mut self, data: &[u8]) { self.state.input(data); } + fn reset(&mut self) { self.state.reset(); } + fn output_bits(&self) -> usize { self.state.output_bits() } + fn block_size(&self) -> usize { self.state.block_size() } +} + +#[derive(Clone, Copy)] +/// Dummy Sha512 that hashes the input, but only returns the first byte of output, masking the +/// rest to 0s. +pub struct Sha512 { + state: sha2::Sha512, +} + +impl Sha512 { + /// Constructs a new dummy Sha512 context + pub fn new() -> Sha512 { + Sha512 { + state: sha2::Sha512::new(), + } + } +} + +impl Digest for Sha512 { + fn result(&mut self, data: &mut [u8]) { + self.state.result(data); + for i in 1..64 { + data[i] = 0; + } + } + + fn input(&mut self, data: &[u8]) { self.state.input(data); } + fn reset(&mut self) { self.state.reset(); } + fn output_bits(&self) -> usize { self.state.output_bits() } + fn block_size(&self) -> usize { self.state.block_size() } +}