1 //! One-pass signature packets.
2 //!
3 //! See [Section 5.4 of RFC 4880] for details.
4 //!
5 //!   [Section 5.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.4
6 
7 use std::fmt;
8 
9 #[cfg(any(test, feature = "quickcheck"))]
10 use quickcheck::{Arbitrary, Gen};
11 
12 use crate::Error;
13 use crate::Packet;
14 use crate::packet;
15 use crate::packet::Signature;
16 use crate::Result;
17 use crate::KeyID;
18 use crate::HashAlgorithm;
19 use crate::PublicKeyAlgorithm;
20 use crate::SignatureType;
21 
22 /// Holds a one-pass signature packet.
23 ///
24 /// See [Section 5.4 of RFC 4880] for details.
25 ///
26 ///   [Section 5.4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.4
27 ///
28 /// # A note on equality
29 ///
30 /// The `last` flag is represented as a `u8` and is compared
31 /// literally, not semantically.
32 // IMPORTANT: If you add fields to this struct, you need to explicitly
33 // IMPORTANT: implement PartialEq, Eq, and Hash.
34 #[derive(Clone, PartialEq, Eq, Hash)]
35 pub struct OnePassSig3 {
36     /// CTB packet header fields.
37     pub(crate) common: packet::Common,
38     /// Type of the signature.
39     typ: SignatureType,
40     /// Hash algorithm used to compute the signature.
41     hash_algo: HashAlgorithm,
42     /// Public key algorithm of this signature.
43     pk_algo: PublicKeyAlgorithm,
44     /// Key ID of the signing key.
45     issuer: KeyID,
46     /// A one-octet number holding a flag showing whether the signature
47     /// is nested.
48     last: u8,
49 }
50 
51 impl fmt::Debug for OnePassSig3 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result52     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
53         f.debug_struct("OnePassSig3")
54             .field("typ", &self.typ)
55             .field("hash_algo", &self.hash_algo)
56             .field("pk_algo", &self.pk_algo)
57             .field("issuer", &self.issuer)
58             .field("last", &self.last)
59             .finish()
60     }
61 }
62 
63 impl OnePassSig3 {
64     /// Returns a new `Signature` packet.
new(typ: SignatureType) -> Self65     pub fn new(typ: SignatureType) ->  Self {
66         OnePassSig3 {
67             common: Default::default(),
68             typ,
69             hash_algo: HashAlgorithm::Unknown(0),
70             pk_algo: PublicKeyAlgorithm::Unknown(0),
71             issuer: KeyID::new(0),
72             last: 1,
73         }
74     }
75 
76     /// Gets the signature type.
typ(&self) -> SignatureType77     pub fn typ(&self) -> SignatureType {
78         self.typ
79     }
80 
81     /// Sets the signature type.
set_type(&mut self, t: SignatureType) -> SignatureType82     pub fn set_type(&mut self, t: SignatureType) -> SignatureType {
83         ::std::mem::replace(&mut self.typ, t)
84     }
85 
86     /// Gets the public key algorithm.
pk_algo(&self) -> PublicKeyAlgorithm87     pub fn pk_algo(&self) -> PublicKeyAlgorithm {
88         self.pk_algo
89     }
90 
91     /// Sets the public key algorithm.
set_pk_algo(&mut self, algo: PublicKeyAlgorithm) -> PublicKeyAlgorithm92     pub fn set_pk_algo(&mut self, algo: PublicKeyAlgorithm) -> PublicKeyAlgorithm {
93         ::std::mem::replace(&mut self.pk_algo, algo)
94     }
95 
96     /// Gets the hash algorithm.
hash_algo(&self) -> HashAlgorithm97     pub fn hash_algo(&self) -> HashAlgorithm {
98         self.hash_algo
99     }
100 
101     /// Sets the hash algorithm.
set_hash_algo(&mut self, algo: HashAlgorithm) -> HashAlgorithm102     pub fn set_hash_algo(&mut self, algo: HashAlgorithm) -> HashAlgorithm {
103         ::std::mem::replace(&mut self.hash_algo, algo)
104     }
105 
106     /// Gets the issuer.
issuer(&self) -> &KeyID107     pub fn issuer(&self) -> &KeyID {
108         &self.issuer
109     }
110 
111     /// Sets the issuer.
set_issuer(&mut self, issuer: KeyID) -> KeyID112     pub fn set_issuer(&mut self, issuer: KeyID) -> KeyID {
113         ::std::mem::replace(&mut self.issuer, issuer)
114     }
115 
116     /// Gets the last flag.
last(&self) -> bool117     pub fn last(&self) -> bool {
118         self.last > 0
119     }
120 
121     /// Sets the last flag.
set_last(&mut self, last: bool) -> bool122     pub fn set_last(&mut self, last: bool) -> bool {
123         ::std::mem::replace(&mut self.last, if last { 1 } else { 0 }) > 0
124     }
125 
126     /// Gets the raw value of the last flag.
last_raw(&self) -> u8127     pub fn last_raw(&self) -> u8 {
128         self.last
129     }
130 
131     /// Sets the raw value of the last flag.
set_last_raw(&mut self, last: u8) -> u8132     pub fn set_last_raw(&mut self, last: u8) -> u8 {
133         ::std::mem::replace(&mut self.last, last)
134     }
135 }
136 
137 impl From<OnePassSig3> for super::OnePassSig {
from(s: OnePassSig3) -> Self138     fn from(s: OnePassSig3) -> Self {
139         super::OnePassSig::V3(s)
140     }
141 }
142 
143 impl From<OnePassSig3> for Packet {
from(p: OnePassSig3) -> Self144     fn from(p: OnePassSig3) -> Self {
145         super::OnePassSig::from(p).into()
146     }
147 }
148 
149 impl<'a> std::convert::TryFrom<&'a Signature> for OnePassSig3 {
150     type Error = anyhow::Error;
151 
try_from(s: &'a Signature) -> Result<Self>152     fn try_from(s: &'a Signature) -> Result<Self> {
153         let issuer = match s.issuers().nth(0) {
154             Some(i) => i.clone(),
155             None =>
156                 return Err(Error::InvalidArgument(
157                     "Signature has no issuer".into()).into()),
158         };
159 
160         Ok(OnePassSig3 {
161             common: Default::default(),
162             typ: s.typ(),
163             hash_algo: s.hash_algo(),
164             pk_algo: s.pk_algo(),
165             issuer,
166             last: 0,
167         })
168     }
169 }
170 
171 #[cfg(any(test, feature = "quickcheck"))]
172 impl Arbitrary for super::OnePassSig {
arbitrary<G: Gen>(g: &mut G) -> Self173     fn arbitrary<G: Gen>(g: &mut G) -> Self {
174         OnePassSig3::arbitrary(g).into()
175     }
176 }
177 
178 #[cfg(any(test, feature = "quickcheck"))]
179 impl Arbitrary for OnePassSig3 {
arbitrary<G: Gen>(g: &mut G) -> Self180     fn arbitrary<G: Gen>(g: &mut G) -> Self {
181         let mut ops = OnePassSig3::new(SignatureType::arbitrary(g));
182         ops.set_hash_algo(HashAlgorithm::arbitrary(g));
183         ops.set_pk_algo(PublicKeyAlgorithm::arbitrary(g));
184         ops.set_issuer(KeyID::arbitrary(g));
185         ops.set_last_raw(u8::arbitrary(g));
186         ops
187     }
188 }
189 
190 #[cfg(test)]
191 mod tests {
192     use super::*;
193     use crate::parse::Parse;
194     use crate::serialize::MarshalInto;
195 
196     quickcheck! {
197         fn roundtrip(p: OnePassSig3) -> bool {
198             let q = OnePassSig3::from_bytes(&p.to_vec().unwrap()).unwrap();
199             assert_eq!(p, q);
200             true
201         }
202     }
203 }
204