1 use crate::ber::bitstring_to_u64; 2 use crate::ber::integer::*; 3 use crate::error::BerError; 4 use crate::oid::Oid; 5 use alloc::borrow::ToOwned; 6 use alloc::boxed::Box; 7 use alloc::vec::Vec; 8 #[cfg(feature = "bitvec")] 9 use bitvec::{order::Msb0, slice::BitSlice}; 10 use core::convert::AsRef; 11 use core::convert::From; 12 use core::convert::TryFrom; 13 use core::fmt; 14 use core::ops::Index; 15 use rusticata_macros::newtype_enum; 16 17 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 18 pub struct BerClassFromIntError(pub(crate) ()); 19 20 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 21 pub struct BerSizeError(pub(crate) ()); 22 23 /// BER Object class of tag 24 #[derive(Debug, Copy, Clone, Eq, PartialEq)] 25 #[repr(u8)] 26 pub enum BerClass { 27 Universal = 0b00, 28 Application = 0b01, 29 ContextSpecific = 0b10, 30 Private = 0b11, 31 } 32 33 /// Ber Object Length 34 #[derive(Debug, Copy, Clone, Eq, PartialEq)] 35 pub enum BerSize { 36 /// Definite form (X.690 8.1.3.3) 37 Definite(usize), 38 /// Indefinite form (X.690 8.1.3.6) 39 Indefinite, 40 } 41 42 /// BER/DER Tag as defined in X.680 section 8.4 43 /// 44 /// X.690 doesn't specify the maximum tag size so we're assuming that people 45 /// aren't going to need anything more than a u32. 46 #[derive(Clone, Copy, PartialEq, Eq)] 47 pub struct BerTag(pub u32); 48 49 newtype_enum! { 50 impl debug BerTag { 51 EndOfContent = 0x0, 52 Boolean = 0x1, 53 Integer = 0x2, 54 BitString = 0x3, 55 OctetString = 0x4, 56 Null = 0x05, 57 Oid = 0x06, 58 ObjDescriptor = 0x07, 59 External = 0x08, 60 RealType = 0x09, 61 Enumerated = 0xa, 62 EmbeddedPdv = 0xb, 63 Utf8String = 0xc, 64 RelativeOid = 0xd, 65 66 Sequence = 0x10, 67 Set = 0x11, 68 NumericString = 0x12, 69 PrintableString = 0x13, 70 T61String = 0x14, 71 VideotexString = 0x15, 72 73 Ia5String = 0x16, 74 UtcTime = 0x17, 75 GeneralizedTime = 0x18, 76 77 GraphicString = 25, // 0x19 78 VisibleString = 26, // 0x1a 79 GeneralString = 27, // 0x1b 80 81 UniversalString = 0x1c, 82 BmpString = 0x1e, 83 84 Invalid = 0xff, 85 } 86 } 87 88 /// Representation of a BER-encoded (X.690) object 89 /// 90 /// A BER object is composed of a header describing the object class, type and length, 91 /// and the content. 92 /// 93 /// Note that the content may sometimes not match the header tag (for ex when parsing IMPLICIT 94 /// tagged values). 95 #[derive(Debug, Clone, PartialEq)] 96 pub struct BerObject<'a> { 97 pub header: BerObjectHeader<'a>, 98 pub content: BerObjectContent<'a>, 99 } 100 101 /// BER object header (identifier and length) 102 #[derive(Clone, Debug)] 103 pub struct BerObjectHeader<'a> { 104 /// Object class: universal, application, context-specific, or private 105 pub class: BerClass, 106 /// Constructed attribute: 1 if constructed, else 0 107 pub structured: u8, 108 /// Tag number 109 pub tag: BerTag, 110 /// Object length: definite or indefinite 111 pub len: BerSize, 112 113 /// Optionally, the raw encoding of the tag 114 /// 115 /// This is useful in some cases, where different representations of the same 116 /// BER tags have different meanings (BER only) 117 pub raw_tag: Option<&'a [u8]>, 118 } 119 120 /// BER object content 121 #[derive(Debug, Clone, PartialEq)] 122 #[allow(clippy::upper_case_acronyms)] 123 pub enum BerObjectContent<'a> { 124 /// EOC (no content) 125 EndOfContent, 126 /// BOOLEAN: decoded value 127 Boolean(bool), 128 /// INTEGER: raw bytes 129 /// 130 /// Note: the reason to store the raw bytes is that integers have non-finite length in the 131 /// spec, and also that the raw encoding is also important for some applications. 132 /// 133 /// To extract the number, see the `as_u64`, `as_u32`, `as_bigint` and `as_biguint` methods. 134 Integer(&'a [u8]), 135 /// BIT STRING: number of unused bits, and object 136 BitString(u8, BitStringObject<'a>), 137 /// OCTET STRING: slice 138 OctetString(&'a [u8]), 139 /// NULL (no content) 140 Null, 141 /// ENUMERATED: decoded enum number 142 Enum(u64), 143 /// OID 144 OID(Oid<'a>), 145 /// RELATIVE OID 146 RelativeOID(Oid<'a>), 147 /// NumericString: decoded string 148 NumericString(&'a str), 149 /// VisibleString: decoded string 150 VisibleString(&'a str), 151 /// PrintableString: decoded string 152 PrintableString(&'a str), 153 /// IA5String: decoded string 154 IA5String(&'a str), 155 /// UTF8String: decoded string 156 UTF8String(&'a str), 157 /// T61String: raw object bytes 158 T61String(&'a [u8]), 159 /// VideotexString: raw object bytes 160 VideotexString(&'a [u8]), 161 162 /// BmpString: raw object bytes 163 BmpString(&'a [u8]), 164 /// UniversalString: raw object bytes 165 UniversalString(&'a [u8]), 166 167 /// SEQUENCE: list of objects 168 Sequence(Vec<BerObject<'a>>), 169 /// SET: list of objects 170 Set(Vec<BerObject<'a>>), 171 172 /// UTCTime: decoded string 173 UTCTime(&'a str), 174 /// GeneralizedTime: decoded string 175 GeneralizedTime(&'a str), 176 177 /// Object descriptor: raw object bytes 178 ObjectDescriptor(&'a [u8]), 179 /// GraphicString: raw object bytes 180 GraphicString(&'a [u8]), 181 /// GeneralString: raw object bytes 182 GeneralString(&'a [u8]), 183 184 /// Optional object 185 Optional(Option<Box<BerObject<'a>>>), 186 /// Tagged object (EXPLICIT): class, tag and content of inner object 187 Tagged(BerClass, BerTag, Box<BerObject<'a>>), 188 /// Private 189 Private(BerObjectHeader<'a>, &'a [u8]), 190 191 /// Unknown object: object tag (copied from header), and raw content 192 Unknown(BerClass, BerTag, &'a [u8]), 193 } 194 195 impl fmt::Display for BerClass { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 197 let s = match self { 198 BerClass::Universal => "UNIVERSAL", 199 BerClass::Application => "APPLICATION", 200 BerClass::ContextSpecific => "CONTEXT-SPECIFIC", 201 BerClass::Private => "PRIVATE", 202 }; 203 write!(f, "{}", s) 204 } 205 } 206 207 impl From<u32> for BerTag { from(v: u32) -> Self208 fn from(v: u32) -> Self { 209 BerTag(v) 210 } 211 } 212 213 impl BerSize { 214 /// Return true if length is definite and equal to 0 is_null(&self) -> bool215 pub fn is_null(&self) -> bool { 216 *self == BerSize::Definite(0) 217 } 218 219 /// Get length of primitive object 220 #[inline] primitive(&self) -> Result<usize, BerError>221 pub fn primitive(&self) -> Result<usize, BerError> { 222 match self { 223 BerSize::Definite(sz) => Ok(*sz), 224 BerSize::Indefinite => Err(BerError::IndefiniteLengthUnexpected), 225 } 226 } 227 } 228 229 impl From<usize> for BerSize { from(v: usize) -> Self230 fn from(v: usize) -> Self { 231 BerSize::Definite(v) 232 } 233 } 234 235 impl TryFrom<u64> for BerSize { 236 type Error = BerSizeError; 237 try_from(value: u64) -> Result<Self, Self::Error>238 fn try_from(value: u64) -> Result<Self, Self::Error> { 239 let v = usize::try_from(value).or(Err(BerSizeError(())))?; 240 Ok(BerSize::Definite(v)) 241 } 242 } 243 244 impl TryFrom<BerSize> for usize { 245 type Error = BerSizeError; 246 247 #[inline] try_from(value: BerSize) -> Result<Self, Self::Error>248 fn try_from(value: BerSize) -> Result<Self, Self::Error> { 249 match value { 250 BerSize::Definite(sz) => Ok(sz), 251 BerSize::Indefinite => Err(BerSizeError(())), 252 } 253 } 254 } 255 256 impl TryFrom<u8> for BerClass { 257 type Error = BerClassFromIntError; 258 259 #[inline] try_from(value: u8) -> Result<Self, Self::Error>260 fn try_from(value: u8) -> Result<Self, Self::Error> { 261 match value { 262 0b00 => Ok(BerClass::Universal), 263 0b01 => Ok(BerClass::Application), 264 0b10 => Ok(BerClass::ContextSpecific), 265 0b11 => Ok(BerClass::Private), 266 _ => Err(BerClassFromIntError(())), 267 } 268 } 269 } 270 271 impl<'a> BerObjectHeader<'a> { 272 /// Build a new BER header new<Len: Into<BerSize>>(class: BerClass, structured: u8, tag: BerTag, len: Len) -> Self273 pub fn new<Len: Into<BerSize>>(class: BerClass, structured: u8, tag: BerTag, len: Len) -> Self { 274 BerObjectHeader { 275 tag, 276 structured, 277 class, 278 len: len.into(), 279 raw_tag: None, 280 } 281 } 282 283 /// Update header class 284 #[inline] with_class(self, class: BerClass) -> Self285 pub fn with_class(self, class: BerClass) -> Self { 286 BerObjectHeader { class, ..self } 287 } 288 289 /// Update header tag 290 #[inline] with_tag(self, tag: BerTag) -> Self291 pub fn with_tag(self, tag: BerTag) -> Self { 292 BerObjectHeader { tag, ..self } 293 } 294 295 /// Update header length 296 #[inline] with_len(self, len: BerSize) -> Self297 pub fn with_len(self, len: BerSize) -> Self { 298 BerObjectHeader { len, ..self } 299 } 300 301 /// Update header to add reference to raw tag 302 #[inline] with_raw_tag(self, raw_tag: Option<&'a [u8]>) -> Self303 pub fn with_raw_tag(self, raw_tag: Option<&'a [u8]>) -> Self { 304 BerObjectHeader { raw_tag, ..self } 305 } 306 307 /// Test if object class is Universal 308 #[inline] is_universal(&self) -> bool309 pub fn is_universal(&self) -> bool { 310 self.class == BerClass::Universal 311 } 312 /// Test if object class is Application 313 #[inline] is_application(&self) -> bool314 pub fn is_application(&self) -> bool { 315 self.class == BerClass::Application 316 } 317 /// Test if object class is Context-specific 318 #[inline] is_contextspecific(&self) -> bool319 pub fn is_contextspecific(&self) -> bool { 320 self.class == BerClass::ContextSpecific 321 } 322 /// Test if object class is Private 323 #[inline] is_private(&self) -> bool324 pub fn is_private(&self) -> bool { 325 self.class == BerClass::Private 326 } 327 328 /// Test if object is primitive 329 #[inline] is_primitive(&self) -> bool330 pub fn is_primitive(&self) -> bool { 331 self.structured == 0 332 } 333 /// Test if object is constructed 334 #[inline] is_constructed(&self) -> bool335 pub fn is_constructed(&self) -> bool { 336 self.structured == 1 337 } 338 } 339 340 impl<'a> BerObject<'a> { 341 /// Build a BerObject from a header and content. 342 /// 343 /// Note: values are not checked, so the tag can be different from the real content, or flags 344 /// can be invalid. from_header_and_content<'o>( header: BerObjectHeader<'o>, content: BerObjectContent<'o>, ) -> BerObject<'o>345 pub fn from_header_and_content<'o>( 346 header: BerObjectHeader<'o>, 347 content: BerObjectContent<'o>, 348 ) -> BerObject<'o> { 349 BerObject { header, content } 350 } 351 352 /// Build a BerObject from its content, using default flags (no class, correct tag, 353 /// and structured flag set only for Set and Sequence) from_obj(c: BerObjectContent) -> BerObject354 pub fn from_obj(c: BerObjectContent) -> BerObject { 355 let class = BerClass::Universal; 356 let tag = c.tag(); 357 let structured = match tag { 358 BerTag::Sequence | BerTag::Set => 1, 359 _ => 0, 360 }; 361 let header = BerObjectHeader::new(class, structured, tag, BerSize::Definite(0)); 362 BerObject { header, content: c } 363 } 364 365 /// Build a DER integer object from a slice containing an encoded integer from_int_slice(i: &'a [u8]) -> BerObject<'a>366 pub fn from_int_slice(i: &'a [u8]) -> BerObject<'a> { 367 let header = BerObjectHeader::new( 368 BerClass::Universal, 369 0, 370 BerTag::Integer, 371 BerSize::Definite(0), 372 ); 373 BerObject { 374 header, 375 content: BerObjectContent::Integer(i), 376 } 377 } 378 379 /// Set a tag for the BER object set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject380 pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject { 381 let header = BerObjectHeader { 382 raw_tag, 383 ..self.header 384 }; 385 BerObject { header, ..self } 386 } 387 388 /// Build a DER sequence object from a vector of DER objects from_seq(l: Vec<BerObject>) -> BerObject389 pub fn from_seq(l: Vec<BerObject>) -> BerObject { 390 BerObject::from_obj(BerObjectContent::Sequence(l)) 391 } 392 393 /// Build a DER set object from a vector of DER objects from_set(l: Vec<BerObject>) -> BerObject394 pub fn from_set(l: Vec<BerObject>) -> BerObject { 395 BerObject::from_obj(BerObjectContent::Set(l)) 396 } 397 398 /// Attempt to read a signed integer value from DER object. 399 /// 400 /// This can fail if the object is not an integer, or if it is too large. 401 /// 402 /// # Examples 403 /// 404 /// ```rust 405 /// # use der_parser::ber::BerObject; 406 /// let der_int = BerObject::from_int_slice(b"\x80"); 407 /// assert_eq!( 408 /// der_int.as_i64(), 409 /// Ok(-128) 410 /// ); 411 /// ``` as_i64(&self) -> Result<i64, BerError>412 pub fn as_i64(&self) -> Result<i64, BerError> { 413 self.content.as_i64() 414 } 415 416 /// Attempt to read a signed integer value from DER object. 417 /// 418 /// This can fail if the object is not an integer, or if it is too large. 419 /// 420 /// # Examples 421 /// 422 /// ```rust 423 /// # use der_parser::ber::BerObject; 424 /// let der_int = BerObject::from_int_slice(b"\x80"); 425 /// assert_eq!( 426 /// der_int.as_i32(), 427 /// Ok(-128) 428 /// ); 429 /// ``` as_i32(&self) -> Result<i32, BerError>430 pub fn as_i32(&self) -> Result<i32, BerError> { 431 self.content.as_i32() 432 } 433 434 /// Attempt to read integer value from DER object. 435 /// 436 /// This can fail if the object is not an unsigned integer, or if it is too large. 437 /// 438 /// # Examples 439 /// 440 /// ```rust 441 /// # use der_parser::ber::BerObject; 442 /// let der_int = BerObject::from_int_slice(b"\x01\x00\x01"); 443 /// assert_eq!( 444 /// der_int.as_u64(), 445 /// Ok(0x10001) 446 /// ); 447 /// ``` as_u64(&self) -> Result<u64, BerError>448 pub fn as_u64(&self) -> Result<u64, BerError> { 449 self.content.as_u64() 450 } 451 452 /// Attempt to read integer value from DER object. 453 /// 454 /// This can fail if the object is not an unsigned integer, or if it is too large. 455 /// 456 /// # Examples 457 /// 458 /// ```rust 459 /// # extern crate der_parser; 460 /// # use der_parser::ber::{BerObject,BerObjectContent}; 461 /// let der_int = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); 462 /// assert_eq!( 463 /// der_int.as_u32(), 464 /// Ok(0x10001) 465 /// ); 466 /// ``` as_u32(&self) -> Result<u32, BerError>467 pub fn as_u32(&self) -> Result<u32, BerError> { 468 self.content.as_u32() 469 } 470 471 /// Attempt to read integer value from DER object. 472 /// This can fail if the object is not a boolean. as_bool(&self) -> Result<bool, BerError>473 pub fn as_bool(&self) -> Result<bool, BerError> { 474 self.content.as_bool() 475 } 476 477 /// Attempt to read an OID value from DER object. 478 /// This can fail if the object is not an OID. as_oid(&self) -> Result<&Oid<'a>, BerError>479 pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> { 480 self.content.as_oid() 481 } 482 483 /// Attempt to read an OID value from DER object. 484 /// This can fail if the object is not an OID. as_oid_val(&self) -> Result<Oid<'a>, BerError>485 pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> { 486 self.content.as_oid_val() 487 } 488 489 /// Attempt to get a reference on the content from an optional object. 490 /// This can fail if the object is not optional. as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError>491 pub fn as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError> { 492 self.content.as_optional() 493 } 494 495 /// Attempt to get a reference on the content from a tagged object. 496 /// This can fail if the object is not tagged. as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError>497 pub fn as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError> { 498 self.content.as_tagged() 499 } 500 501 /// Attempt to read a reference to a BitString value from DER object. 502 /// This can fail if the object is not an BitString. 503 /// 504 /// Note that this function returns a reference to the BitString. To get an owned value, 505 /// use [`as_bitstring`](struct.BerObject.html#method.as_bitstring) as_bitstring_ref(&self) -> Result<&BitStringObject, BerError>506 pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> { 507 self.content.as_bitstring_ref() 508 } 509 510 /// Attempt to read a BitString value from DER object. 511 /// This can fail if the object is not an BitString. as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError>512 pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> { 513 self.content.as_bitstring() 514 } 515 516 /// Constructs a shared `&BitSlice` reference over the object data, if available as slice. 517 #[cfg(feature = "bitvec")] as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError>518 pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> { 519 self.content.as_bitslice() 520 } 521 522 /// Attempt to extract the list of objects from a DER sequence. 523 /// This can fail if the object is not a sequence. as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError>524 pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> { 525 self.content.as_sequence() 526 } 527 528 /// Attempt to extract the list of objects from a DER set. 529 /// This can fail if the object is not a set. as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError>530 pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> { 531 self.content.as_set() 532 } 533 534 /// Attempt to get the content from a DER object, as a slice. 535 /// This can fail if the object does not contain a type directly equivalent to a slice (e.g a 536 /// sequence). 537 /// This function mostly concerns string types, integers, or unknown DER objects. as_slice(&self) -> Result<&'a [u8], BerError>538 pub fn as_slice(&self) -> Result<&'a [u8], BerError> { 539 self.content.as_slice() 540 } 541 542 /// Attempt to get the content from a DER object, as a str. 543 /// This can fail if the object does not contain a string type. 544 /// 545 /// Only NumericString, VisibleString, UTCTime, GeneralizedTime, 546 /// PrintableString, UTF8String and IA5String are considered here. Other 547 /// string types can be read using `as_slice`. as_str(&self) -> Result<&'a str, BerError>548 pub fn as_str(&self) -> Result<&'a str, BerError> { 549 self.content.as_str() 550 } 551 552 /// Test if object class is Universal is_universal(&self) -> bool553 pub fn is_universal(&self) -> bool { 554 self.header.class == BerClass::Universal 555 } 556 /// Test if object class is Application is_application(&self) -> bool557 pub fn is_application(&self) -> bool { 558 self.header.class == BerClass::Application 559 } 560 /// Test if object class is Context-specific is_contextspecific(&self) -> bool561 pub fn is_contextspecific(&self) -> bool { 562 self.header.class == BerClass::ContextSpecific 563 } 564 /// Test if object class is Private is_private(&self) -> bool565 pub fn is_private(&self) -> bool { 566 self.header.class == BerClass::Private 567 } 568 569 /// Test if object is primitive is_primitive(&self) -> bool570 pub fn is_primitive(&self) -> bool { 571 self.header.structured == 0 572 } 573 /// Test if object is constructed is_constructed(&self) -> bool574 pub fn is_constructed(&self) -> bool { 575 self.header.structured == 1 576 } 577 } 578 579 /// Build a DER object from an OID. 580 impl<'a> From<Oid<'a>> for BerObject<'a> { from(oid: Oid<'a>) -> BerObject<'a>581 fn from(oid: Oid<'a>) -> BerObject<'a> { 582 BerObject::from_obj(BerObjectContent::OID(oid)) 583 } 584 } 585 586 /// Build a DER object from a BerObjectContent. 587 impl<'a> From<BerObjectContent<'a>> for BerObject<'a> { from(obj: BerObjectContent<'a>) -> BerObject<'a>588 fn from(obj: BerObjectContent<'a>) -> BerObject<'a> { 589 BerObject::from_obj(obj) 590 } 591 } 592 593 /// Compare two BER headers. `len` fields are compared only if both objects have it set (same for `raw_tag`) 594 impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> { eq(&self, other: &BerObjectHeader) -> bool595 fn eq(&self, other: &BerObjectHeader) -> bool { 596 self.class == other.class 597 && self.tag == other.tag 598 && self.structured == other.structured 599 && { 600 if self.len.is_null() && other.len.is_null() { 601 self.len == other.len 602 } else { 603 true 604 } 605 } 606 && { 607 // it tag is present for both, compare it 608 if self.raw_tag.xor(other.raw_tag).is_none() { 609 self.raw_tag == other.raw_tag 610 } else { 611 true 612 } 613 } 614 } 615 } 616 617 impl<'a> BerObjectContent<'a> { 618 /// Attempt to read a signed integer value from this object. 619 /// 620 /// This can fail if the object is not an integer, or if it is too large. 621 /// 622 /// # Examples 623 /// 624 /// ```rust 625 /// # use der_parser::ber::BerObject; 626 /// let der_int = BerObject::from_int_slice(b"\x80"); 627 /// assert_eq!( 628 /// der_int.as_i64(), 629 /// Ok(-128) 630 /// ); 631 /// ``` as_i64(&self) -> Result<i64, BerError>632 pub fn as_i64(&self) -> Result<i64, BerError> { 633 if let BerObjectContent::Integer(bytes) = self { 634 let result = if is_highest_bit_set(bytes) { 635 <i64>::from_be_bytes(decode_array_int8(bytes)?) 636 } else { 637 <u64>::from_be_bytes(decode_array_uint8(bytes)?) as i64 638 }; 639 Ok(result) 640 } else { 641 Err(BerError::InvalidTag) 642 } 643 } 644 645 /// Attempt to read a signed integer value from this object. 646 /// 647 /// This can fail if the object is not an integer, or if it is too large. 648 /// 649 /// # Examples 650 /// 651 /// ```rust 652 /// # use der_parser::ber::BerObject; 653 /// let der_int = BerObject::from_int_slice(b"\x80"); 654 /// assert_eq!( 655 /// der_int.as_i32(), 656 /// Ok(-128) 657 /// ); 658 /// ``` as_i32(&self) -> Result<i32, BerError>659 pub fn as_i32(&self) -> Result<i32, BerError> { 660 if let BerObjectContent::Integer(bytes) = self { 661 let result = if is_highest_bit_set(bytes) { 662 <i32>::from_be_bytes(decode_array_int4(bytes)?) 663 } else { 664 <u32>::from_be_bytes(decode_array_uint4(bytes)?) as i32 665 }; 666 Ok(result) 667 } else { 668 Err(BerError::InvalidTag) 669 } 670 } 671 672 /// Attempt to read integer value from this object. 673 /// 674 /// This can fail if the object is not an unsigned integer, or if it is too large. 675 /// 676 /// # Examples 677 /// 678 /// ```rust 679 /// # use der_parser::ber::BerObject; 680 /// let der_int = BerObject::from_int_slice(b"\x01\x00\x01"); 681 /// assert_eq!( 682 /// der_int.as_u64(), 683 /// Ok(0x10001) 684 /// ); 685 /// ``` as_u64(&self) -> Result<u64, BerError>686 pub fn as_u64(&self) -> Result<u64, BerError> { 687 match self { 688 BerObjectContent::Integer(i) => { 689 let result = <u64>::from_be_bytes(decode_array_uint8(i)?); 690 Ok(result) 691 } 692 BerObjectContent::BitString(ignored_bits, data) => { 693 bitstring_to_u64(*ignored_bits as usize, data) 694 } 695 BerObjectContent::Enum(i) => Ok(*i as u64), 696 _ => Err(BerError::BerTypeError), 697 } 698 } 699 700 /// Attempt to read integer value from this object. 701 /// 702 /// This can fail if the object is not an unsigned integer, or if it is too large. 703 /// 704 /// # Examples 705 /// 706 /// ```rust 707 /// # extern crate der_parser; 708 /// # use der_parser::ber::{BerObject,BerObjectContent}; 709 /// let der_int = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); 710 /// assert_eq!( 711 /// der_int.as_u32(), 712 /// Ok(0x10001) 713 /// ); 714 /// ``` as_u32(&self) -> Result<u32, BerError>715 pub fn as_u32(&self) -> Result<u32, BerError> { 716 match self { 717 BerObjectContent::Integer(i) => { 718 let result = <u32>::from_be_bytes(decode_array_uint4(i)?); 719 Ok(result) 720 } 721 BerObjectContent::BitString(ignored_bits, data) => { 722 bitstring_to_u64(*ignored_bits as usize, data).and_then(|x| { 723 if x > u64::from(core::u32::MAX) { 724 Err(BerError::IntegerTooLarge) 725 } else { 726 Ok(x as u32) 727 } 728 }) 729 } 730 BerObjectContent::Enum(i) => { 731 if *i > u64::from(core::u32::MAX) { 732 Err(BerError::IntegerTooLarge) 733 } else { 734 Ok(*i as u32) 735 } 736 } 737 _ => Err(BerError::BerTypeError), 738 } 739 } 740 as_bool(&self) -> Result<bool, BerError>741 pub fn as_bool(&self) -> Result<bool, BerError> { 742 match *self { 743 BerObjectContent::Boolean(b) => Ok(b), 744 _ => Err(BerError::BerTypeError), 745 } 746 } 747 as_oid(&self) -> Result<&Oid<'a>, BerError>748 pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> { 749 match *self { 750 BerObjectContent::OID(ref o) => Ok(o), 751 BerObjectContent::RelativeOID(ref o) => Ok(o), 752 _ => Err(BerError::BerTypeError), 753 } 754 } 755 as_oid_val(&self) -> Result<Oid<'a>, BerError>756 pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> { 757 self.as_oid().map(|o| o.clone()) 758 } 759 as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError>760 pub fn as_optional(&'a self) -> Result<Option<&'_ BerObject<'a>>, BerError> { 761 match *self { 762 BerObjectContent::Optional(Some(ref o)) => Ok(Some(o)), 763 BerObjectContent::Optional(None) => Ok(None), 764 _ => Err(BerError::BerTypeError), 765 } 766 } 767 as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError>768 pub fn as_tagged(&'a self) -> Result<(BerClass, BerTag, &'_ BerObject<'a>), BerError> { 769 match *self { 770 BerObjectContent::Tagged(class, tag, ref o) => Ok((class, tag, o.as_ref())), 771 _ => Err(BerError::BerTypeError), 772 } 773 } 774 as_bitstring_ref(&self) -> Result<&BitStringObject, BerError>775 pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> { 776 match *self { 777 BerObjectContent::BitString(_, ref b) => Ok(b), 778 _ => Err(BerError::BerTypeError), 779 } 780 } 781 as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError>782 pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> { 783 match *self { 784 BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()), 785 _ => Err(BerError::BerTypeError), 786 } 787 } 788 789 /// Constructs a shared `&BitSlice` reference over the object data, if available as slice. 790 #[cfg(feature = "bitvec")] as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError>791 pub fn as_bitslice(&self) -> Result<&BitSlice<Msb0, u8>, BerError> { 792 self.as_slice() 793 .and_then(|s| BitSlice::<Msb0, _>::from_slice(s).map_err(|_| BerError::BerValueError)) 794 } 795 as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError>796 pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> { 797 match *self { 798 BerObjectContent::Sequence(ref s) => Ok(s), 799 _ => Err(BerError::BerTypeError), 800 } 801 } 802 as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError>803 pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> { 804 match *self { 805 BerObjectContent::Set(ref s) => Ok(s), 806 _ => Err(BerError::BerTypeError), 807 } 808 } 809 810 #[rustfmt::skip] as_slice(&self) -> Result<&'a [u8],BerError>811 pub fn as_slice(&self) -> Result<&'a [u8],BerError> { 812 match *self { 813 BerObjectContent::NumericString(s) | 814 BerObjectContent::GeneralizedTime(s) | 815 BerObjectContent::UTCTime(s) | 816 BerObjectContent::VisibleString(s) | 817 BerObjectContent::PrintableString(s) | 818 BerObjectContent::UTF8String(s) | 819 BerObjectContent::IA5String(s) => Ok(s.as_ref()), 820 BerObjectContent::Integer(s) | 821 BerObjectContent::BitString(_,BitStringObject{data:s}) | 822 BerObjectContent::OctetString(s) | 823 BerObjectContent::T61String(s) | 824 BerObjectContent::VideotexString(s) | 825 BerObjectContent::BmpString(s) | 826 BerObjectContent::UniversalString(s) | 827 BerObjectContent::ObjectDescriptor(s) | 828 BerObjectContent::GraphicString(s) | 829 BerObjectContent::GeneralString(s) | 830 BerObjectContent::Unknown(_, _,s) | 831 BerObjectContent::Private(_,s) => Ok(s), 832 _ => Err(BerError::BerTypeError), 833 } 834 } 835 836 #[rustfmt::skip] as_str(&self) -> Result<&'a str,BerError>837 pub fn as_str(&self) -> Result<&'a str,BerError> { 838 match *self { 839 BerObjectContent::NumericString(s) | 840 BerObjectContent::GeneralizedTime(s) | 841 BerObjectContent::UTCTime(s) | 842 BerObjectContent::VisibleString(s) | 843 BerObjectContent::PrintableString(s) | 844 BerObjectContent::UTF8String(s) | 845 BerObjectContent::IA5String(s) => Ok(s), 846 _ => Err(BerError::BerTypeError), 847 } 848 } 849 850 #[rustfmt::skip] tag(&self) -> BerTag851 fn tag(&self) -> BerTag { 852 match self { 853 BerObjectContent::EndOfContent => BerTag::EndOfContent, 854 BerObjectContent::Boolean(_) => BerTag::Boolean, 855 BerObjectContent::Integer(_) => BerTag::Integer, 856 BerObjectContent::BitString(_,_) => BerTag::BitString, 857 BerObjectContent::OctetString(_) => BerTag::OctetString, 858 BerObjectContent::Null => BerTag::Null, 859 BerObjectContent::Enum(_) => BerTag::Enumerated, 860 BerObjectContent::OID(_) => BerTag::Oid, 861 BerObjectContent::NumericString(_) => BerTag::NumericString, 862 BerObjectContent::VisibleString(_) => BerTag::VisibleString, 863 BerObjectContent::PrintableString(_) => BerTag::PrintableString, 864 BerObjectContent::IA5String(_) => BerTag::Ia5String, 865 BerObjectContent::UTF8String(_) => BerTag::Utf8String, 866 BerObjectContent::RelativeOID(_) => BerTag::RelativeOid, 867 BerObjectContent::T61String(_) => BerTag::T61String, 868 BerObjectContent::VideotexString(_) => BerTag::VideotexString, 869 BerObjectContent::BmpString(_) => BerTag::BmpString, 870 BerObjectContent::UniversalString(_) => BerTag::UniversalString, 871 BerObjectContent::Sequence(_) => BerTag::Sequence, 872 BerObjectContent::Set(_) => BerTag::Set, 873 BerObjectContent::UTCTime(_) => BerTag::UtcTime, 874 BerObjectContent::GeneralizedTime(_) => BerTag::GeneralizedTime, 875 BerObjectContent::ObjectDescriptor(_) => BerTag::ObjDescriptor, 876 BerObjectContent::GraphicString(_) => BerTag::GraphicString, 877 BerObjectContent::GeneralString(_) => BerTag::GeneralString, 878 BerObjectContent::Tagged(_,x,_) | 879 BerObjectContent::Unknown(_, x,_) => *x, 880 &BerObjectContent::Private(ref hdr, _) => hdr.tag, 881 BerObjectContent::Optional(Some(obj)) => obj.content.tag(), 882 BerObjectContent::Optional(None) => BerTag(0x00), // XXX invalid ! 883 } 884 } 885 } 886 887 #[cfg(feature = "bigint")] 888 #[cfg_attr(docsrs, doc(cfg(feature = "bigint")))] 889 use num_bigint::{BigInt, BigUint}; 890 891 #[cfg(feature = "bigint")] 892 #[cfg_attr(docsrs, doc(cfg(feature = "bigint")))] 893 impl<'a> BerObject<'a> { 894 /// Attempt to read an integer value from this object. 895 /// 896 /// This can fail if the object is not an integer. 897 /// 898 /// # Examples 899 /// 900 /// ```rust 901 /// use der_parser::ber::*; 902 /// 903 /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01]; 904 /// 905 /// let (_, object) = parse_ber_integer(data).expect("parsing failed"); 906 /// # #[cfg(feature = "bigint")] 907 /// assert_eq!(object.as_bigint(), Ok(65537.into())) 908 /// ``` as_bigint(&self) -> Result<BigInt, BerError>909 pub fn as_bigint(&self) -> Result<BigInt, BerError> { 910 match self.content { 911 BerObjectContent::Integer(s) => Ok(BigInt::from_signed_bytes_be(s)), 912 _ => Err(BerError::InvalidTag), 913 } 914 } 915 916 /// Attempt to read a positive integer value from this object. 917 /// 918 /// This can fail if the object is not an integer, or is negative. 919 /// 920 /// # Examples 921 /// 922 /// ```rust 923 /// use der_parser::ber::*; 924 /// 925 /// let data = &[0x02, 0x03, 0x01, 0x00, 0x01]; 926 /// 927 /// let (_, object) = parse_ber_integer(data).expect("parsing failed"); 928 /// # #[cfg(feature = "bigint")] 929 /// assert_eq!(object.as_biguint(), Ok(65537_u32.into())) 930 /// ``` as_biguint(&self) -> Result<BigUint, BerError>931 pub fn as_biguint(&self) -> Result<BigUint, BerError> { 932 match self.content { 933 BerObjectContent::Integer(s) => { 934 if is_highest_bit_set(s) { 935 return Err(BerError::IntegerNegative); 936 } 937 Ok(BigUint::from_bytes_be(s)) 938 } 939 _ => Err(BerError::InvalidTag), 940 } 941 } 942 } 943 944 // This is a consuming iterator 945 impl<'a> IntoIterator for BerObject<'a> { 946 type Item = BerObject<'a>; 947 type IntoIter = BerObjectIntoIterator<'a>; 948 into_iter(self) -> Self::IntoIter949 fn into_iter(self) -> Self::IntoIter { 950 // match self { 951 // BerObjectContent::Sequence(ref v) => (), 952 // _ => (), 953 // }; 954 BerObjectIntoIterator { val: self, idx: 0 } 955 } 956 } 957 958 #[derive(Debug)] 959 pub struct BerObjectIntoIterator<'a> { 960 val: BerObject<'a>, 961 idx: usize, 962 } 963 964 impl<'a> Iterator for BerObjectIntoIterator<'a> { 965 type Item = BerObject<'a>; next(&mut self) -> Option<BerObject<'a>>966 fn next(&mut self) -> Option<BerObject<'a>> { 967 // let result = if self.idx < self.vec.len() { 968 // Some(self.vec[self.idx].clone()) 969 // } else { 970 // None 971 // }; 972 let res = match self.val.content { 973 BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()), 974 BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()), 975 _ => { 976 if self.idx == 0 { 977 Some(self.val.clone()) 978 } else { 979 None 980 } 981 } 982 }; 983 self.idx += 1; 984 res 985 } 986 } 987 988 // impl<'a> Iterator for BerObjectContent<'a> { 989 // type Item = BerObjectContent<'a>; 990 // 991 // fn next(&mut self) -> Option<BerObjectContent<'a>> { 992 // None 993 // } 994 // } 995 996 #[derive(Debug)] 997 pub struct BerObjectRefIterator<'a> { 998 obj: &'a BerObject<'a>, 999 idx: usize, 1000 } 1001 1002 impl<'a> Iterator for BerObjectRefIterator<'a> { 1003 type Item = &'a BerObject<'a>; next(&mut self) -> Option<&'a BerObject<'a>>1004 fn next(&mut self) -> Option<&'a BerObject<'a>> { 1005 let res = match (*self.obj).content { 1006 BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]), 1007 BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]), 1008 _ => None, 1009 }; 1010 self.idx += 1; 1011 res 1012 } 1013 } 1014 1015 impl<'a> BerObject<'a> { ref_iter(&'a self) -> BerObjectRefIterator<'a>1016 pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> { 1017 BerObjectRefIterator { obj: self, idx: 0 } 1018 } 1019 } 1020 1021 impl<'a> Index<usize> for BerObject<'a> { 1022 type Output = BerObject<'a>; 1023 index(&self, idx: usize) -> &BerObject<'a>1024 fn index(&self, idx: usize) -> &BerObject<'a> { 1025 match (*self).content { 1026 BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx], 1027 BerObjectContent::Set(ref v) if idx < v.len() => &v[idx], 1028 _ => panic!("Try to index BerObjectContent which is not structured"), 1029 } 1030 // XXX the following 1031 // self.ref_iter().nth(idx).unwrap() 1032 // fails with: 1033 // error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495] 1034 // self.ref_iter().nth(idx).unwrap() 1035 } 1036 } 1037 1038 /// BitString wrapper 1039 #[derive(Clone, Debug, PartialEq)] 1040 pub struct BitStringObject<'a> { 1041 pub data: &'a [u8], 1042 } 1043 1044 impl<'a> BitStringObject<'a> { 1045 /// Test if bit `bitnum` is set is_set(&self, bitnum: usize) -> bool1046 pub fn is_set(&self, bitnum: usize) -> bool { 1047 let byte_pos = bitnum / 8; 1048 if byte_pos >= self.data.len() { 1049 return false; 1050 } 1051 let b = 7 - (bitnum % 8); 1052 (self.data[byte_pos] & (1 << b)) != 0 1053 } 1054 1055 /// Constructs a shared `&BitSlice` reference over the object data. 1056 #[cfg(feature = "bitvec")] as_bitslice(&self) -> Option<&BitSlice<Msb0, u8>>1057 pub fn as_bitslice(&self) -> Option<&BitSlice<Msb0, u8>> { 1058 BitSlice::<Msb0, _>::from_slice(self.data).ok() 1059 } 1060 } 1061 1062 impl<'a> AsRef<[u8]> for BitStringObject<'a> { as_ref(&self) -> &[u8]1063 fn as_ref(&self) -> &[u8] { 1064 self.data 1065 } 1066 } 1067 1068 #[cfg(test)] 1069 mod tests { 1070 use crate::ber::*; 1071 use crate::oid::*; 1072 1073 #[test] test_der_as_u64()1074 fn test_der_as_u64() { 1075 let der_obj = BerObject::from_int_slice(b"\x01\x00\x02"); 1076 assert_eq!(der_obj.as_u64(), Ok(0x10002)); 1077 } 1078 1079 #[test] test_ber_as_u64_bitstring()1080 fn test_ber_as_u64_bitstring() { 1081 let (_, ber_obj) = parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xc0").unwrap(); 1082 assert_eq!(ber_obj.as_u64(), Ok(0b011011100101110111)); 1083 1084 let (_, ber_obj_with_nonzero_padding) = 1085 parse_ber_bitstring(b"\x03\x04\x06\x6e\x5d\xe0").unwrap(); 1086 assert_eq!( 1087 ber_obj_with_nonzero_padding.as_u64(), 1088 Ok(0b011011100101110111) 1089 ); 1090 } 1091 1092 #[test] test_der_seq_iter()1093 fn test_der_seq_iter() { 1094 let der_obj = BerObject::from_obj(BerObjectContent::Sequence(vec![ 1095 BerObject::from_int_slice(b"\x01\x00\x01"), 1096 BerObject::from_int_slice(b"\x01\x00\x00"), 1097 ])); 1098 let expected_values = vec![ 1099 BerObject::from_int_slice(b"\x01\x00\x01"), 1100 BerObject::from_int_slice(b"\x01\x00\x00"), 1101 ]; 1102 1103 for (idx, v) in der_obj.ref_iter().enumerate() { 1104 // println!("v: {:?}", v); 1105 assert_eq!((*v), expected_values[idx]); 1106 } 1107 } 1108 1109 #[test] test_der_from_oid()1110 fn test_der_from_oid() { 1111 let obj: BerObject = Oid::from(&[1, 2]).unwrap().into(); 1112 let expected = BerObject::from_obj(BerObjectContent::OID(Oid::from(&[1, 2]).unwrap())); 1113 1114 assert_eq!(obj, expected); 1115 } 1116 1117 #[test] test_der_bitstringobject()1118 fn test_der_bitstringobject() { 1119 let obj = BitStringObject { 1120 data: &[0x0f, 0x00, 0x40], 1121 }; 1122 assert!(!obj.is_set(0)); 1123 assert!(obj.is_set(7)); 1124 assert!(!obj.is_set(9)); 1125 assert!(obj.is_set(17)); 1126 } 1127 1128 #[cfg(feature = "bitvec")] 1129 #[test] test_der_bitslice()1130 fn test_der_bitslice() { 1131 use std::string::String; 1132 let obj = BitStringObject { 1133 data: &[0x0f, 0x00, 0x40], 1134 }; 1135 let slice = obj.as_bitslice().expect("as_bitslice"); 1136 assert_eq!(slice.get(0).as_deref(), Some(&false)); 1137 assert_eq!(slice.get(7).as_deref(), Some(&true)); 1138 assert_eq!(slice.get(9).as_deref(), Some(&false)); 1139 assert_eq!(slice.get(17).as_deref(), Some(&true)); 1140 let s = slice.iter().fold(String::with_capacity(24), |mut acc, b| { 1141 acc += if *b { "1" } else { "0" }; 1142 acc 1143 }); 1144 assert_eq!(&s, "000011110000000001000000"); 1145 } 1146 1147 #[test] test_der_bistringobject_asref()1148 fn test_der_bistringobject_asref() { 1149 fn assert_equal<T: AsRef<[u8]>>(s: T, b: &[u8]) { 1150 assert_eq!(s.as_ref(), b); 1151 } 1152 let b: &[u8] = &[0x0f, 0x00, 0x40]; 1153 let obj = BitStringObject { data: b }; 1154 assert_equal(obj, b); 1155 } 1156 1157 #[cfg(feature = "bigint")] 1158 #[test] test_der_to_bigint()1159 fn test_der_to_bigint() { 1160 let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); 1161 let expected = ::num_bigint::BigInt::from(0x10001); 1162 1163 assert_eq!(obj.as_bigint(), Ok(expected)); 1164 } 1165 1166 #[cfg(feature = "bigint")] 1167 #[test] test_der_to_biguint()1168 fn test_der_to_biguint() { 1169 let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); 1170 let expected = ::num_bigint::BigUint::from(0x10001_u32); 1171 1172 assert_eq!(obj.as_biguint(), Ok(expected)); 1173 } 1174 } 1175