1 // Copyright 2018 Brian Smith. 2 // 3 // Permission to use, copy, modify, and/or distribute this software for any 4 // purpose with or without fee is hereby granted, provided that the above 5 // copyright notice and this permission notice appear in all copies. 6 // 7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 use crate::{endian::*, polyfill}; 16 17 /// An array of 16 bytes that can (in the x86_64 and AAarch64 ABIs, at least) 18 /// be efficiently passed by value and returned by value (i.e. in registers), 19 /// and which meets the alignment requirements of `u32` and `u64` (at least) 20 /// for the target. 21 #[repr(C)] 22 #[derive(Copy, Clone)] 23 pub struct Block { 24 subblocks: [u64; 2], 25 } 26 27 pub const BLOCK_LEN: usize = 16; 28 29 impl Block { 30 #[inline] zero() -> Self31 pub fn zero() -> Self { 32 Self { subblocks: [0, 0] } 33 } 34 35 // TODO: Remove this. 36 #[inline] from_u64_le(first: LittleEndian<u64>, second: LittleEndian<u64>) -> Self37 pub fn from_u64_le(first: LittleEndian<u64>, second: LittleEndian<u64>) -> Self { 38 #[allow(deprecated)] 39 Self { 40 subblocks: [first.into_raw_value(), second.into_raw_value()], 41 } 42 } 43 44 // TODO: Remove this. 45 #[inline] from_u64_be(first: BigEndian<u64>, second: BigEndian<u64>) -> Self46 pub fn from_u64_be(first: BigEndian<u64>, second: BigEndian<u64>) -> Self { 47 #[allow(deprecated)] 48 Self { 49 subblocks: [first.into_raw_value(), second.into_raw_value()], 50 } 51 } 52 u64s_be_to_native(&self) -> [u64; 2]53 pub fn u64s_be_to_native(&self) -> [u64; 2] { 54 [ 55 u64::from_be(self.subblocks[0]), 56 u64::from_be(self.subblocks[1]), 57 ] 58 } 59 60 #[inline] overwrite_part_at(&mut self, index: usize, a: &[u8])61 pub fn overwrite_part_at(&mut self, index: usize, a: &[u8]) { 62 let mut tmp: [u8; BLOCK_LEN] = *self.as_ref(); 63 tmp[index..][..a.len()].copy_from_slice(a); 64 *self = Self::from(&tmp) 65 } 66 67 #[inline] zero_from(&mut self, index: usize)68 pub fn zero_from(&mut self, index: usize) { 69 let mut tmp: [u8; BLOCK_LEN] = *self.as_ref(); 70 polyfill::slice::fill(&mut tmp[index..], 0); 71 *self = Self::from(&tmp) 72 } 73 74 #[inline] bitxor_assign(&mut self, a: Block)75 pub fn bitxor_assign(&mut self, a: Block) { 76 for (r, a) in self.subblocks.iter_mut().zip(a.subblocks.iter()) { 77 *r ^= *a; 78 } 79 } 80 } 81 82 impl From<&'_ [u8; BLOCK_LEN]> for Block { 83 #[inline] from(bytes: &[u8; BLOCK_LEN]) -> Self84 fn from(bytes: &[u8; BLOCK_LEN]) -> Self { 85 unsafe { core::mem::transmute_copy(bytes) } 86 } 87 } 88 89 impl AsRef<[u8; BLOCK_LEN]> for Block { 90 #[allow(clippy::transmute_ptr_to_ptr)] 91 #[inline] as_ref(&self) -> &[u8; BLOCK_LEN]92 fn as_ref(&self) -> &[u8; BLOCK_LEN] { 93 unsafe { core::mem::transmute(self) } 94 } 95 } 96 97 #[cfg(test)] 98 mod tests { 99 use super::*; 100 101 #[test] test_bitxor_assign()102 fn test_bitxor_assign() { 103 const ONES: u64 = -1i64 as u64; 104 const TEST_CASES: &[([u64; 2], [u64; 2], [u64; 2])] = &[ 105 ([0, 0], [0, 0], [0, 0]), 106 ([0, 0], [ONES, ONES], [ONES, ONES]), 107 ([0, ONES], [ONES, 0], [ONES, ONES]), 108 ([ONES, 0], [0, ONES], [ONES, ONES]), 109 ([ONES, ONES], [ONES, ONES], [0, 0]), 110 ]; 111 for (expected_result, a, b) in TEST_CASES { 112 let mut r = Block::from_u64_le(a[0].into(), a[1].into()); 113 r.bitxor_assign(Block::from_u64_le(b[0].into(), b[1].into())); 114 assert_eq!(*expected_result, r.subblocks); 115 116 // XOR is symmetric. 117 let mut r = Block::from_u64_le(b[0].into(), b[1].into()); 118 r.bitxor_assign(Block::from_u64_le(a[0].into(), a[1].into())); 119 assert_eq!(*expected_result, r.subblocks); 120 } 121 } 122 } 123