1use alloc::vec::Vec;
20
21pub const TAG_INTEGER: u8 = 0x02;
23pub const TAG_BIT_STRING: u8 = 0x03;
25pub const TAG_OCTET_STRING: u8 = 0x04;
27pub const TAG_NULL: u8 = 0x05;
29pub const TAG_OID: u8 = 0x06;
31pub const TAG_SEQUENCE: u8 = 0x30;
33pub const TAG_SET: u8 = 0x31;
35
36pub const MAX_DER_LEN: usize = 16_777_216;
38
39#[must_use]
41pub fn read_tag(input: &[u8], expected: u8) -> Option<&[u8]> {
42 let (tag, rest) = input.split_first()?;
43 if *tag == expected { Some(rest) } else { None }
44}
45
46#[must_use]
53pub fn read_length(input: &[u8]) -> Option<(usize, &[u8])> {
54 let (first, rest) = input.split_first()?;
55 if *first < 0x80 {
56 Some((*first as usize, rest))
57 } else if *first == 0x81 {
58 let (b, rest) = rest.split_first()?;
59 if *b < 0x80 {
60 return None; }
62 Some((*b as usize, rest))
63 } else if *first == 0x82 {
64 let (hi, rest) = rest.split_first()?;
65 let (lo, rest) = rest.split_first()?;
66 let len = (usize::from(*hi) << 8) | usize::from(*lo);
67 if len < 256 {
68 return None; }
70 Some((len, rest))
71 } else if *first == 0x83 {
72 let (b2, rest) = rest.split_first()?;
73 let (b1, rest) = rest.split_first()?;
74 let (b0, rest) = rest.split_first()?;
75 let len = (usize::from(*b2) << 16) | (usize::from(*b1) << 8) | usize::from(*b0);
76 if len < 65_536 {
77 return None; }
79 Some((len, rest))
80 } else {
81 None
83 }
84}
85
86#[must_use]
91pub fn read_tlv(input: &[u8], expected: u8) -> Option<(&[u8], &[u8])> {
92 let rest = read_tag(input, expected)?;
93 let (len, rest) = read_length(rest)?;
94 if rest.len() < len {
95 return None;
96 }
97 Some(rest.split_at(len))
98}
99
100#[must_use]
114pub fn read_integer(input: &[u8]) -> Option<(&[u8], &[u8])> {
115 let (bytes, rest) = read_tlv(input, TAG_INTEGER)?;
116 if bytes.is_empty() {
117 return None;
118 }
119 if bytes[0] & 0x80 != 0 {
120 return None; }
122 let unsigned = if bytes[0] == 0x00 {
123 if bytes.len() == 1 {
124 bytes
126 } else if bytes[1] & 0x80 == 0 {
127 return None;
130 } else {
131 &bytes[1..]
132 }
133 } else {
134 bytes
135 };
136 Some((unsigned, rest))
137}
138
139#[must_use]
143pub fn read_octet_string(input: &[u8]) -> Option<(&[u8], &[u8])> {
144 read_tlv(input, TAG_OCTET_STRING)
145}
146
147#[must_use]
149pub fn read_null(input: &[u8]) -> Option<&[u8]> {
150 let (value, rest) = read_tlv(input, TAG_NULL)?;
151 if !value.is_empty() {
152 return None;
153 }
154 Some(rest)
155}
156
157#[must_use]
166pub fn read_oid(input: &[u8]) -> Option<(&[u8], &[u8])> {
167 let (value, rest) = read_tlv(input, TAG_OID)?;
168 if value.is_empty() {
169 return None;
170 }
171 if value[value.len() - 1] & 0x80 != 0 {
173 return None;
174 }
175 Some((value, rest))
176}
177
178#[must_use]
186pub fn read_bit_string(input: &[u8]) -> Option<(u8, &[u8], &[u8])> {
187 let (value, rest) = read_tlv(input, TAG_BIT_STRING)?;
188 let (unused, bit_bytes) = value.split_first()?;
189 if *unused > 7 {
190 return None;
191 }
192 Some((*unused, bit_bytes, rest))
193}
194
195#[must_use]
201pub fn read_sequence(input: &[u8]) -> Option<(&[u8], &[u8])> {
202 read_tlv(input, TAG_SEQUENCE)
203}
204
205#[must_use]
211pub fn read_context_tagged_explicit(input: &[u8], n: u8) -> Option<(&[u8], &[u8])> {
212 if n > 30 {
213 return None;
214 }
215 let tag = 0xA0 | n;
218 read_tlv(input, tag)
219}
220
221#[must_use]
224pub fn read_context_tagged_implicit(input: &[u8], n: u8) -> Option<(&[u8], &[u8])> {
225 if n > 30 {
226 return None;
227 }
228 let tag = 0x80 | n;
230 read_tlv(input, tag)
231}
232
233#[must_use]
240pub fn collect_sequence_of<'a, T, F>(body: &'a [u8], mut read_item: F) -> Option<Vec<T>>
241where
242 F: FnMut(&'a [u8]) -> Option<(T, &'a [u8])>,
243{
244 let mut items = Vec::new();
245 let mut cursor = body;
246 while !cursor.is_empty() {
247 let (item, next) = read_item(cursor)?;
248 items.push(item);
249 cursor = next;
250 }
251 Some(items)
252}
253
254#[cfg(test)]
255mod tests {
256 use super::*;
257
258 #[test]
261 fn length_one_byte_forms() {
262 assert_eq!(read_length(&[0x00]), Some((0, &[][..])));
263 assert_eq!(read_length(&[0x7F]), Some((127, &[][..])));
264 assert_eq!(
266 read_length(&[0x05, 0xAA, 0xBB]),
267 Some((5, &[0xAA, 0xBB][..]))
268 );
269 }
270
271 #[test]
272 fn length_two_byte_form() {
273 assert_eq!(read_length(&[0x81, 0x80]), Some((128, &[][..])));
274 assert_eq!(read_length(&[0x81, 0xFF]), Some((255, &[][..])));
275 }
276
277 #[test]
278 fn length_two_byte_non_minimal_rejected() {
279 assert_eq!(read_length(&[0x81, 0x05]), None);
281 assert_eq!(read_length(&[0x81, 0x7F]), None);
282 }
283
284 #[test]
285 fn length_three_byte_form() {
286 assert_eq!(read_length(&[0x82, 0x01, 0x00]), Some((256, &[][..])));
287 assert_eq!(read_length(&[0x82, 0xFF, 0xFF]), Some((65_535, &[][..])));
288 }
289
290 #[test]
291 fn length_three_byte_non_minimal_rejected() {
292 assert_eq!(read_length(&[0x82, 0x00, 0xFF]), None);
294 assert_eq!(read_length(&[0x82, 0x00, 0xFF]), None);
296 }
297
298 #[test]
299 fn length_four_byte_form() {
300 assert_eq!(
301 read_length(&[0x83, 0x01, 0x00, 0x00]),
302 Some((65_536, &[][..]))
303 );
304 assert_eq!(
305 read_length(&[0x83, 0xFF, 0xFF, 0xFF]),
306 Some((16_777_215, &[][..]))
307 );
308 }
309
310 #[test]
311 fn length_four_byte_non_minimal_rejected() {
312 assert_eq!(read_length(&[0x83, 0x00, 0xFF, 0xFF]), None);
313 }
314
315 #[test]
316 fn length_above_max_rejected() {
317 assert_eq!(read_length(&[0x84, 0x01, 0x00, 0x00, 0x00]), None);
319 }
320
321 #[test]
322 fn length_truncated_rejected() {
323 assert_eq!(read_length(&[]), None);
324 assert_eq!(read_length(&[0x81]), None);
325 assert_eq!(read_length(&[0x82, 0x01]), None);
326 assert_eq!(read_length(&[0x83, 0x01, 0x00]), None);
327 }
328
329 #[test]
332 fn integer_canonical_zero() {
333 let (bytes, rest) = read_integer(&[0x02, 0x01, 0x00]).expect("zero");
334 assert_eq!(bytes, &[0x00]);
335 assert!(rest.is_empty());
336 }
337
338 #[test]
339 fn integer_small_positive() {
340 let (bytes, _) = read_integer(&[0x02, 0x01, 0x01]).unwrap();
341 assert_eq!(bytes, &[0x01]);
342 let (bytes, _) = read_integer(&[0x02, 0x01, 0x7F]).unwrap();
343 assert_eq!(bytes, &[0x7F]);
344 }
345
346 #[test]
347 fn integer_strips_disambiguating_pad() {
348 let (bytes, _) = read_integer(&[0x02, 0x02, 0x00, 0x80]).unwrap();
351 assert_eq!(bytes, &[0x80]);
352 }
353
354 #[test]
355 fn integer_rejects_redundant_pad() {
356 assert!(read_integer(&[0x02, 0x02, 0x00, 0x01]).is_none());
359 }
360
361 #[test]
362 fn integer_rejects_negative() {
363 assert!(read_integer(&[0x02, 0x01, 0x80]).is_none());
366 assert!(read_integer(&[0x02, 0x01, 0xFF]).is_none());
367 }
368
369 #[test]
370 fn integer_rejects_empty_content() {
371 assert!(read_integer(&[0x02, 0x00]).is_none());
372 }
373
374 #[test]
375 fn integer_rejects_wrong_tag() {
376 assert!(read_integer(&[0x03, 0x01, 0x01]).is_none());
377 }
378
379 #[test]
380 fn integer_preserves_remainder() {
381 let (bytes, rest) = read_integer(&[0x02, 0x01, 0x05, 0xDE, 0xAD]).unwrap();
382 assert_eq!(bytes, &[0x05]);
383 assert_eq!(rest, &[0xDE, 0xAD]);
384 }
385
386 #[test]
389 fn octet_string_round_trip() {
390 let (value, rest) = read_octet_string(&[0x04, 0x03, 0x01, 0x02, 0x03]).unwrap();
391 assert_eq!(value, &[0x01, 0x02, 0x03]);
392 assert!(rest.is_empty());
393 }
394
395 #[test]
396 fn octet_string_empty() {
397 let (value, rest) = read_octet_string(&[0x04, 0x00]).unwrap();
398 assert!(value.is_empty());
399 assert!(rest.is_empty());
400 }
401
402 #[test]
405 fn null_canonical() {
406 assert_eq!(read_null(&[0x05, 0x00]), Some(&[][..]));
407 assert_eq!(read_null(&[0x05, 0x00, 0xFF]), Some(&[0xFF][..]));
408 }
409
410 #[test]
411 fn null_with_content_rejected() {
412 assert!(read_null(&[0x05, 0x01, 0x00]).is_none());
413 }
414
415 #[test]
418 fn oid_id_pbkdf2() {
419 let der = [
421 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x05, 0x0C,
422 ];
423 let (value, rest) = read_oid(&der).unwrap();
424 assert_eq!(value, &der[2..]);
425 assert!(rest.is_empty());
426 }
427
428 #[test]
429 fn oid_empty_rejected() {
430 assert!(read_oid(&[0x06, 0x00]).is_none());
431 }
432
433 #[test]
434 fn oid_unterminated_continuation_rejected() {
435 assert!(read_oid(&[0x06, 0x01, 0x80]).is_none());
438 assert!(read_oid(&[0x06, 0x02, 0x2A, 0x80]).is_none());
439 }
440
441 #[test]
444 fn bit_string_zero_unused() {
445 let (unused, bytes, rest) = read_bit_string(&[0x03, 0x03, 0x00, 0xAB, 0xCD]).unwrap();
446 assert_eq!(unused, 0);
447 assert_eq!(bytes, &[0xAB, 0xCD]);
448 assert!(rest.is_empty());
449 }
450
451 #[test]
452 fn bit_string_unused_above_7_rejected() {
453 assert!(read_bit_string(&[0x03, 0x02, 0x08, 0xFF]).is_none());
454 }
455
456 #[test]
457 fn bit_string_empty_value_rejected() {
458 assert!(read_bit_string(&[0x03, 0x00]).is_none());
460 }
461
462 #[test]
465 fn sequence_round_trip() {
466 let der = [0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x02];
468 let (body, rest) = read_sequence(&der).unwrap();
469 assert_eq!(body, &der[2..]);
470 assert!(rest.is_empty());
471 let (a, body) = read_integer(body).unwrap();
473 let (b, body) = read_integer(body).unwrap();
474 assert_eq!(a, &[0x01]);
475 assert_eq!(b, &[0x02]);
476 assert!(body.is_empty());
477 }
478
479 #[test]
482 fn context_explicit_round_trip() {
483 let der = [0xA0, 0x03, 0x02, 0x01, 0x01];
485 let (inner, rest) = read_context_tagged_explicit(&der, 0).unwrap();
486 assert!(rest.is_empty());
487 let (val, _) = read_integer(inner).unwrap();
488 assert_eq!(val, &[0x01]);
489 }
490
491 #[test]
492 fn context_implicit_round_trip() {
493 let der = [0x81, 0x02, 0x61, 0x62];
495 let (value, rest) = read_context_tagged_implicit(&der, 1).unwrap();
496 assert_eq!(value, b"ab");
497 assert!(rest.is_empty());
498 }
499
500 #[test]
501 fn context_explicit_wrong_number_rejected() {
502 let der = [0xA0, 0x03, 0x02, 0x01, 0x01];
503 assert!(read_context_tagged_explicit(&der, 1).is_none());
504 }
505
506 #[test]
507 fn context_explicit_above_30_rejected() {
508 assert!(read_context_tagged_explicit(&[0xBF, 0x1F, 0x00], 31).is_none());
510 }
511
512 #[test]
515 fn collect_three_integers() {
516 let body = [0x02, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x03];
517 let items = collect_sequence_of(&body, |b| {
518 let (v, rest) = read_integer(b)?;
519 Some((v[0], rest))
520 })
521 .unwrap();
522 assert_eq!(items, alloc::vec![1u8, 2, 3]);
523 }
524
525 #[test]
526 fn collect_stops_on_short_input() {
527 let body = [0x02, 0x01, 0x01, 0x02, 0x01]; let result: Option<Vec<u8>> = collect_sequence_of(&body, |b| {
529 let (v, rest) = read_integer(b)?;
530 Some((v[0], rest))
531 });
532 assert!(result.is_none());
533 }
534}