1use crate::{Encryption, Identity, Result};
2
3pub trait EncryptionCodec: crate::sealed::Sealed {
6 const FORMAT: Encryption;
8 #[doc(hidden)]
10 fn seal(&self, index: u64, buffer: &mut Vec<u8>) -> Result<()>;
11 #[doc(hidden)]
13 fn open(&self, index: u64, buffer: &mut Vec<u8>) -> Result<()>;
14}
15
16impl EncryptionCodec for Identity {
17 const FORMAT: Encryption = Encryption::None;
18 fn seal(&self, _: u64, _: &mut Vec<u8>) -> Result<()> {
19 Ok(())
20 }
21 fn open(&self, _: u64, _: &mut Vec<u8>) -> Result<()> {
22 Ok(())
23 }
24}
25
26#[cfg(feature = "aes-gcm")]
32pub struct Aes256Gcm(aes_gcm::Aes256Gcm);
33
34#[cfg(feature = "aes-gcm")]
35impl Aes256Gcm {
36 pub fn new(key: &[u8; 32]) -> Self {
39 use aes_gcm::KeyInit;
40 Self(aes_gcm::Aes256Gcm::new(key.into()))
41 }
42}
43
44#[cfg(feature = "aes-gcm")]
45impl crate::sealed::Sealed for Aes256Gcm {}
46
47#[cfg(feature = "aes-gcm")]
48fn nonce(index: u64) -> aes_gcm::Nonce<aes_gcm::aead::consts::U12> {
49 let mut bytes = [0; 12];
50 bytes[4..].copy_from_slice(&index.to_be_bytes());
51 bytes.into()
52}
53
54#[cfg(feature = "aes-gcm")]
55impl EncryptionCodec for Aes256Gcm {
56 const FORMAT: Encryption = Encryption::Aes256Gcm;
57
58 fn seal(&self, index: u64, buffer: &mut Vec<u8>) -> Result<()> {
59 use aes_gcm::aead::AeadInOut;
60 buffer
61 .try_reserve(crate::TAG_LEN)
62 .map_err(|_| crate::Error::Allocation)?;
63 let tag = self
64 .0
65 .encrypt_inout_detached(&nonce(index), b"", buffer.as_mut_slice().into())
66 .map_err(|_| crate::Error::EncryptionFailed)?;
67 buffer.extend_from_slice(&tag);
68 Ok(())
69 }
70
71 fn open(&self, index: u64, buffer: &mut Vec<u8>) -> Result<()> {
72 use aes_gcm::aead::AeadInOut;
73 let payload_len = buffer
74 .len()
75 .checked_sub(crate::TAG_LEN)
76 .ok_or(crate::Error::InvalidStoredLength)?;
77 let tag: [u8; crate::TAG_LEN] = buffer[payload_len..].try_into().unwrap();
78 self.0
79 .decrypt_inout_detached(
80 &nonce(index),
81 b"",
82 (&mut buffer[..payload_len]).into(),
83 &tag.into(),
84 )
85 .map_err(|_| crate::Error::AuthenticationFailed)?;
86 buffer.truncate(payload_len);
87 Ok(())
88 }
89}