Skip to main content

aws_lc_rs/
iv.rs

1// Copyright 2018 Brian Smith.
2// SPDX-License-Identifier: ISC
3// Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4// SPDX-License-Identifier: Apache-2.0 OR ISC
5#![allow(dead_code)]
6
7//! Initialization Vector (IV) cryptographic primitives
8
9use crate::error::Unspecified;
10use crate::rand;
11use zeroize::Zeroize;
12
13/// Length of a 64-bit IV in bytes (used by DES/3DES).
14#[cfg(feature = "legacy-des")]
15pub(crate) const IV_LEN_64_BIT: usize = 8;
16
17/// Length of a 128-bit IV in bytes.
18pub const IV_LEN_128_BIT: usize = 16;
19
20/// An initialization vector that must be unique for the lifetime of the associated key
21/// it is used with.
22pub struct FixedLength<const L: usize>([u8; L]);
23
24impl<const L: usize> FixedLength<L> {
25    /// Returns the size of the iv in bytes.
26    #[allow(clippy::must_use_candidate)]
27    pub fn size(&self) -> usize {
28        L
29    }
30
31    /// Constructs a new [`FixedLength`] from pseudo-random bytes.
32    ///
33    /// # Errors
34    ///
35    /// * [`Unspecified`]: Returned if there is a failure generating `L` bytes.
36    pub fn new() -> Result<Self, Unspecified> {
37        let mut iv_bytes = [0u8; L];
38        rand::fill(&mut iv_bytes)?;
39        Ok(Self(iv_bytes))
40    }
41}
42
43impl<const L: usize> Drop for FixedLength<L> {
44    fn drop(&mut self) {
45        self.0.zeroize();
46    }
47}
48
49impl<const L: usize> AsRef<[u8; L]> for FixedLength<L> {
50    #[inline]
51    fn as_ref(&self) -> &[u8; L] {
52        &self.0
53    }
54}
55
56impl<const L: usize> From<&[u8; L]> for FixedLength<L> {
57    #[inline]
58    fn from(bytes: &[u8; L]) -> Self {
59        FixedLength(bytes.to_owned())
60    }
61}
62
63impl<const L: usize> From<[u8; L]> for FixedLength<L> {
64    #[inline]
65    fn from(bytes: [u8; L]) -> Self {
66        FixedLength(bytes)
67    }
68}
69
70impl<const L: usize> TryFrom<&[u8]> for FixedLength<L> {
71    type Error = Unspecified;
72
73    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
74        let value: &[u8; L] = value.try_into()?;
75        Ok(Self::from(*value))
76    }
77}
78
79impl<const L: usize> TryFrom<FixedLength<L>> for [u8; L] {
80    type Error = Unspecified;
81
82    fn try_from(value: FixedLength<L>) -> Result<Self, Self::Error> {
83        Ok(value.0)
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use crate::iv::FixedLength;
90
91    #[test]
92    fn test_size() {
93        let fixed = FixedLength::from([0u8; 16]);
94        assert_eq!(16, fixed.size());
95
96        let array = [0u8; 12];
97        let fixed = FixedLength::<12>::try_from(array.as_slice()).unwrap();
98        assert_eq!(12, fixed.size());
99
100        assert!(FixedLength::<16>::try_from(array.as_slice()).is_err());
101
102        assert!(TryInto::<[u8; 12]>::try_into(fixed).is_ok());
103    }
104}