From: Matt Corallo Date: Tue, 18 Dec 2018 04:58:02 +0000 (-0500) Subject: Switch Sha256 to using bitcoin_hashes and our own HKDF X-Git-Tag: v0.0.12~253^2~6 X-Git-Url: http://git.bitcoin.ninja/index.cgi?p=rust-lightning;a=commitdiff_plain;h=f1e400f142c3411b229b108587401c45a5f51cc8 Switch Sha256 to using bitcoin_hashes and our own HKDF --- diff --git a/Cargo.toml b/Cargo.toml index b3c5f3ac..a14984a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ build = "build.rs" [features] # Supports tracking channels with a non-bitcoin chain hashes. Currently enables all kinds of fun DoS attacks. non_bitcoin_chain_hash_routing = [] -fuzztarget = ["secp256k1/fuzztarget", "bitcoin/fuzztarget"] +fuzztarget = ["secp256k1/fuzztarget", "bitcoin/fuzztarget", "bitcoin_hashes/fuzztarget"] # Unlog messages superior at targeted level. max_level_off = [] max_level_error = [] @@ -24,6 +24,7 @@ max_level_debug = [] [dependencies] bitcoin = "0.15" +bitcoin_hashes = { git = "https://github.com/TheBlueMatt/bitcoin_hashes", branch = "rust-lightning-dep" } rust-crypto = "0.2" rand = "0.4" secp256k1 = "0.11" diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index c8ed4b61..c1069d32 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -19,9 +19,9 @@ honggfuzz_fuzz = ["honggfuzz"] afl = { version = "0.4", optional = true } lightning = { path = "..", features = ["fuzztarget"] } bitcoin = { version = "0.15", features = ["fuzztarget"] } +bitcoin_hashes = { git = "https://github.com/TheBlueMatt/bitcoin_hashes", branch = "rust-lightning-dep", features=["fuzztarget"] } hex = "0.3" honggfuzz = { version = "0.5", optional = true } -rust-crypto = "0.2" secp256k1 = { version = "0.11", features=["fuzztarget"] } [build-dependencies] diff --git a/fuzz/fuzz_targets/full_stack_target.rs b/fuzz/fuzz_targets/full_stack_target.rs index 3e105038..0b43ff44 100644 --- a/fuzz/fuzz_targets/full_stack_target.rs +++ b/fuzz/fuzz_targets/full_stack_target.rs @@ -1,5 +1,5 @@ extern crate bitcoin; -extern crate crypto; +extern crate bitcoin_hashes; extern crate lightning; extern crate secp256k1; @@ -11,7 +11,9 @@ use bitcoin::consensus::encode::deserialize; use bitcoin::network::constants::Network; use bitcoin::util::hash::{BitcoinHash, Sha256dHash, Hash160}; -use crypto::digest::Digest; +use bitcoin_hashes::Hash as TraitImport; +use bitcoin_hashes::HashEngine as TraitImportEngine; +use bitcoin_hashes::sha256::Hash as Sha256; use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil}; use lightning::chain::transaction::OutPoint; @@ -23,7 +25,6 @@ use lightning::ln::router::Router; use lightning::util::events::{EventsProvider,Event}; use lightning::util::{reset_rng_state, fill_bytes}; use lightning::util::logger::Logger; -use lightning::util::sha2::Sha256; use lightning::util::config::UserConfig; mod utils; @@ -382,9 +383,9 @@ pub fn do_test(data: &[u8], logger: &Arc) { }; let mut payment_hash = PaymentHash([0; 32]); payment_hash.0[0..8].copy_from_slice(&be64_to_array(payments_sent)); - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&payment_hash.0[..]); - sha.result(&mut payment_hash.0[..]); + payment_hash.0 = Sha256::from_engine(sha).into_inner(); payments_sent += 1; match channelmanager.send_payment(route, payment_hash) { Ok(_) => {}, diff --git a/src/chain/keysinterface.rs b/src/chain/keysinterface.rs index 18e22edc..390b0cc5 100644 --- a/src/chain/keysinterface.rs +++ b/src/chain/keysinterface.rs @@ -9,13 +9,13 @@ use bitcoin::network::constants::Network; use bitcoin::util::hash::Hash160; use bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber}; +use bitcoin_hashes::{Hash, HashEngine}; +use bitcoin_hashes::sha256::Hash as Sha256; + use secp256k1::key::{SecretKey, PublicKey}; use secp256k1::Secp256k1; use secp256k1; -use crypto::digest::Digest; - -use util::sha2::Sha256; use util::logger::Logger; use util::rng; use util::byte_utils; @@ -187,7 +187,7 @@ impl KeysInterface for KeysManager { // entropy, everything else just ensures uniqueness. We generally don't expect // all clients to have non-broken RNGs here, so we also include the current // time as a fallback to get uniqueness. - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); let mut seed = [0u8; 32]; rng::fill_bytes(&mut seed[..]); @@ -201,25 +201,21 @@ impl KeysInterface for KeysManager { let child_privkey = self.channel_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32)).expect("Your RNG is busted"); sha.input(&child_privkey.secret_key[..]); - sha.result(&mut seed); + seed = Sha256::from_engine(sha).into_inner(); let commitment_seed = { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&seed); sha.input(&b"commitment seed"[..]); - let mut res = [0; 32]; - sha.result(&mut res); - res + Sha256::from_engine(sha).into_inner() }; macro_rules! key_step { ($info: expr, $prev_key: expr) => {{ - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&seed); sha.input(&$prev_key[..]); sha.input(&$info[..]); - let mut res = [0; 32]; - sha.result(&mut res); - SecretKey::from_slice(&self.secp_ctx, &res).expect("SHA-256 is busted") + SecretKey::from_slice(&self.secp_ctx, &Sha256::from_engine(sha).into_inner()).expect("SHA-256 is busted") }} } let funding_key = key_step!(b"funding key", commitment_seed); @@ -239,8 +235,7 @@ impl KeysInterface for KeysManager { } fn get_session_key(&self) -> SecretKey { - let mut sha = Sha256::new(); - let mut res = [0u8; 32]; + let mut sha = Sha256::engine(); let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time went backwards"); sha.input(&byte_utils::be32_to_array(now.subsec_nanos())); @@ -249,7 +244,6 @@ impl KeysInterface for KeysManager { let child_ix = self.session_child_index.fetch_add(1, Ordering::AcqRel); let child_privkey = self.session_master_key.ckd_priv(&self.secp_ctx, ChildNumber::from_hardened_idx(child_ix as u32)).expect("Your RNG is busted"); sha.input(&child_privkey.secret_key[..]); - sha.result(&mut res); - SecretKey::from_slice(&self.secp_ctx, &res).expect("Your RNG is busted") + SecretKey::from_slice(&self.secp_ctx, &Sha256::from_engine(sha).into_inner()).expect("Your RNG is busted") } } diff --git a/src/lib.rs b/src/lib.rs index bd71b15f..5564a575 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ #![cfg_attr(not(feature = "fuzztarget"), deny(missing_docs))] extern crate bitcoin; +extern crate bitcoin_hashes; extern crate crypto; extern crate rand; extern crate secp256k1; diff --git a/src/ln/chan_utils.rs b/src/ln/chan_utils.rs index dbd6bdcc..98fc6d7f 100644 --- a/src/ln/chan_utils.rs +++ b/src/ln/chan_utils.rs @@ -3,6 +3,9 @@ use bitcoin::blockdata::opcodes; use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction}; use bitcoin::util::hash::{Hash160,Sha256dHash}; +use bitcoin_hashes::{Hash, HashEngine}; +use bitcoin_hashes::sha256::Hash as Sha256; + use ln::channelmanager::PaymentHash; use secp256k1::key::{PublicKey,SecretKey}; @@ -12,8 +15,6 @@ use secp256k1; use crypto::digest::Digest; use crypto::ripemd160::Ripemd160; -use util::sha2::Sha256; - pub const HTLC_SUCCESS_TX_WEIGHT: u64 = 703; pub const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663; @@ -26,20 +27,17 @@ pub fn build_commitment_secret(commitment_seed: [u8; 32], idx: u64) -> [u8; 32] let bitpos = 47 - i; if idx & (1 << bitpos) == (1 << bitpos) { res[bitpos / 8] ^= 1 << (bitpos & 7); - let mut sha = Sha256::new(); - sha.input(&res); - sha.result(&mut res); + res = Sha256::hash(&res).into_inner(); } } res } pub fn derive_private_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&per_commitment_point.serialize()); sha.input(&PublicKey::from_secret_key(&secp_ctx, &base_secret).serialize()); - let mut res = [0; 32]; - sha.result(&mut res); + let res = Sha256::from_engine(sha).into_inner(); let mut key = base_secret.clone(); key.add_assign(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &res)?)?; @@ -47,11 +45,10 @@ pub fn derive_private_key(secp_ctx: &Secp256k1, per_co } pub fn derive_public_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&per_commitment_point.serialize()); sha.input(&base_point.serialize()); - let mut res = [0; 32]; - sha.result(&mut res); + let res = Sha256::from_engine(sha).into_inner(); let hashkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&secp_ctx, &res)?); base_point.combine(&secp_ctx, &hashkey) @@ -63,22 +60,18 @@ pub fn derive_private_revocation_key(secp_ctx: &Secp256k1 let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret); let rev_append_commit_hash_key = { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&revocation_base_point.serialize()); sha.input(&per_commitment_point.serialize()); - let mut res = [0; 32]; - sha.result(&mut res); - SecretKey::from_slice(&secp_ctx, &res)? + SecretKey::from_slice(&secp_ctx, &Sha256::from_engine(sha).into_inner())? }; let commit_append_rev_hash_key = { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&per_commitment_point.serialize()); sha.input(&revocation_base_point.serialize()); - let mut res = [0; 32]; - sha.result(&mut res); - SecretKey::from_slice(&secp_ctx, &res)? + SecretKey::from_slice(&secp_ctx, &Sha256::from_engine(sha).into_inner())? }; let mut part_a = revocation_base_secret.clone(); @@ -91,22 +84,18 @@ pub fn derive_private_revocation_key(secp_ctx: &Secp256k1 pub fn derive_public_revocation_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result { let rev_append_commit_hash_key = { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&revocation_base_point.serialize()); sha.input(&per_commitment_point.serialize()); - let mut res = [0; 32]; - sha.result(&mut res); - SecretKey::from_slice(&secp_ctx, &res)? + SecretKey::from_slice(&secp_ctx, &Sha256::from_engine(sha).into_inner())? }; let commit_append_rev_hash_key = { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&per_commitment_point.serialize()); sha.input(&revocation_base_point.serialize()); - let mut res = [0; 32]; - sha.result(&mut res); - SecretKey::from_slice(&secp_ctx, &res)? + SecretKey::from_slice(&secp_ctx, &Sha256::from_engine(sha).into_inner())? }; let mut part_a = revocation_base_point.clone(); diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 1e5c38b4..5bc5fdf8 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -6,12 +6,13 @@ use bitcoin::util::hash::{BitcoinHash, Sha256dHash, Hash160}; use bitcoin::util::bip143; use bitcoin::consensus::encode::{self, Encodable, Decodable}; +use bitcoin_hashes::{Hash, HashEngine}; +use bitcoin_hashes::sha256::Hash as Sha256; + use secp256k1::key::{PublicKey,SecretKey}; use secp256k1::{Secp256k1,Message,Signature}; use secp256k1; -use crypto::digest::Digest; - use ln::msgs; use ln::msgs::DecodeError; use ln::channelmonitor::ChannelMonitor; @@ -23,7 +24,6 @@ use chain::transaction::OutPoint; use chain::keysinterface::{ChannelKeys, KeysInterface}; use util::{transaction_utils,rng}; use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor}; -use util::sha2::Sha256; use util::logger::Logger; use util::errors::APIError; use util::config::{UserConfig,ChannelConfig}; @@ -722,7 +722,7 @@ impl Channel { // Utilities to build transactions: fn get_commitment_transaction_number_obscure_factor(&self) -> u64 { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); let our_payment_basepoint = PublicKey::from_secret_key(&self.secp_ctx, &self.local_keys.payment_base_key); if self.channel_outbound { @@ -732,8 +732,7 @@ impl Channel { sha.input(&self.their_payment_basepoint.unwrap().serialize()); sha.input(&our_payment_basepoint.serialize()); } - let mut res = [0; 32]; - sha.result(&mut res); + let res = Sha256::from_engine(sha).into_inner(); ((res[26] as u64) << 5*8) | ((res[27] as u64) << 4*8) | @@ -1151,10 +1150,7 @@ impl Channel { } assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0); - let mut sha = Sha256::new(); - sha.input(&payment_preimage_arg.0[..]); - let mut payment_hash_calc = PaymentHash([0; 32]); - sha.result(&mut payment_hash_calc.0[..]); + let payment_hash_calc = PaymentHash(Sha256::hash(&payment_preimage_arg.0[..]).into_inner()); // ChannelManager may generate duplicate claims/fails due to HTLC update events from // on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop @@ -1650,11 +1646,7 @@ impl Channel { return Err(ChannelError::Close("Peer sent update_fulfill_htlc when we needed a channel_reestablish")); } - let mut sha = Sha256::new(); - sha.input(&msg.payment_preimage.0[..]); - let mut payment_hash = PaymentHash([0; 32]); - sha.result(&mut payment_hash.0[..]); - + let payment_hash = PaymentHash(Sha256::hash(&msg.payment_preimage.0[..]).into_inner()); self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None).map(|source| source.clone()) } @@ -3927,8 +3919,8 @@ mod tests { use util::logger::Logger; use secp256k1::{Secp256k1,Message,Signature}; use secp256k1::key::{SecretKey,PublicKey}; - use crypto::sha2::Sha256; - use crypto::digest::Digest; + use bitcoin_hashes::sha256::Hash as Sha256; + use bitcoin_hashes::Hash; use std::sync::Arc; struct TestFeeEstimator { @@ -4054,12 +4046,7 @@ mod tests { let mut preimage: Option = None; if !htlc.offered { for i in 0..5 { - let mut sha = Sha256::new(); - sha.input(&[i; 32]); - - let mut out = PaymentHash([0; 32]); - sha.result(&mut out.0[..]); - + let out = PaymentHash(Sha256::hash(&[i; 32]).into_inner()); if out == htlc.payment_hash { preimage = Some(PaymentPreimage([i; 32])); } @@ -4091,9 +4078,7 @@ mod tests { payment_hash: PaymentHash([0; 32]), state: InboundHTLCState::Committed, }; - let mut sha = Sha256::new(); - sha.input(&hex::decode("0000000000000000000000000000000000000000000000000000000000000000").unwrap()); - sha.result(&mut out.payment_hash.0[..]); + out.payment_hash.0 = Sha256::hash(&hex::decode("0000000000000000000000000000000000000000000000000000000000000000").unwrap()).into_inner(); out }); chan.pending_inbound_htlcs.push({ @@ -4104,9 +4089,7 @@ mod tests { payment_hash: PaymentHash([0; 32]), state: InboundHTLCState::Committed, }; - let mut sha = Sha256::new(); - sha.input(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()); - sha.result(&mut out.payment_hash.0[..]); + out.payment_hash.0 = Sha256::hash(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()).into_inner(); out }); chan.pending_outbound_htlcs.push({ @@ -4119,9 +4102,7 @@ mod tests { source: HTLCSource::dummy(), fail_reason: None, }; - let mut sha = Sha256::new(); - sha.input(&hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap()); - sha.result(&mut out.payment_hash.0[..]); + out.payment_hash.0 = Sha256::hash(&hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap()).into_inner(); out }); chan.pending_outbound_htlcs.push({ @@ -4134,9 +4115,7 @@ mod tests { source: HTLCSource::dummy(), fail_reason: None, }; - let mut sha = Sha256::new(); - sha.input(&hex::decode("0303030303030303030303030303030303030303030303030303030303030303").unwrap()); - sha.result(&mut out.payment_hash.0[..]); + out.payment_hash.0 = Sha256::hash(&hex::decode("0303030303030303030303030303030303030303030303030303030303030303").unwrap()).into_inner(); out }); chan.pending_inbound_htlcs.push({ @@ -4147,9 +4126,7 @@ mod tests { payment_hash: PaymentHash([0; 32]), state: InboundHTLCState::Committed, }; - let mut sha = Sha256::new(); - sha.input(&hex::decode("0404040404040404040404040404040404040404040404040404040404040404").unwrap()); - sha.result(&mut out.payment_hash.0[..]); + out.payment_hash.0 = Sha256::hash(&hex::decode("0404040404040404040404040404040404040404040404040404040404040404").unwrap()).into_inner(); out }); diff --git a/src/ln/channelmanager.rs b/src/ln/channelmanager.rs index 2a96344e..28bf4fd7 100644 --- a/src/ln/channelmanager.rs +++ b/src/ln/channelmanager.rs @@ -14,6 +14,10 @@ use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::constants::Network; use bitcoin::util::hash::{BitcoinHash, Sha256dHash}; +use bitcoin_hashes::{Hash, HashEngine}; +use bitcoin_hashes::hmac::{Hmac, HmacEngine}; +use bitcoin_hashes::sha256::Hash as Sha256; + use secp256k1::key::{SecretKey,PublicKey}; use secp256k1::{Secp256k1,Message}; use secp256k1::ecdh::SharedSecret; @@ -29,7 +33,6 @@ use ln::msgs::{ChannelMessageHandler, DecodeError, HandleError}; use chain::keysinterface::KeysInterface; use util::config::UserConfig; use util::{byte_utils, events, internal_traits, rng}; -use util::sha2::Sha256; use util::ser::{Readable, ReadableArgs, Writeable, Writer}; use util::chacha20poly1305rfc::ChaCha20; use util::logger::Logger; @@ -37,9 +40,6 @@ use util::errors::APIError; use util::errors; use crypto; -use crypto::mac::{Mac,MacResult}; -use crypto::hmac::Hmac; -use crypto::digest::Digest; use crypto::symmetriccipher::SynchronousStreamCipher; use std::{cmp, ptr, mem}; @@ -722,39 +722,31 @@ impl ChannelManager { fn gen_rho_mu_from_shared_secret(shared_secret: &[u8]) -> ([u8; 32], [u8; 32]) { assert_eq!(shared_secret.len(), 32); ({ - let mut hmac = Hmac::new(Sha256::new(), &[0x72, 0x68, 0x6f]); // rho + let mut hmac = HmacEngine::::new(&[0x72, 0x68, 0x6f]); // rho hmac.input(&shared_secret[..]); - let mut res = [0; 32]; - hmac.raw_result(&mut res); - res + Hmac::from_engine(hmac).into_inner() }, { - let mut hmac = Hmac::new(Sha256::new(), &[0x6d, 0x75]); // mu + let mut hmac = HmacEngine::::new(&[0x6d, 0x75]); // mu hmac.input(&shared_secret[..]); - let mut res = [0; 32]; - hmac.raw_result(&mut res); - res + Hmac::from_engine(hmac).into_inner() }) } #[inline] fn gen_um_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] { assert_eq!(shared_secret.len(), 32); - let mut hmac = Hmac::new(Sha256::new(), &[0x75, 0x6d]); // um + let mut hmac = HmacEngine::::new(&[0x75, 0x6d]); // um hmac.input(&shared_secret[..]); - let mut res = [0; 32]; - hmac.raw_result(&mut res); - res + Hmac::from_engine(hmac).into_inner() } #[inline] fn gen_ammag_from_shared_secret(shared_secret: &[u8]) -> [u8; 32] { assert_eq!(shared_secret.len(), 32); - let mut hmac = Hmac::new(Sha256::new(), &[0x61, 0x6d, 0x6d, 0x61, 0x67]); // ammag + let mut hmac = HmacEngine::::new(&[0x61, 0x6d, 0x6d, 0x61, 0x67]); // ammag hmac.input(&shared_secret[..]); - let mut res = [0; 32]; - hmac.raw_result(&mut res); - res + Hmac::from_engine(hmac).into_inner() } // can only fail if an intermediary hop has an invalid public key or session_priv is invalid @@ -766,11 +758,10 @@ impl ChannelManager { for hop in route.hops.iter() { let shared_secret = SharedSecret::new(secp_ctx, &hop.pubkey, &blinded_priv); - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&blinded_pub.serialize()[..]); sha.input(&shared_secret[..]); - let mut blinding_factor = [0u8; 32]; - sha.result(&mut blinding_factor); + let blinding_factor = Sha256::from_engine(sha).into_inner(); let ephemeral_pubkey = blinded_pub; @@ -896,10 +887,10 @@ impl ChannelManager { packet_data[20*65 - filler.len()..20*65].copy_from_slice(&filler[..]); } - let mut hmac = Hmac::new(Sha256::new(), &keys.mu); + let mut hmac = HmacEngine::::new(&keys.mu); hmac.input(&packet_data); hmac.input(&associated_data.0[..]); - hmac.raw_result(&mut hmac_res); + hmac_res = Hmac::from_engine(hmac).into_inner(); } msgs::OnionPacket{ @@ -948,9 +939,9 @@ impl ChannelManager { pad: pad, }; - let mut hmac = Hmac::new(Sha256::new(), &um); + let mut hmac = HmacEngine::::new(&um); hmac.input(&packet.encode()[32..]); - hmac.raw_result(&mut packet.hmac); + packet.hmac = Hmac::from_engine(hmac).into_inner(); packet } @@ -966,14 +957,10 @@ impl ChannelManager { ($msg: expr, $err_code: expr) => { { log_info!(self, "Failed to accept/forward incoming HTLC: {}", $msg); - let mut sha256_of_onion = [0; 32]; - let mut sha = Sha256::new(); - sha.input(&msg.onion_routing_packet.hop_data); - sha.result(&mut sha256_of_onion); return (PendingHTLCStatus::Fail(HTLCFailureMsg::Malformed(msgs::UpdateFailMalformedHTLC { channel_id: msg.channel_id, htlc_id: msg.htlc_id, - sha256_of_onion, + sha256_of_onion: Sha256::hash(&msg.onion_routing_packet.hop_data).into_inner(), failure_code: $err_code, })), self.channel_state.lock().unwrap()); } @@ -1001,10 +988,11 @@ impl ChannelManager { return_malformed_err!("Unknown onion packet version", 0x8000 | 0x4000 | 4); } - let mut hmac = Hmac::new(Sha256::new(), &mu); + + let mut hmac = HmacEngine::::new(&mu); hmac.input(&msg.onion_routing_packet.hop_data); hmac.input(&msg.payment_hash.0[..]); - if hmac.result() != MacResult::new(&msg.onion_routing_packet.hmac) { + if !crypto::util::fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &msg.onion_routing_packet.hmac) { return_malformed_err!("HMAC Check failed", 0x8000 | 0x4000 | 5); } @@ -1077,12 +1065,10 @@ impl ChannelManager { let mut new_pubkey = msg.onion_routing_packet.public_key.unwrap(); let blinding_factor = { - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&new_pubkey.serialize()[..]); sha.input(&shared_secret); - let mut res = [0u8; 32]; - sha.result(&mut res); - SecretKey::from_slice(&self.secp_ctx, &res).expect("SHA-256 is broken?") + SecretKey::from_slice(&self.secp_ctx, &Sha256::from_engine(sha).into_inner()).expect("SHA-256 is broken?") }; let public_key = if let Err(e) = new_pubkey.mul_assign(&self.secp_ctx, &blinding_factor) { @@ -1652,10 +1638,7 @@ impl ChannelManager { /// /// May panic if called except in response to a PaymentReceived event. pub fn claim_funds(&self, payment_preimage: PaymentPreimage) -> bool { - let mut sha = Sha256::new(); - sha.input(&payment_preimage.0[..]); - let mut payment_hash = PaymentHash([0; 32]); - sha.result(&mut payment_hash.0[..]); + let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner()); let _ = self.total_consistency_lock.read().unwrap(); @@ -2156,12 +2139,10 @@ impl ChannelManager { if let Ok(err_packet) = msgs::DecodedOnionErrorPacket::read(&mut Cursor::new(&packet_decrypted)) { let um = ChannelManager::gen_um_from_shared_secret(&shared_secret[..]); - let mut hmac = Hmac::new(Sha256::new(), &um); + let mut hmac = HmacEngine::::new(&um); hmac.input(&err_packet.encode()[32..]); - let mut calc_tag = [0u8; 32]; - hmac.raw_result(&mut calc_tag); - if crypto::util::fixed_time_eq(&calc_tag, &err_packet.hmac) { + if crypto::util::fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &err_packet.hmac) { if let Some(error_code_slice) = err_packet.failuremsg.get(0..2) { const PERM: u16 = 0x4000; const NODE: u16 = 0x2000; @@ -3382,14 +3363,14 @@ mod tests { use bitcoin::blockdata::constants::genesis_block; use bitcoin::network::constants::Network; + use bitcoin_hashes::sha256::Hash as Sha256; + use bitcoin_hashes::Hash; + use hex; use secp256k1::{Secp256k1, Message}; use secp256k1::key::{PublicKey,SecretKey}; - use crypto::sha2::Sha256; - use crypto::digest::Digest; - use rand::{thread_rng,Rng}; use std::cell::RefCell; @@ -4030,10 +4011,7 @@ mod tests { { let payment_preimage = PaymentPreimage([*$node.network_payment_count.borrow(); 32]); *$node.network_payment_count.borrow_mut() += 1; - let mut payment_hash = PaymentHash([0; 32]); - let mut sha = Sha256::new(); - sha.input(&payment_preimage.0[..]); - sha.result(&mut payment_hash.0[..]); + let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()); (payment_preimage, payment_hash) } } diff --git a/src/ln/channelmonitor.rs b/src/ln/channelmonitor.rs index beb5a510..045ee36d 100644 --- a/src/ln/channelmonitor.rs +++ b/src/ln/channelmonitor.rs @@ -20,7 +20,8 @@ use bitcoin::consensus::encode::{self, Decodable, Encodable}; use bitcoin::util::hash::{Hash160, BitcoinHash,Sha256dHash}; use bitcoin::util::bip143; -use crypto::digest::Digest; +use bitcoin_hashes::Hash; +use bitcoin_hashes::sha256::Hash as Sha256; use secp256k1::{Secp256k1,Message,Signature}; use secp256k1::key::{SecretKey,PublicKey}; @@ -36,7 +37,6 @@ use chain::transaction::OutPoint; use chain::keysinterface::SpendableOutputDescriptor; use util::logger::Logger; use util::ser::{ReadableArgs, Readable, Writer, Writeable, WriterWriteAdaptor, U48}; -use util::sha2::Sha256; use util::{byte_utils, events}; use std::collections::{HashMap, hash_map}; @@ -487,9 +487,7 @@ impl ChannelMonitor { let bitpos = bits - 1 - i; if idx & (1 << bitpos) == (1 << bitpos) { res[(bitpos / 8) as usize] ^= 1 << (bitpos & 7); - let mut sha = Sha256::new(); - sha.input(&res); - sha.result(&mut res); + res = Sha256::hash(&res).into_inner(); } } res @@ -2098,13 +2096,9 @@ impl ReadableArgs> for (Sha256dHash, ChannelM let payment_preimages_len: u64 = Readable::read(reader)?; let mut payment_preimages = HashMap::with_capacity(cmp::min(payment_preimages_len as usize, MAX_ALLOC_SIZE / 32)); - let mut sha = Sha256::new(); for _ in 0..payment_preimages_len { let preimage: PaymentPreimage = Readable::read(reader)?; - sha.reset(); - sha.input(&preimage.0[..]); - let mut hash = PaymentHash([0; 32]); - sha.result(&mut hash.0[..]); + let hash = PaymentHash(Sha256::hash(&preimage.0[..]).into_inner()); if let Some(_) = payment_preimages.insert(hash, preimage) { return Err(DecodeError::InvalidValue); } @@ -2148,12 +2142,12 @@ impl ReadableArgs> for (Sha256dHash, ChannelM mod tests { use bitcoin::blockdata::script::Script; use bitcoin::blockdata::transaction::Transaction; - use crypto::digest::Digest; + use bitcoin_hashes::Hash; + use bitcoin_hashes::sha256::Hash as Sha256; use hex; use ln::channelmanager::{PaymentPreimage, PaymentHash}; use ln::channelmonitor::ChannelMonitor; use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys}; - use util::sha2::Sha256; use util::test_utils::TestLogger; use secp256k1::key::{SecretKey,PublicKey}; use secp256k1::{Secp256k1, Signature}; @@ -2544,10 +2538,7 @@ mod tests { for _ in 0..20 { let mut preimage = PaymentPreimage([0; 32]); rng.fill_bytes(&mut preimage.0[..]); - let mut sha = Sha256::new(); - sha.input(&preimage.0[..]); - let mut hash = PaymentHash([0; 32]); - sha.result(&mut hash.0[..]); + let hash = PaymentHash(Sha256::hash(&preimage.0[..]).into_inner()); preimages.push((preimage, hash)); } } diff --git a/src/ln/peer_channel_encryptor.rs b/src/ln/peer_channel_encryptor.rs index eaf2f683..2c4f5ced 100644 --- a/src/ln/peer_channel_encryptor.rs +++ b/src/ln/peer_channel_encryptor.rs @@ -1,19 +1,18 @@ use ln::msgs::HandleError; use ln::msgs; +use bitcoin_hashes::{Hash, HashEngine, Hmac, HmacEngine}; +use bitcoin_hashes::sha256::Hash as Sha256; + use secp256k1::Secp256k1; use secp256k1::key::{PublicKey,SecretKey}; use secp256k1::ecdh::SharedSecret; use secp256k1; -use crypto::digest::Digest; -use crypto::hkdf::{hkdf_extract,hkdf_expand}; - use crypto::aead::{AeadEncryptor, AeadDecryptor}; use util::chacha20poly1305rfc::ChaCha20Poly1305RFC; use util::{byte_utils,rng}; -use util::sha2::Sha256; // Sha256("Noise_XK_secp256k1_ChaChaPoly_SHA256") const NOISE_CK: [u8; 32] = [0x26, 0x40, 0xf5, 0x2e, 0xeb, 0xcd, 0x9e, 0x88, 0x29, 0x58, 0x95, 0x1c, 0x79, 0x42, 0x50, 0xee, 0xdb, 0x28, 0x00, 0x2c, 0x05, 0xd7, 0xdc, 0x2e, 0xa0, 0xf1, 0x95, 0x40, 0x60, 0x42, 0xca, 0xf1]; @@ -80,11 +79,10 @@ impl PeerChannelEncryptor { let secp_ctx = Secp256k1::signing_only(); let sec_key = SecretKey::from_slice(&secp_ctx, &key).unwrap(); //TODO: nicer rng-is-bad error message - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&NOISE_H); sha.input(&their_node_id.serialize()[..]); - let mut h = [0; 32]; - sha.result(&mut h); + let h = Sha256::from_engine(sha).into_inner(); PeerChannelEncryptor { their_node_id: Some(their_node_id), @@ -105,12 +103,11 @@ impl PeerChannelEncryptor { pub fn new_inbound(our_node_secret: &SecretKey) -> PeerChannelEncryptor { let secp_ctx = Secp256k1::signing_only(); - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&NOISE_H); let our_node_id = PublicKey::from_secret_key(&secp_ctx, our_node_secret); sha.input(&our_node_id.serialize()[..]); - let mut h = [0; 32]; - sha.result(&mut h); + let h = Sha256::from_engine(sha).into_inner(); PeerChannelEncryptor { their_node_id: None, @@ -153,28 +150,34 @@ impl PeerChannelEncryptor { Ok(()) } + fn hkdf_extract_expand(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) { + let mut hmac = HmacEngine::::new(salt); + hmac.input(ikm); + let prk = Hmac::from_engine(hmac).into_inner(); + let mut hmac = HmacEngine::::new(&prk[..]); + hmac.input(&[1; 1]); + let t1 = Hmac::from_engine(hmac).into_inner(); + let mut hmac = HmacEngine::::new(&prk[..]); + hmac.input(&t1); + hmac.input(&[2; 1]); + (t1, Hmac::from_engine(hmac).into_inner()) + } + #[inline] fn hkdf(state: &mut BidirectionalNoiseState, ss: SharedSecret) -> [u8; 32] { - let mut hkdf = [0; 64]; - { - let mut prk = [0; 32]; - hkdf_extract(Sha256::new(), &state.ck, &ss[..], &mut prk); - hkdf_expand(Sha256::new(), &prk, &[0;0], &mut hkdf); - } - state.ck.copy_from_slice(&hkdf[0..32]); - let mut res = [0; 32]; - res.copy_from_slice(&hkdf[32..]); - res + let (t1, t2) = Self::hkdf_extract_expand(&state.ck, &ss[..]); + state.ck = t1; + t2 } #[inline] fn outbound_noise_act(secp_ctx: &Secp256k1, state: &mut BidirectionalNoiseState, our_key: &SecretKey, their_key: &PublicKey) -> ([u8; 50], [u8; 32]) { let our_pub = PublicKey::from_secret_key(secp_ctx, &our_key); - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&state.h); sha.input(&our_pub.serialize()[..]); - sha.result(&mut state.h); + state.h = Sha256::from_engine(sha).into_inner(); let ss = SharedSecret::new(secp_ctx, &their_key, &our_key); let temp_k = PeerChannelEncryptor::hkdf(state, ss); @@ -183,10 +186,10 @@ impl PeerChannelEncryptor { res[1..34].copy_from_slice(&our_pub.serialize()[..]); PeerChannelEncryptor::encrypt_with_ad(&mut res[34..], 0, &temp_k, &state.h, &[0; 0]); - sha.reset(); + let mut sha = Sha256::engine(); sha.input(&state.h); sha.input(&res[34..]); - sha.result(&mut state.h); + state.h = Sha256::from_engine(sha).into_inner(); (res, temp_k) } @@ -204,10 +207,10 @@ impl PeerChannelEncryptor { Ok(key) => key, }; - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&state.h); sha.input(&their_pub.serialize()[..]); - sha.result(&mut state.h); + state.h = Sha256::from_engine(sha).into_inner(); let ss = SharedSecret::new(secp_ctx, &their_pub, &our_key); let temp_k = PeerChannelEncryptor::hkdf(state, ss); @@ -215,10 +218,10 @@ impl PeerChannelEncryptor { let mut dec = [0; 0]; PeerChannelEncryptor::decrypt_with_ad(&mut dec, 0, &temp_k, &state.h, &act[34..])?; - sha.reset(); + let mut sha = Sha256::engine(); sha.input(&state.h); sha.input(&act[34..]); - sha.result(&mut state.h); + state.h = Sha256::from_engine(sha).into_inner(); Ok((their_pub, temp_k)) } @@ -282,7 +285,7 @@ impl PeerChannelEncryptor { pub fn process_act_two(&mut self, act_two: &[u8], our_node_secret: &SecretKey) -> Result<([u8; 66], PublicKey), HandleError> { assert_eq!(act_two.len(), 50); - let mut final_hkdf = [0; 64]; + let final_hkdf; let ck; let res: [u8; 66] = match self.noise_state { NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => @@ -299,19 +302,16 @@ impl PeerChannelEncryptor { PeerChannelEncryptor::encrypt_with_ad(&mut res[1..50], 1, &temp_k2, &bidirectional_state.h, &our_node_id.serialize()[..]); - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&bidirectional_state.h); sha.input(&res[1..50]); - sha.result(&mut bidirectional_state.h); + bidirectional_state.h = Sha256::from_engine(sha).into_inner(); let ss = SharedSecret::new(&self.secp_ctx, &re, our_node_secret); let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); PeerChannelEncryptor::encrypt_with_ad(&mut res[50..], 0, &temp_k, &bidirectional_state.h, &[0; 0]); - - let mut prk = [0; 32]; - hkdf_extract(Sha256::new(), &bidirectional_state.ck, &[0; 0], &mut prk); - hkdf_expand(Sha256::new(), &prk, &[0;0], &mut final_hkdf); + final_hkdf = Self::hkdf_extract_expand(&bidirectional_state.ck, &[0; 0]); ck = bidirectional_state.ck.clone(); res }, @@ -320,11 +320,7 @@ impl PeerChannelEncryptor { _ => panic!("Cannot get act one after noise handshake completes"), }; - let mut sk = [0; 32]; - let mut rk = [0; 32]; - sk.copy_from_slice(&final_hkdf[0..32]); - rk.copy_from_slice(&final_hkdf[32..]); - + let (sk, rk) = final_hkdf; self.noise_state = NoiseState::Finished { sk: sk, sn: 0, @@ -340,7 +336,7 @@ impl PeerChannelEncryptor { pub fn process_act_three(&mut self, act_three: &[u8]) -> Result { assert_eq!(act_three.len(), 66); - let mut final_hkdf = [0; 64]; + let final_hkdf; let ck; match self.noise_state { NoiseState::InProgress { ref state, ref directional_state, ref mut bidirectional_state } => @@ -360,19 +356,16 @@ impl PeerChannelEncryptor { Err(_) => return Err(HandleError{err: "Bad node_id from peer", action: Some(msgs::ErrorAction::DisconnectPeer{ msg: None })}), }); - let mut sha = Sha256::new(); + let mut sha = Sha256::engine(); sha.input(&bidirectional_state.h); sha.input(&act_three[1..50]); - sha.result(&mut bidirectional_state.h); + bidirectional_state.h = Sha256::from_engine(sha).into_inner(); let ss = SharedSecret::new(&self.secp_ctx, &self.their_node_id.unwrap(), &re.unwrap()); let temp_k = PeerChannelEncryptor::hkdf(bidirectional_state, ss); PeerChannelEncryptor::decrypt_with_ad(&mut [0; 0], 0, &temp_k, &bidirectional_state.h, &act_three[50..])?; - - let mut prk = [0; 32]; - hkdf_extract(Sha256::new(), &bidirectional_state.ck, &[0; 0], &mut prk); - hkdf_expand(Sha256::new(), &prk, &[0;0], &mut final_hkdf); + final_hkdf = Self::hkdf_extract_expand(&bidirectional_state.ck, &[0; 0]); ck = bidirectional_state.ck.clone(); }, _ => panic!("Wrong direction for act"), @@ -380,11 +373,7 @@ impl PeerChannelEncryptor { _ => panic!("Cannot get act one after noise handshake completes"), } - let mut rk = [0; 32]; - let mut sk = [0; 32]; - rk.copy_from_slice(&final_hkdf[0..32]); - sk.copy_from_slice(&final_hkdf[32..]); - + let (rk, sk) = final_hkdf; self.noise_state = NoiseState::Finished { sk: sk, sn: 0, @@ -410,13 +399,9 @@ impl PeerChannelEncryptor { match self.noise_state { NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => { if *sn >= 1000 { - let mut prk = [0; 32]; - hkdf_extract(Sha256::new(), sck, sk, &mut prk); - let mut hkdf = [0; 64]; - hkdf_expand(Sha256::new(), &prk, &[0;0], &mut hkdf); - - sck[..].copy_from_slice(&hkdf[0..32]); - sk[..].copy_from_slice(&hkdf[32..]); + let (new_sck, new_sk) = Self::hkdf_extract_expand(sck, sk); + *sck = new_sck; + *sk = new_sk; *sn = 0; } @@ -440,13 +425,9 @@ impl PeerChannelEncryptor { match self.noise_state { NoiseState::Finished { sk: _, sn: _, sck: _, ref mut rk, ref mut rn, ref mut rck } => { if *rn >= 1000 { - let mut prk = [0; 32]; - hkdf_extract(Sha256::new(), rck, rk, &mut prk); - let mut hkdf = [0; 64]; - hkdf_expand(Sha256::new(), &prk, &[0;0], &mut hkdf); - - rck[..].copy_from_slice(&hkdf[0..32]); - rk[..].copy_from_slice(&hkdf[32..]); + let (new_rck, new_rk) = Self::hkdf_extract_expand(rck, rk); + *rck = new_rck; + *rk = new_rk; *rn = 0; } diff --git a/src/util/mod.rs b/src/util/mod.rs index 3df1529e..78886f11 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -19,11 +19,6 @@ pub(crate) mod macro_logger; pub mod logger; pub mod config; -#[cfg(feature = "fuzztarget")] -pub mod sha2; -#[cfg(not(feature = "fuzztarget"))] -pub(crate) mod sha2; - #[cfg(feature = "fuzztarget")] pub use self::rng::{reset_rng_state, fill_bytes}; diff --git a/src/util/sha2.rs b/src/util/sha2.rs deleted file mode 100644 index 2c9eab93..00000000 --- a/src/util/sha2.rs +++ /dev/null @@ -1,35 +0,0 @@ -#[cfg(not(feature = "fuzztarget"))] -pub use crypto::sha2::Sha256; - -#[cfg(feature = "fuzztarget")] -mod fuzzy_sha { - use crypto::digest::Digest; - - pub struct Sha256 { - state: u8, - } - - impl Sha256 { - pub fn new() -> Sha256 { - Sha256 { - state: 0, - } - } - } - - impl Digest for Sha256 { - fn result(&mut self, data: &mut [u8]) { - data[0] = self.state; - for i in 1..32 { - data[i] = 0; - } - } - - fn input(&mut self, data: &[u8]) { for i in data { self.state ^= i; } } - fn reset(&mut self) { self.state = 0; } - fn output_bits(&self) -> usize { 256 } - fn block_size(&self) -> usize { 64 } - } -} -#[cfg(feature = "fuzztarget")] -pub use self::fuzzy_sha::Sha256;