1use crate::{Encryption, Result};
2
3#[allow(clippy::large_enum_variant)]
5pub(crate) enum EncryptionState {
6 None,
7 #[cfg(feature = "aes-gcm")]
8 Aes256Gcm(Aes256Gcm),
9}
10
11impl EncryptionState {
12 pub(crate) fn new(parameters: &Encryption) -> Result<Self> {
13 match parameters {
14 Encryption::None => Ok(Self::None),
15 #[cfg(feature = "aes-gcm")]
16 Encryption::Aes256Gcm { key } => Ok(Self::Aes256Gcm(Aes256Gcm::new(key))),
17 #[cfg(not(feature = "aes-gcm"))]
18 Encryption::Aes256Gcm { .. } => Err(crate::Error::EncryptionUnavailable),
19 }
20 }
21
22 pub(crate) fn overhead(&self) -> usize {
24 match self {
25 Self::None => 0,
26 #[cfg(feature = "aes-gcm")]
27 Self::Aes256Gcm(_) => crate::TAG_LEN,
28 }
29 }
30
31 pub(crate) fn seal(&self, _index: u64, _buffer: &mut Vec<u8>) -> Result<()> {
32 match self {
33 Self::None => Ok(()),
34 #[cfg(feature = "aes-gcm")]
35 Self::Aes256Gcm(codec) => codec.seal(_index, _buffer),
36 }
37 }
38
39 pub(crate) fn open(&self, _index: u64, _buffer: &mut Vec<u8>) -> Result<()> {
40 match self {
41 Self::None => Ok(()),
42 #[cfg(feature = "aes-gcm")]
43 Self::Aes256Gcm(codec) => codec.open(_index, _buffer),
44 }
45 }
46}
47
48#[cfg(feature = "aes-gcm")]
54pub(crate) struct Aes256Gcm(aes_gcm::Aes256Gcm);
55
56#[cfg(feature = "aes-gcm")]
57impl Aes256Gcm {
58 pub(crate) fn new(key: &[u8; 32]) -> Self {
61 use aes_gcm::KeyInit;
62 Self(aes_gcm::Aes256Gcm::new(key.into()))
63 }
64}
65
66#[cfg(feature = "aes-gcm")]
67fn nonce(index: u64) -> aes_gcm::Nonce<aes_gcm::aead::consts::U12> {
68 let [a, b, c, d, e, f, g, h] = index.to_be_bytes();
69 [0, 0, 0, 0, a, b, c, d, e, f, g, h].into()
70}
71
72#[cfg(feature = "aes-gcm")]
73impl Aes256Gcm {
74 fn seal(&self, index: u64, buffer: &mut Vec<u8>) -> Result<()> {
75 use aes_gcm::aead::AeadInOut;
76 buffer
77 .try_reserve(crate::TAG_LEN)
78 .map_err(|_| crate::Error::Allocation)?;
79 let tag = self
80 .0
81 .encrypt_inout_detached(&nonce(index), b"", buffer.as_mut_slice().into())
82 .map_err(|_| crate::Error::EncryptionFailed)?;
83 buffer.extend_from_slice(&tag);
84 Ok(())
85 }
86
87 fn open(&self, index: u64, buffer: &mut Vec<u8>) -> Result<()> {
88 use aes_gcm::aead::AeadInOut;
89 let payload_len = buffer
90 .len()
91 .checked_sub(crate::TAG_LEN)
92 .ok_or(crate::Error::InvalidStoredLength)?;
93 let tag: [u8; crate::TAG_LEN] = buffer
94 .get(payload_len..)
95 .ok_or(crate::Error::InvalidStoredLength)?
96 .try_into()
97 .map_err(|_| crate::Error::InvalidStoredLength)?;
98 let payload = buffer
99 .get_mut(..payload_len)
100 .ok_or(crate::Error::InvalidStoredLength)?;
101 self.0
102 .decrypt_inout_detached(&nonce(index), b"", payload.into(), &tag.into())
103 .map_err(|_| crate::Error::AuthenticationFailed)?;
104 buffer.truncate(payload_len);
105 Ok(())
106 }
107}