ring/aead/
block.rs

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
15use crate::polyfill::ArrayFlatten;
16use core::ops::{BitXor, BitXorAssign};
17
18#[repr(transparent)]
19#[derive(Copy, Clone)]
20pub struct Block([u8; 16]);
21
22pub const BLOCK_LEN: usize = 16;
23
24impl Block {
25    #[inline]
26    pub fn zero() -> Self {
27        Self([0; 16])
28    }
29
30    #[inline]
31    pub fn overwrite_part_at(&mut self, index: usize, a: &[u8]) {
32        let mut tmp: [u8; BLOCK_LEN] = *self.as_ref();
33        tmp[index..][..a.len()].copy_from_slice(a);
34        *self = Self::from(&tmp)
35    }
36
37    #[inline]
38    pub fn zero_from(&mut self, index: usize) {
39        let mut tmp: [u8; BLOCK_LEN] = *self.as_ref();
40        tmp[index..].fill(0);
41        *self = Self::from(&tmp)
42    }
43}
44
45impl BitXorAssign for Block {
46    #[inline]
47    fn bitxor_assign(&mut self, a: Self) {
48        // Relies heavily on optimizer to optimize this into word- or vector-
49        // level XOR.
50        for (r, a) in self.0.iter_mut().zip(a.0.iter()) {
51            *r ^= *a;
52        }
53    }
54}
55
56impl BitXor for Block {
57    type Output = Self;
58
59    #[inline]
60    fn bitxor(self, a: Self) -> Self {
61        let mut r = self;
62        r.bitxor_assign(a);
63        r
64    }
65}
66
67impl<T> From<T> for Block
68where
69    T: ArrayFlatten<Output = [u8; 16]>,
70{
71    #[inline]
72    fn from(bytes: T) -> Self {
73        Self(bytes.array_flatten())
74    }
75}
76
77impl From<&'_ [u8; BLOCK_LEN]> for Block {
78    #[inline]
79    fn from(bytes: &[u8; BLOCK_LEN]) -> Self {
80        Self(*bytes)
81    }
82}
83
84impl AsRef<[u8; BLOCK_LEN]> for Block {
85    #[inline]
86    fn as_ref(&self) -> &[u8; BLOCK_LEN] {
87        &self.0
88    }
89}