1pub mod ber;
26#[cfg(feature = "der")]
27pub mod der;
28pub mod codec;
29pub mod parsing;
30pub(crate) mod utils;
31
32pub use crate::ber::*;
33pub use crate::codec::*;
34pub use crate::parsing::*;
35pub use crate::utils::primitive;
36
37use crate::utils::likely;
38use wildboar_asn1::error::{ASN1Error, ASN1ErrorCode, ASN1Result};
39use wildboar_asn1::{
40 ByteSlice, CharacterString, EmbeddedPDV, ExternalEncoding,
41 ExternalIdentification, GeneralizedTime,
42 PresentationContextSwitchingTypeIdentification, Tag, TagClass, TagNumber,
43 UTCTime,
44 UNIV_TAG_INTEGER,
45 UNIV_TAG_OBJECT_IDENTIFIER, UNIV_TAG_OCTET_STRING,
46 UNIV_TAG_OBJECT_DESCRIPTOR, BIT_STRING, BOOLEAN, DATE, DATE_TIME,
47 DURATION_EQUIVALENT, EXTERNAL, INTEGER, OBJECT_IDENTIFIER,
48 OCTET_STRING, REAL, RELATIVE_OID, TIME, TIME_OF_DAY,
49 UNIV_TAG_NULL,
50 UNIV_TAG_BOOLEAN,
51};
52use wildboar_asn1::{ENUMERATED, read_i64, DURATION, ComponentSpec, TagSelector};
53use std::borrow::Cow;
54use std::io::{Error, ErrorKind, Result, Write};
55use std::mem::size_of;
56use std::sync::Arc;
57use bytes::{Bytes, BytesMut, BufMut};
58
59pub const X690_TAG_CLASS_UNIVERSAL: u8 = 0b0000_0000;
61
62pub const X690_TAG_CLASS_APPLICATION: u8 = 0b0100_0000;
64
65pub const X690_TAG_CLASS_CONTEXT: u8 = 0b1000_0000;
67
68pub const X690_TAG_CLASS_PRIVATE: u8 = 0b1100_0000;
70
71pub const X690_SPECIAL_REAL_PLUS_INFINITY: u8 = 0b0000_0000;
73
74pub const X690_SPECIAL_REAL_MINUS_INFINITY: u8 = 0b0000_0001;
76
77pub const X690_SPECIAL_REAL_NOT_A_NUMBER: u8 = 0b0000_0010;
79
80pub const X690_SPECIAL_REAL_MINUS_ZERO: u8 = 0b0000_0011;
82
83pub const X690_REAL_SPECIAL: u8 = 0b0100_0000;
85
86pub const X690_REAL_BASE10: u8 = 0b0000_0000;
88
89pub const X690_REAL_BINARY: u8 = 0b1000_0000;
91
92pub const X690_REAL_POSITIVE: u8 = 0b0000_0000;
94
95pub const X690_REAL_NEGATIVE: u8 = 0b0100_0000;
97
98pub const X690_REAL_SIGN_MASK: u8 = 0b0100_0000;
100
101pub const X690_REAL_BASE_MASK: u8 = 0b0011_0000;
103
104pub const X690_REAL_BASE_2: u8 = 0b0000_0000;
106
107pub const X690_REAL_BASE_8: u8 = 0b0001_0000;
109
110pub const X690_REAL_BASE_16: u8 = 0b0010_0000;
112
113pub const X690_REAL_BASE_RESERVED: u8 = 0b0011_0000;
115
116pub const X690_REAL_BINARY_SCALING_MASK: u8 = 0b0000_1100;
118
119pub const X690_REAL_EXPONENT_FORMAT_MASK: u8 = 0b0000_0011;
121
122pub const X690_REAL_EXPONENT_FORMAT_1_OCTET: u8 = 0b0000_0000;
124
125pub const X690_REAL_EXPONENT_FORMAT_2_OCTET: u8 = 0b0000_0001;
127
128pub const X690_REAL_EXPONENT_FORMAT_3_OCTET: u8 = 0b0000_0010;
130
131pub const X690_REAL_EXPONENT_FORMAT_VAR_OCTET: u8 = 0b0000_0011;
133
134pub const X690_REAL_NR1: u8 = 1;
136
137pub const X690_REAL_NR2: u8 = 2;
139
140pub const X690_REAL_NR3: u8 = 3;
142
143#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq)]
148pub enum X690Length {
149 Definite(usize),
151 Indefinite,
153}
154
155#[derive(Clone, Debug, Hash)]
160pub enum X690Value {
161 Primitive(Bytes),
163 Constructed(Arc<Vec<X690Element>>),
165 Serialized(Bytes),
167}
168
169impl X690Value {
170
171 pub fn len(&self) -> usize {
177 match self {
178 X690Value::Primitive(v) => v.len(),
179 X690Value::Constructed(components) => {
180 let mut sum: usize = 0;
181 for component in components.iter() {
182 sum += component.len();
183 }
184 sum
185 },
186 X690Value::Serialized(v) => {
187 match BER.decode_from_slice(&v) {
188 Ok((_, el)) => el.len(),
189 Err(_) => return 0,
190 }
191 }
192 }
193 }
194
195 #[inline]
199 pub fn from_explicit(inner: X690Element) -> Self {
200 X690Value::Constructed(Arc::new(Vec::from([ inner ])))
201 }
202
203 pub fn components(&self) -> ASN1Result<Arc<Vec<X690Element>>> {
209 match self {
210 X690Value::Constructed(components) => Ok(components.clone()),
211 X690Value::Serialized(v) => {
212 let (_, el) = BER.decode_from_slice(&v)?;
213 el.value.components()
214 },
215 _ => Err(ASN1Error::new(ASN1ErrorCode::invalid_construction)),
216 }
217 }
218
219}
220
221#[derive(Clone, Debug, Hash)]
227pub struct X690Element {
228 pub tag: Tag,
230 pub value: X690Value,
232}
233
234impl X690Element {
235
236 #[inline]
238 pub const fn new(tag: Tag, value: X690Value) -> X690Element {
239 X690Element { tag, value }
240 }
241
242 #[inline]
244 pub const fn null() -> X690Element {
245 X690Element {
246 tag: Tag::new(TagClass::UNIVERSAL, UNIV_TAG_NULL),
247 value: X690Value::Primitive(Bytes::new()),
248 }
249 }
250
251 #[inline]
253 pub const fn boolean_true() -> X690Element {
254 X690Element {
255 tag: Tag::new(TagClass::UNIVERSAL, UNIV_TAG_BOOLEAN),
256 value: X690Value::Primitive(Bytes::from_static(&[ 0xff ])),
257 }
258 }
259
260 #[inline]
262 pub const fn boolean_false() -> X690Element {
263 X690Element {
264 tag: Tag::new(TagClass::UNIVERSAL, UNIV_TAG_BOOLEAN),
265 value: X690Value::Primitive(Bytes::from_static(&[ 0x00 ])),
266 }
267 }
268
269 pub fn len(&self) -> usize {
273 let tag_length: usize = get_written_x690_tag_length(self.tag.tag_number);
274 let value_length = self.value.len();
275 let length_length: usize = get_written_x690_length_length(value_length);
276 let ret = tag_length + length_length + value_length;
277 ret
278 }
279
280 #[inline]
286 pub fn is_constructed (&self) -> bool {
287 if let X690Value::Serialized(v) = &self.value {
288 return v.get(0).is_some_and(|b| (*b & 0b0010_0000) == 0b0010_0000);
289 }
290 if let X690Value::Constructed(_) = self.value {
291 true
292 } else {
293 false
294 }
295 }
296
297 #[inline]
301 pub fn components (&self) -> ASN1Result<Arc<Vec<X690Element>>> {
302 self.value.components()
303 }
304
305 pub fn inner(&self) -> ASN1Result<X690Element> {
310 match &self.value {
311 X690Value::Constructed(components) => {
312 if components.len() != 1 {
313 return Err(self.to_asn1_error(ASN1ErrorCode::invalid_construction));
314 }
315 Ok(components[0].clone())
316 },
317 X690Value::Serialized(v) => {
318 let (_, el) = BER.decode_from_slice(&v)?;
319 el.inner()
320 },
321 _ => Err(self.to_asn1_error(ASN1ErrorCode::invalid_construction)),
322 }
323 }
324
325 pub fn content_octets <'a> (&'a self) -> ASN1Result<Cow<'a, [u8]>> {
331 match &self.value {
332 X690Value::Primitive(v) => Ok(Cow::Borrowed(&v)),
333 X690Value::Constructed(_) => {
334 let mut output = BytesMut::with_capacity(self.len()).writer();
335 x690_write_value(&mut output, &self.value)?;
336 Ok(Cow::Owned(output.into_inner().into()))
337 },
338 X690Value::Serialized(v) => {
339 let (_, el) = BER.decode_from_slice(v).unwrap();
340 match el.value {
341 X690Value::Primitive(inner) => Ok(Cow::Owned(inner.to_vec())),
342 X690Value::Constructed(_) => {
343 let mut output = BytesMut::with_capacity(el.len()).writer();
344 x690_write_value(&mut output, &el.value)?;
345 Ok(Cow::Owned(output.into_inner().into()))
346 },
347 _ => panic!("ASN.1 / X.690 decoding returned serialized value"),
348 }
349 }
350 }
351 }
352
353 #[inline]
358 pub fn to_asn1_error (&self, errcode: ASN1ErrorCode) -> ASN1Error {
359 ASN1Error {
360 error_code: errcode,
361 component_name: None,
362 tag: Some(Tag::new(self.tag.tag_class, self.tag.tag_number)),
363 length: Some(self.len()),
364 constructed: Some(self.is_constructed()),
365 value_preview: None,
366 bytes_read: None,
367 values_read: None,
368 err_source: None,
369 }
370 }
371
372 pub fn to_asn1_err_named (&self, errcode: ASN1ErrorCode, name: &str) -> ASN1Error {
377 let mut e = self.to_asn1_error(errcode);
378 e.component_name = Some(name.to_string());
379 e
380 }
381
382 #[inline]
388 pub fn is_empty (&self) -> bool {
389 match &self.value {
390 X690Value::Primitive(v) => v.len() == 0,
391 X690Value::Constructed(components) => components.len() == 0,
392 X690Value::Serialized(v) => v.len() <= 2,
393 }
394 }
395
396 #[inline]
413 pub fn iter_deconstruction<'a>(&'a self) -> DeconstructionIterator<'a> {
414 DeconstructionIterator::new(self)
415 }
416
417}
418
419impl From<i8> for X690Element {
420 #[inline]
422 fn from(value: i8) -> Self {
423 BER.encode_i8(value).unwrap()
424 }
425}
426
427impl From<i16> for X690Element {
428 #[inline]
430 fn from(value: i16) -> Self {
431 BER.encode_i16(value).unwrap()
432 }
433}
434
435impl From<i32> for X690Element {
436 #[inline]
438 fn from(value: i32) -> Self {
439 BER.encode_i32(value).unwrap()
440 }
441}
442
443impl From<i64> for X690Element {
444 #[inline]
446 fn from(value: i64) -> Self {
447 BER.encode_i64(value).unwrap()
448 }
449}
450
451impl From<u8> for X690Element {
452 #[inline]
454 fn from(value: u8) -> Self {
455 BER.encode_u8(value).unwrap()
456 }
457}
458
459impl From<u16> for X690Element {
460 #[inline]
462 fn from(value: u16) -> Self {
463 BER.encode_u16(value).unwrap()
464 }
465}
466
467impl From<u32> for X690Element {
468 #[inline]
470 fn from(value: u32) -> Self {
471 BER.encode_u32(value).unwrap()
472 }
473}
474
475impl From<u64> for X690Element {
476 #[inline]
478 fn from(value: u64) -> Self {
479 BER.encode_u64(value).unwrap()
480 }
481}
482
483impl From<OBJECT_IDENTIFIER> for X690Element {
484 #[inline]
486 fn from(value: OBJECT_IDENTIFIER) -> Self {
487 X690Element::from(&value)
488 }
489}
490
491impl From<&OBJECT_IDENTIFIER> for X690Element {
492 #[inline]
494 fn from(value: &OBJECT_IDENTIFIER) -> Self {
495 BER.encode_object_identifier(value).unwrap()
496 }
497}
498
499impl From<bool> for X690Element {
500 #[inline]
502 fn from(value: bool) -> Self {
503 BER.encode_boolean(&value).unwrap()
504 }
505}
506
507impl From<DATE> for X690Element {
508 #[inline]
510 fn from(value: DATE) -> Self {
511 BER.encode_date(&value).unwrap()
512 }
513}
514
515impl From<TIME_OF_DAY> for X690Element {
516 #[inline]
518 fn from(value: TIME_OF_DAY) -> Self {
519 BER.encode_time_of_day(&value).unwrap()
520 }
521}
522
523impl From<DATE_TIME> for X690Element {
524 #[inline]
526 fn from(value: DATE_TIME) -> Self {
527 BER.encode_date_time(&value).unwrap()
528 }
529}
530
531impl From<TIME> for X690Element {
532 #[inline]
534 fn from(value: TIME) -> Self {
535 BER.encode_time(&value).unwrap()
536 }
537}
538
539impl From<DURATION> for X690Element {
540 #[inline]
542 fn from(value: DURATION) -> Self {
543 BER.encode_duration(&value).unwrap()
544 }
545}
546
547impl TryInto<i8> for X690Element {
548 type Error = ASN1Error;
549 #[inline]
551 fn try_into(self) -> ASN1Result<i8> {
552 BER.decode_i8(&self)
553 }
554}
555
556impl TryInto<i16> for X690Element {
557 type Error = ASN1Error;
558 #[inline]
560 fn try_into(self) -> ASN1Result<i16> {
561 BER.decode_i16(&self)
562 }
563}
564
565impl TryInto<i32> for X690Element {
566 type Error = ASN1Error;
567 #[inline]
569 fn try_into(self) -> ASN1Result<i32> {
570 BER.decode_i32(&self)
571 }
572}
573
574impl TryInto<i64> for X690Element {
575 type Error = ASN1Error;
576 #[inline]
578 fn try_into(self) -> ASN1Result<i64> {
579 BER.decode_i64(&self)
580 }
581}
582
583impl TryInto<i128> for X690Element {
584 type Error = ASN1Error;
585 #[inline]
587 fn try_into(self) -> ASN1Result<i128> {
588 BER.decode_i128(&self)
589 }
590}
591
592impl TryInto<u8> for X690Element {
593 type Error = ASN1Error;
594 #[inline]
596 fn try_into(self) -> ASN1Result<u8> {
597 BER.decode_u8(&self)
598 }
599}
600
601impl TryInto<u16> for X690Element {
602 type Error = ASN1Error;
603 #[inline]
605 fn try_into(self) -> ASN1Result<u16> {
606 BER.decode_u16(&self)
607 }
608}
609
610impl TryInto<u32> for X690Element {
611 type Error = ASN1Error;
612 #[inline]
614 fn try_into(self) -> ASN1Result<u32> {
615 BER.decode_u32(&self)
616 }
617}
618
619impl TryInto<u64> for X690Element {
620 type Error = ASN1Error;
621 #[inline]
623 fn try_into(self) -> ASN1Result<u64> {
624 BER.decode_u64(&self)
625 }
626}
627
628impl TryInto<u128> for X690Element {
629 type Error = ASN1Error;
630 #[inline]
632 fn try_into(self) -> ASN1Result<u128> {
633 BER.decode_u128(&self)
634 }
635}
636
637impl TryInto<BOOLEAN> for X690Element {
638 type Error = ASN1Error;
639 #[inline]
641 fn try_into(self) -> ASN1Result<BOOLEAN> {
642 BER.decode_boolean(&self)
643 }
644}
645
646impl PartialEq for X690Element {
647 fn eq(&self, other: &Self) -> bool {
653 fn as_decoded<'a>(el: &'a X690Element) -> Cow<'a, X690Element> {
655 match &el.value {
656 X690Value::Serialized(bytes) => {
657 match BER.decode_from_slice(bytes) {
658 Ok((_, decoded)) => Cow::Owned(decoded),
659 Err(_) => Cow::Borrowed(el), }
661 }
662 _ => Cow::Borrowed(el),
663 }
664 }
665
666 let left = as_decoded(self);
667 let right = as_decoded(other);
668
669 match (&left.value, &right.value) {
670 (X690Value::Primitive(a), X690Value::Primitive(b)) => a == b,
671 (X690Value::Constructed(a), X690Value::Constructed(b)) => {
672 if a.len() != b.len() {
673 return false;
674 }
675 a.iter().zip(b.iter()).all(|(x, y)| x == y)
676 }
677 (X690Value::Primitive(_), _) | (X690Value::Constructed(_), _) | (_, X690Value::Primitive(_)) | (_, X690Value::Constructed(_)) => false,
678 _ => false,
680 }
681 }
682}
683
684impl Eq for X690Element {}
685
686pub fn x690_decode_tag(bytes: ByteSlice) -> ASN1Result<(usize, Tag, bool)> {
695 if bytes.len() == 0 {
696 return Err(ASN1Error::new(ASN1ErrorCode::tlv_truncated));
697 }
698 let mut bytes_read = 1;
699 let tag_class = match (bytes[0] & 0b1100_0000) >> 6 {
700 0 => TagClass::UNIVERSAL,
701 1 => TagClass::APPLICATION,
702 2 => TagClass::CONTEXT,
703 3 => TagClass::PRIVATE,
704 _ => panic!("Impossible tag class"),
705 };
706 let constructed = (bytes[0] & 0b0010_0000) > 0;
707 let mut tag_number: TagNumber = 0;
708
709 if (bytes[0] & 0b00011111) == 0b00011111 {
710 for byte in bytes[1..].iter() {
712 let final_byte: bool = ((*byte) & 0b1000_0000) == 0;
713 if (tag_number > 0) && !final_byte {
714 return Err(ASN1Error::new(ASN1ErrorCode::tag_too_big));
717 }
718 let seven_bits = ((*byte) & 0b0111_1111) as u16;
719 if !final_byte && (seven_bits == 0) {
720 return Err(ASN1Error::new(ASN1ErrorCode::padding_in_tag_number));
722 }
723 tag_number <<= 7;
724 tag_number += seven_bits;
725 bytes_read += 1;
726 if final_byte {
727 break;
728 }
729 }
730 if tag_number <= 30 {
731 return Err(ASN1Error::new(ASN1ErrorCode::tag_number_could_have_used_short_form));
733 }
734 } else {
735 tag_number = (bytes[0] & 0b00011111) as TagNumber;
736 }
737
738 let tag = Tag::new(tag_class, tag_number);
739 Ok((bytes_read, tag, constructed))
740}
741
742pub fn get_x690_tag_and_length_length(bytes: ByteSlice) -> usize {
747 if bytes.len() == 0 {
748 return 0;
749 }
750 let mut len: usize = 1;
751 if (bytes[0] & 0b00011111) == 0b00011111 {
752 for byte in bytes[1..].iter() {
754 len += 1; if ((*byte) & 0b1000_0000) == 0 {
756 break;
757 }
758 }
759 }
760 if len >= bytes.len() {
761 return len;
762 }
763 let length_byte_0 = bytes[len - 1];
764 len += 1;
765 if (length_byte_0 & 0b1000_0000) == 0 {
766 return len;
768 }
769 (length_byte_0 & 0b0111_1111) as usize
770}
771
772const fn base_128_len(num: u32) -> usize {
777 if likely(num < 128) {
778 return 1;
779 }
780 let mut l = 0;
781 let mut i = num;
782 while i > 0 {
783 l += 1;
784 i >>= 7;
785 }
786 return l;
787}
788
789fn write_base_128<W>(output: &mut W, mut num: u32) -> Result<usize>
796where
797 W: Write,
798{
799 #[cfg(feature = "likely_stable")]
800 if likely(num < 128) {
801 return output.write(&[num as u8]);
802 }
803
804 let mut encoded: [u8; 5] = [0; 5];
806 let mut byte_count: usize = 0;
807 while num > 0b0111_1111 {
808 encoded[byte_count] = (num & 0b0111_1111) as u8 | 0b1000_0000;
809 byte_count += 1;
810 num >>= 7;
811 }
812 encoded[byte_count] = num as u8;
813 output.write(&encoded[0..byte_count+1])
814}
815
816pub const fn get_written_x690_tag_length(tagnum: TagNumber) -> usize {
821 if tagnum < 31 {
822 return 1;
824 }
825 base_128_len(tagnum as u32) + 1
826}
827
828pub const fn get_written_x690_length_length(len: usize) -> usize {
833 if len <= 127 {
834 return 1;
836 }
837 let octets_needed: usize = match len {
838 0..=255 => 1,
839 256..=65535 => 2,
840 65536..=16777215 => 3,
841 16777216..=4294967295 => 4,
842 _ => return 5, };
844 octets_needed + 1
845}
846
847pub fn x690_write_tag<W>(
854 output: &mut W,
855 class: TagClass,
856 constructed: bool,
857 tagnum: TagNumber,
858) -> Result<usize>
859where
860 W: Write,
861{
862 let k: u8 = match class {
863 TagClass::UNIVERSAL => X690_TAG_CLASS_UNIVERSAL,
864 TagClass::APPLICATION => X690_TAG_CLASS_APPLICATION,
865 TagClass::CONTEXT => X690_TAG_CLASS_CONTEXT,
866 TagClass::PRIVATE => X690_TAG_CLASS_PRIVATE,
867 };
868 if tagnum < 31 {
869 return output.write(&[k
871 | if constructed {
872 0b0010_0000
873 } else {
874 0b0000_0000
875 }
876 | tagnum as u8]);
877 } else {
878 let first_byte_result = output.write(&[k
879 | if constructed {
880 0b0010_0000
881 } else {
882 0b0000_0000
883 }
884 | 0b0001_1111u8]);
885 if let Err(e) = first_byte_result {
886 return Err(e);
887 }
888 return write_base_128(output, tagnum.into());
889 }
890}
891
892pub fn x690_write_length<W>(output: &mut W, length: usize) -> Result<usize>
899where
900 W: Write,
901{
902 if length <= 127 {
903 return output.write(&[length as u8]);
905 } else {
906 let octets_needed: u8 = match length {
909 0..=255 => 1,
910 256..=65535 => 2,
911 65536..=16777215 => 3,
912 16777216..=4294967295 => 4,
913 _ => return Err(Error::from(ErrorKind::Unsupported)),
914 };
915 let length_bytes = length.to_be_bytes();
916 output.write(&[0b1000_0000 | octets_needed])?;
917 output.write(&length_bytes[std::mem::size_of::<usize>()-octets_needed as usize..])
918 .map(|n| n + 1)
919 }
920}
921
922#[inline]
928pub fn x690_write_boolean_value<W>(output: &mut W, value: &BOOLEAN) -> Result<usize>
929where
930 W: Write,
931{
932 if *value {
933 return output.write(&[0xFF]);
934 } else {
935 return output.write(&[0x00]);
936 }
937}
938
939#[inline]
945pub fn x690_write_integer_value<W>(output: &mut W, value: &INTEGER) -> Result<usize>
946where
947 W: Write,
948{
949 if value.len() == 0 {
950 return Err(std::io::Error::from(ErrorKind::InvalidData));
951 }
952 if value.len() == 1 {
953 return output.write(value);
954 }
955 if value[0] == 0x00 && (value[1] & 0b1000_0000) == 0 {
956 return Err(std::io::Error::from(ErrorKind::InvalidData));
957 }
958 if value[0] == 0xFF && (value[1] & 0b1000_0000) > 0 {
959 return Err(std::io::Error::from(ErrorKind::InvalidData));
960 }
961 output.write(value)
962}
963
964pub fn x690_write_i64_value<W>(output: &mut W, value: i64) -> Result<usize>
971where
972 W: Write,
973{
974 let bytes: [u8; 8] = value.to_be_bytes();
975 let padding_byte: u8 = if value >= 0 { 0x00 } else { 0xFF };
976 let mut number_of_padding_bytes: usize = 0;
977 for byte in bytes {
978 if byte == padding_byte {
979 number_of_padding_bytes += 1;
980 } else {
981 break;
982 }
983 }
984 let mut bytes_written: usize = 0;
985 if (number_of_padding_bytes == size_of::<i64>())
986 || (value >= 0 && ((bytes[number_of_padding_bytes] & 0b1000_0000) > 0))
987 || (value < 0 && ((bytes[number_of_padding_bytes] & 0b1000_0000) == 0)) {
988 bytes_written += output.write(&[padding_byte])?;
989 }
990 bytes_written += output.write(&(bytes[number_of_padding_bytes..size_of::<i64>()]))?;
991 Ok(bytes_written)
992}
993
994#[inline]
1000pub fn x690_write_enum_value<W>(output: &mut W, value: &ENUMERATED) -> Result<usize>
1001where
1002 W: Write,
1003{
1004 x690_write_i64_value(output, *value)
1005}
1006
1007pub fn x690_write_bit_string_value<W>(output: &mut W, value: &BIT_STRING) -> Result<usize>
1013where
1014 W: Write,
1015{
1016 let trailing_bits = value.get_trailing_bits_count();
1017 output.write(&[trailing_bits])?;
1018 if trailing_bits == 0 {
1019 let bytes_written = output.write(value.get_bytes_ref())?;
1020 return Ok(bytes_written + 1);
1021 }
1022 let maybe_last_byte = value.get_bytes_ref().last();
1024 let der_violated;
1025 let bytes = value.get_bytes_ref();
1026 let correct_last_byte: u8;
1027 if let Some(last_byte) = maybe_last_byte {
1028 let trailing_bits_mask = !(0xFFu8 << trailing_bits);
1029 der_violated = (last_byte & trailing_bits_mask) > 0;
1030 correct_last_byte = last_byte & (0xFFu8 << trailing_bits);
1031 } else {
1032 return Err(std::io::Error::from(ErrorKind::InvalidData));
1033 }
1034
1035 if likely(!der_violated) {
1037 let bytes_written = output.write(value.get_bytes_ref())?;
1038 return Ok(bytes_written + 1);
1039 }
1040
1041 debug_assert!(maybe_last_byte.is_some());
1042 let mut bytes_written = output.write(&bytes[..bytes.len() - 1])?;
1043 bytes_written += output.write(&[ correct_last_byte ])?;
1044 Ok(bytes_written + 1)
1045}
1046
1047#[inline]
1053pub fn x690_write_octet_string_value<W>(output: &mut W, value: &OCTET_STRING) -> Result<usize>
1054where
1055 W: Write,
1056{
1057 output.write(value)
1058}
1059
1060#[inline]
1066pub fn x690_write_object_identifier_value<W>(
1067 output: &mut W,
1068 value: &OBJECT_IDENTIFIER,
1069) -> Result<usize>
1070where
1071 W: Write,
1072{
1073 output.write(value.as_x690_slice())
1074}
1075
1076#[inline]
1082pub fn x690_write_object_descriptor_value<W>(
1083 output: &mut W,
1084 value: &str,
1085) -> Result<usize>
1086where
1087 W: Write,
1088{
1089 output.write(value.as_bytes())
1090}
1091
1092pub fn x690_encode_external_components (value: &EXTERNAL) -> Result<Vec<X690Element>> {
1106 let mut inner_elements: Vec<X690Element> = Vec::with_capacity(4);
1107 match &value.identification {
1108 ExternalIdentification::syntax(oid) => {
1109 let mut bytes = BytesMut::new().writer();
1110 x690_write_object_identifier_value(&mut bytes, &oid)?;
1111 let element = X690Element::new(
1112 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OBJECT_IDENTIFIER),
1113 X690Value::Primitive(bytes.into_inner().into()),
1114 );
1115 inner_elements.push(element);
1116 }
1117 ExternalIdentification::presentation_context_id(pci) => {
1118 let mut bytes = BytesMut::new().writer();
1119 x690_write_integer_value(&mut bytes, pci)?;
1120 let element = X690Element::new(
1121 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER),
1122 X690Value::Primitive(bytes.into_inner().into()),
1123 );
1124 inner_elements.push(element);
1125 }
1126 ExternalIdentification::context_negotiation(cn) => {
1127 let mut direct_ref_bytes = BytesMut::new().writer();
1128 x690_write_object_identifier_value(&mut direct_ref_bytes, &cn.transfer_syntax)?;
1129 let direct_ref_element = X690Element::new(
1130 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OBJECT_IDENTIFIER),
1131 X690Value::Primitive(direct_ref_bytes.into_inner().into()),
1132 );
1133 inner_elements.push(direct_ref_element);
1134 let mut indirect_ref_bytes = BytesMut::new().writer();
1135 x690_write_integer_value(&mut indirect_ref_bytes, &cn.presentation_context_id)?;
1136 let indirect_ref_element = X690Element::new(
1137 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER),
1138 X690Value::Primitive(indirect_ref_bytes.into_inner().into()),
1139 );
1140 inner_elements.push(indirect_ref_element);
1141 }
1142 };
1143 match &value.data_value_descriptor {
1144 Some(dvd) => {
1145 let mut bytes = BytesMut::new().writer();
1146 x690_write_object_descriptor_value(&mut bytes, &dvd)?;
1147 let element = X690Element::new(
1148 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OBJECT_DESCRIPTOR),
1149 X690Value::Primitive(bytes.into_inner().into()),
1150 );
1151 inner_elements.push(element);
1152 }
1153 None => (),
1154 };
1155 let mut data_value_bytes = BytesMut::new().writer();
1156 match &value.data_value {
1157 ExternalEncoding::single_ASN1_type(t) => {
1158 let el = BER.encode_any(t)?;
1159 x690_write_tlv(&mut data_value_bytes, &el)?
1160 },
1161 ExternalEncoding::octet_aligned(o) => x690_write_octet_string_value(&mut data_value_bytes, o)?,
1162 ExternalEncoding::arbitrary(b) => x690_write_bit_string_value(&mut data_value_bytes, b)?,
1163 };
1164 let data_value_element = X690Element::new(
1165 Tag::new(TagClass::CONTEXT, 1),
1166 X690Value::Primitive(data_value_bytes.into_inner().into()),
1167 );
1168 inner_elements.push(data_value_element);
1169 Ok(inner_elements)
1170}
1171
1172pub fn x690_write_external_value<W>(output: &mut W, value: &EXTERNAL) -> Result<usize>
1187where
1188 W: Write,
1189{
1190 let components = x690_encode_external_components(value)?;
1191 let mut bytes_written: usize = 0;
1192 for component in components {
1193 bytes_written += x690_write_tlv(output, &component)?;
1194 }
1195 Ok(bytes_written)
1196}
1197
1198pub fn x690_write_real_value<W>(output: &mut W, value: &REAL) -> Result<usize>
1215where
1216 W: Write,
1217{
1218 let is_zero = *value == 0.0;
1222 if is_zero {
1224 return Ok(0);
1225 }
1226 if is_zero && value.is_sign_negative() {
1228 return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_MINUS_ZERO]);
1229 }
1230
1231 if value.is_nan() {
1232 return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_NOT_A_NUMBER]);
1233 }
1234
1235 if value.is_infinite() {
1236 if value.is_sign_negative() {
1237 return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_MINUS_INFINITY]);
1238 } else {
1239 return output.write(&[X690_REAL_SPECIAL | X690_SPECIAL_REAL_PLUS_INFINITY]);
1240 }
1241 }
1242
1243 let sign_bit: u8 = if value.is_sign_negative() {
1244 X690_REAL_NEGATIVE
1245 } else {
1246 X690_REAL_POSITIVE
1247 };
1248 let base_bits: u8 = X690_REAL_BASE_2;
1249 let scaling_factor: u8 = 0;
1250 let bits = value.to_bits();
1251 let mantissa_mask = (1u64 << 52) - 1;
1252 let mantissa: u64 = bits & mantissa_mask;
1253 let biased_exp = ((bits >> 52) & 0x7FF) as u16;
1254
1255 let mut mantissa = if biased_exp != 0 { mantissa | (1u64 << 52) } else { mantissa };
1257 let mut exponent = if biased_exp != 0 { biased_exp as i16 - 1023 - 52 } else { -1023 - 51 };
1258
1259 while mantissa > 0 && mantissa & 1 == 0 {
1261 mantissa >>= 1;
1262 exponent += 1;
1263 }
1264
1265 let e_bytes = exponent.to_be_bytes();
1266 let mut bytes_written: usize = 0;
1267 if exponent > u8::MAX as i16 {
1268 let byte0: u8 = X690_REAL_BINARY
1269 | sign_bit
1270 | base_bits
1271 | scaling_factor
1272 | X690_REAL_EXPONENT_FORMAT_2_OCTET;
1273 bytes_written += output.write(&[byte0, e_bytes[0], e_bytes[1]])?;
1274 } else {
1275 let byte0: u8 = X690_REAL_BINARY
1276 | sign_bit
1277 | base_bits
1278 | scaling_factor
1279 | X690_REAL_EXPONENT_FORMAT_1_OCTET;
1280 bytes_written += output.write(&[byte0, e_bytes[1]])?;
1281 };
1282
1283 return match x690_write_i64_value(output, mantissa as i64) {
1284 Err(e) => return Err(e),
1285 Ok(wrote) => Ok(wrote + bytes_written),
1286 };
1287}
1288
1289pub fn x690_encode_context_switching_identification(
1303 id: &PresentationContextSwitchingTypeIdentification,
1304) -> Result<X690Element> {
1305 match id {
1306 PresentationContextSwitchingTypeIdentification::syntaxes(syntaxes) => {
1307 let mut abstract_value_bytes = BytesMut::new().writer();
1308 let mut transfer_value_bytes = BytesMut::new().writer();
1309 x690_write_object_identifier_value(
1310 &mut abstract_value_bytes,
1311 &syntaxes.r#abstract,
1312 )?;
1313 x690_write_object_identifier_value(&mut transfer_value_bytes, &syntaxes.transfer)?;
1314 let mut syntaxes_elements: Vec<X690Element> = Vec::with_capacity(2);
1315 syntaxes_elements.push(X690Element::new(
1316 Tag::new(TagClass::CONTEXT, 0),
1317 X690Value::Primitive(abstract_value_bytes.into_inner().into()),
1318 ));
1319 syntaxes_elements.push(X690Element::new(
1320 Tag::new(TagClass::CONTEXT, 1),
1321 X690Value::Primitive(transfer_value_bytes.into_inner().into()),
1322 ));
1323 let element = X690Element::new(
1324 Tag::new(TagClass::CONTEXT, 0),
1325 X690Value::Constructed(Arc::new(syntaxes_elements)),
1326 );
1327 return Ok(X690Element::new(
1328 Tag::new(TagClass::CONTEXT, 0),
1329 X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1330 ));
1331 }
1332 PresentationContextSwitchingTypeIdentification::syntax(oid) => {
1333 let mut bytes = BytesMut::with_capacity(oid.as_x690_slice().len()).writer();
1335 x690_write_object_identifier_value(&mut bytes, &oid)?;
1336 let element = X690Element::new(
1337 Tag::new(TagClass::CONTEXT, 1),
1338 X690Value::Primitive(bytes.into_inner().into()),
1339 );
1340 return Ok(X690Element::new(
1341 Tag::new(TagClass::CONTEXT, 0),
1342 X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1343 ));
1344 }
1345 PresentationContextSwitchingTypeIdentification::presentation_context_id(pci) => {
1346 let mut bytes = BytesMut::with_capacity(pci.len()).writer();
1347 x690_write_integer_value(&mut bytes, pci)?;
1348 let element = X690Element::new(
1349 Tag::new(TagClass::CONTEXT, 2),
1350 X690Value::Primitive(bytes.into_inner().into()),
1351 );
1352 return Ok(X690Element::new(
1353 Tag::new(TagClass::CONTEXT, 0),
1354 X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1355 ));
1356 }
1357 PresentationContextSwitchingTypeIdentification::context_negotiation(cn) => {
1358 let mut pci_bytes = BytesMut::new().writer();
1359 x690_write_integer_value(&mut pci_bytes, &cn.presentation_context_id)?;
1360 let pci_element = X690Element::new(
1361 Tag::new(TagClass::CONTEXT, 0),
1362 X690Value::Primitive(pci_bytes.into_inner().into()),
1363 );
1364 let mut transfer_syntax_bytes = BytesMut::new().writer();
1365 x690_write_object_identifier_value(
1366 &mut transfer_syntax_bytes,
1367 &cn.transfer_syntax,
1368 )?;
1369 let transfer_syntax_element = X690Element::new(
1370 Tag::new(TagClass::CONTEXT, 1),
1371 X690Value::Primitive(transfer_syntax_bytes.into_inner().into()),
1372 );
1373 let cn_elements: Vec<X690Element> = vec![pci_element, transfer_syntax_element];
1374 let element = X690Element::new(
1375 Tag::new(TagClass::CONTEXT, 3),
1376 X690Value::Constructed(Arc::new(cn_elements)),
1377 );
1378 return Ok(X690Element::new(
1379 Tag::new(TagClass::CONTEXT, 0),
1380 X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1381 ));
1382 }
1383 PresentationContextSwitchingTypeIdentification::transfer_syntax(ts) => {
1384 let mut bytes = BytesMut::new().writer();
1385 x690_write_object_identifier_value(&mut bytes, &ts)?;
1386 let element = X690Element::new(
1387 Tag::new(TagClass::CONTEXT, 4),
1388 X690Value::Primitive(bytes.into_inner().into()),
1389 );
1390 return Ok(X690Element::new(
1391 Tag::new(TagClass::CONTEXT, 0),
1392 X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1393 ));
1394 }
1395 PresentationContextSwitchingTypeIdentification::fixed => {
1396 let element = X690Element::new(
1397 Tag::new(TagClass::CONTEXT, 5),
1398 X690Value::Primitive(Bytes::new()),
1399 );
1400 return Ok(X690Element::new(
1401 Tag::new(TagClass::CONTEXT, 0),
1402 X690Value::Constructed(Arc::new(Vec::from([ element ]))),
1403 ));
1404 }
1405 }
1406}
1407
1408pub fn x690_encode_embedded_pdv_components (value: &EmbeddedPDV) -> Result<Vec<X690Element>> {
1419 let id = x690_encode_context_switching_identification(&value.identification)?;
1420 let mut data_value_bytes = BytesMut::new().writer();
1421 x690_write_octet_string_value(&mut data_value_bytes, &value.data_value)?;
1422 let data_value_element = X690Element::new(
1423 Tag::new(TagClass::CONTEXT, 1),
1424 X690Value::Primitive(data_value_bytes.into_inner().into()),
1425 );
1426 Ok(vec![id, data_value_element])
1427}
1428
1429pub fn x690_write_embedded_pdv_value<W>(output: &mut W, value: &EmbeddedPDV) -> Result<usize>
1443where
1444 W: Write,
1445{
1446 let components: Vec<X690Element> = x690_encode_embedded_pdv_components(value)?;
1447 let mut bytes_written: usize = 0;
1448 for component in components {
1449 bytes_written += x690_write_tlv(output, &component)?;
1450 }
1451 Ok(bytes_written)
1452}
1453
1454#[inline]
1456pub fn x690_write_utf8_string_value<W>(output: &mut W, value: &str) -> Result<usize>
1457where
1458 W: Write,
1459{
1460 output.write(value.as_bytes())
1461}
1462
1463#[inline]
1465pub fn x690_write_relative_oid_value<W>(output: &mut W, value: &RELATIVE_OID) -> Result<usize>
1466where
1467 W: Write,
1468{
1469 output.write(value.as_x690_slice())
1470}
1471
1472#[inline]
1474pub fn x690_write_time_value<W>(output: &mut W, value: &TIME) -> Result<usize>
1475where
1476 W: Write,
1477{
1478 output.write(value.as_bytes())
1479}
1480
1481#[inline]
1483pub fn x690_write_utc_time_value<W>(output: &mut W, value: &UTCTime) -> Result<usize>
1484where
1485 W: Write,
1486{
1487 output.write(value.to_string().as_bytes())
1488}
1489
1490#[inline]
1492pub fn x690_write_generalized_time_value<W>(
1493 output: &mut W,
1494 value: &GeneralizedTime,
1495) -> Result<usize>
1496where
1497 W: Write,
1498{
1499 output.write(value.to_string().as_bytes())
1500}
1501
1502#[inline]
1504pub fn x690_write_universal_string_value<W>(
1505 output: &mut W,
1506 value: &[u32],
1507) -> Result<usize>
1508where
1509 W: Write,
1510{
1511 for c in value {
1512 output.write(&c.to_be_bytes())?;
1513 }
1514 Ok(value.len() * 4)
1515}
1516
1517pub fn x690_encode_character_string_components (value: &CharacterString) -> Result<Vec<X690Element>> {
1531 let id = x690_encode_context_switching_identification(&value.identification)?;
1532 let mut data_value_bytes = BytesMut::new().writer();
1533 x690_write_octet_string_value(&mut data_value_bytes, &value.string_value)?;
1534 let data_value_element = X690Element::new(
1535 Tag::new(TagClass::CONTEXT, 1),
1536 X690Value::Primitive(data_value_bytes.into_inner().into()),
1537 );
1538 Ok(vec![id, data_value_element])
1539}
1540
1541pub fn x690_write_character_string_value<W>(
1554 output: &mut W,
1555 value: &CharacterString,
1556) -> Result<usize>
1557where
1558 W: Write,
1559{
1560 let components: Vec<X690Element> = x690_encode_character_string_components(value)?;
1561 let mut bytes_written: usize = 0;
1562 for component in components {
1563 bytes_written += x690_write_tlv(output, &component)?;
1564 }
1565 Ok(bytes_written)
1566}
1567
1568pub fn x690_write_bmp_string_value<W>(output: &mut W, value: &[u16]) -> Result<usize>
1570where
1571 W: Write,
1572{
1573 for c in value {
1574 output.write(&c.to_be_bytes())?;
1575 }
1576 Ok(value.len() * 2)
1577}
1578
1579#[inline]
1581pub fn x690_write_string_value<W>(output: &mut W, value: &str) -> Result<usize>
1582where
1583 W: Write,
1584{
1585 output.write(value.as_bytes())
1586}
1587
1588pub fn x690_write_date_value<W>(output: &mut W, value: &DATE) -> Result<usize>
1590where
1591 W: Write,
1592{
1593 if value.month > 12 || value.month == 0 || value.day > 31 || value.day == 0 {
1594 return Err(Error::from(ErrorKind::InvalidData));
1595 }
1596 output.write(value.to_num_string().as_bytes())
1597}
1598
1599pub fn x690_write_time_of_day_value<W>(output: &mut W, value: &TIME_OF_DAY) -> Result<usize>
1601where
1602 W: Write,
1603{
1604 if value.hour > 23 || value.minute > 59 || value.second > 59 {
1605 return Err(Error::from(ErrorKind::InvalidData));
1606 }
1607 output.write(value.to_num_string().as_bytes())
1608}
1609
1610pub fn x690_write_date_time_value<W>(output: &mut W, value: &DATE_TIME) -> Result<usize>
1612where
1613 W: Write,
1614{
1615 output.write(value.to_num_string().as_bytes())
1616}
1617
1618pub fn x690_write_duration_value<W>(output: &mut W, value: &DURATION_EQUIVALENT) -> Result<usize>
1620where
1621 W: Write,
1622{
1623 output.write(&value.to_string().as_bytes()[1..]) }
1625
1626fn x690_write_value<W>(output: &mut W, encoding: &X690Value) -> Result<usize>
1628where
1629 W: Write,
1630{
1631 match encoding {
1632 X690Value::Primitive(v) => output.write(&v),
1633 X690Value::Constructed(components) => {
1634 let mut sum: usize = 0;
1635 for component in components.iter() {
1636 sum += x690_write_tlv(output, component)?;
1637 }
1638 Ok(sum)
1639 },
1640 X690Value::Serialized(v) => {
1641 let (_, el) = BER.decode_from_slice(&v)?;
1642 x690_write_value(output, &el.value)
1643 }
1644 }
1645}
1646
1647pub fn x690_write_tlv<W>(output: &mut W, node: &X690Element) -> Result<usize>
1649where
1650 W: Write,
1651{
1652 if let X690Value::Serialized(serialized) = &node.value {
1653 return output.write(&serialized);
1654 }
1655 let mut bytes_written: usize = 0;
1656 bytes_written += x690_write_tag(output, node.tag.tag_class, node.is_constructed(), node.tag.tag_number)?;
1657 bytes_written += x690_write_length(output, node.value.len())?;
1658 bytes_written += x690_write_value(output, &node.value)?;
1659 Ok(bytes_written)
1660}
1661
1662pub fn deconstruct<'a>(el: &'a X690Element) -> ASN1Result<Cow<'a, [u8]>> {
1682 match &el.value {
1683 X690Value::Primitive(bytes) => Ok(Cow::Borrowed(bytes)),
1684 X690Value::Constructed(children) => {
1685 let mut deconstructed_value = BytesMut::new();
1686 for child in children.iter() {
1687 if child.tag.tag_class != TagClass::UNIVERSAL
1690 || child.tag.tag_number != UNIV_TAG_OCTET_STRING
1691 {
1692 let mut err =
1693 ASN1Error::new(ASN1ErrorCode::string_constructed_with_invalid_tagging);
1694 err.tag = Some(Tag::new(el.tag.tag_class, el.tag.tag_number));
1695 err.length = Some(el.len());
1696 err.constructed = Some(true);
1697 return Err(err);
1698 }
1699 let deconstructed_child = deconstruct(&child)?;
1700 deconstructed_value.put(deconstructed_child.as_ref());
1701 }
1702 Ok(Cow::Owned(Vec::<u8>::from(deconstructed_value)))
1703 },
1704 X690Value::Serialized(v) => {
1705 let (_, el) = BER.decode_from_slice(&v)?;
1706 Ok(Cow::Owned(deconstruct(&el)?.into_owned()))
1707 }
1708 }
1709}
1710
1711pub struct DeconstructionIterator<'a> {
1728 el: &'a X690Element,
1729 i: usize,
1730 child: Option<Box<DeconstructionIterator<'a>>>,
1731 recursion_limit: usize,
1732 recursion_depth: usize,
1733}
1734
1735impl <'a> DeconstructionIterator<'a> {
1736
1737 pub fn new(el: &'a X690Element) -> DeconstructionIterator<'a> {
1739 DeconstructionIterator {
1740 el, i: 0,
1741 child: None,
1742 recursion_limit: 5,
1743 recursion_depth: 0,
1744 }
1745 }
1746}
1747
1748impl <'a> Iterator for DeconstructionIterator<'a> {
1749 type Item = ASN1Result<Cow<'a, [u8]>>;
1750
1751 fn next(&mut self) -> Option<Self::Item> {
1752 if self.recursion_depth > self.recursion_limit {
1753 return None;
1754 }
1755 if let Some(child) = self.child.as_mut() {
1756 if let Some(next) = child.next() {
1757 return Some(next);
1758 }
1759 }
1760 match &self.el.value {
1761 X690Value::Primitive(bytes) => {
1762 if self.i > 0 {
1763 return None;
1764 }
1765 self.i += 1;
1766 Some(Ok(Cow::Borrowed(bytes.as_ref())))
1767 },
1768 X690Value::Constructed(children) => {
1769 while let Some(child) = children.get(self.i) {
1772 if child.tag.tag_class != TagClass::UNIVERSAL
1773 || child.tag.tag_number != UNIV_TAG_OCTET_STRING
1774 {
1775 let mut err =
1776 ASN1Error::new(ASN1ErrorCode::string_constructed_with_invalid_tagging);
1777 err.tag = Some(Tag::new(child.tag.tag_class, child.tag.tag_number));
1778 err.length = Some(child.len());
1779 err.constructed = Some(true);
1780 return Some(Err(err));
1781 }
1782 self.i = self.i.saturating_add(1);
1783 let mut new_iter = DeconstructionIterator{
1784 el: child,
1785 i: 0,
1786 child: None,
1787 recursion_limit: self.recursion_limit,
1788 recursion_depth: self.recursion_depth.saturating_add(1),
1789 };
1790 let maybe_grandchild = new_iter.next();
1791 if let Some(grandchild) = maybe_grandchild {
1792 self.child = Some(Box::new(new_iter));
1793 return Some(grandchild);
1794 }
1795 }
1796 self.recursion_depth = usize::MAX;
1797 None
1798 },
1799 X690Value::Serialized(v) => {
1800 if self.i > 0 {
1801 return None;
1802 }
1803 let (_, el) = match BER.decode_from_slice(&v) {
1804 Ok(x) => x,
1805 Err(e) => return Some(Err(e)),
1806 };
1807 self.i += 1;
1808 let decon = match deconstruct(&el) {
1809 Ok(x) => x,
1810 Err(e) => return Some(Err(e)),
1811 };
1812 Some(Ok(Cow::Owned(decon.into_owned())))
1813 },
1814 }
1815 }
1816
1817}
1818
1819pub const fn x690_read_boolean_value(value_bytes: ByteSlice) -> ASN1Result<BOOLEAN> {
1821 if value_bytes.len() != 1 {
1822 let err = ASN1Error::new(ASN1ErrorCode::x690_boolean_not_one_byte);
1823 return Err(err);
1824 }
1825 Ok(value_bytes[0] > 0)
1826}
1827
1828#[inline]
1830pub fn x690_read_integer_value(value_bytes: ByteSlice) -> ASN1Result<INTEGER> {
1831 Ok(Vec::from(value_bytes))
1834}
1835
1836#[inline]
1838pub fn x690_read_i64_value(value_bytes: ByteSlice) -> ASN1Result<i64> {
1839 match read_i64(value_bytes) {
1840 Some(v) => Ok(v),
1841 None => Err(ASN1Error::new(ASN1ErrorCode::value_too_big)),
1842 }
1843}
1844
1845#[inline]
1847pub fn x690_read_enum_value(value_bytes: ByteSlice) -> ASN1Result<ENUMERATED> {
1848 x690_read_i64_value(value_bytes)
1849}
1850
1851#[inline]
1853pub fn x690_read_object_identifier_value(value_bytes: ByteSlice) -> ASN1Result<OBJECT_IDENTIFIER> {
1854 OBJECT_IDENTIFIER::from_x690_encoding_slice(value_bytes)
1855}
1856
1857#[inline]
1859pub fn x690_read_relative_oid_value(value_bytes: ByteSlice) -> ASN1Result<RELATIVE_OID> {
1860 RELATIVE_OID::from_x690_encoding_slice(value_bytes)
1861}
1862
1863#[inline]
1865pub fn x690_read_date_value(value_bytes: ByteSlice) -> ASN1Result<DATE> {
1866 DATE::try_from(value_bytes)
1867}
1868
1869#[inline]
1871pub fn x690_read_time_of_day_value(value_bytes: ByteSlice) -> ASN1Result<TIME_OF_DAY> {
1872 TIME_OF_DAY::try_from(value_bytes)
1873}
1874
1875#[inline]
1877pub fn x690_read_date_time_value(value_bytes: ByteSlice) -> ASN1Result<DATE_TIME> {
1878 DATE_TIME::try_from(value_bytes)
1879}
1880
1881#[inline]
1883pub fn x690_read_duration_value(value_bytes: ByteSlice) -> ASN1Result<DURATION> {
1884 DURATION::try_from(value_bytes)
1885}
1886
1887pub trait RelateTLV {
1889
1890 fn relate_tlv (&mut self, el: &X690Element);
1892}
1893
1894impl RelateTLV for ASN1Error {
1895 fn relate_tlv (&mut self, el: &X690Element) {
1896 self.tag = Some(el.tag);
1897 self.constructed = Some(el.is_constructed());
1898 self.length = Some(el.len());
1899 }
1900}
1901
1902pub const _RCTL1_FOR_EXTERNAL: &[ComponentSpec; 4] = &[
1918 ComponentSpec::new(
1919 "direct-reference",
1920 true,
1921 TagSelector::tag((
1922 TagClass::UNIVERSAL,
1923 UNIV_TAG_OBJECT_IDENTIFIER,
1924 )),
1925 None,
1926 None,
1927 ),
1928 ComponentSpec::new(
1929 "indirect-reference",
1930 true,
1931 TagSelector::tag((TagClass::UNIVERSAL, UNIV_TAG_INTEGER)),
1932 None,
1933 None,
1934 ),
1935 ComponentSpec::new(
1936 "data-value-descriptor",
1937 true,
1938 TagSelector::tag((
1939 TagClass::UNIVERSAL,
1940 UNIV_TAG_OBJECT_DESCRIPTOR,
1941 )),
1942 None,
1943 None,
1944 ),
1945 ComponentSpec::new(
1946 "encoding",
1947 false,
1948 TagSelector::or(&[
1949 &TagSelector::tag((TagClass::CONTEXT, 0)),
1950 &TagSelector::tag((TagClass::CONTEXT, 1)),
1951 &TagSelector::tag((TagClass::CONTEXT, 2)),
1952 ]),
1953 None,
1954 None,
1955 ),
1956];
1957
1958pub const _EAL_FOR_EXTERNAL: &[ComponentSpec; 0] = &[];
1962
1963pub const _RCTL2_FOR_EXTERNAL: &[ComponentSpec; 0] = &[];
1967
1968#[cfg(test)]
1969mod tests {
1970
1971 use super::*;
1972 use std::sync::Arc;
1973 use wildboar_asn1::{
1974 Tag, TagClass, UNIV_TAG_BOOLEAN, UNIV_TAG_IA5_STRING, UNIV_TAG_OCTET_STRING, UNIV_TAG_SEQUENCE
1975 };
1976 use bytes::Bytes;
1977
1978 #[test]
1979 fn test_x690_write_boolean_value() {
1980 let mut output = BytesMut::new().writer();
1981 crate::x690_write_boolean_value(&mut output, &true).unwrap();
1982 crate::x690_write_boolean_value(&mut output, &false).unwrap();
1983 let output: Bytes = output.into_inner().into();
1984 assert_eq!(output.len(), 2);
1985 assert!(output.starts_with(&[0xFF, 0x00]));
1986 }
1987
1988 #[test]
1989 fn test_x690_write_integer_value() {
1990 let mut output = BytesMut::new();
1991 let mut i = 0;
1992 for value in -128i8..127i8 {
1993 let mut out = output.writer();
1994 crate::x690_write_enum_value(&mut out, &i64::from(value)).unwrap();
1995 output = out.into_inner();
1996 assert_eq!(output[i] as i8, value);
1997 i += 1;
1998 }
1999 assert_eq!(output.len(), 255);
2000 }
2001
2002 #[test]
2003 fn test_x690_write_octet_string_value() {
2004 let mut output = BytesMut::new().writer();
2005 let bytes: Vec<u8> = vec![1, 3, 5, 7, 9];
2006 crate::x690_write_octet_string_value(&mut output, &bytes).unwrap();
2007 let output: Bytes = output.into_inner().into();
2008 assert_eq!(output.len(), 5);
2009 assert!(output.starts_with(&[1, 3, 5, 7, 9]));
2010 }
2011
2012 #[test]
2013 fn test_x690_write_object_identifier_value() {
2014 let mut output = BytesMut::new().writer();
2015 let oid = wildboar_asn1::OBJECT_IDENTIFIER::try_from(vec![2u32, 5, 4, 3]).unwrap();
2016 crate::x690_write_object_identifier_value(&mut output, &oid).unwrap();
2017 let output: Bytes = output.into_inner().into();
2018 assert_eq!(output.len(), 3);
2019 assert!(output.starts_with(&[0x55, 0x04, 0x03]));
2020 }
2021
2022 #[test]
2023 fn test_x690_write_object_descriptor_value() {
2024 let mut output = BytesMut::new().writer();
2025 let value = String::from("commonName");
2026 crate::x690_write_object_descriptor_value(&mut output, &value).unwrap();
2027 let output: Bytes = output.into_inner().into();
2028 assert_eq!(output.len(), value.len());
2029 assert_eq!(
2030 String::from_utf8(output.into()).unwrap(),
2031 String::from("commonName")
2032 );
2033 }
2034
2035 #[test]
2036 fn test_x690_write_real_value() {
2037 let output = BytesMut::new();
2038 let value = 1.2345;
2039 crate::x690_write_real_value(&mut output.writer(), &value).unwrap();
2040 }
2041
2042 #[test]
2043 fn test_constructed_encoding() {
2044 let asn1_data = X690Element::new(
2045 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_SEQUENCE),
2046 crate::X690Value::Constructed(Arc::new(vec![
2047 X690Element::new(
2048 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_BOOLEAN),
2049 crate::X690Value::Primitive(Bytes::copy_from_slice(&[ 0xFF ])),
2050 ),
2051 X690Element::new(
2052 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER),
2053 crate::X690Value::Primitive(Bytes::copy_from_slice(&[ 0x01, 0x03 ])),
2054 ),
2055 ])),
2056 );
2057 let mut output = Vec::new();
2058 match x690_write_tlv(&mut output, &asn1_data) {
2059 Ok(bytes_written) => {
2060 assert_eq!(bytes_written, 9);
2061 }
2062 Err(e) => panic!("{}", e),
2063 }
2064 assert!(output.starts_with(&[
2065 X690_TAG_CLASS_UNIVERSAL
2066 | 0b0010_0000 | UNIV_TAG_SEQUENCE as u8,
2068 0x07,
2069 0x01,
2070 0x01,
2071 0xFF,
2072 0x02,
2073 0x02,
2074 0x01,
2075 0x03,
2076 ]));
2077 }
2078
2079 #[test]
2080 fn test_ber_decode_definite_short() {
2081 let encoded_data: Vec<u8> = vec![
2082 X690_TAG_CLASS_UNIVERSAL
2083 | 0b0010_0000 | UNIV_TAG_SEQUENCE as u8,
2085 0x06,
2086 0x01,
2087 0x01,
2088 0xFF,
2089 0x02,
2090 0x01,
2091 0x7F,
2092 ];
2093 match BER.decode_from_slice(encoded_data.as_slice()) {
2094 Ok((bytes_read, el)) => {
2095 assert_eq!(bytes_read, 8);
2096 assert_eq!(el.tag.tag_class, TagClass::UNIVERSAL);
2097 assert_eq!(el.tag.tag_number, UNIV_TAG_SEQUENCE);
2098 if let X690Value::Constructed(children) = el.value {
2099 assert_eq!(children.len(), 2);
2100 assert_eq!(children[0].tag.tag_class, TagClass::UNIVERSAL);
2101 assert_eq!(children[1].tag.tag_class, TagClass::UNIVERSAL);
2102 assert_eq!(children[0].tag.tag_number, UNIV_TAG_BOOLEAN);
2103 assert_eq!(children[1].tag.tag_number, UNIV_TAG_INTEGER);
2104 } else {
2105 panic!("Decoded non-constructed.");
2106 }
2107 }
2108 Err(e) => panic!("{}", e),
2109 };
2110 }
2111
2112 #[test]
2113 fn test_ber_decode_indefinite() {
2114 let encoded_data: Vec<u8> = vec![
2115 X690_TAG_CLASS_UNIVERSAL
2116 | 0b0010_0000 | UNIV_TAG_SEQUENCE as u8,
2118 0x80, 0x01,
2120 0x01,
2121 0xFF,
2122 0x02,
2123 0x01,
2124 0x7F,
2125 0x00, 0x00,
2127 ];
2128 match BER.decode_from_slice(encoded_data.as_slice()) {
2129 Ok((bytes_read, el)) => {
2130 assert_eq!(bytes_read, 10);
2131 assert_eq!(el.tag.tag_class, TagClass::UNIVERSAL);
2132 assert_eq!(el.tag.tag_number, UNIV_TAG_SEQUENCE);
2133 if let X690Value::Constructed(children) = el.value {
2134 assert_eq!(children.len(), 2);
2135 assert_eq!(children[0].tag.tag_class, TagClass::UNIVERSAL);
2136 assert_eq!(children[1].tag.tag_class, TagClass::UNIVERSAL);
2137 assert_eq!(children[0].tag.tag_number, UNIV_TAG_BOOLEAN);
2138 assert_eq!(children[1].tag.tag_number, UNIV_TAG_INTEGER);
2139 } else {
2140 panic!("Decoded non-constructed.");
2141 }
2142 }
2143 Err(e) => panic!("{}", e),
2144 };
2145 }
2146
2147 #[test]
2148 fn test_deconstruct_primitive() {
2149 let bytes = Bytes::copy_from_slice(&[0x01, 0x02, 0x03, 0x04]);
2151 let element = X690Element::new(
2152 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2153 X690Value::Primitive(bytes.clone()),
2154 );
2155
2156 let result = deconstruct(&element).unwrap();
2157 assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2158 assert!(matches!(result, Cow::Borrowed(_)));
2160 }
2161
2162 #[test]
2163 fn test_deconstruct_constructed_valid() {
2164 let child1 = X690Element::new(
2166 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2167 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2168 );
2169 let child2 = X690Element::new(
2170 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2171 X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2172 );
2173
2174 let element = X690Element::new(
2175 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2176 X690Value::Constructed(Arc::new(vec![child1, child2])),
2177 );
2178
2179 let result = deconstruct(&element).unwrap();
2180 assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2181 assert!(matches!(result, Cow::Owned(_)));
2183 }
2184
2185 #[test]
2186 fn test_deconstruct_constructed_invalid_tag_class() {
2187 let child = X690Element::new(
2189 Tag::new(TagClass::APPLICATION, UNIV_TAG_OCTET_STRING), X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2191 );
2192
2193 let element = X690Element::new(
2194 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2195 X690Value::Constructed(Arc::new(vec![child])),
2196 );
2197
2198 let result = deconstruct(&element);
2199 assert!(result.is_err());
2200 let err = result.unwrap_err();
2201 assert_eq!(err.error_code, ASN1ErrorCode::string_constructed_with_invalid_tagging);
2202 }
2203
2204 #[test]
2205 fn test_deconstruct_constructed_invalid_tag_number() {
2206 let child = X690Element::new(
2208 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_INTEGER), X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2210 );
2211
2212 let element = X690Element::new(
2213 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2214 X690Value::Constructed(Arc::new(vec![child])),
2215 );
2216
2217 let result = deconstruct(&element);
2218 assert!(result.is_err());
2219 let err = result.unwrap_err();
2220 assert_eq!(err.error_code, ASN1ErrorCode::string_constructed_with_invalid_tagging);
2221 }
2222
2223 #[test]
2224 fn test_deconstruct_constructed_nested() {
2225 let grandchild1 = X690Element::new(
2227 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2228 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2229 );
2230 let grandchild2 = X690Element::new(
2231 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2232 X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2233 );
2234
2235 let child = X690Element::new(
2236 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2237 X690Value::Constructed(Arc::new(vec![grandchild1, grandchild2])),
2238 );
2239
2240 let element = X690Element::new(
2241 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2242 X690Value::Constructed(Arc::new(vec![child])),
2243 );
2244
2245 let result = deconstruct(&element).unwrap();
2246 assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2247 }
2248
2249 #[test]
2250 fn test_deconstruct_constructed_empty() {
2251 let element = X690Element::new(
2253 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2254 X690Value::Constructed(Arc::new(vec![])),
2255 );
2256
2257 let result = deconstruct(&element).unwrap();
2258 let empty: [u8; 0] = [];
2259 assert_eq!(result.as_ref(), &empty);
2260 }
2261
2262 #[test]
2263 fn test_deconstruct_serialized() {
2264 let inner_bytes = Bytes::copy_from_slice(&[0x01, 0x02, 0x03, 0x04]);
2266 let inner_element = X690Element::new(
2267 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2268 X690Value::Primitive(inner_bytes),
2269 );
2270
2271 let mut serialized = Vec::new();
2273 x690_write_tlv(&mut serialized, &inner_element).unwrap();
2274
2275 let element = X690Element::new(
2276 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2277 X690Value::Serialized(Bytes::copy_from_slice(&serialized)),
2278 );
2279
2280 let result = deconstruct(&element).unwrap();
2281 assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2282 assert!(matches!(result, Cow::Owned(_)));
2284 }
2285
2286 #[test]
2287 fn test_deconstruct_serialized_constructed() {
2288 let child1 = X690Element::new(
2290 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2291 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2292 );
2293 let child2 = X690Element::new(
2294 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2295 X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2296 );
2297
2298 let inner_element = X690Element::new(
2299 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2300 X690Value::Constructed(Arc::new(vec![child1, child2])),
2301 );
2302
2303 let mut serialized = Vec::new();
2305 x690_write_tlv(&mut serialized, &inner_element).unwrap();
2306
2307 let element = X690Element::new(
2308 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2309 X690Value::Serialized(Bytes::copy_from_slice(&serialized)),
2310 );
2311
2312 let result = deconstruct(&element).unwrap();
2313 assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04]);
2314 }
2315
2316 #[test]
2317 fn test_deconstruct_mixed_constructed() {
2318 let primitive_child = X690Element::new(
2320 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2321 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2322 );
2323
2324 let grandchild1 = X690Element::new(
2325 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2326 X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2327 );
2328 let grandchild2 = X690Element::new(
2329 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2330 X690Value::Primitive(Bytes::copy_from_slice(&[0x05, 0x06])),
2331 );
2332
2333 let constructed_child = X690Element::new(
2334 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2335 X690Value::Constructed(Arc::new(vec![grandchild1, grandchild2])),
2336 );
2337
2338 let element = X690Element::new(
2339 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2340 X690Value::Constructed(Arc::new(vec![primitive_child, constructed_child])),
2341 );
2342
2343 let result = deconstruct(&element).unwrap();
2344 assert_eq!(result.as_ref(), &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
2345 }
2346
2347 #[test]
2348 fn test_deconstruct_large_data() {
2349 let mut children = Vec::new();
2351 let mut expected = Vec::new();
2352
2353 for i in 0..100 {
2354 let data = vec![i as u8, (i + 1) as u8, (i + 2) as u8];
2355 expected.extend_from_slice(&data);
2356
2357 let child = X690Element::new(
2358 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2359 X690Value::Primitive(Bytes::copy_from_slice(&data)),
2360 );
2361 children.push(child);
2362 }
2363
2364 let element = X690Element::new(
2365 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2366 X690Value::Constructed(Arc::new(children)),
2367 );
2368
2369 let result = deconstruct(&element).unwrap();
2370 assert_eq!(result.as_ref(), &expected);
2371 }
2372
2373 #[test]
2374 fn test_deconstruct_serialized_invalid_data() {
2375 let element = X690Element::new(
2377 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2378 X690Value::Serialized(Bytes::copy_from_slice(&[0x01, 0x02, 0x03])), );
2380
2381 let result = deconstruct(&element);
2382 assert!(result.is_err());
2383 }
2384
2385 #[test]
2386 fn test_element_equality_1() {
2387 let element1 = X690Element::new(
2388 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2389 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2390 );
2391 let element2 = X690Element::new(
2392 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2393 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2394 );
2395 assert_eq!(element1, element2);
2396 }
2397
2398 #[test]
2399 fn test_deconstruct_iter_mixed_constructed() {
2400 let primitive_child = X690Element::new(
2402 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2403 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2404 );
2405
2406 let grandchild1 = X690Element::new(
2407 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2408 X690Value::Primitive(Bytes::copy_from_slice(&[0x03, 0x04])),
2409 );
2410 let grandchild2 = X690Element::new(
2411 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2412 X690Value::Primitive(Bytes::copy_from_slice(&[0x05, 0x06])),
2413 );
2414
2415 let constructed_child = X690Element::new(
2416 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2417 X690Value::Constructed(Arc::new(vec![grandchild1, grandchild2])),
2418 );
2419
2420 let element = X690Element::new(
2421 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_IA5_STRING),
2422 X690Value::Constructed(Arc::new(vec![primitive_child, constructed_child])),
2423 );
2424
2425 let chunks: ASN1Result<Vec<Cow<[u8]>>> = element.iter_deconstruction().collect();
2426 let chunks = chunks.unwrap();
2427 assert_eq!(chunks.len(), 3);
2428 assert_eq!(chunks[0].as_ref(), &[0x01, 0x02]);
2429 assert_eq!(chunks[1].as_ref(), &[0x03, 0x04]);
2430 assert_eq!(chunks[2].as_ref(), &[0x05, 0x06]);
2431 }
2432
2433 #[test]
2434 fn test_deconstruct_iter_empty_child() {
2435 let primitive_child = X690Element::new(
2437 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2438 X690Value::Primitive(Bytes::copy_from_slice(&[0x01, 0x02])),
2439 );
2440
2441 let grandchild1 = X690Element::new(
2442 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2443 X690Value::Constructed(Arc::new(vec![])),
2444 );
2445 let grandchild2 = X690Element::new(
2446 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2447 X690Value::Primitive(Bytes::copy_from_slice(&[0x05, 0x06])),
2448 );
2449
2450 let constructed_child = X690Element::new(
2451 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_OCTET_STRING),
2452 X690Value::Constructed(Arc::new(vec![grandchild1, grandchild2])),
2453 );
2454
2455 let element = X690Element::new(
2456 Tag::new(TagClass::UNIVERSAL, UNIV_TAG_IA5_STRING),
2457 X690Value::Constructed(Arc::new(vec![primitive_child, constructed_child])),
2458 );
2459
2460 let chunks: ASN1Result<Vec<Cow<[u8]>>> = element.iter_deconstruction().collect();
2461 let chunks = chunks.unwrap();
2462 assert_eq!(chunks.len(), 2);
2463 assert_eq!(chunks[0].as_ref(), &[0x01, 0x02]);
2464 assert_eq!(chunks[1].as_ref(), &[0x05, 0x06]);
2465 }
2466
2467}