sequoia_openpgp/packet/seip/
v2.rs

1//! Symmetrically Encrypted Integrity Protected data packets version 2.
2//!
3//! An encrypted data packet is a container.  See [Version 2
4//! Symmetrically Encrypted and Integrity Protected Data Packet
5//! Format] for details.
6//!
7//! [Version 2 Symmetrically Encrypted and Integrity Protected Data Packet Format]: https://www.rfc-editor.org/rfc/rfc9580.html#name-version-2-symmetrically-enc
8use crate::{
9    Error,
10    packet::{
11        self,
12        Packet,
13        SEIP,
14    },
15    Result,
16    types::{
17        AEADAlgorithm,
18        SymmetricAlgorithm,
19    },
20};
21
22/// Holds an encrypted data packet.
23///
24/// An encrypted data packet is a container.  See [Version 2
25/// Symmetrically Encrypted and Integrity Protected Data Packet
26/// Format] for details.
27///
28/// [Version 2 Symmetrically Encrypted and Integrity Protected Data Packet Format]: https://www.rfc-editor.org/rfc/rfc9580.html#name-version-2-symmetrically-enc
29///
30/// # A note on equality
31///
32/// An unprocessed (encrypted) `SEIP2` packet is never considered equal
33/// to a processed (decrypted) one.  Likewise, a processed (decrypted)
34/// packet is never considered equal to a structured (parsed) one.
35// IMPORTANT: If you add fields to this struct, you need to explicitly
36// IMPORTANT: implement PartialEq, Eq, and Hash.
37#[derive(Clone, Debug, PartialEq, Eq, Hash)]
38pub struct SEIP2 {
39    /// CTB packet header fields.
40    pub(crate) common: packet::Common,
41
42    /// Symmetric algorithm.
43    sym_algo: SymmetricAlgorithm,
44
45    /// AEAD algorithm.
46    aead: AEADAlgorithm,
47
48    /// Chunk size.
49    chunk_size: u64,
50
51    /// Salt.
52    salt: [u8; 32],
53
54    /// This is a container packet.
55    container: packet::Container,
56}
57
58assert_send_and_sync!(SEIP2);
59
60impl SEIP2 {
61    /// Creates a new SEIP2 packet.
62    pub fn new(sym_algo: SymmetricAlgorithm,
63               aead: AEADAlgorithm,
64               chunk_size: u64,
65               salt: [u8; 32])
66               -> Result<Self>
67    {
68        if chunk_size.count_ones() != 1 {
69            return Err(Error::InvalidArgument(
70                format!("chunk size is not a power of two: {}", chunk_size))
71                .into());
72        }
73
74        if chunk_size < 64 {
75            return Err(Error::InvalidArgument(
76                format!("chunk size is too small: {}", chunk_size))
77                .into());
78        }
79
80        Ok(SEIP2 {
81            common: Default::default(),
82            sym_algo,
83            aead,
84            chunk_size,
85            salt,
86            container: Default::default(),
87        })
88    }
89
90    /// Gets the symmetric algorithm.
91    pub fn symmetric_algo(&self) -> SymmetricAlgorithm {
92        self.sym_algo
93    }
94
95    /// Sets the symmetric algorithm.
96    pub fn set_symmetric_algo(&mut self, sym_algo: SymmetricAlgorithm)
97                              -> SymmetricAlgorithm {
98        std::mem::replace(&mut self.sym_algo, sym_algo)
99    }
100
101    /// Gets the AEAD algorithm.
102    pub fn aead(&self) -> AEADAlgorithm {
103        self.aead
104    }
105
106    /// Sets the AEAD algorithm.
107    pub fn set_aead(&mut self, aead: AEADAlgorithm) -> AEADAlgorithm {
108        std::mem::replace(&mut self.aead, aead)
109    }
110
111    /// Gets the chunk size.
112    pub fn chunk_size(&self) -> u64 {
113        self.chunk_size
114    }
115
116    /// Sets the chunk size.
117    pub fn set_chunk_size(&mut self, chunk_size: u64) -> Result<()> {
118        if chunk_size.count_ones() != 1 {
119            return Err(Error::InvalidArgument(
120                format!("chunk size is not a power of two: {}", chunk_size))
121                .into());
122        }
123
124        if chunk_size < 64 {
125            return Err(Error::InvalidArgument(
126                format!("chunk size is too small: {}", chunk_size))
127                .into());
128        }
129
130        self.chunk_size = chunk_size;
131        Ok(())
132    }
133
134    /// Gets the size of a chunk with a digest.
135    pub fn chunk_digest_size(&self) -> Result<u64> {
136        Ok(self.chunk_size + self.aead.digest_size()? as u64)
137    }
138
139    /// Gets the salt.
140    pub fn salt(&self) -> &[u8; 32] {
141        &self.salt
142    }
143
144    /// Sets the salt.
145    pub fn set_salt(&mut self, salt: [u8; 32]) -> [u8; 32] {
146        std::mem::replace(&mut self.salt, salt)
147    }
148}
149
150impl_processed_body_forwards!(SEIP2);
151
152impl From<SEIP2> for SEIP {
153    fn from(p: SEIP2) -> Self {
154        SEIP::V2(p)
155    }
156}
157
158impl From<SEIP2> for Packet {
159    fn from(s: SEIP2) -> Self {
160        Packet::SEIP(s.into())
161    }
162}