gpg_inspector_lib/packet/
misc.rs1use crate::error::Result;
11use crate::lookup::{lookup_aead_algorithm, lookup_symmetric_algorithm};
12use crate::stream::ByteStream;
13
14use super::Field;
15
16#[derive(Debug, Clone)]
25pub struct MarkerPacket {
26 pub valid: bool,
28}
29
30pub fn parse_marker(
34 stream: &mut ByteStream,
35 fields: &mut Vec<Field>,
36 body_offset: usize,
37) -> Result<MarkerPacket> {
38 let marker_start = body_offset + stream.pos();
39 let data = stream.rest();
40
41 let valid = data == [0x50, 0x47, 0x50]; let status = if valid {
43 "PGP (valid)"
44 } else if data.len() == 3 {
45 "Invalid marker"
46 } else {
47 "Invalid length"
48 };
49
50 fields.push(Field::field(
51 "Marker",
52 status,
53 (marker_start, marker_start + data.len()),
54 ));
55
56 Ok(MarkerPacket { valid })
57}
58
59#[derive(Debug, Clone)]
68pub struct SymmetricallyEncryptedDataPacket {
69 pub encrypted_data: Vec<u8>,
71}
72
73pub fn parse_symmetrically_encrypted_data(
77 stream: &mut ByteStream,
78 fields: &mut Vec<Field>,
79 body_offset: usize,
80) -> Result<SymmetricallyEncryptedDataPacket> {
81 let data_start = body_offset + stream.pos();
82 let encrypted_data = stream.rest();
83 let data_end = body_offset + stream.pos();
84
85 fields.push(Field::field(
86 "Encrypted Data",
87 format!("{} bytes (legacy CFB, no MDC)", encrypted_data.len()),
88 (data_start, data_end),
89 ));
90
91 Ok(SymmetricallyEncryptedDataPacket { encrypted_data })
92}
93
94#[derive(Debug, Clone)]
102pub struct AeadEncryptedDataPacket {
103 pub version: u8,
105 pub cipher_algorithm: u8,
107 pub aead_algorithm: u8,
109 pub chunk_size: u8,
111 pub iv: Vec<u8>,
113 pub encrypted_data: Vec<u8>,
115}
116
117pub fn parse_aead_encrypted_data(
119 stream: &mut ByteStream,
120 fields: &mut Vec<Field>,
121 body_offset: usize,
122) -> Result<AeadEncryptedDataPacket> {
123 let version_start = body_offset + stream.pos();
124 let version = stream.octet()?;
125 fields.push(Field::field(
126 "Version",
127 version.to_string(),
128 (version_start, version_start + 1),
129 ));
130
131 let cipher_start = body_offset + stream.pos();
132 let cipher_algorithm = stream.octet()?;
133 let cipher_lookup = lookup_symmetric_algorithm(cipher_algorithm);
134 fields.push(Field::field(
135 "Cipher Algorithm",
136 cipher_lookup.display(),
137 (cipher_start, cipher_start + 1),
138 ));
139
140 let aead_start = body_offset + stream.pos();
141 let aead_algorithm = stream.octet()?;
142 let aead_lookup = lookup_aead_algorithm(aead_algorithm);
143 fields.push(Field::field(
144 "AEAD Algorithm",
145 aead_lookup.display(),
146 (aead_start, aead_start + 1),
147 ));
148
149 let chunk_start = body_offset + stream.pos();
150 let chunk_size = stream.octet()?;
151 let chunk_bytes = 1u64 << (chunk_size + 6);
152 fields.push(Field::field(
153 "Chunk Size",
154 format!("{} bytes (2^{})", chunk_bytes, chunk_size + 6),
155 (chunk_start, chunk_start + 1),
156 ));
157
158 let iv_len = match aead_algorithm {
160 1 => 16, 2 => 15, 3 => 12, _ => 16, };
165
166 let iv_start = body_offset + stream.pos();
167 let iv = stream.bytes(iv_len)?;
168 let iv_hex: String = iv.iter().map(|b| format!("{:02X}", b)).collect();
169 fields.push(Field::field(
170 "IV/Nonce",
171 iv_hex,
172 (iv_start, iv_start + iv_len),
173 ));
174
175 let data_start = body_offset + stream.pos();
176 let encrypted_data = stream.rest();
177 let data_end = body_offset + stream.pos();
178
179 if !encrypted_data.is_empty() {
180 fields.push(Field::field(
181 "Encrypted Data",
182 format!("{} bytes (with auth tags)", encrypted_data.len()),
183 (data_start, data_end),
184 ));
185 }
186
187 Ok(AeadEncryptedDataPacket {
188 version,
189 cipher_algorithm,
190 aead_algorithm,
191 chunk_size,
192 iv,
193 encrypted_data,
194 })
195}
196
197#[derive(Debug, Clone)]
205pub struct PaddingPacket {
206 pub padding: Vec<u8>,
208}
209
210pub fn parse_padding(
212 stream: &mut ByteStream,
213 fields: &mut Vec<Field>,
214 body_offset: usize,
215) -> Result<PaddingPacket> {
216 let padding_start = body_offset + stream.pos();
217 let padding = stream.rest();
218 let padding_end = body_offset + stream.pos();
219
220 fields.push(Field::field(
221 "Padding",
222 format!("{} bytes", padding.len()),
223 (padding_start, padding_end),
224 ));
225
226 Ok(PaddingPacket { padding })
227}