mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 07:17:40 +01:00
Merge pull request #270 from TheBlueMatt/2018-12-drop-rust-crypto
Drop rust-crypto for bitcoin_hashes
This commit is contained in:
commit
50ed320503
18 changed files with 1113 additions and 403 deletions
|
@ -9,12 +9,11 @@ A Bitcoin Lightning library in Rust.
|
|||
Does most of the hard work, without implying a specific runtime, requiring clients implement basic network logic, chain interactions and disk storage.
|
||||
Still missing tons of error-handling. See GitHub issues for suggested projects if you want to contribute. Don't have to bother telling you not to use this for anything serious, because you'd have to build a client around it to even try.
|
||||
"""
|
||||
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,13 +23,10 @@ max_level_debug = []
|
|||
|
||||
[dependencies]
|
||||
bitcoin = "0.15"
|
||||
rust-crypto = "0.2"
|
||||
bitcoin_hashes = { git = "https://github.com/TheBlueMatt/bitcoin_hashes", branch = "rust-lightning-dep" }
|
||||
rand = "0.4"
|
||||
secp256k1 = "0.11"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0"
|
||||
|
||||
[dev-dependencies.bitcoin]
|
||||
version = "0.15"
|
||||
features = ["bitcoinconsensus"]
|
||||
|
|
10
build.rs
10
build.rs
|
@ -1,10 +0,0 @@
|
|||
extern crate cc;
|
||||
|
||||
fn main() {
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "arm")))]
|
||||
{
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.file("src/util/rust_crypto_nonstd_arch.c");
|
||||
cfg.compile("lib_rust_crypto_nonstd_arch.a");
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ publish = false
|
|||
# Because the function is unused it gets dropped before we link lightning, so
|
||||
# we have to duplicate build.rs here. Note that this is only required for
|
||||
# fuzztarget mode.
|
||||
build = "../build.rs"
|
||||
|
||||
[package.metadata]
|
||||
cargo-fuzz = true
|
||||
|
@ -19,9 +18,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]
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -6,17 +6,16 @@ use bitcoin::blockdata::transaction::{OutPoint, TxOut};
|
|||
use bitcoin::blockdata::script::{Script, Builder};
|
||||
use bitcoin::blockdata::opcodes;
|
||||
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 bitcoin_hashes::hash160::Hash as Hash160;
|
||||
|
||||
use secp256k1::key::{SecretKey, PublicKey};
|
||||
use secp256k1::Secp256k1;
|
||||
use secp256k1;
|
||||
|
||||
use crypto::hkdf::{hkdf_extract,hkdf_expand};
|
||||
use crypto::digest::Digest;
|
||||
|
||||
use util::sha2::Sha256;
|
||||
use util::logger::Logger;
|
||||
use util::rng;
|
||||
use util::byte_utils;
|
||||
|
@ -109,43 +108,6 @@ impl_writeable!(ChannelKeys, 0, {
|
|||
commitment_seed
|
||||
});
|
||||
|
||||
impl ChannelKeys {
|
||||
/// Generate a set of lightning keys needed to operate a channel by HKDF-expanding a given
|
||||
/// random 32-byte seed
|
||||
pub fn new_from_seed(seed: &[u8; 32]) -> ChannelKeys {
|
||||
let mut prk = [0; 32];
|
||||
hkdf_extract(Sha256::new(), b"rust-lightning key gen salt", seed, &mut prk);
|
||||
let secp_ctx = Secp256k1::without_caps();
|
||||
|
||||
let mut okm = [0; 32];
|
||||
hkdf_expand(Sha256::new(), &prk, b"rust-lightning funding key info", &mut okm);
|
||||
let funding_key = SecretKey::from_slice(&secp_ctx, &okm).expect("Sha256 is broken");
|
||||
|
||||
hkdf_expand(Sha256::new(), &prk, b"rust-lightning revocation base key info", &mut okm);
|
||||
let revocation_base_key = SecretKey::from_slice(&secp_ctx, &okm).expect("Sha256 is broken");
|
||||
|
||||
hkdf_expand(Sha256::new(), &prk, b"rust-lightning payment base key info", &mut okm);
|
||||
let payment_base_key = SecretKey::from_slice(&secp_ctx, &okm).expect("Sha256 is broken");
|
||||
|
||||
hkdf_expand(Sha256::new(), &prk, b"rust-lightning delayed payment base key info", &mut okm);
|
||||
let delayed_payment_base_key = SecretKey::from_slice(&secp_ctx, &okm).expect("Sha256 is broken");
|
||||
|
||||
hkdf_expand(Sha256::new(), &prk, b"rust-lightning htlc base key info", &mut okm);
|
||||
let htlc_base_key = SecretKey::from_slice(&secp_ctx, &okm).expect("Sha256 is broken");
|
||||
|
||||
hkdf_expand(Sha256::new(), &prk, b"rust-lightning local commitment seed info", &mut okm);
|
||||
|
||||
ChannelKeys {
|
||||
funding_key: funding_key,
|
||||
revocation_base_key: revocation_base_key,
|
||||
payment_base_key: payment_base_key,
|
||||
delayed_payment_base_key: delayed_payment_base_key,
|
||||
htlc_base_key: htlc_base_key,
|
||||
commitment_seed: okm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple KeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key
|
||||
/// and derives keys from that.
|
||||
///
|
||||
|
@ -176,9 +138,9 @@ impl KeysManager {
|
|||
let node_secret = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0)).expect("Your RNG is busted").secret_key;
|
||||
let destination_script = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1)) {
|
||||
Ok(destination_key) => {
|
||||
let pubkey_hash160 = Hash160::from_data(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.serialize()[..]);
|
||||
let pubkey_hash160 = Hash160::hash(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.serialize()[..]);
|
||||
Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0)
|
||||
.push_slice(pubkey_hash160.as_bytes())
|
||||
.push_slice(&pubkey_hash160.into_inner())
|
||||
.into_script()
|
||||
},
|
||||
Err(_) => panic!("Your RNG is busted"),
|
||||
|
@ -225,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[..]);
|
||||
|
@ -239,13 +201,41 @@ 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);
|
||||
ChannelKeys::new_from_seed(&seed)
|
||||
seed = Sha256::from_engine(sha).into_inner();
|
||||
|
||||
let commitment_seed = {
|
||||
let mut sha = Sha256::engine();
|
||||
sha.input(&seed);
|
||||
sha.input(&b"commitment seed"[..]);
|
||||
Sha256::from_engine(sha).into_inner()
|
||||
};
|
||||
macro_rules! key_step {
|
||||
($info: expr, $prev_key: expr) => {{
|
||||
let mut sha = Sha256::engine();
|
||||
sha.input(&seed);
|
||||
sha.input(&$prev_key[..]);
|
||||
sha.input(&$info[..]);
|
||||
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);
|
||||
let revocation_base_key = key_step!(b"revocation base key", funding_key);
|
||||
let payment_base_key = key_step!(b"payment base key", revocation_base_key);
|
||||
let delayed_payment_base_key = key_step!(b"delayed payment base key", payment_base_key);
|
||||
let htlc_base_key = key_step!(b"HTLC base key", delayed_payment_base_key);
|
||||
|
||||
ChannelKeys {
|
||||
funding_key,
|
||||
revocation_base_key,
|
||||
payment_base_key,
|
||||
delayed_payment_base_key,
|
||||
htlc_base_key,
|
||||
commitment_seed,
|
||||
}
|
||||
}
|
||||
|
||||
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()));
|
||||
|
@ -254,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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#![cfg_attr(not(feature = "fuzztarget"), deny(missing_docs))]
|
||||
|
||||
extern crate bitcoin;
|
||||
extern crate crypto;
|
||||
extern crate bitcoin_hashes;
|
||||
extern crate rand;
|
||||
extern crate secp256k1;
|
||||
#[cfg(test)] extern crate hex;
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
use bitcoin::blockdata::script::{Script,Builder};
|
||||
use bitcoin::blockdata::opcodes;
|
||||
use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction};
|
||||
use bitcoin::util::hash::{Hash160,Sha256dHash};
|
||||
use bitcoin::util::hash::{Sha256dHash};
|
||||
|
||||
use bitcoin_hashes::{Hash, HashEngine};
|
||||
use bitcoin_hashes::sha256::Hash as Sha256;
|
||||
use bitcoin_hashes::ripemd160::Hash as Ripemd160;
|
||||
use bitcoin_hashes::hash160::Hash as Hash160;
|
||||
|
||||
use ln::channelmanager::PaymentHash;
|
||||
|
||||
|
@ -9,11 +14,6 @@ use secp256k1::key::{PublicKey,SecretKey};
|
|||
use secp256k1::Secp256k1;
|
||||
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 +26,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<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
|
||||
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 +44,10 @@ pub fn derive_private_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_co
|
|||
}
|
||||
|
||||
pub fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
|
||||
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 +59,18 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(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 +83,18 @@ pub fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1
|
|||
|
||||
pub fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, revocation_base_point: &PublicKey) -> Result<PublicKey, secp256k1::Error> {
|
||||
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();
|
||||
|
@ -164,17 +152,11 @@ pub struct HTLCOutputInCommitment {
|
|||
|
||||
#[inline]
|
||||
pub fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script {
|
||||
let payment_hash160 = {
|
||||
let mut ripemd = Ripemd160::new();
|
||||
ripemd.input(&htlc.payment_hash.0[..]);
|
||||
let mut res = [0; 20];
|
||||
ripemd.result(&mut res);
|
||||
res
|
||||
};
|
||||
let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).into_inner();
|
||||
if htlc.offered {
|
||||
Builder::new().push_opcode(opcodes::All::OP_DUP)
|
||||
.push_opcode(opcodes::All::OP_HASH160)
|
||||
.push_slice(&Hash160::from_data(&revocation_key.serialize())[..])
|
||||
.push_slice(&Hash160::hash(&revocation_key.serialize())[..])
|
||||
.push_opcode(opcodes::All::OP_EQUAL)
|
||||
.push_opcode(opcodes::All::OP_IF)
|
||||
.push_opcode(opcodes::All::OP_CHECKSIG)
|
||||
|
@ -202,7 +184,7 @@ pub fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a
|
|||
} else {
|
||||
Builder::new().push_opcode(opcodes::All::OP_DUP)
|
||||
.push_opcode(opcodes::All::OP_HASH160)
|
||||
.push_slice(&Hash160::from_data(&revocation_key.serialize())[..])
|
||||
.push_slice(&Hash160::hash(&revocation_key.serialize())[..])
|
||||
.push_opcode(opcodes::All::OP_EQUAL)
|
||||
.push_opcode(opcodes::All::OP_IF)
|
||||
.push_opcode(opcodes::All::OP_CHECKSIG)
|
||||
|
|
|
@ -2,16 +2,18 @@ use bitcoin::blockdata::block::BlockHeader;
|
|||
use bitcoin::blockdata::script::{Script,Builder};
|
||||
use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
|
||||
use bitcoin::blockdata::opcodes;
|
||||
use bitcoin::util::hash::{BitcoinHash, Sha256dHash, Hash160};
|
||||
use bitcoin::util::hash::{BitcoinHash, Sha256dHash};
|
||||
use bitcoin::util::bip143;
|
||||
use bitcoin::consensus::encode::{self, Encodable, Decodable};
|
||||
|
||||
use bitcoin_hashes::{Hash, HashEngine};
|
||||
use bitcoin_hashes::sha256::Hash as Sha256;
|
||||
use bitcoin_hashes::hash160::Hash as Hash160;
|
||||
|
||||
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 +25,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 +723,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 +733,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) |
|
||||
|
@ -907,7 +907,7 @@ impl Channel {
|
|||
if value_to_b >= (dust_limit_satoshis as i64) {
|
||||
txouts.push((TxOut {
|
||||
script_pubkey: Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0)
|
||||
.push_slice(&Hash160::from_data(&keys.b_payment_key.serialize())[..])
|
||||
.push_slice(&Hash160::hash(&keys.b_payment_key.serialize())[..])
|
||||
.into_script(),
|
||||
value: value_to_b as u64
|
||||
}, None));
|
||||
|
@ -940,7 +940,7 @@ impl Channel {
|
|||
|
||||
#[inline]
|
||||
fn get_closing_scriptpubkey(&self) -> Script {
|
||||
let our_channel_close_key_hash = Hash160::from_data(&self.shutdown_pubkey.serialize());
|
||||
let our_channel_close_key_hash = Hash160::hash(&self.shutdown_pubkey.serialize());
|
||||
Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script()
|
||||
}
|
||||
|
||||
|
@ -1151,10 +1151,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 +1647,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 +3920,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 +4047,7 @@ mod tests {
|
|||
let mut preimage: Option<PaymentPreimage> = 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 +4079,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 +4090,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 +4103,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 +4116,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 +4127,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
|
||||
});
|
||||
|
||||
|
|
|
@ -14,6 +14,11 @@ 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 bitcoin_hashes::cmp::fixed_time_eq;
|
||||
|
||||
use secp256k1::key::{SecretKey,PublicKey};
|
||||
use secp256k1::{Secp256k1,Message};
|
||||
use secp256k1::ecdh::SharedSecret;
|
||||
|
@ -29,19 +34,12 @@ 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::chacha20::ChaCha20;
|
||||
use util::logger::Logger;
|
||||
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};
|
||||
use std::collections::{HashMap, hash_map, HashSet};
|
||||
use std::io::Cursor;
|
||||
|
@ -722,39 +720,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::<Sha256>::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::<Sha256>::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::<Sha256>::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::<Sha256>::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 +756,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 +885,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::<Sha256>::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 +937,9 @@ impl ChannelManager {
|
|||
pad: pad,
|
||||
};
|
||||
|
||||
let mut hmac = Hmac::new(Sha256::new(), &um);
|
||||
let mut hmac = HmacEngine::<Sha256>::new(&um);
|
||||
hmac.input(&packet.encode()[32..]);
|
||||
hmac.raw_result(&mut packet.hmac);
|
||||
packet.hmac = Hmac::from_engine(hmac).into_inner();
|
||||
|
||||
packet
|
||||
}
|
||||
|
@ -966,14 +955,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 +986,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::<Sha256>::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 !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 +1063,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 +1636,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 +2137,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::<Sha256>::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 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 +3361,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 +4009,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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,12 @@ use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
|
|||
use bitcoin::blockdata::script::{Script, Builder};
|
||||
use bitcoin::blockdata::opcodes;
|
||||
use bitcoin::consensus::encode::{self, Decodable, Encodable};
|
||||
use bitcoin::util::hash::{Hash160, BitcoinHash,Sha256dHash};
|
||||
use bitcoin::util::hash::{BitcoinHash,Sha256dHash};
|
||||
use bitcoin::util::bip143;
|
||||
|
||||
use crypto::digest::Digest;
|
||||
use bitcoin_hashes::Hash;
|
||||
use bitcoin_hashes::sha256::Hash as Sha256;
|
||||
use bitcoin_hashes::hash160::Hash as Hash160;
|
||||
|
||||
use secp256k1::{Secp256k1,Message,Signature};
|
||||
use secp256k1::key::{SecretKey,PublicKey};
|
||||
|
@ -36,7 +38,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 +488,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
|
||||
|
@ -569,6 +568,8 @@ impl ChannelMonitor {
|
|||
}
|
||||
|
||||
let new_txid = unsigned_commitment_tx.txid();
|
||||
log_trace!(self, "Tracking new remote commitment transaction with txid {} at commitment number {} with {} HTLC outputs", new_txid, commitment_number, htlc_outputs.len());
|
||||
log_trace!(self, "New potential remote commitment transaction: {}", encode::serialize_hex(unsigned_commitment_tx));
|
||||
if let Storage::Local { ref mut current_remote_commitment_txid, ref mut prev_remote_commitment_txid, .. } = self.key_storage {
|
||||
*prev_remote_commitment_txid = current_remote_commitment_txid.take();
|
||||
*current_remote_commitment_txid = Some(new_txid);
|
||||
|
@ -1079,7 +1080,7 @@ impl ChannelMonitor {
|
|||
let local_payment_p2wpkh = if let Some(payment_key) = local_payment_key {
|
||||
// Note that the Network here is ignored as we immediately drop the address for the
|
||||
// script_pubkey version.
|
||||
let payment_hash160 = Hash160::from_data(&PublicKey::from_secret_key(&self.secp_ctx, &payment_key).serialize());
|
||||
let payment_hash160 = Hash160::hash(&PublicKey::from_secret_key(&self.secp_ctx, &payment_key).serialize());
|
||||
Some(Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script())
|
||||
} else { None };
|
||||
|
||||
|
@ -1247,6 +1248,8 @@ impl ChannelMonitor {
|
|||
watch_outputs.append(&mut tx.output.clone());
|
||||
self.remote_commitment_txn_on_chain.insert(commitment_txid, (commitment_number, tx.output.iter().map(|output| { output.script_pubkey.clone() }).collect()));
|
||||
|
||||
log_trace!(self, "Got broadcast of non-revoked remote commitment transaction {}", commitment_txid);
|
||||
|
||||
if let Some(revocation_points) = self.their_cur_revocation_points {
|
||||
let revocation_point_option =
|
||||
if revocation_points.0 == commitment_number { Some(&revocation_points.1) }
|
||||
|
@ -1621,7 +1624,7 @@ impl ChannelMonitor {
|
|||
if tx.input[0].sequence == 0xFFFFFFFF && !tx.input[0].witness.is_empty() && tx.input[0].witness.last().unwrap().len() == 71 {
|
||||
match self.key_storage {
|
||||
Storage::Local { ref shutdown_pubkey, .. } => {
|
||||
let our_channel_close_key_hash = Hash160::from_data(&shutdown_pubkey.serialize());
|
||||
let our_channel_close_key_hash = Hash160::hash(&shutdown_pubkey.serialize());
|
||||
let shutdown_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script();
|
||||
for (idx, output) in tx.output.iter().enumerate() {
|
||||
if shutdown_script == output.script_pubkey {
|
||||
|
@ -2098,13 +2101,9 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> 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 +2147,12 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> 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 +2543,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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
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 +77,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 +101,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 +148,34 @@ impl PeerChannelEncryptor {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn hkdf_extract_expand(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
|
||||
let mut hmac = HmacEngine::<Sha256>::new(salt);
|
||||
hmac.input(ikm);
|
||||
let prk = Hmac::from_engine(hmac).into_inner();
|
||||
let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
|
||||
hmac.input(&[1; 1]);
|
||||
let t1 = Hmac::from_engine(hmac).into_inner();
|
||||
let mut hmac = HmacEngine::<Sha256>::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<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, 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 +184,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 +205,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 +216,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 +283,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 +300,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 +318,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 +334,7 @@ impl PeerChannelEncryptor {
|
|||
pub fn process_act_three(&mut self, act_three: &[u8]) -> Result<PublicKey, HandleError> {
|
||||
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 +354,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 +371,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 +397,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 +423,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,13 @@ pub fn slice_to_be32(v: &[u8]) -> u32 {
|
|||
((v[3] as u32) << 8*0)
|
||||
}
|
||||
#[inline]
|
||||
pub fn slice_to_le32(v: &[u8]) -> u32 {
|
||||
((v[0] as u32) << 8*0) |
|
||||
((v[1] as u32) << 8*1) |
|
||||
((v[2] as u32) << 8*2) |
|
||||
((v[3] as u32) << 8*3)
|
||||
}
|
||||
#[inline]
|
||||
pub fn slice_to_be48(v: &[u8]) -> u64 {
|
||||
((v[0] as u64) << 8*5) |
|
||||
((v[1] as u64) << 8*4) |
|
||||
|
@ -48,6 +55,15 @@ pub fn be32_to_array(u: u32) -> [u8; 4] {
|
|||
v
|
||||
}
|
||||
#[inline]
|
||||
pub fn le32_to_array(u: u32) -> [u8; 4] {
|
||||
let mut v = [0; 4];
|
||||
v[0] = ((u >> 8*0) & 0xff) as u8;
|
||||
v[1] = ((u >> 8*1) & 0xff) as u8;
|
||||
v[2] = ((u >> 8*2) & 0xff) as u8;
|
||||
v[3] = ((u >> 8*3) & 0xff) as u8;
|
||||
v
|
||||
}
|
||||
#[inline]
|
||||
pub fn be48_to_array(u: u64) -> [u8; 6] {
|
||||
assert!(u & 0xffff_0000_0000_0000 == 0);
|
||||
let mut v = [0; 6];
|
||||
|
|
550
src/util/chacha20.rs
Normal file
550
src/util/chacha20.rs
Normal file
|
@ -0,0 +1,550 @@
|
|||
// This file was stolen from rust-crypto.
|
||||
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[cfg(not(feature = "fuzztarget"))]
|
||||
mod real_chacha {
|
||||
use std::cmp;
|
||||
use util::byte_utils::{slice_to_le32, le32_to_array};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct u32x4(pub u32, pub u32, pub u32, pub u32);
|
||||
impl ::std::ops::Add for u32x4 {
|
||||
type Output = u32x4;
|
||||
fn add(self, rhs: u32x4) -> u32x4 {
|
||||
u32x4(self.0.wrapping_add(rhs.0),
|
||||
self.1.wrapping_add(rhs.1),
|
||||
self.2.wrapping_add(rhs.2),
|
||||
self.3.wrapping_add(rhs.3))
|
||||
}
|
||||
}
|
||||
impl ::std::ops::Sub for u32x4 {
|
||||
type Output = u32x4;
|
||||
fn sub(self, rhs: u32x4) -> u32x4 {
|
||||
u32x4(self.0.wrapping_sub(rhs.0),
|
||||
self.1.wrapping_sub(rhs.1),
|
||||
self.2.wrapping_sub(rhs.2),
|
||||
self.3.wrapping_sub(rhs.3))
|
||||
}
|
||||
}
|
||||
impl ::std::ops::BitXor for u32x4 {
|
||||
type Output = u32x4;
|
||||
fn bitxor(self, rhs: u32x4) -> u32x4 {
|
||||
u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
|
||||
}
|
||||
}
|
||||
impl ::std::ops::Shr<u32x4> for u32x4 {
|
||||
type Output = u32x4;
|
||||
fn shr(self, rhs: u32x4) -> u32x4 {
|
||||
u32x4(self.0 >> rhs.0, self.1 >> rhs.1, self.2 >> rhs.2, self.3 >> rhs.3)
|
||||
}
|
||||
}
|
||||
impl ::std::ops::Shl<u32x4> for u32x4 {
|
||||
type Output = u32x4;
|
||||
fn shl(self, rhs: u32x4) -> u32x4 {
|
||||
u32x4(self.0 << rhs.0, self.1 << rhs.1, self.2 << rhs.2, self.3 << rhs.3)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone,Copy)]
|
||||
struct ChaChaState {
|
||||
a: u32x4,
|
||||
b: u32x4,
|
||||
c: u32x4,
|
||||
d: u32x4
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
pub struct ChaCha20 {
|
||||
state : ChaChaState,
|
||||
output : [u8; 64],
|
||||
offset : usize,
|
||||
}
|
||||
|
||||
impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
|
||||
|
||||
macro_rules! swizzle {
|
||||
($b: expr, $c: expr, $d: expr) => {{
|
||||
let u32x4(b10, b11, b12, b13) = $b;
|
||||
$b = u32x4(b11, b12, b13, b10);
|
||||
let u32x4(c10, c11, c12, c13) = $c;
|
||||
$c = u32x4(c12, c13,c10, c11);
|
||||
let u32x4(d10, d11, d12, d13) = $d;
|
||||
$d = u32x4(d13, d10, d11, d12);
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! state_to_buffer {
|
||||
($state: expr, $output: expr) => {{
|
||||
let u32x4(a1, a2, a3, a4) = $state.a;
|
||||
let u32x4(b1, b2, b3, b4) = $state.b;
|
||||
let u32x4(c1, c2, c3, c4) = $state.c;
|
||||
let u32x4(d1, d2, d3, d4) = $state.d;
|
||||
let lens = [
|
||||
a1,a2,a3,a4,
|
||||
b1,b2,b3,b4,
|
||||
c1,c2,c3,c4,
|
||||
d1,d2,d3,d4
|
||||
];
|
||||
for i in 0..lens.len() {
|
||||
$output[i*4..(i+1)*4].copy_from_slice(&le32_to_array(lens[i]));
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! round{
|
||||
($state: expr) => {{
|
||||
$state.a = $state.a + $state.b;
|
||||
rotate!($state.d, $state.a, S16);
|
||||
$state.c = $state.c + $state.d;
|
||||
rotate!($state.b, $state.c, S12);
|
||||
$state.a = $state.a + $state.b;
|
||||
rotate!($state.d, $state.a, S8);
|
||||
$state.c = $state.c + $state.d;
|
||||
rotate!($state.b, $state.c, S7);
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! rotate {
|
||||
($a: expr, $b: expr, $c:expr) => {{
|
||||
let v = $a ^ $b;
|
||||
let r = S32 - $c;
|
||||
let right = v >> r;
|
||||
$a = (v << $c) ^ right
|
||||
}}
|
||||
}
|
||||
|
||||
const S32:u32x4 = u32x4(32, 32, 32, 32);
|
||||
const S16:u32x4 = u32x4(16, 16, 16, 16);
|
||||
const S12:u32x4 = u32x4(12, 12, 12, 12);
|
||||
const S8:u32x4 = u32x4(8, 8, 8, 8);
|
||||
const S7:u32x4 = u32x4(7, 7, 7, 7);
|
||||
|
||||
impl ChaCha20 {
|
||||
pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
|
||||
assert!(key.len() == 16 || key.len() == 32);
|
||||
assert!(nonce.len() == 8 || nonce.len() == 12);
|
||||
|
||||
ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; 64], offset: 64 }
|
||||
}
|
||||
|
||||
fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
|
||||
let constant = match key.len() {
|
||||
16 => b"expand 16-byte k",
|
||||
32 => b"expand 32-byte k",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
ChaChaState {
|
||||
a: u32x4(
|
||||
slice_to_le32(&constant[0..4]),
|
||||
slice_to_le32(&constant[4..8]),
|
||||
slice_to_le32(&constant[8..12]),
|
||||
slice_to_le32(&constant[12..16])
|
||||
),
|
||||
b: u32x4(
|
||||
slice_to_le32(&key[0..4]),
|
||||
slice_to_le32(&key[4..8]),
|
||||
slice_to_le32(&key[8..12]),
|
||||
slice_to_le32(&key[12..16])
|
||||
),
|
||||
c: if key.len() == 16 {
|
||||
u32x4(
|
||||
slice_to_le32(&key[0..4]),
|
||||
slice_to_le32(&key[4..8]),
|
||||
slice_to_le32(&key[8..12]),
|
||||
slice_to_le32(&key[12..16])
|
||||
)
|
||||
} else {
|
||||
u32x4(
|
||||
slice_to_le32(&key[16..20]),
|
||||
slice_to_le32(&key[20..24]),
|
||||
slice_to_le32(&key[24..28]),
|
||||
slice_to_le32(&key[28..32])
|
||||
)
|
||||
},
|
||||
d: if nonce.len() == 16 {
|
||||
u32x4(
|
||||
slice_to_le32(&nonce[0..4]),
|
||||
slice_to_le32(&nonce[4..8]),
|
||||
slice_to_le32(&nonce[8..12]),
|
||||
slice_to_le32(&nonce[12..16])
|
||||
)
|
||||
} else if nonce.len() == 12 {
|
||||
u32x4(
|
||||
0,
|
||||
slice_to_le32(&nonce[0..4]),
|
||||
slice_to_le32(&nonce[4..8]),
|
||||
slice_to_le32(&nonce[8..12])
|
||||
)
|
||||
} else {
|
||||
u32x4(
|
||||
0,
|
||||
0,
|
||||
slice_to_le32(&nonce[0..4]),
|
||||
slice_to_le32(&nonce[4..8])
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// put the the next 64 keystream bytes into self.output
|
||||
fn update(&mut self) {
|
||||
let mut state = self.state;
|
||||
|
||||
for _ in 0..10 {
|
||||
round!(state);
|
||||
swizzle!(state.b, state.c, state.d);
|
||||
round!(state);
|
||||
swizzle!(state.d, state.c, state.b);
|
||||
}
|
||||
state.a = state.a + self.state.a;
|
||||
state.b = state.b + self.state.b;
|
||||
state.c = state.c + self.state.c;
|
||||
state.d = state.d + self.state.d;
|
||||
|
||||
state_to_buffer!(state, self.output);
|
||||
|
||||
self.state.d = self.state.d + u32x4(1, 0, 0, 0);
|
||||
let u32x4(c12, _, _, _) = self.state.d;
|
||||
if c12 == 0 {
|
||||
// we could increment the other counter word with an 8 byte nonce
|
||||
// but other implementations like boringssl have this same
|
||||
// limitation
|
||||
panic!("counter is exhausted");
|
||||
}
|
||||
|
||||
self.offset = 0;
|
||||
}
|
||||
|
||||
pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
|
||||
assert!(input.len() == output.len());
|
||||
let len = input.len();
|
||||
let mut i = 0;
|
||||
while i < len {
|
||||
// If there is no keystream available in the output buffer,
|
||||
// generate the next block.
|
||||
if self.offset == 64 {
|
||||
self.update();
|
||||
}
|
||||
|
||||
// Process the min(available keystream, remaining input length).
|
||||
let count = cmp::min(64 - self.offset, len - i);
|
||||
// explicitly assert lengths to avoid bounds checks:
|
||||
assert!(output.len() >= i + count);
|
||||
assert!(input.len() >= i + count);
|
||||
assert!(self.output.len() >= self.offset + count);
|
||||
for j in 0..count {
|
||||
output[i + j] = input[i + j] ^ self.output[self.offset + j];
|
||||
}
|
||||
i += count;
|
||||
self.offset += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "fuzztarget"))]
|
||||
pub use self::real_chacha::ChaCha20;
|
||||
|
||||
#[cfg(feature = "fuzztarget")]
|
||||
mod fuzzy_chacha {
|
||||
pub struct ChaCha20 {}
|
||||
|
||||
impl ChaCha20 {
|
||||
pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
|
||||
assert!(key.len() == 16 || key.len() == 32);
|
||||
assert!(nonce.len() == 8 || nonce.len() == 12);
|
||||
Self {}
|
||||
}
|
||||
|
||||
pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
|
||||
output.copy_from_slice(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "fuzztarget")]
|
||||
pub use self::fuzzy_chacha::ChaCha20;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::iter::repeat;
|
||||
|
||||
use super::ChaCha20;
|
||||
|
||||
#[test]
|
||||
fn test_chacha20_256_tls_vectors() {
|
||||
struct TestVector {
|
||||
key: [u8; 32],
|
||||
nonce: [u8; 8],
|
||||
keystream: Vec<u8>,
|
||||
};
|
||||
// taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
|
||||
let test_vectors = vec!(
|
||||
TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
|
||||
keystream: vec!(
|
||||
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
|
||||
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
|
||||
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
|
||||
0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
|
||||
0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
|
||||
0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
|
||||
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
|
||||
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
],
|
||||
nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
|
||||
keystream: vec!(
|
||||
0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
|
||||
0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
|
||||
0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
|
||||
0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
|
||||
0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
|
||||
0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
|
||||
0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
|
||||
0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
|
||||
keystream: vec!(
|
||||
0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
|
||||
0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
|
||||
0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
|
||||
0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
|
||||
0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
|
||||
0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
|
||||
0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
|
||||
0x44, 0x5f, 0x41, 0xe3,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
|
||||
keystream: vec!(
|
||||
0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
|
||||
0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
|
||||
0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
|
||||
0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
|
||||
0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
|
||||
0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
|
||||
0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
|
||||
0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
],
|
||||
nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
|
||||
keystream: vec!(
|
||||
0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
|
||||
0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
|
||||
0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
|
||||
0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
|
||||
0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
|
||||
0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
|
||||
0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
|
||||
0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
|
||||
0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
|
||||
0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
|
||||
0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
|
||||
0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
|
||||
0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
|
||||
0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
|
||||
0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
|
||||
0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
|
||||
0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
|
||||
0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
|
||||
0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
|
||||
0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
|
||||
0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
|
||||
0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
|
||||
0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
|
||||
0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
|
||||
0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
|
||||
0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
|
||||
0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
|
||||
0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
|
||||
0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
|
||||
0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
|
||||
0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
|
||||
0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
for tv in test_vectors.iter() {
|
||||
let mut c = ChaCha20::new(&tv.key, &tv.nonce);
|
||||
let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
|
||||
let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
|
||||
c.process(&input[..], &mut output[..]);
|
||||
assert_eq!(output, tv.keystream);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chacha20_256_tls_vectors_96_nonce() {
|
||||
struct TestVector {
|
||||
key: [u8; 32],
|
||||
nonce: [u8; 12],
|
||||
keystream: Vec<u8>,
|
||||
};
|
||||
// taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
|
||||
let test_vectors = vec!(
|
||||
TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
|
||||
keystream: vec!(
|
||||
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
|
||||
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
|
||||
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
|
||||
0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
|
||||
0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
|
||||
0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
|
||||
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
|
||||
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
],
|
||||
nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
|
||||
keystream: vec!(
|
||||
0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
|
||||
0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
|
||||
0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
|
||||
0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
|
||||
0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
|
||||
0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
|
||||
0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
|
||||
0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
|
||||
keystream: vec!(
|
||||
0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
|
||||
0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
|
||||
0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
|
||||
0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
|
||||
0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
|
||||
0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
|
||||
0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
|
||||
0x44, 0x5f, 0x41, 0xe3,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
],
|
||||
nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
|
||||
keystream: vec!(
|
||||
0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
|
||||
0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
|
||||
0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
|
||||
0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
|
||||
0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
|
||||
0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
|
||||
0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
|
||||
0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
|
||||
),
|
||||
}, TestVector{
|
||||
key: [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
],
|
||||
nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
|
||||
keystream: vec!(
|
||||
0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
|
||||
0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
|
||||
0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
|
||||
0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
|
||||
0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
|
||||
0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
|
||||
0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
|
||||
0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
|
||||
0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
|
||||
0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
|
||||
0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
|
||||
0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
|
||||
0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
|
||||
0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
|
||||
0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
|
||||
0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
|
||||
0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
|
||||
0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
|
||||
0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
|
||||
0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
|
||||
0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
|
||||
0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
|
||||
0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
|
||||
0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
|
||||
0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
|
||||
0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
|
||||
0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
|
||||
0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
|
||||
0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
|
||||
0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
|
||||
0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
|
||||
0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
|
||||
),
|
||||
},
|
||||
);
|
||||
|
||||
for tv in test_vectors.iter() {
|
||||
let mut c = ChaCha20::new(&tv.key, &tv.nonce);
|
||||
let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
|
||||
let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
|
||||
c.process(&input[..], &mut output[..]);
|
||||
assert_eq!(output, tv.keystream);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,19 +12,15 @@
|
|||
|
||||
#[cfg(not(feature = "fuzztarget"))]
|
||||
mod real_chachapoly {
|
||||
use crypto::aead::{AeadEncryptor,AeadDecryptor};
|
||||
use crypto::symmetriccipher::SynchronousStreamCipher;
|
||||
use crypto::poly1305::Poly1305;
|
||||
use crypto::mac::Mac;
|
||||
use crypto::util::fixed_time_eq;
|
||||
|
||||
pub use crypto::chacha20::ChaCha20;
|
||||
use util::chacha20::ChaCha20;
|
||||
use util::poly1305::Poly1305;
|
||||
use bitcoin_hashes::cmp::fixed_time_eq;
|
||||
|
||||
use util::byte_utils;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ChaCha20Poly1305RFC {
|
||||
cipher : ChaCha20,
|
||||
cipher: ChaCha20,
|
||||
mac: Poly1305,
|
||||
finished: bool,
|
||||
data_len: usize,
|
||||
|
@ -62,10 +58,8 @@ mod real_chachapoly {
|
|||
aad_len: aad.len() as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AeadEncryptor for ChaCha20Poly1305RFC {
|
||||
fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
|
||||
pub fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
|
||||
assert!(input.len() == output.len());
|
||||
assert!(self.finished == false);
|
||||
self.cipher.process(input, output);
|
||||
|
@ -77,10 +71,8 @@ mod real_chachapoly {
|
|||
self.mac.input(&byte_utils::le64_to_array(self.data_len as u64));
|
||||
self.mac.raw_result(out_tag);
|
||||
}
|
||||
}
|
||||
|
||||
impl AeadDecryptor for ChaCha20Poly1305RFC {
|
||||
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
|
||||
pub fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
|
||||
assert!(input.len() == output.len());
|
||||
assert!(self.finished == false);
|
||||
|
||||
|
@ -105,13 +97,10 @@ mod real_chachapoly {
|
|||
}
|
||||
}
|
||||
#[cfg(not(feature = "fuzztarget"))]
|
||||
pub use self::real_chachapoly::{ChaCha20Poly1305RFC, ChaCha20};
|
||||
pub use self::real_chachapoly::ChaCha20Poly1305RFC;
|
||||
|
||||
#[cfg(feature = "fuzztarget")]
|
||||
mod fuzzy_chachapoly {
|
||||
use crypto::aead::{AeadEncryptor,AeadDecryptor};
|
||||
use crypto::symmetriccipher::SynchronousStreamCipher;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ChaCha20Poly1305RFC {
|
||||
tag: [u8; 16],
|
||||
|
@ -133,10 +122,8 @@ mod fuzzy_chachapoly {
|
|||
finished: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AeadEncryptor for ChaCha20Poly1305RFC {
|
||||
fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
|
||||
pub fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
|
||||
assert!(input.len() == output.len());
|
||||
assert!(self.finished == false);
|
||||
|
||||
|
@ -144,10 +131,8 @@ mod fuzzy_chachapoly {
|
|||
out_tag.copy_from_slice(&self.tag);
|
||||
self.finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
impl AeadDecryptor for ChaCha20Poly1305RFC {
|
||||
fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
|
||||
pub fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
|
||||
assert!(input.len() == output.len());
|
||||
assert!(self.finished == false);
|
||||
|
||||
|
@ -157,22 +142,6 @@ mod fuzzy_chachapoly {
|
|||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChaCha20 {}
|
||||
|
||||
impl ChaCha20 {
|
||||
pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
|
||||
assert!(key.len() == 16 || key.len() == 32);
|
||||
assert!(nonce.len() == 8 || nonce.len() == 12);
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl SynchronousStreamCipher for ChaCha20 {
|
||||
fn process(&mut self, input: &[u8], output: &mut [u8]) {
|
||||
output.copy_from_slice(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "fuzztarget")]
|
||||
pub use self::fuzzy_chachapoly::{ChaCha20Poly1305RFC, ChaCha20};
|
||||
pub use self::fuzzy_chachapoly::ChaCha20Poly1305RFC;
|
||||
|
|
|
@ -5,6 +5,8 @@ pub mod errors;
|
|||
pub mod ser;
|
||||
|
||||
pub(crate) mod byte_utils;
|
||||
pub(crate) mod chacha20;
|
||||
pub(crate) mod poly1305;
|
||||
pub(crate) mod chacha20poly1305rfc;
|
||||
pub(crate) mod internal_traits;
|
||||
pub(crate) mod rng;
|
||||
|
@ -19,11 +21,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};
|
||||
|
||||
|
|
340
src/util/poly1305.rs
Normal file
340
src/util/poly1305.rs
Normal file
|
@ -0,0 +1,340 @@
|
|||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// This is a port of Andrew Moons poly1305-donna
|
||||
// https://github.com/floodyberry/poly1305-donna
|
||||
|
||||
use std::cmp::min;
|
||||
use util::byte_utils::{slice_to_le32, le32_to_array};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Poly1305 {
|
||||
r : [u32; 5],
|
||||
h : [u32; 5],
|
||||
pad : [u32; 4],
|
||||
leftover : usize,
|
||||
buffer : [u8; 16],
|
||||
finalized : bool,
|
||||
}
|
||||
|
||||
impl Poly1305 {
|
||||
pub fn new(key: &[u8]) -> Poly1305 {
|
||||
assert!(key.len() == 32);
|
||||
let mut poly = Poly1305{ r: [0u32; 5], h: [0u32; 5], pad: [0u32; 4], leftover: 0, buffer: [0u8; 16], finalized: false };
|
||||
|
||||
// r &= 0xffffffc0ffffffc0ffffffc0fffffff
|
||||
poly.r[0] = (slice_to_le32(&key[0..4]) ) & 0x3ffffff;
|
||||
poly.r[1] = (slice_to_le32(&key[3..7]) >> 2) & 0x3ffff03;
|
||||
poly.r[2] = (slice_to_le32(&key[6..10]) >> 4) & 0x3ffc0ff;
|
||||
poly.r[3] = (slice_to_le32(&key[9..13]) >> 6) & 0x3f03fff;
|
||||
poly.r[4] = (slice_to_le32(&key[12..16]) >> 8) & 0x00fffff;
|
||||
|
||||
poly.pad[0] = slice_to_le32(&key[16..20]);
|
||||
poly.pad[1] = slice_to_le32(&key[20..24]);
|
||||
poly.pad[2] = slice_to_le32(&key[24..28]);
|
||||
poly.pad[3] = slice_to_le32(&key[28..32]);
|
||||
|
||||
poly
|
||||
}
|
||||
|
||||
fn block(&mut self, m: &[u8]) {
|
||||
let hibit : u32 = if self.finalized { 0 } else { 1 << 24 };
|
||||
|
||||
let r0 = self.r[0];
|
||||
let r1 = self.r[1];
|
||||
let r2 = self.r[2];
|
||||
let r3 = self.r[3];
|
||||
let r4 = self.r[4];
|
||||
|
||||
let s1 = r1 * 5;
|
||||
let s2 = r2 * 5;
|
||||
let s3 = r3 * 5;
|
||||
let s4 = r4 * 5;
|
||||
|
||||
let mut h0 = self.h[0];
|
||||
let mut h1 = self.h[1];
|
||||
let mut h2 = self.h[2];
|
||||
let mut h3 = self.h[3];
|
||||
let mut h4 = self.h[4];
|
||||
|
||||
// h += m
|
||||
h0 += (slice_to_le32(&m[0..4]) ) & 0x3ffffff;
|
||||
h1 += (slice_to_le32(&m[3..7]) >> 2) & 0x3ffffff;
|
||||
h2 += (slice_to_le32(&m[6..10]) >> 4) & 0x3ffffff;
|
||||
h3 += (slice_to_le32(&m[9..13]) >> 6) & 0x3ffffff;
|
||||
h4 += (slice_to_le32(&m[12..16]) >> 8) | hibit;
|
||||
|
||||
// h *= r
|
||||
let d0 = (h0 as u64 * r0 as u64) + (h1 as u64 * s4 as u64) + (h2 as u64 * s3 as u64) + (h3 as u64 * s2 as u64) + (h4 as u64 * s1 as u64);
|
||||
let mut d1 = (h0 as u64 * r1 as u64) + (h1 as u64 * r0 as u64) + (h2 as u64 * s4 as u64) + (h3 as u64 * s3 as u64) + (h4 as u64 * s2 as u64);
|
||||
let mut d2 = (h0 as u64 * r2 as u64) + (h1 as u64 * r1 as u64) + (h2 as u64 * r0 as u64) + (h3 as u64 * s4 as u64) + (h4 as u64 * s3 as u64);
|
||||
let mut d3 = (h0 as u64 * r3 as u64) + (h1 as u64 * r2 as u64) + (h2 as u64 * r1 as u64) + (h3 as u64 * r0 as u64) + (h4 as u64 * s4 as u64);
|
||||
let mut d4 = (h0 as u64 * r4 as u64) + (h1 as u64 * r3 as u64) + (h2 as u64 * r2 as u64) + (h3 as u64 * r1 as u64) + (h4 as u64 * r0 as u64);
|
||||
|
||||
// (partial) h %= p
|
||||
let mut c : u32;
|
||||
c = (d0 >> 26) as u32; h0 = d0 as u32 & 0x3ffffff;
|
||||
d1 += c as u64; c = (d1 >> 26) as u32; h1 = d1 as u32 & 0x3ffffff;
|
||||
d2 += c as u64; c = (d2 >> 26) as u32; h2 = d2 as u32 & 0x3ffffff;
|
||||
d3 += c as u64; c = (d3 >> 26) as u32; h3 = d3 as u32 & 0x3ffffff;
|
||||
d4 += c as u64; c = (d4 >> 26) as u32; h4 = d4 as u32 & 0x3ffffff;
|
||||
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
self.h[0] = h0;
|
||||
self.h[1] = h1;
|
||||
self.h[2] = h2;
|
||||
self.h[3] = h3;
|
||||
self.h[4] = h4;
|
||||
}
|
||||
|
||||
pub fn finish(&mut self) {
|
||||
if self.leftover > 0 {
|
||||
self.buffer[self.leftover] = 1;
|
||||
for i in self.leftover+1..16 {
|
||||
self.buffer[i] = 0;
|
||||
}
|
||||
self.finalized = true;
|
||||
let tmp = self.buffer;
|
||||
self.block(&tmp);
|
||||
}
|
||||
|
||||
// fully carry h
|
||||
let mut h0 = self.h[0];
|
||||
let mut h1 = self.h[1];
|
||||
let mut h2 = self.h[2];
|
||||
let mut h3 = self.h[3];
|
||||
let mut h4 = self.h[4];
|
||||
|
||||
let mut c : u32;
|
||||
c = h1 >> 26; h1 = h1 & 0x3ffffff;
|
||||
h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
|
||||
h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
|
||||
h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
|
||||
h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
|
||||
h1 += c;
|
||||
|
||||
// compute h + -p
|
||||
let mut g0 = h0.wrapping_add(5); c = g0 >> 26; g0 &= 0x3ffffff;
|
||||
let mut g1 = h1.wrapping_add(c); c = g1 >> 26; g1 &= 0x3ffffff;
|
||||
let mut g2 = h2.wrapping_add(c); c = g2 >> 26; g2 &= 0x3ffffff;
|
||||
let mut g3 = h3.wrapping_add(c); c = g3 >> 26; g3 &= 0x3ffffff;
|
||||
let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26);
|
||||
|
||||
// select h if h < p, or h + -p if h >= p
|
||||
let mut mask = (g4 >> (32 - 1)).wrapping_sub(1);
|
||||
g0 &= mask;
|
||||
g1 &= mask;
|
||||
g2 &= mask;
|
||||
g3 &= mask;
|
||||
g4 &= mask;
|
||||
mask = !mask;
|
||||
h0 = (h0 & mask) | g0;
|
||||
h1 = (h1 & mask) | g1;
|
||||
h2 = (h2 & mask) | g2;
|
||||
h3 = (h3 & mask) | g3;
|
||||
h4 = (h4 & mask) | g4;
|
||||
|
||||
// h = h % (2^128)
|
||||
h0 = ((h0 ) | (h1 << 26)) & 0xffffffff;
|
||||
h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff;
|
||||
h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
|
||||
h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff;
|
||||
|
||||
// h = mac = (h + pad) % (2^128)
|
||||
let mut f : u64;
|
||||
f = h0 as u64 + self.pad[0] as u64 ; h0 = f as u32;
|
||||
f = h1 as u64 + self.pad[1] as u64 + (f >> 32); h1 = f as u32;
|
||||
f = h2 as u64 + self.pad[2] as u64 + (f >> 32); h2 = f as u32;
|
||||
f = h3 as u64 + self.pad[3] as u64 + (f >> 32); h3 = f as u32;
|
||||
|
||||
self.h[0] = h0;
|
||||
self.h[1] = h1;
|
||||
self.h[2] = h2;
|
||||
self.h[3] = h3;
|
||||
}
|
||||
|
||||
pub fn input(&mut self, data: &[u8]) {
|
||||
assert!(!self.finalized);
|
||||
let mut m = data;
|
||||
|
||||
if self.leftover > 0 {
|
||||
let want = min(16 - self.leftover, m.len());
|
||||
for i in 0..want {
|
||||
self.buffer[self.leftover+i] = m[i];
|
||||
}
|
||||
m = &m[want..];
|
||||
self.leftover += want;
|
||||
|
||||
if self.leftover < 16 {
|
||||
return;
|
||||
}
|
||||
|
||||
// self.block(self.buffer[..]);
|
||||
let tmp = self.buffer;
|
||||
self.block(&tmp);
|
||||
|
||||
self.leftover = 0;
|
||||
}
|
||||
|
||||
while m.len() >= 16 {
|
||||
self.block(&m[0..16]);
|
||||
m = &m[16..];
|
||||
}
|
||||
|
||||
for i in 0..m.len() {
|
||||
self.buffer[i] = m[i];
|
||||
}
|
||||
self.leftover = m.len();
|
||||
}
|
||||
|
||||
pub fn raw_result(&mut self, output: &mut [u8]) {
|
||||
assert!(output.len() >= 16);
|
||||
if !self.finalized{
|
||||
self.finish();
|
||||
}
|
||||
output[0..4].copy_from_slice(&le32_to_array(self.h[0]));
|
||||
output[4..8].copy_from_slice(&le32_to_array(self.h[1]));
|
||||
output[8..12].copy_from_slice(&le32_to_array(self.h[2]));
|
||||
output[12..16].copy_from_slice(&le32_to_array(self.h[3]));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::iter::repeat;
|
||||
|
||||
use util::poly1305::Poly1305;
|
||||
|
||||
fn poly1305(key: &[u8], msg: &[u8], mac: &mut [u8]) {
|
||||
let mut poly = Poly1305::new(key);
|
||||
poly.input(msg);
|
||||
poly.raw_result(mac);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nacl_vector() {
|
||||
let key = [
|
||||
0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91,
|
||||
0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25,
|
||||
0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65,
|
||||
0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80,
|
||||
];
|
||||
|
||||
let msg = [
|
||||
0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
|
||||
0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
|
||||
0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
|
||||
0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
|
||||
0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
|
||||
0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
|
||||
0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
|
||||
0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
|
||||
0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
|
||||
0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
|
||||
0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
|
||||
0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
|
||||
0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
|
||||
0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
|
||||
0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
|
||||
0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
|
||||
0xe3,0x55,0xa5,
|
||||
];
|
||||
|
||||
let expected = [
|
||||
0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
|
||||
0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
|
||||
];
|
||||
|
||||
let mut mac = [0u8; 16];
|
||||
poly1305(&key, &msg, &mut mac);
|
||||
assert_eq!(&mac[..], &expected[..]);
|
||||
|
||||
let mut poly = Poly1305::new(&key);
|
||||
poly.input(&msg[0..32]);
|
||||
poly.input(&msg[32..96]);
|
||||
poly.input(&msg[96..112]);
|
||||
poly.input(&msg[112..120]);
|
||||
poly.input(&msg[120..124]);
|
||||
poly.input(&msg[124..126]);
|
||||
poly.input(&msg[126..127]);
|
||||
poly.input(&msg[127..128]);
|
||||
poly.input(&msg[128..129]);
|
||||
poly.input(&msg[129..130]);
|
||||
poly.input(&msg[130..131]);
|
||||
poly.raw_result(&mut mac);
|
||||
assert_eq!(&mac[..], &expected[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn donna_self_test() {
|
||||
let wrap_key = [
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
];
|
||||
|
||||
let wrap_msg = [
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
];
|
||||
|
||||
let wrap_mac = [
|
||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
];
|
||||
|
||||
let mut mac = [0u8; 16];
|
||||
poly1305(&wrap_key, &wrap_msg, &mut mac);
|
||||
assert_eq!(&mac[..], &wrap_mac[..]);
|
||||
|
||||
let total_key = [
|
||||
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff,
|
||||
0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
];
|
||||
|
||||
let total_mac = [
|
||||
0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
|
||||
0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39,
|
||||
];
|
||||
|
||||
let mut tpoly = Poly1305::new(&total_key);
|
||||
for i in 0..256 {
|
||||
let key: Vec<u8> = repeat(i as u8).take(32).collect();
|
||||
let msg: Vec<u8> = repeat(i as u8).take(256).collect();
|
||||
let mut mac = [0u8; 16];
|
||||
poly1305(&key[..], &msg[0..i], &mut mac);
|
||||
tpoly.input(&mac);
|
||||
}
|
||||
tpoly.raw_result(&mut mac);
|
||||
assert_eq!(&mac[..], &total_mac[..]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tls_vectors() {
|
||||
// from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
|
||||
let key = b"this is 32-byte key for Poly1305";
|
||||
let msg = [0u8; 32];
|
||||
let expected = [
|
||||
0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6,
|
||||
0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07,
|
||||
];
|
||||
let mut mac = [0u8; 16];
|
||||
poly1305(key, &msg, &mut mac);
|
||||
assert_eq!(&mac[..], &expected[..]);
|
||||
|
||||
let msg = b"Hello world!";
|
||||
let expected= [
|
||||
0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16,
|
||||
0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0,
|
||||
];
|
||||
poly1305(key, msg, &mut mac);
|
||||
assert_eq!(&mac[..], &expected[..]);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
uint32_t rust_crypto_util_fixed_time_eq_asm(uint8_t* lhsp, uint8_t* rhsp, size_t count) {
|
||||
if (count == 0) {
|
||||
return 1;
|
||||
}
|
||||
uint8_t result = 0;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
result |= (lhsp[i] ^ rhsp[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -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;
|
Loading…
Add table
Reference in a new issue