1use byteorder::{BigEndian, WriteBytesExt};
2use failure::Error;
3use nom::{ErrorKind, be_u16, be_u32, be_u8};
4use nom::Err as NomErr;
5use nom::IResult;
6
7use compression::*;
8use key::*;
9use literal::*;
10use marker;
11use signature::*;
12use types::NomError;
13use userid;
14
15named!(old_tag_format<(&[u8], usize), (u8, &[u8])>,
16 do_parse!(
17 tag: take_bits!(u8, 4) >>
18 length: switch!(take_bits!(u8, 2),
19 0 => bytes!(map!(be_u8, u32::from)) |
20 1 => bytes!(map!(be_u16, u32::from)) |
21 2 => bytes!(call!(be_u32)) |
22 _ => value!(0)
23 ) >>
24 data: bytes!(take!(length)) >>
25 ((tag, data))
26 )
27);
28
29fn new_tag_format(inp: (&[u8], usize)) -> IResult<(&[u8], usize), (u8, &[u8])> {
30 let (remaining, tag) = match take_bits!(inp, u8, 6) {
31 IResult::Done(remaining, tag) => (remaining, tag),
32 IResult::Error(e) => return IResult::Error(e),
33 IResult::Incomplete(i) => return IResult::Incomplete(i),
34 };
35
36 let (remaining, first_octet) = match bytes!(remaining, be_u8) {
37 IResult::Done(remaining, first_octet) => (remaining, first_octet),
38 IResult::Error(e) => return IResult::Error(e),
39 IResult::Incomplete(i) => return IResult::Incomplete(i),
40 };
41
42 if first_octet < 192 {
43 match bytes!(remaining, take!(first_octet)) {
44 IResult::Done(remaining, contents) => return IResult::Done(remaining, (tag, contents)),
45 IResult::Error(e) => return IResult::Error(e),
46 IResult::Incomplete(i) => return IResult::Incomplete(i),
47 }
48 } else if first_octet < 224 {
49 let (remaining, second_octet) = match bytes!(remaining, be_u8) {
50 IResult::Done(remaining, second_octet) => (remaining, second_octet),
51 IResult::Error(e) => return IResult::Error(e),
52 IResult::Incomplete(i) => return IResult::Incomplete(i),
53 };
54
55 let length = ((first_octet as u16 - 192) << 8) + second_octet as u16 + 192;
56
57 match bytes!(remaining, take!(length)) {
58 IResult::Done(remaining, contents) => return IResult::Done(remaining, (tag, contents)),
59 IResult::Error(e) => return IResult::Error(e),
60 IResult::Incomplete(i) => return IResult::Incomplete(i),
61 }
62 } else if first_octet == 255 {
63 let (remaining, length) = match bytes!(remaining, be_u32) {
64 IResult::Done(remaining, length) => (remaining, length),
65 IResult::Error(e) => return IResult::Error(e),
66 IResult::Incomplete(i) => return IResult::Incomplete(i),
67 };
68
69 match bytes!(remaining, take!(length)) {
70 IResult::Done(remaining, contents) => return IResult::Done(remaining, (tag, contents)),
71 IResult::Error(e) => return IResult::Error(e),
72 IResult::Incomplete(i) => return IResult::Incomplete(i),
73 }
74 }
75
76 IResult::Error(NomErr::Code(ErrorKind::Custom(
78 NomError::Unimplemented as u32,
79 )))
80}
81
82named!(
83 pgp_packet_header<(u8, &[u8])>,
84 bits!(preceded!(
85 tag_bits!(u8, 1, 0b1),
86 switch!(take_bits!(u8, 1),
87 0 => call!(old_tag_format) |
88 1 => call!(new_tag_format)
89 )
90 ))
91);
92
93#[derive(Clone, Debug)]
98pub enum Packet {
99 PublicKeySessionKey,
100 Signature(SignaturePacket),
101 SymmetricKeySessionKey,
102 OnePassSignature,
103 SecretKey(Key),
104 PublicKey(Key),
105 SecretSubkey(Key),
106 CompressedData(CompressedDataPacket),
107 SymmetricEncryptedData,
108 Marker,
109 LiteralData(LiteralPacket),
110 Trust,
111 UserId(String),
112 PublicSubkey(Key),
113 UserAttribute,
114 SymmetricEncryptedIntegrityProtectedData,
115 ModificationDetectionCode,
116}
117
118impl Packet {
119 fn packet_tag(&self) -> u8 {
120 match *self {
121 Packet::PublicKeySessionKey => 1,
122 Packet::Signature(_) => 2,
123 Packet::SymmetricKeySessionKey => 3,
124 Packet::OnePassSignature => 4,
125 Packet::SecretKey(_) => 5,
126 Packet::PublicKey(_) => 6,
127 Packet::SecretSubkey(_) => 7,
128 Packet::CompressedData(_) => 8,
129 Packet::SymmetricEncryptedData => 9,
130 Packet::Marker => 10,
131 Packet::LiteralData(_) => 11,
132 Packet::Trust => 12,
133 Packet::UserId(_) => 13,
134 Packet::PublicSubkey(_) => 14,
135 Packet::UserAttribute => 17,
136 Packet::SymmetricEncryptedIntegrityProtectedData => 18,
137 Packet::ModificationDetectionCode => 19,
138 }
139 }
140
141 pub fn to_bytes(&self) -> Result<Vec<u8>, Error> {
142 let mut out = Vec::new();
143
144 let body = match self {
145 &Packet::Signature(ref signature) => signature.to_bytes()?,
146 &Packet::SecretKey(ref key) => key.to_bytes()?,
147 &Packet::PublicKey(ref key) => key.to_bytes()?,
148 &Packet::SecretSubkey(ref key) => key.to_bytes()?,
149 &Packet::CompressedData(ref cdata) => cdata.to_bytes()?,
150 &Packet::Marker => Vec::from(marker::MARKER_PACKET),
151 &Packet::LiteralData(ref data) => data.to_bytes()?,
152 &Packet::UserId(ref id) => Vec::from(id.as_bytes()),
153 &Packet::PublicSubkey(ref key) => key.to_bytes()?,
154 p => bail!(PacketError::UnimplementedType { packet_type: format!("{:?}", p) }),
155 };
156
157 let mut packet_tag = 0b1000_0000;
158 let packet_type = self.packet_tag() << 2;
159 packet_tag |= packet_type;
160
161 if body.len() < ::std::u8::MAX as usize {
162 out.push(packet_tag);
164 out.push(body.len() as u8);
165 } else if body.len() < ::std::u16::MAX as usize {
166 out.push(packet_tag | 0x1);
168 out.write_u16::<BigEndian>(body.len() as u16)?;
169 } else {
170 out.push(packet_tag | 0x2);
172 out.write_u32::<BigEndian>(body.len() as u32)?;
173 }
174
175 out.extend(&body);
176
177 Ok(out)
178 }
179
180 pub fn from_bytes(bytes: &[u8]) -> Result<(Packet, &[u8]), Error> {
181 let (remaining, packet_tag, packet_data) = match pgp_packet_header(bytes) {
182 IResult::Done(remaining, (tag, data)) => (remaining, tag, data),
183 IResult::Error(NomErr::Code(ErrorKind::Custom(e))) => {
184 let e = NomError::from(e);
185
186 bail!(PacketError::UnsupportedHeader {
187 reason: format!("{:?}", e),
188 })
189 }
190 IResult::Error(e) => bail!(PacketError::InvalidHeader {
191 reason: format!("{}", e),
192 }),
193 IResult::Incomplete(i) => bail!(PacketError::InvalidHeader {
194 reason: format!("{:?}", i),
195 }),
196 };
197
198 let packet = match packet_tag {
199 0 => bail!(PacketError::InvalidHeader {
200 reason: format!("packet has reserved tag"),
201 }),
202 1 => Packet::PublicKeySessionKey,
203 2 => Packet::Signature(SignaturePacket::from_bytes(packet_data)?),
204 3 => Packet::SymmetricKeySessionKey,
205 4 => Packet::OnePassSignature,
206 5 => Packet::SecretKey(Key::from_bytes(packet_data)?),
207 6 => Packet::PublicKey(Key::from_bytes(packet_data)?),
208 7 => Packet::SecretSubkey(Key::from_bytes(packet_data)?),
209 8 => Packet::CompressedData(CompressedDataPacket::from_bytes(packet_data)?),
210 9 => Packet::SymmetricEncryptedData,
211 10 => {
212 marker::verify_marker(packet_data)?;
213 Packet::Marker
214 }
215 11 => Packet::LiteralData(LiteralPacket::from_bytes(packet_data)?),
216 12 => Packet::Trust,
217 13 => Packet::UserId(userid::parse_userid(packet_data)?),
218 14 => Packet::PublicSubkey(Key::from_bytes(packet_data)?),
219 17 => Packet::UserAttribute,
220 18 => Packet::SymmetricEncryptedIntegrityProtectedData,
221 19 => Packet::ModificationDetectionCode,
222 _ => bail!(PacketError::InvalidHeader {
223 reason: format!("unknown tag"),
224 }),
225 };
226
227 Ok((packet, remaining))
228 }
229
230 pub fn all_from_bytes(mut bytes: &[u8]) -> Result<Vec<Packet>, Error> {
231 let mut out = Vec::new();
232
233 while !bytes.is_empty() {
234 let (packet, remaining) = Packet::from_bytes(bytes)?;
235 out.push(packet);
236 bytes = remaining;
237 }
238
239 Ok(out)
240 }
241}
242
243#[derive(Debug, Fail)]
247pub enum PacketError {
248 #[fail(display = "Invalid packet header: {}", reason)]
249 InvalidHeader { reason: String },
250 #[fail(display = "Unsupported packet header: {}", reason)]
251 UnsupportedHeader { reason: String },
252 #[fail(display = "Unimplemented packet type: {}", packet_type)]
253 UnimplementedType { packet_type: String },
254}