1#![allow(dead_code)]
19
20#[cfg(feature = "alloc")]
21extern crate alloc;
22
23#[cfg(feature = "alloc")]
24use alloc::{string::String, vec, vec::Vec};
25
26use crate::error::KernelError;
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34#[repr(u8)]
35pub enum TagClass {
36 Universal = 0,
38 Application = 1,
40 ContextSpecific = 2,
42 Private = 3,
44}
45
46impl TagClass {
47 fn from_byte(b: u8) -> Self {
49 match (b >> 6) & 0x03 {
50 0 => TagClass::Universal,
51 1 => TagClass::Application,
52 2 => TagClass::ContextSpecific,
53 3 => TagClass::Private,
54 _ => TagClass::Universal,
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub enum Tag {
62 Boolean,
64 Integer,
66 BitString,
68 OctetString,
70 Null,
72 ObjectIdentifier,
74 Enumerated,
76 Utf8String,
78 PrintableString,
80 Ia5String,
82 UtcTime,
84 Sequence,
86 Set,
88 ContextSpecific(TagClass, u8),
90}
91
92impl Tag {
93 fn universal_number(&self) -> Option<u8> {
95 match self {
96 Tag::Boolean => Some(1),
97 Tag::Integer => Some(2),
98 Tag::BitString => Some(3),
99 Tag::OctetString => Some(4),
100 Tag::Null => Some(5),
101 Tag::ObjectIdentifier => Some(6),
102 Tag::Enumerated => Some(10),
103 Tag::Utf8String => Some(12),
104 Tag::PrintableString => Some(19),
105 Tag::Ia5String => Some(22),
106 Tag::UtcTime => Some(23),
107 Tag::Sequence => Some(16), Tag::Set => Some(17), Tag::ContextSpecific(_, _) => None,
110 }
111 }
112
113 fn is_constructed(&self) -> bool {
115 matches!(self, Tag::Sequence | Tag::Set | Tag::ContextSpecific(_, _))
116 }
117}
118
119#[cfg(feature = "alloc")]
125#[derive(Debug, Clone, PartialEq, Eq)]
126pub enum AsnValue {
127 Boolean(bool),
129 Integer(i64),
131 BigInteger(Vec<u8>),
133 BitString(Vec<u8>, u8),
135 OctetString(Vec<u8>),
137 Null,
139 Oid(Vec<u32>),
141 Utf8String(String),
143 PrintableString(String),
145 Ia5String(String),
147 UtcTime(String),
149 Sequence(Vec<AsnValue>),
151 Set(Vec<AsnValue>),
153 Enumerated(i64),
155 ContextSpecific(u8, Vec<u8>),
157}
158
159#[cfg(feature = "alloc")]
169pub fn encode_length(length: usize, out: &mut Vec<u8>) {
170 if length < 128 {
171 out.push(length as u8);
172 } else if length <= 0xFF {
173 out.push(0x81);
174 out.push(length as u8);
175 } else if length <= 0xFFFF {
176 out.push(0x82);
177 out.push((length >> 8) as u8);
178 out.push(length as u8);
179 } else if length <= 0xFF_FFFF {
180 out.push(0x83);
181 out.push((length >> 16) as u8);
182 out.push((length >> 8) as u8);
183 out.push(length as u8);
184 } else {
185 out.push(0x84);
186 out.push((length >> 24) as u8);
187 out.push((length >> 16) as u8);
188 out.push((length >> 8) as u8);
189 out.push(length as u8);
190 }
191}
192
193pub fn decode_length(data: &[u8]) -> Result<(usize, usize), KernelError> {
197 if data.is_empty() {
198 return Err(KernelError::InvalidArgument {
199 name: "asn1_length",
200 value: "truncated",
201 });
202 }
203
204 let first = data[0];
205 if first < 128 {
206 Ok((first as usize, 1))
207 } else {
208 let num_bytes = (first & 0x7F) as usize;
209 if num_bytes == 0 || num_bytes > 4 {
210 return Err(KernelError::InvalidArgument {
211 name: "asn1_length",
212 value: "unsupported length encoding",
213 });
214 }
215 if data.len() < 1 + num_bytes {
216 return Err(KernelError::InvalidArgument {
217 name: "asn1_length",
218 value: "truncated long form",
219 });
220 }
221 let mut length: usize = 0;
222 for i in 0..num_bytes {
223 length = (length << 8) | (data[1 + i] as usize);
224 }
225 Ok((length, 1 + num_bytes))
226 }
227}
228
229#[cfg(feature = "alloc")]
240pub fn encode_tag(class: TagClass, constructed: bool, number: u8, out: &mut Vec<u8>) {
241 let class_bits = (class as u8) << 6;
242 let constructed_bit = if constructed { 0x20 } else { 0 };
243
244 if number < 31 {
245 out.push(class_bits | constructed_bit | number);
246 } else {
247 out.push(class_bits | constructed_bit | 0x1F);
248 encode_base128(number as u32, out);
250 }
251}
252
253pub fn decode_tag(data: &[u8]) -> Result<(TagClass, bool, u8, usize), KernelError> {
257 if data.is_empty() {
258 return Err(KernelError::InvalidArgument {
259 name: "asn1_tag",
260 value: "truncated",
261 });
262 }
263
264 let first = data[0];
265 let class = TagClass::from_byte(first);
266 let constructed = (first & 0x20) != 0;
267 let low_bits = first & 0x1F;
268
269 if low_bits < 31 {
270 Ok((class, constructed, low_bits, 1))
271 } else {
272 let mut number: u32 = 0;
274 let mut pos = 1;
275 loop {
276 if pos >= data.len() {
277 return Err(KernelError::InvalidArgument {
278 name: "asn1_tag",
279 value: "truncated high tag",
280 });
281 }
282 let b = data[pos];
283 number = (number << 7) | ((b & 0x7F) as u32);
284 pos += 1;
285 if b & 0x80 == 0 {
286 break;
287 }
288 if number > 255 {
289 return Err(KernelError::InvalidArgument {
290 name: "asn1_tag",
291 value: "tag number too large",
292 });
293 }
294 }
295 Ok((class, constructed, number as u8, pos))
296 }
297}
298
299#[cfg(feature = "alloc")]
308fn encode_oid(arcs: &[u32]) -> Vec<u8> {
309 let mut out = Vec::new();
310 if arcs.len() < 2 {
311 return out;
312 }
313
314 let first_byte = arcs[0].saturating_mul(40).saturating_add(arcs[1]);
316 encode_base128(first_byte, &mut out);
317
318 for &arc in &arcs[2..] {
319 encode_base128(arc, &mut out);
320 }
321
322 out
323}
324
325#[cfg(feature = "alloc")]
327fn decode_oid(data: &[u8]) -> Result<Vec<u32>, KernelError> {
328 if data.is_empty() {
329 return Err(KernelError::InvalidArgument {
330 name: "asn1_oid",
331 value: "empty",
332 });
333 }
334
335 let mut arcs = Vec::new();
336 let mut pos = 0;
337
338 let (first_combined, consumed) = decode_base128(data, pos)?;
340 pos += consumed;
341
342 if first_combined < 40 {
343 arcs.push(0);
344 arcs.push(first_combined);
345 } else if first_combined < 80 {
346 arcs.push(1);
347 arcs.push(first_combined - 40);
348 } else {
349 arcs.push(2);
350 arcs.push(first_combined - 80);
351 }
352
353 while pos < data.len() {
355 let (arc, consumed) = decode_base128(data, pos)?;
356 pos += consumed;
357 arcs.push(arc);
358 }
359
360 Ok(arcs)
361}
362
363#[cfg(feature = "alloc")]
370fn encode_base128(mut value: u32, out: &mut Vec<u8>) {
371 if value == 0 {
372 out.push(0);
373 return;
374 }
375
376 let mut bytes = [0u8; 5];
378 let mut count = 0;
379 while value > 0 {
380 bytes[count] = (value & 0x7F) as u8;
381 value >>= 7;
382 count += 1;
383 }
384
385 for i in (0..count).rev() {
387 let b = bytes[i];
388 if i > 0 {
389 out.push(b | 0x80);
390 } else {
391 out.push(b);
392 }
393 }
394}
395
396fn decode_base128(data: &[u8], start: usize) -> Result<(u32, usize), KernelError> {
399 let mut value: u32 = 0;
400 let mut pos = start;
401
402 loop {
403 if pos >= data.len() {
404 return Err(KernelError::InvalidArgument {
405 name: "asn1_base128",
406 value: "truncated",
407 });
408 }
409 let b = data[pos];
410 value = value
411 .checked_mul(128)
412 .and_then(|v| v.checked_add((b & 0x7F) as u32))
413 .ok_or(KernelError::InvalidArgument {
414 name: "asn1_base128",
415 value: "overflow",
416 })?;
417 pos += 1;
418 if b & 0x80 == 0 {
419 break;
420 }
421 }
422
423 Ok((value, pos - start))
424}
425
426#[cfg(feature = "alloc")]
432pub struct AsnEncoder;
433
434#[cfg(feature = "alloc")]
435impl AsnEncoder {
436 pub fn encode(value: &AsnValue) -> Vec<u8> {
438 let mut out = Vec::new();
439 Self::encode_value(value, &mut out);
440 out
441 }
442
443 fn encode_value(value: &AsnValue, out: &mut Vec<u8>) {
444 match value {
445 AsnValue::Boolean(b) => {
446 out.push(0x01); out.push(0x01); out.push(if *b { 0xFF } else { 0x00 });
449 }
450 AsnValue::Integer(n) => {
451 let content = Self::encode_integer(*n);
452 out.push(0x02); encode_length(content.len(), out);
454 out.extend_from_slice(&content);
455 }
456 AsnValue::BigInteger(bytes) => {
457 out.push(0x02); encode_length(bytes.len(), out);
459 out.extend_from_slice(bytes);
460 }
461 AsnValue::BitString(data, unused_bits) => {
462 out.push(0x03); encode_length(data.len() + 1, out);
464 out.push(*unused_bits);
465 out.extend_from_slice(data);
466 }
467 AsnValue::OctetString(data) => {
468 out.push(0x04); encode_length(data.len(), out);
470 out.extend_from_slice(data);
471 }
472 AsnValue::Null => {
473 out.push(0x05); out.push(0x00); }
476 AsnValue::Oid(arcs) => {
477 let content = encode_oid(arcs);
478 out.push(0x06); encode_length(content.len(), out);
480 out.extend_from_slice(&content);
481 }
482 AsnValue::Utf8String(s) => {
483 out.push(0x0C); encode_length(s.len(), out);
485 out.extend_from_slice(s.as_bytes());
486 }
487 AsnValue::PrintableString(s) => {
488 out.push(0x13); encode_length(s.len(), out);
490 out.extend_from_slice(s.as_bytes());
491 }
492 AsnValue::Ia5String(s) => {
493 out.push(0x16); encode_length(s.len(), out);
495 out.extend_from_slice(s.as_bytes());
496 }
497 AsnValue::UtcTime(s) => {
498 out.push(0x17); encode_length(s.len(), out);
500 out.extend_from_slice(s.as_bytes());
501 }
502 AsnValue::Sequence(items) => {
503 let mut content = Vec::new();
504 for item in items {
505 Self::encode_value(item, &mut content);
506 }
507 out.push(0x30); encode_length(content.len(), out);
509 out.extend_from_slice(&content);
510 }
511 AsnValue::Set(items) => {
512 let mut content = Vec::new();
513 for item in items {
514 Self::encode_value(item, &mut content);
515 }
516 out.push(0x31); encode_length(content.len(), out);
518 out.extend_from_slice(&content);
519 }
520 AsnValue::Enumerated(n) => {
521 let content = Self::encode_integer(*n);
522 out.push(0x0A); encode_length(content.len(), out);
524 out.extend_from_slice(&content);
525 }
526 AsnValue::ContextSpecific(number, data) => {
527 encode_tag(TagClass::ContextSpecific, true, *number, out);
529 encode_length(data.len(), out);
530 out.extend_from_slice(data);
531 }
532 }
533 }
534
535 fn encode_integer(value: i64) -> Vec<u8> {
537 if value == 0 {
538 return vec![0x00];
539 }
540
541 let bytes = value.to_be_bytes();
542 let mut start = 0;
543
544 if value > 0 {
545 while start < 7 && bytes[start] == 0x00 {
547 start += 1;
548 }
549 if bytes[start] & 0x80 != 0 {
551 let mut result = vec![0x00];
552 result.extend_from_slice(&bytes[start..]);
553 return result;
554 }
555 } else {
556 while start < 7 && bytes[start] == 0xFF {
558 start += 1;
559 }
560 if bytes[start] & 0x80 == 0 {
561 let mut result = vec![0xFF];
562 result.extend_from_slice(&bytes[start..]);
563 return result;
564 }
565 }
566
567 bytes[start..].to_vec()
568 }
569}
570
571#[cfg(feature = "alloc")]
577pub struct AsnDecoder;
578
579#[cfg(feature = "alloc")]
580impl AsnDecoder {
581 pub fn decode(data: &[u8]) -> Result<(AsnValue, usize), KernelError> {
585 if data.is_empty() {
586 return Err(KernelError::InvalidArgument {
587 name: "asn1_decode",
588 value: "empty input",
589 });
590 }
591
592 let (class, constructed, tag_number, tag_len) = decode_tag(data)?;
593 let (content_len, len_bytes) = decode_length(&data[tag_len..])?;
594 let header_len = tag_len + len_bytes;
595
596 if data.len() < header_len + content_len {
597 return Err(KernelError::InvalidArgument {
598 name: "asn1_decode",
599 value: "truncated content",
600 });
601 }
602
603 let content = &data[header_len..header_len + content_len];
604 let total = header_len + content_len;
605
606 if class == TagClass::ContextSpecific || class == TagClass::Application {
608 return Ok((
609 AsnValue::ContextSpecific(tag_number, content.to_vec()),
610 total,
611 ));
612 }
613
614 let value = if constructed {
616 match tag_number {
617 16 => {
618 let items = Self::decode_sequence(content)?;
620 AsnValue::Sequence(items)
621 }
622 17 => {
623 let items = Self::decode_sequence(content)?;
625 AsnValue::Set(items)
626 }
627 _ => AsnValue::ContextSpecific(tag_number, content.to_vec()),
628 }
629 } else {
630 match tag_number {
631 1 => {
632 if content.is_empty() {
634 return Err(KernelError::InvalidArgument {
635 name: "asn1_boolean",
636 value: "empty",
637 });
638 }
639 AsnValue::Boolean(content[0] != 0)
640 }
641 2 => {
642 Self::decode_integer(content)?
644 }
645 3 => {
646 if content.is_empty() {
648 return Err(KernelError::InvalidArgument {
649 name: "asn1_bitstring",
650 value: "empty",
651 });
652 }
653 let unused_bits = content[0];
654 AsnValue::BitString(content[1..].to_vec(), unused_bits)
655 }
656 4 => {
657 AsnValue::OctetString(content.to_vec())
659 }
660 5 => {
661 AsnValue::Null
663 }
664 6 => {
665 let arcs = decode_oid(content)?;
667 AsnValue::Oid(arcs)
668 }
669 10 => {
670 match Self::decode_integer(content)? {
672 AsnValue::Integer(n) => AsnValue::Enumerated(n),
673 AsnValue::BigInteger(b) => {
674 let n = Self::big_to_i64(&b);
676 AsnValue::Enumerated(n)
677 }
678 _ => {
679 return Err(KernelError::InvalidArgument {
680 name: "asn1_enumerated",
681 value: "unexpected decode",
682 })
683 }
684 }
685 }
686 12 => {
687 let s = core::str::from_utf8(content).map_err(|_| {
689 KernelError::InvalidArgument {
690 name: "asn1_utf8string",
691 value: "invalid utf8",
692 }
693 })?;
694 AsnValue::Utf8String(String::from(s))
695 }
696 19 => {
697 let s = core::str::from_utf8(content).map_err(|_| {
699 KernelError::InvalidArgument {
700 name: "asn1_printablestring",
701 value: "invalid utf8",
702 }
703 })?;
704 AsnValue::PrintableString(String::from(s))
705 }
706 22 => {
707 let s = core::str::from_utf8(content).map_err(|_| {
709 KernelError::InvalidArgument {
710 name: "asn1_ia5string",
711 value: "invalid utf8",
712 }
713 })?;
714 AsnValue::Ia5String(String::from(s))
715 }
716 23 => {
717 let s = core::str::from_utf8(content).map_err(|_| {
719 KernelError::InvalidArgument {
720 name: "asn1_utctime",
721 value: "invalid utf8",
722 }
723 })?;
724 AsnValue::UtcTime(String::from(s))
725 }
726 _ => AsnValue::OctetString(content.to_vec()),
727 }
728 };
729
730 Ok((value, total))
731 }
732
733 fn decode_sequence(data: &[u8]) -> Result<Vec<AsnValue>, KernelError> {
735 let mut items = Vec::new();
736 let mut pos = 0;
737 while pos < data.len() {
738 let (value, consumed) = Self::decode(&data[pos..])?;
739 items.push(value);
740 pos += consumed;
741 }
742 Ok(items)
743 }
744
745 fn decode_integer(content: &[u8]) -> Result<AsnValue, KernelError> {
750 if content.is_empty() {
751 return Err(KernelError::InvalidArgument {
752 name: "asn1_integer",
753 value: "empty",
754 });
755 }
756
757 if content.len() <= 8 {
759 let negative = content[0] & 0x80 != 0;
760 let mut value: i64 = if negative { -1 } else { 0 };
761 for &b in content {
762 value = (value << 8) | (b as i64);
763 }
764 Ok(AsnValue::Integer(value))
765 } else {
766 Ok(AsnValue::BigInteger(content.to_vec()))
767 }
768 }
769
770 fn big_to_i64(bytes: &[u8]) -> i64 {
772 if bytes.is_empty() {
773 return 0;
774 }
775 let negative = bytes[0] & 0x80 != 0;
776 let mut value: i64 = if negative { -1 } else { 0 };
777 let start = if bytes.len() > 8 { bytes.len() - 8 } else { 0 };
778 for &b in &bytes[start..] {
779 value = (value << 8) | (b as i64);
780 }
781 value
782 }
783}
784
785#[cfg(feature = "alloc")]
803pub struct AsnBuilder {
804 items: Vec<AsnValue>,
805}
806
807#[cfg(feature = "alloc")]
808impl Default for AsnBuilder {
809 fn default() -> Self {
810 Self::new()
811 }
812}
813
814#[cfg(feature = "alloc")]
815impl AsnBuilder {
816 pub fn new() -> Self {
818 Self { items: Vec::new() }
819 }
820
821 pub fn boolean(mut self, value: bool) -> Self {
823 self.items.push(AsnValue::Boolean(value));
824 self
825 }
826
827 pub fn integer(mut self, value: i64) -> Self {
829 self.items.push(AsnValue::Integer(value));
830 self
831 }
832
833 pub fn big_integer(mut self, bytes: &[u8]) -> Self {
835 self.items.push(AsnValue::BigInteger(bytes.to_vec()));
836 self
837 }
838
839 pub fn bit_string(mut self, data: &[u8], unused_bits: u8) -> Self {
841 self.items
842 .push(AsnValue::BitString(data.to_vec(), unused_bits));
843 self
844 }
845
846 pub fn octet_string(mut self, data: &[u8]) -> Self {
848 self.items.push(AsnValue::OctetString(data.to_vec()));
849 self
850 }
851
852 pub fn null(mut self) -> Self {
854 self.items.push(AsnValue::Null);
855 self
856 }
857
858 pub fn oid(mut self, arcs: &[u32]) -> Self {
860 self.items.push(AsnValue::Oid(arcs.to_vec()));
861 self
862 }
863
864 pub fn utf8_string(mut self, s: &str) -> Self {
866 self.items.push(AsnValue::Utf8String(String::from(s)));
867 self
868 }
869
870 pub fn enumerated(mut self, value: i64) -> Self {
872 self.items.push(AsnValue::Enumerated(value));
873 self
874 }
875
876 pub fn context_specific(mut self, number: u8, data: &[u8]) -> Self {
878 self.items
879 .push(AsnValue::ContextSpecific(number, data.to_vec()));
880 self
881 }
882
883 pub fn context_specific_value(mut self, number: u8, value: &AsnValue) -> Self {
885 let encoded = AsnEncoder::encode(value);
886 self.items.push(AsnValue::ContextSpecific(number, encoded));
887 self
888 }
889
890 pub fn sequence<F>(mut self, f: F) -> Self
892 where
893 F: FnOnce(AsnBuilder) -> AsnBuilder,
894 {
895 let inner = f(AsnBuilder::new());
896 self.items.push(AsnValue::Sequence(inner.items));
897 self
898 }
899
900 pub fn set<F>(mut self, f: F) -> Self
902 where
903 F: FnOnce(AsnBuilder) -> AsnBuilder,
904 {
905 let inner = f(AsnBuilder::new());
906 self.items.push(AsnValue::Set(inner.items));
907 self
908 }
909
910 pub fn value(mut self, v: AsnValue) -> Self {
912 self.items.push(v);
913 self
914 }
915
916 pub fn build(self) -> Vec<u8> {
921 if self.items.len() == 1 {
922 AsnEncoder::encode(&self.items[0])
923 } else {
924 AsnEncoder::encode(&AsnValue::Sequence(self.items))
925 }
926 }
927
928 pub fn build_value(self) -> AsnValue {
930 if self.items.len() == 1 {
931 self.items.into_iter().next().unwrap_or(AsnValue::Null)
932 } else {
933 AsnValue::Sequence(self.items)
934 }
935 }
936}
937
938#[cfg(feature = "alloc")]
946pub fn encode_context_specific(number: u8, constructed: bool, content: &[u8]) -> Vec<u8> {
947 let mut out = Vec::new();
948 encode_tag(TagClass::ContextSpecific, constructed, number, &mut out);
949 encode_length(content.len(), &mut out);
950 out.extend_from_slice(content);
951 out
952}
953
954#[cfg(feature = "alloc")]
956pub fn encode_application(number: u8, constructed: bool, content: &[u8]) -> Vec<u8> {
957 let mut out = Vec::new();
958 encode_tag(TagClass::Application, constructed, number, &mut out);
959 encode_length(content.len(), &mut out);
960 out.extend_from_slice(content);
961 out
962}
963
964#[cfg(test)]
969mod tests {
970 use super::*;
971
972 #[test]
973 fn test_encode_length_short() {
974 let mut out = Vec::new();
975 encode_length(0, &mut out);
976 assert_eq!(out, [0x00]);
977
978 let mut out = Vec::new();
979 encode_length(127, &mut out);
980 assert_eq!(out, [0x7F]);
981 }
982
983 #[test]
984 fn test_encode_length_long() {
985 let mut out = Vec::new();
986 encode_length(128, &mut out);
987 assert_eq!(out, [0x81, 0x80]);
988
989 let mut out = Vec::new();
990 encode_length(256, &mut out);
991 assert_eq!(out, [0x82, 0x01, 0x00]);
992 }
993
994 #[test]
995 fn test_decode_length_short() {
996 let data = [0x05];
997 let (len, consumed) = decode_length(&data).unwrap();
998 assert_eq!(len, 5);
999 assert_eq!(consumed, 1);
1000 }
1001
1002 #[test]
1003 fn test_decode_length_long() {
1004 let data = [0x82, 0x01, 0x00];
1005 let (len, consumed) = decode_length(&data).unwrap();
1006 assert_eq!(len, 256);
1007 assert_eq!(consumed, 3);
1008 }
1009
1010 #[test]
1011 fn test_encode_decode_boolean() {
1012 let val = AsnValue::Boolean(true);
1013 let encoded = AsnEncoder::encode(&val);
1014 let (decoded, consumed) = AsnDecoder::decode(&encoded).unwrap();
1015 assert_eq!(consumed, encoded.len());
1016 assert_eq!(decoded, AsnValue::Boolean(true));
1017 }
1018
1019 #[test]
1020 fn test_encode_decode_integer_positive() {
1021 let val = AsnValue::Integer(42);
1022 let encoded = AsnEncoder::encode(&val);
1023 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1024 assert_eq!(decoded, AsnValue::Integer(42));
1025 }
1026
1027 #[test]
1028 fn test_encode_decode_integer_negative() {
1029 let val = AsnValue::Integer(-128);
1030 let encoded = AsnEncoder::encode(&val);
1031 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1032 assert_eq!(decoded, AsnValue::Integer(-128));
1033 }
1034
1035 #[test]
1036 fn test_encode_decode_integer_zero() {
1037 let val = AsnValue::Integer(0);
1038 let encoded = AsnEncoder::encode(&val);
1039 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1040 assert_eq!(decoded, AsnValue::Integer(0));
1041 }
1042
1043 #[test]
1044 fn test_encode_decode_null() {
1045 let val = AsnValue::Null;
1046 let encoded = AsnEncoder::encode(&val);
1047 assert_eq!(encoded, [0x05, 0x00]);
1048 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1049 assert_eq!(decoded, AsnValue::Null);
1050 }
1051
1052 #[test]
1053 fn test_encode_decode_octet_string() {
1054 let val = AsnValue::OctetString(vec![0x01, 0x02, 0x03]);
1055 let encoded = AsnEncoder::encode(&val);
1056 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1057 assert_eq!(decoded, val);
1058 }
1059
1060 #[test]
1061 fn test_encode_decode_utf8_string() {
1062 let val = AsnValue::Utf8String(String::from("hello"));
1063 let encoded = AsnEncoder::encode(&val);
1064 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1065 assert_eq!(decoded, AsnValue::Utf8String(String::from("hello")));
1066 }
1067
1068 #[test]
1069 fn test_encode_decode_oid() {
1070 let val = AsnValue::Oid(vec![1, 2, 840, 113549, 1, 1, 1]);
1072 let encoded = AsnEncoder::encode(&val);
1073 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1074 assert_eq!(decoded, val);
1075 }
1076
1077 #[test]
1078 fn test_encode_decode_sequence() {
1079 let val = AsnValue::Sequence(vec![
1080 AsnValue::Integer(1),
1081 AsnValue::Boolean(true),
1082 AsnValue::OctetString(vec![0xAB]),
1083 ]);
1084 let encoded = AsnEncoder::encode(&val);
1085 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1086 assert_eq!(decoded, val);
1087 }
1088
1089 #[test]
1090 fn test_encode_decode_enumerated() {
1091 let val = AsnValue::Enumerated(3);
1092 let encoded = AsnEncoder::encode(&val);
1093 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1094 assert_eq!(decoded, AsnValue::Enumerated(3));
1095 }
1096
1097 #[test]
1098 fn test_encode_decode_bit_string() {
1099 let val = AsnValue::BitString(vec![0xFF, 0x80], 1);
1100 let encoded = AsnEncoder::encode(&val);
1101 let (decoded, _) = AsnDecoder::decode(&encoded).unwrap();
1102 assert_eq!(decoded, val);
1103 }
1104
1105 #[test]
1106 fn test_builder_single_value() {
1107 let data = AsnBuilder::new().integer(42).build();
1108 let (decoded, _) = AsnDecoder::decode(&data).unwrap();
1109 assert_eq!(decoded, AsnValue::Integer(42));
1110 }
1111
1112 #[test]
1113 fn test_builder_sequence() {
1114 let data = AsnBuilder::new()
1115 .sequence(|s| s.integer(1).boolean(false).null())
1116 .build();
1117 let (decoded, _) = AsnDecoder::decode(&data).unwrap();
1118 match decoded {
1119 AsnValue::Sequence(items) => {
1120 assert_eq!(items.len(), 3);
1121 assert_eq!(items[0], AsnValue::Integer(1));
1122 assert_eq!(items[1], AsnValue::Boolean(false));
1123 assert_eq!(items[2], AsnValue::Null);
1124 }
1125 _ => panic!("expected sequence"),
1126 }
1127 }
1128
1129 #[test]
1130 fn test_decode_truncated_returns_error() {
1131 let data: &[u8] = &[0x02, 0x05, 0x01]; let result = AsnDecoder::decode(data);
1133 assert!(result.is_err());
1134 }
1135
1136 #[test]
1137 fn test_tag_encode_decode_roundtrip() {
1138 let mut out = Vec::new();
1139 encode_tag(TagClass::Application, true, 3, &mut out);
1140 let (class, constructed, number, _) = decode_tag(&out).unwrap();
1141 assert_eq!(class, TagClass::Application);
1142 assert!(constructed);
1143 assert_eq!(number, 3);
1144 }
1145}