1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum DerError {
15 Truncated,
17 InvalidLength,
19 UnexpectedTag,
21 TrailingData,
23 Unsupported,
25}
26
27impl core::fmt::Display for DerError {
28 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29 match self {
30 DerError::Truncated => write!(f, "truncated DER input"),
31 DerError::InvalidLength => write!(f, "invalid DER length"),
32 DerError::UnexpectedTag => write!(f, "unexpected DER tag"),
33 DerError::TrailingData => write!(f, "trailing DER data"),
34 DerError::Unsupported => write!(f, "unsupported DER encoding"),
35 }
36 }
37}
38
39impl core::error::Error for DerError {}
40
41const TAG_INTEGER: u8 = 0x02;
42const TAG_BIT_STRING: u8 = 0x03;
43const TAG_OCTET_STRING: u8 = 0x04;
44const TAG_OID: u8 = 0x06;
45const TAG_SEQUENCE: u8 = 0x30;
46
47#[derive(Debug, Clone)]
52pub struct Reader<'a> {
53 data: &'a [u8],
54 pos: usize,
55}
56
57impl<'a> Reader<'a> {
58 pub const fn new(data: &'a [u8]) -> Self {
60 Self {
61 data,
62 pos: 0,
63 }
64 }
65
66 pub fn is_empty(&self) -> bool {
68 self.pos >= self.data.len()
69 }
70
71 pub fn remaining(&self) -> usize {
73 self.data.len() - self.pos
74 }
75
76 pub fn peek_tag(&self) -> Result<u8, DerError> {
80 self.data.get(self.pos).copied().ok_or(DerError::Truncated)
81 }
82
83 pub fn read_tlv(&mut self) -> Result<(u8, &'a [u8]), DerError> {
88 let tag = *self.data.get(self.pos).ok_or(DerError::Truncated)?;
89 if tag & 0x1f == 0x1f {
90 return Err(DerError::Unsupported);
91 }
92 self.pos += 1;
93
94 let first = *self.data.get(self.pos).ok_or(DerError::Truncated)?;
95 self.pos += 1;
96
97 let len = match first {
98 0x00..=0x7f => first as usize,
99 0x80 => return Err(DerError::InvalidLength),
101 0x81..=0x84 => {
102 let n = (first & 0x7f) as usize;
103 let mut len: usize = 0;
104 for _ in 0..n {
105 let b = *self.data.get(self.pos).ok_or(DerError::Truncated)?;
106 self.pos += 1;
107 len = (len << 8) | b as usize;
108 }
109 if len < 0x80 {
111 return Err(DerError::InvalidLength);
112 }
113 len
114 }
115 _ => return Err(DerError::InvalidLength),
116 };
117
118 let end = self.pos.checked_add(len).ok_or(DerError::InvalidLength)?;
119 if end > self.data.len() {
120 return Err(DerError::Truncated);
121 }
122 let content = &self.data[self.pos..end];
123 self.pos = end;
124 Ok((tag, content))
125 }
126
127 pub fn read_expected(&mut self, tag: u8) -> Result<&'a [u8], DerError> {
129 let (actual, content) = self.read_tlv()?;
130 if actual != tag {
131 return Err(DerError::UnexpectedTag);
132 }
133 Ok(content)
134 }
135
136 pub fn read_sequence(&mut self) -> Result<Reader<'a>, DerError> {
138 Ok(Reader::new(self.read_expected(TAG_SEQUENCE)?))
139 }
140
141 pub fn read_integer(&mut self) -> Result<&'a [u8], DerError> {
146 let content = self.read_expected(TAG_INTEGER)?;
147 if content.is_empty() {
148 return Err(DerError::UnexpectedTag);
149 }
150 if content.len() > 1 && content[0] == 0 && content[1] & 0x80 == 0 {
152 return Err(DerError::InvalidLength);
153 }
154 Ok(content)
155 }
156
157 pub fn read_octet_string(&mut self) -> Result<&'a [u8], DerError> {
159 self.read_expected(TAG_OCTET_STRING)
160 }
161
162 pub fn read_bit_string(&mut self) -> Result<&'a [u8], DerError> {
168 let content = self.read_expected(TAG_BIT_STRING)?;
169 let (unused, rest) = content.split_first().ok_or(DerError::UnexpectedTag)?;
170 if *unused != 0 {
171 return Err(DerError::Unsupported);
172 }
173 Ok(rest)
174 }
175
176 pub fn read_oid(&mut self) -> Result<&'a [u8], DerError> {
179 let content = self.read_expected(TAG_OID)?;
180 if content.is_empty() {
181 return Err(DerError::UnexpectedTag);
182 }
183 Ok(content)
184 }
185
186 pub fn read_explicit(&mut self, tag: u8) -> Result<Reader<'a>, DerError> {
189 Ok(Reader::new(self.read_expected(tag)?))
190 }
191
192 pub fn finish(self) -> Result<(), DerError> {
196 if self.pos == self.data.len() {
197 Ok(())
198 } else {
199 Err(DerError::TrailingData)
200 }
201 }
202}
203
204#[cfg(test)]
205mod tests {
206 use super::*;
207
208 #[test]
209 fn reads_short_form_sequence() {
210 let der = [0x30, 0x03, 0x02, 0x01, 0x01];
212 let mut r = Reader::new(&der);
213 let mut seq = r.read_sequence().unwrap();
214 r.finish().unwrap();
215 assert_eq!(seq.read_integer().unwrap(), &[0x01]);
216 seq.finish().unwrap();
217 }
218
219 #[test]
220 fn reads_long_form_length() {
221 let mut der = vec![0x04, 0x81, 0xc8];
223 der.extend_from_slice(&[0u8; 200]);
224 let mut r = Reader::new(&der);
225 assert_eq!(r.read_octet_string().unwrap().len(), 200);
226 r.finish().unwrap();
227 }
228
229 #[test]
230 fn rejects_indefinite_length() {
231 let der = [0x30, 0x80, 0x00, 0x00];
232 assert_eq!(Reader::new(&der).read_sequence().unwrap_err(), DerError::InvalidLength);
233 }
234
235 #[test]
236 fn rejects_non_minimal_length() {
237 let der = [0x04, 0x81, 0x01, 0xff];
239 assert_eq!(Reader::new(&der).read_octet_string().unwrap_err(), DerError::InvalidLength);
240 }
241
242 #[test]
243 fn rejects_truncated_content() {
244 let der = [0x04, 0x05, 0x00, 0x00];
245 assert_eq!(Reader::new(&der).read_octet_string().unwrap_err(), DerError::Truncated);
246 }
247
248 #[test]
249 fn rejects_wrong_tag() {
250 let der = [0x02, 0x01, 0x01];
251 assert_eq!(Reader::new(&der).read_octet_string().unwrap_err(), DerError::UnexpectedTag);
252 }
253
254 #[test]
255 fn rejects_trailing_data() {
256 let der = [0x02, 0x01, 0x01, 0xff];
257 let mut r = Reader::new(&der);
258 r.read_integer().unwrap();
259 assert_eq!(r.finish().unwrap_err(), DerError::TrailingData);
260 }
261
262 #[test]
263 fn rejects_redundant_integer_zero() {
264 let der = [0x02, 0x02, 0x00, 0x01];
266 assert_eq!(Reader::new(&der).read_integer().unwrap_err(), DerError::InvalidLength);
267 }
268
269 #[test]
270 fn reads_bit_string_ignoring_unused_bits_byte() {
271 let der = [0x03, 0x03, 0x00, 0x04, 0x01];
273 assert_eq!(Reader::new(&der).read_bit_string().unwrap(), &[0x04, 0x01]);
274 }
275
276 #[test]
277 fn rejects_non_zero_unused_bits() {
278 let der = [0x03, 0x03, 0x07, 0x04, 0x01];
279 assert_eq!(Reader::new(&der).read_bit_string().unwrap_err(), DerError::Unsupported);
280 }
281
282 #[test]
283 fn reads_explicit_context_tag() {
284 let der = [0xa0, 0x03, 0x02, 0x01, 0x02];
286 let mut r = Reader::new(&der);
287 let mut inner = r.read_explicit(0xa0).unwrap();
288 assert_eq!(inner.read_integer().unwrap(), &[0x02]);
289 }
290}