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 128-bit IV in bytes.
14pub const IV_LEN_128_BIT: usize = 16;
15
16/// An initialization vector that must be unique for the lifetime of the associated key
17/// it is used with.
18pub struct FixedLength<const L: usize>([u8; L]);
19
20impl<const L: usize> FixedLength<L> {
21    /// Returns the size of the iv in bytes.
22    #[allow(clippy::must_use_candidate)]
23    pub fn size(&self) -> usize {
24        L
25    }
26
27    /// Constructs a new [`FixedLength`] from pseudo-random bytes.
28    ///
29    /// # Errors
30    ///
31    /// * [`Unspecified`]: Returned if there is a failure generating `L` bytes.
32    pub fn new() -> Result<Self, Unspecified> {
33        let mut iv_bytes = [0u8; L];
34        rand::fill(&mut iv_bytes)?;
35        Ok(Self(iv_bytes))
36    }
37}
38
39impl<const L: usize> Drop for FixedLength<L> {
40    fn drop(&mut self) {
41        self.0.zeroize();
42    }
43}
44
45impl<const L: usize> AsRef<[u8; L]> for FixedLength<L> {
46    #[inline]
47    fn as_ref(&self) -> &[u8; L] {
48        &self.0
49    }
50}
51
52impl<const L: usize> From<&[u8; L]> for FixedLength<L> {
53    #[inline]
54    fn from(bytes: &[u8; L]) -> Self {
55        FixedLength(bytes.to_owned())
56    }
57}
58
59impl<const L: usize> From<[u8; L]> for FixedLength<L> {
60    #[inline]
61    fn from(bytes: [u8; L]) -> Self {
62        FixedLength(bytes)
63    }
64}
65
66impl<const L: usize> TryFrom<&[u8]> for FixedLength<L> {
67    type Error = Unspecified;
68
69    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
70        let value: &[u8; L] = value.try_into()?;
71        Ok(Self::from(*value))
72    }
73}
74
75impl<const L: usize> TryFrom<FixedLength<L>> for [u8; L] {
76    type Error = Unspecified;
77
78    fn try_from(value: FixedLength<L>) -> Result<Self, Self::Error> {
79        Ok(value.0)
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use crate::iv::FixedLength;
86
87    #[test]
88    fn test_size() {
89        let fixed = FixedLength::from([0u8; 16]);
90        assert_eq!(16, fixed.size());
91
92        let array = [0u8; 12];
93        let fixed = FixedLength::<12>::try_from(array.as_slice()).unwrap();
94        assert_eq!(12, fixed.size());
95
96        assert!(FixedLength::<16>::try_from(array.as_slice()).is_err());
97
98        assert!(TryInto::<[u8; 12]>::try_into(fixed).is_ok());
99    }
100}