diff --git a/src/librustpkg/cryptoutil.rs b/src/librustpkg/cryptoutil.rs index dfed31bad9f5c..55199b1f2cc76 100644 --- a/src/librustpkg/cryptoutil.rs +++ b/src/librustpkg/cryptoutil.rs @@ -8,22 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::num::{One, Zero, CheckedAdd}; +use std::num::{Zero, CheckedAdd}; use std::vec::bytes::{MutableByteVector, copy_memory}; -/// Write a u64 into a vector, which must be 8 bytes long. The value is written in big-endian -/// format. -pub fn write_u64_be(dst: &mut[u8], input: u64) { - use std::cast::transmute; - use std::unstable::intrinsics::to_be64; - assert!(dst.len() == 8); - unsafe { - let x: *mut i64 = transmute(dst.unsafe_mut_ref(0)); - *x = to_be64(input as i64); - } -} - /// Write a u32 into a vector, which must be 4 bytes long. The value is written in big-endian /// format. pub fn write_u32_be(dst: &mut[u8], input: u32) { @@ -36,34 +24,6 @@ pub fn write_u32_be(dst: &mut[u8], input: u32) { } } -/// Write a u32 into a vector, which must be 4 bytes long. The value is written in little-endian -/// format. -pub fn write_u32_le(dst: &mut[u8], input: u32) { - use std::cast::transmute; - use std::unstable::intrinsics::to_le32; - assert!(dst.len() == 4); - unsafe { - let x: *mut i32 = transmute(dst.unsafe_mut_ref(0)); - *x = to_le32(input as i32); - } -} - -/// Read a vector of bytes into a vector of u64s. The values are read in big-endian format. -pub fn read_u64v_be(dst: &mut[u64], input: &[u8]) { - use std::cast::transmute; - use std::unstable::intrinsics::to_be64; - assert!(dst.len() * 8 == input.len()); - unsafe { - let mut x: *mut i64 = transmute(dst.unsafe_mut_ref(0)); - let mut y: *i64 = transmute(input.unsafe_ref(0)); - do dst.len().times() { - *x = to_be64(*y); - x = x.offset(1); - y = y.offset(1); - } - } -} - /// Read a vector of bytes into a vector of u32s. The values are read in big-endian format. pub fn read_u32v_be(dst: &mut[u32], input: &[u8]) { use std::cast::transmute; @@ -80,22 +40,6 @@ pub fn read_u32v_be(dst: &mut[u32], input: &[u8]) { } } -/// Read a vector of bytes into a vector of u32s. The values are read in little-endian format. -pub fn read_u32v_le(dst: &mut[u32], input: &[u8]) { - use std::cast::transmute; - use std::unstable::intrinsics::to_le32; - assert!(dst.len() * 4 == input.len()); - unsafe { - let mut x: *mut i32 = transmute(dst.unsafe_mut_ref(0)); - let mut y: *i32 = transmute(input.unsafe_ref(0)); - do dst.len().times() { - *x = to_le32(*y); - x = x.offset(1); - y = y.offset(1); - } - } -} - trait ToBits { /// Convert the value in bytes to the number of bits, a tuple where the 1st item is the @@ -124,51 +68,6 @@ pub fn add_bytes_to_bits(bits: T, bytes: T) -> T { } } -/// Adds the specified number of bytes to the bit count, which is a tuple where the first element is -/// the high order value. fail!() if this would cause numeric overflow. -pub fn add_bytes_to_bits_tuple - - (bits: (T, T), bytes: T) -> (T, T) { - let (new_high_bits, new_low_bits) = bytes.to_bits(); - let (hi, low) = bits; - - // Add the low order value - if there is no overflow, then add the high order values - // If the addition of the low order values causes overflow, add one to the high order values - // before adding them. - match low.checked_add(&new_low_bits) { - Some(x) => { - if new_high_bits == Zero::zero() { - // This is the fast path - every other alternative will rarely occur in practice - // considering how large an input would need to be for those paths to be used. - return (hi, x); - } else { - match hi.checked_add(&new_high_bits) { - Some(y) => return (y, x), - None => fail!("Numeric overflow occured.") - } - } - }, - None => { - let one: T = One::one(); - let z = match new_high_bits.checked_add(&one) { - Some(w) => w, - None => fail!("Numeric overflow occured.") - }; - match hi.checked_add(&z) { - // This re-executes the addition that was already performed earlier when overflow - // occured, this time allowing the overflow to happen. Technically, this could be - // avoided by using the checked add intrinsic directly, but that involves using - // unsafe code and is not really worthwhile considering how infrequently code will - // run in practice. This is the reason that this function requires that the type T - // be Unsigned - overflow is not defined for Signed types. This function could be - // implemented for signed types as well if that were needed. - Some(y) => return (y, low + new_low_bits), - None => fail!("Numeric overflow occured.") - } - } - } -} - /// A FixedBuffer, likes its name implies, is a fixed size buffer. When the buffer becomes full, it /// must be processed. The input() method takes care of processing and then clearing the buffer @@ -204,83 +103,6 @@ pub trait FixedBuffer { fn size(&self) -> uint; } -macro_rules! impl_fixed_buffer( ($name:ident, $size:expr) => ( - impl FixedBuffer for $name { - fn input(&mut self, input: &[u8], func: &fn(&[u8])) { - let mut i = 0; - - // FIXME: #6304 - This local variable shouldn't be necessary. - let size = $size; - - // If there is already data in the buffer, copy as much as we can into it and process - // the data if the buffer becomes full. - if self.buffer_idx != 0 { - let buffer_remaining = size - self.buffer_idx; - if input.len() >= buffer_remaining { - copy_memory( - self.buffer.mut_slice(self.buffer_idx, size), - input.slice_to(buffer_remaining), - buffer_remaining); - self.buffer_idx = 0; - func(self.buffer); - i += buffer_remaining; - } else { - copy_memory( - self.buffer.mut_slice(self.buffer_idx, self.buffer_idx + input.len()), - input, - input.len()); - self.buffer_idx += input.len(); - return; - } - } - - // While we have at least a full buffer size chunks's worth of data, process that data - // without copying it into the buffer - while input.len() - i >= size { - func(input.slice(i, i + size)); - i += size; - } - - // Copy any input data into the buffer. At this point in the method, the ammount of - // data left in the input vector will be less than the buffer size and the buffer will - // be empty. - let input_remaining = input.len() - i; - copy_memory( - self.buffer.mut_slice(0, input_remaining), - input.slice_from(i), - input.len() - i); - self.buffer_idx += input_remaining; - } - - fn reset(&mut self) { - self.buffer_idx = 0; - } - - fn zero_until(&mut self, idx: uint) { - assert!(idx >= self.buffer_idx); - self.buffer.mut_slice(self.buffer_idx, idx).set_memory(0); - self.buffer_idx = idx; - } - - fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8] { - self.buffer_idx += len; - return self.buffer.mut_slice(self.buffer_idx - len, self.buffer_idx); - } - - fn full_buffer<'s>(&'s mut self) -> &'s [u8] { - assert!(self.buffer_idx == $size); - self.buffer_idx = 0; - return self.buffer.slice_to($size); - } - - fn position(&self) -> uint { self.buffer_idx } - - fn remaining(&self) -> uint { $size - self.buffer_idx } - - fn size(&self) -> uint { $size } - } -)) - /// A fixed size buffer of 64 bytes useful for cryptographic operations. pub struct FixedBuffer64 { @@ -298,25 +120,80 @@ impl FixedBuffer64 { } } -impl_fixed_buffer!(FixedBuffer64, 64) +impl FixedBuffer for FixedBuffer64 { + fn input(&mut self, input: &[u8], func: &fn(&[u8])) { + let mut i = 0; -/// A fixed size buffer of 128 bytes useful for cryptographic operations. -pub struct FixedBuffer128 { - priv buffer: [u8, ..128], - priv buffer_idx: uint, -} + // FIXME: #6304 - This local variable shouldn't be necessary. + let size = 64; -impl FixedBuffer128 { - /// Create a new buffer - pub fn new() -> FixedBuffer128 { - return FixedBuffer128 { - buffer: [0u8, ..128], - buffer_idx: 0 - }; + // If there is already data in the buffer, copy as much as we can into it and process + // the data if the buffer becomes full. + if self.buffer_idx != 0 { + let buffer_remaining = size - self.buffer_idx; + if input.len() >= buffer_remaining { + copy_memory( + self.buffer.mut_slice(self.buffer_idx, size), + input.slice_to(buffer_remaining), + buffer_remaining); + self.buffer_idx = 0; + func(self.buffer); + i += buffer_remaining; + } else { + copy_memory( + self.buffer.mut_slice(self.buffer_idx, self.buffer_idx + input.len()), + input, + input.len()); + self.buffer_idx += input.len(); + return; + } + } + + // While we have at least a full buffer size chunks's worth of data, process that data + // without copying it into the buffer + while input.len() - i >= size { + func(input.slice(i, i + size)); + i += size; + } + + // Copy any input data into the buffer. At this point in the method, the ammount of + // data left in the input vector will be less than the buffer size and the buffer will + // be empty. + let input_remaining = input.len() - i; + copy_memory( + self.buffer.mut_slice(0, input_remaining), + input.slice_from(i), + input.len() - i); + self.buffer_idx += input_remaining; + } + + fn reset(&mut self) { + self.buffer_idx = 0; + } + + fn zero_until(&mut self, idx: uint) { + assert!(idx >= self.buffer_idx); + self.buffer.mut_slice(self.buffer_idx, idx).set_memory(0); + self.buffer_idx = idx; + } + + fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8] { + self.buffer_idx += len; + return self.buffer.mut_slice(self.buffer_idx - len, self.buffer_idx); } -} -impl_fixed_buffer!(FixedBuffer128, 128) + fn full_buffer<'s>(&'s mut self) -> &'s [u8] { + assert!(self.buffer_idx == 64); + self.buffer_idx = 0; + return self.buffer.slice_to(64); + } + + fn position(&self) -> uint { self.buffer_idx } + + fn remaining(&self) -> uint { 64 - self.buffer_idx } + + fn size(&self) -> uint { 64 } +} /// The StandardPadding trait adds a method useful for various hash algorithms to a FixedBuffer @@ -351,7 +228,7 @@ pub mod test { use std::vec; use extra::hex::FromHex; - use cryptoutil::{add_bytes_to_bits, add_bytes_to_bits_tuple}; + use cryptoutil::add_bytes_to_bits; use digest::Digest; /// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is @@ -391,38 +268,4 @@ pub mod test { fn test_add_bytes_to_bits_overflow() { add_bytes_to_bits::(Bounded::max_value(), 1); } - - // A normal addition - no overflow occurs (fast path) - #[test] - fn test_add_bytes_to_bits_tuple_ok() { - assert!(add_bytes_to_bits_tuple::((5, 100), 10) == (5, 180)); - } - - // The low order value overflows into the high order value - #[test] - fn test_add_bytes_to_bits_tuple_ok2() { - assert!(add_bytes_to_bits_tuple::((5, Bounded::max_value()), 1) == (6, 7)); - } - - // The value to add is too large to be converted into bits without overflowing its type - #[test] - fn test_add_bytes_to_bits_tuple_ok3() { - assert!(add_bytes_to_bits_tuple::((5, 0), 0x4000000000000001) == (7, 8)); - } - - // A simple failure case - adding 1 to the max value - #[test] - #[should_fail] - fn test_add_bytes_to_bits_tuple_overflow() { - add_bytes_to_bits_tuple::((Bounded::max_value(), Bounded::max_value()), 1); - } - - // The value to add is too large to convert to bytes without overflowing its type, but the high - // order value from this conversion overflows when added to the existing high order value - #[test] - #[should_fail] - fn test_add_bytes_to_bits_tuple_overflow2() { - let value: u64 = Bounded::max_value(); - add_bytes_to_bits_tuple::((value - 1, 0), 0x8000000000000000); - } } diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs index 89a7bfae86a93..229eecffbea05 100644 --- a/src/librustpkg/rustpkg.rs +++ b/src/librustpkg/rustpkg.rs @@ -18,7 +18,7 @@ #[license = "MIT/ASL2"]; #[crate_type = "lib"]; -#[feature(globs, managed_boxes, macro_rules)]; +#[feature(globs, managed_boxes)]; extern mod extra; extern mod rustc;