sequoia_openpgp/packet/
mdc.rs

1use std::cmp::Ordering;
2
3use crate::crypto;
4use crate::crypto::mem;
5use crate::packet;
6use crate::Packet;
7
8/// Holds an MDC packet.
9///
10/// A modification detection code packet.  This packet appears after a
11/// SEIP packet.  See [Section 5.13.1 of RFC 9580] for details.
12///
13/// [Section 5.13.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.13.1
14///
15/// # A note on equality
16///
17/// Two `MDC` packets are considered equal if their serialized form is
18/// equal.  This excludes the computed digest.
19#[derive(Clone, Debug)]
20pub struct MDC {
21    /// CTB packet header fields.
22    pub(crate) common: packet::Common,
23    /// Our SHA-1 hash.
24    computed_digest: [u8; 20],
25    /// A 20-octet SHA-1 hash of the preceding plaintext data.
26    digest: [u8; 20],
27}
28assert_send_and_sync!(MDC);
29
30impl PartialEq for MDC {
31    fn eq(&self, other: &MDC) -> bool {
32        self.common == other.common
33            && self.digest == other.digest
34    }
35}
36
37impl Eq for MDC {}
38
39impl std::hash::Hash for MDC {
40    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
41        std::hash::Hash::hash(&self.common, state);
42        std::hash::Hash::hash(&self.digest, state);
43    }
44}
45
46impl MDC {
47    /// Creates an MDC packet.
48    pub fn new(digest: [u8; 20], computed_digest: [u8; 20]) -> Self {
49        MDC {
50            common: Default::default(),
51            computed_digest,
52            digest,
53        }
54    }
55
56    /// Gets the packet's hash value.
57    pub fn digest(&self) -> &[u8] {
58        &self.digest[..]
59    }
60
61    /// Gets the computed hash value.
62    pub fn computed_digest(&self) -> &[u8] {
63        &self.computed_digest[..]
64    }
65
66    /// Returns whether the data protected by the MDC is valid.
67    pub fn valid(&self) -> bool {
68        if self.digest == [ 0; 20 ] {
69            // If the computed_digest and digest are uninitialized, then
70            // return false.
71            false
72        } else {
73            mem::secure_cmp(&self.computed_digest, &self.digest) == Ordering::Equal
74        }
75    }
76}
77
78impl From<MDC> for Packet {
79    fn from(s: MDC) -> Self {
80        #[allow(deprecated)]
81        Packet::MDC(s)
82    }
83}
84
85impl From<[u8; 20]> for MDC {
86    fn from(digest: [u8; 20]) -> Self {
87        MDC {
88            common: Default::default(),
89            // All 0s.
90            computed_digest: Default::default(),
91            digest,
92        }
93    }
94}
95
96impl From<crypto::hash::Context> for MDC {
97    fn from(mut hash: crypto::hash::Context) -> Self {
98        let mut value : [u8; 20] = Default::default();
99        let _ = hash.digest(&mut value[..]);
100        value.into()
101    }
102}