X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fchacha20.rs;h=c23856b60c8d69fb412e04f2eb3934b8ac29ff35;hb=0d75a63ead0601ae36e7141834f67c881c31eb85;hp=dd90b20f694587f754e1f6e7fe16ecc13db4892d;hpb=88fef649b15fa030cb91de76d58346a0bc408834;p=rust-lightning diff --git a/lightning/src/util/chacha20.rs b/lightning/src/util/chacha20.rs index dd90b20f..c23856b6 100644 --- a/lightning/src/util/chacha20.rs +++ b/lightning/src/util/chacha20.rs @@ -2,12 +2,14 @@ // 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. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +use std::io; #[cfg(not(feature = "fuzztarget"))] mod real_chacha { @@ -54,6 +56,8 @@ mod real_chacha { } } + const BLOCK_SIZE: usize = 64; + #[derive(Clone,Copy)] struct ChaChaState { a: u32x4, @@ -65,7 +69,7 @@ mod real_chacha { #[derive(Copy)] pub struct ChaCha20 { state : ChaChaState, - output : [u8; 64], + output : [u8; BLOCK_SIZE], offset : usize, } @@ -133,7 +137,7 @@ mod real_chacha { 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 } + ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 } } fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState { @@ -195,7 +199,7 @@ mod real_chacha { } } - // put the the next 64 keystream bytes into self.output + // put the the next BLOCK_SIZE keystream bytes into self.output fn update(&mut self) { let mut state = self.state; @@ -224,6 +228,7 @@ mod real_chacha { self.offset = 0; } + #[inline] // Useful cause input may be 0s on stack that should be optimized out pub fn process(&mut self, input: &[u8], output: &mut [u8]) { assert!(input.len() == output.len()); let len = input.len(); @@ -231,12 +236,12 @@ mod real_chacha { while i < len { // If there is no keystream available in the output buffer, // generate the next block. - if self.offset == 64 { + if self.offset == BLOCK_SIZE { self.update(); } // Process the min(available keystream, remaining input length). - let count = cmp::min(64 - self.offset, len - i); + let count = cmp::min(BLOCK_SIZE - self.offset, len - i); // explicitly assert lengths to avoid bounds checks: assert!(output.len() >= i + count); assert!(input.len() >= i + count); @@ -248,6 +253,29 @@ mod real_chacha { self.offset += count; } } + + pub fn process_in_place(&mut self, input_output: &mut [u8]) { + let len = input_output.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 == BLOCK_SIZE { + self.update(); + } + + // Process the min(available keystream, remaining input length). + let count = cmp::min(BLOCK_SIZE - self.offset, len - i); + // explicitly assert lengths to avoid bounds checks: + assert!(input_output.len() >= i + count); + assert!(self.output.len() >= self.offset + count); + for j in 0..count { + input_output[i + j] ^= self.output[self.offset + j]; + } + i += count; + self.offset += count; + } + } } } #[cfg(not(feature = "fuzztarget"))] @@ -267,11 +295,27 @@ mod fuzzy_chacha { pub fn process(&mut self, input: &[u8], output: &mut [u8]) { output.copy_from_slice(input); } + + pub fn process_in_place(&mut self, _input_output: &mut [u8]) {} } } #[cfg(feature = "fuzztarget")] pub use self::fuzzy_chacha::ChaCha20; +pub(crate) struct ChaChaReader<'a, R: io::Read> { + pub chacha: &'a mut ChaCha20, + pub read: R, +} +impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> { + fn read(&mut self, dest: &mut [u8]) -> Result { + let res = self.read.read(dest)?; + if res > 0 { + self.chacha.process_in_place(&mut dest[0..res]); + } + Ok(res) + } +} + #[cfg(test)] mod test { use std::iter::repeat; @@ -284,7 +328,7 @@ mod test { key: [u8; 32], nonce: [u8; 8], keystream: Vec, - }; + } // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 let test_vectors = vec!( TestVector{ @@ -419,7 +463,7 @@ mod test { key: [u8; 32], nonce: [u8; 12], keystream: Vec, - }; + } // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 let test_vectors = vec!( TestVector{