summaryrefslogtreecommitdiffstats
path: root/openpgp/src/packet/seip/v2.rs
blob: 9942e02a140787fe168830e79f6f42500c7eb0b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! Symmetrically Encrypted Integrity Protected data packets version 2.
//!
//! An encrypted data packet is a container.  See [Section 5.13.2 of
//! draft-ietf-openpgp-crypto-refresh-10] for details.
//!
//! [Section 5.13.2 of draft-ietf-openpgp-crypto-refresh-10]: https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-version-2-symmetrically-enc
use crate::{
    Error,
    packet::{
        self,
        Packet,
        SEIP,
    },
    Result,
    types::{
        AEADAlgorithm,
        SymmetricAlgorithm,
    },
};

/// Holds an encrypted data packet.
///
/// An encrypted data packet is a container.  See [Section 5.13.2 of
/// draft-ietf-openpgp-crypto-refresh-10] for details.
///
/// [Section 5.13.2 of draft-ietf-openpgp-crypto-refresh-10]: https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-10.html#name-version-2-symmetrically-enc
///
/// # A note on equality
///
/// An unprocessed (encrypted) `SEIP2` packet is never considered equal
/// to a processed (decrypted) one.  Likewise, a processed (decrypted)
/// packet is never considered equal to a structured (parsed) one.
// IMPORTANT: If you add fields to this struct, you need to explicitly
// IMPORTANT: implement PartialEq, Eq, and Hash.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SEIP2 {
    /// CTB packet header fields.
    pub(crate) common: packet::Common,

    /// Symmetric algorithm.
    sym_algo: SymmetricAlgorithm,
    /// AEAD algorithm.
    aead: AEADAlgorithm,
    /// Chunk size.
    chunk_size: u64,
    /// Salt.
    salt: [u8; 32],

    /// This is a container packet.
    container: packet::Container,
}

assert_send_and_sync!(SEIP2);

impl std::ops::Deref for SEIP2 {
    type Target = packet::Container;
    fn deref(&self) -> &Self::Target {
        &self.container
    }
}

impl std::ops::DerefMut for SEIP2 {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.container
    }
}

impl SEIP2 {
    /// Creates a new SEIP2 packet.
    pub fn new(sym_algo: SymmetricAlgorithm,
               aead: AEADAlgorithm,
               chunk_size: u64,
               salt: [u8; 32]) -> Result<Self> {
        if chunk_size.count_ones() != 1 {
            return Err(Error::InvalidArgument(
                format!("chunk size is not a power of two: {}", chunk_size))
                .into());
        }

        if chunk_size < 64 {
            return Err(Error::InvalidArgument(
                format!("chunk size is too small: {}", chunk_size))
                .into());
        }

        Ok(SEIP2 {
            common: Default::default(),
            sym_algo,
            aead,
            chunk_size,
            salt,
            container: Default::default(),
        })
    }

    /// Gets the symmetric algorithm.
    pub fn symmetric_algo(&self) -> SymmetricAlgorithm {
        self.sym_algo
    }

    /// Sets the symmetric algorithm.
    pub fn set_symmetric_algo(&mut self, sym_algo: SymmetricAlgorithm)
                              -> SymmetricAlgorithm {
        std::mem::replace(&mut self.sym_algo, sym_algo)
    }

    /// Gets the AEAD algorithm.
    pub fn aead(&self) -> AEADAlgorithm {
        self.aead
    }

    /// Sets the AEAD algorithm.
    pub fn set_aead(&mut self, aead: AEADAlgorithm) -> AEADAlgorithm {
        std::mem::replace(&mut self.aead, aead)
    }

    /// Gets the chunk size.
    pub fn chunk_size(&self) -> u64 {
        self.chunk_size
    }

    /// Sets the chunk size.
    pub fn set_chunk_size(&mut self, chunk_size: u64) -> Result<()> {
        if chunk_size.count_ones() != 1 {
            return Err(Error::InvalidArgument(
                format!("chunk size is not a power of two: {}", chunk_size))
                .into());
        }

        if chunk_size < 64 {
            return Err(Error::InvalidArgument(
                format!("chunk size is too small: {}", chunk_size))
                .into());
        }

        self.chunk_size = chunk_size;
        Ok(())
    }

    /// Gets the size of a chunk with a digest.
    pub fn chunk_digest_size(&self) -> Result<u64> {
        Ok(self.chunk_size + self.aead.digest_size()? as u64)
    }

    /// Gets the salt.
    pub fn salt(&self) -> &[u8; 32] {
        &self.salt
    }

    /// Sets the salt.
    pub fn set_salt(&mut self, salt: [u8; 32]) -> [u8; 32] {
        std::mem::replace(&mut self.salt, salt)
    }
}

impl From<SEIP2> for SEIP {
    fn from(p: SEIP2) -> Self {
        SEIP::V2(p)
    }
}

impl From<SEIP2> for Packet {
    fn from(s: SEIP2) -> Self {
        Packet::SEIP(s.into())
    }
}