X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fchacha20.rs;h=e8c6e229c1c00129cc22ace046845c1d6b5e5922;hb=c7e198e6fca8fc31e004b51368978b109c1caff6;hp=c96577da02c4a31ec1a3827b0ac38d9003e1a831;hpb=9f30b305e6ee9c411f1f14aaded665b5001d994f;p=rust-lightning diff --git a/lightning/src/util/chacha20.rs b/lightning/src/util/chacha20.rs index c96577da..e8c6e229 100644 --- a/lightning/src/util/chacha20.rs +++ b/lightning/src/util/chacha20.rs @@ -2,22 +2,24 @@ // 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 { - use std::cmp; + use core::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 { + impl ::core::ops::Add for u32x4 { type Output = u32x4; fn add(self, rhs: u32x4) -> u32x4 { u32x4(self.0.wrapping_add(rhs.0), @@ -26,7 +28,7 @@ mod real_chacha { self.3.wrapping_add(rhs.3)) } } - impl ::std::ops::Sub for u32x4 { + impl ::core::ops::Sub for u32x4 { type Output = u32x4; fn sub(self, rhs: u32x4) -> u32x4 { u32x4(self.0.wrapping_sub(rhs.0), @@ -35,25 +37,27 @@ mod real_chacha { self.3.wrapping_sub(rhs.3)) } } - impl ::std::ops::BitXor for u32x4 { + impl ::core::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 for u32x4 { + impl ::core::ops::Shr 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 for u32x4 { + impl ::core::ops::Shl 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) } } + 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; @@ -232,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); @@ -249,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"))] @@ -268,14 +295,30 @@ 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; + use core::iter::repeat; use super::ChaCha20; @@ -285,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{ @@ -420,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{