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