/rust/registry/src/github.com-1ecc6299db9ec823/der-parser-4.0.2/src/ber/ber.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use crate::ber::bytes_to_u64; |
2 | | use crate::error::BerError; |
3 | | use crate::oid::Oid; |
4 | | use rusticata_macros::newtype_enum; |
5 | | use std::convert::AsRef; |
6 | | use std::convert::From; |
7 | | use std::convert::TryFrom; |
8 | | use std::ops::Index; |
9 | | use std::vec::Vec; |
10 | | |
11 | 0 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] Unexecuted instantiation: <der_parser::ber::ber::BerClassFromIntError as core::cmp::PartialEq>::ne Unexecuted instantiation: <der_parser::ber::ber::BerClassFromIntError as core::cmp::PartialEq>::eq |
12 | | pub struct BerClassFromIntError(pub(crate) ()); |
13 | | |
14 | | /// BER Object class of tag |
15 | 464k | #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
16 | | #[repr(u8)] |
17 | | pub enum BerClass { |
18 | | Universal = 0b00, |
19 | | Application = 0b01, |
20 | | ContextSpecific = 0b10, |
21 | | Private = 0b11, |
22 | | } |
23 | | |
24 | | /// Defined in X.680 section 8.4 |
25 | | /// X.690 doesn't specify the maxmimum tag size so we're assuming that people |
26 | | /// aren't going to need anything more than a u32. |
27 | 5.25M | #[derive(Clone, Copy, PartialEq, Eq)] <der_parser::ber::ber::BerTag as core::cmp::PartialEq>::eq Line | Count | Source | 27 | 526k | #[derive(Clone, Copy, PartialEq, Eq)] |
<der_parser::ber::ber::BerTag as core::cmp::PartialEq>::ne Line | Count | Source | 27 | 4.73M | #[derive(Clone, Copy, PartialEq, Eq)] |
|
28 | | pub struct BerTag(pub u32); |
29 | | |
30 | | newtype_enum! { |
31 | | impl debug BerTag { |
32 | | EndOfContent = 0x0, |
33 | | Boolean = 0x1, |
34 | | Integer = 0x2, |
35 | | BitString = 0x3, |
36 | | OctetString = 0x4, |
37 | | Null = 0x05, |
38 | | Oid = 0x06, |
39 | | ObjDescriptor = 0x07, |
40 | | External = 0x08, |
41 | | RealType = 0x09, |
42 | | Enumerated = 0xa, |
43 | | EmbeddedPdv = 0xb, |
44 | | Utf8String = 0xc, |
45 | | RelativeOid = 0xd, |
46 | | |
47 | | Sequence = 0x10, |
48 | | Set = 0x11, |
49 | | NumericString = 0x12, |
50 | | PrintableString = 0x13, |
51 | | T61String = 0x14, |
52 | | |
53 | | Ia5String = 0x16, |
54 | | UtcTime = 0x17, |
55 | | GeneralizedTime = 0x18, |
56 | | |
57 | | GeneralString = 27, // 0x1b |
58 | | |
59 | | BmpString = 0x1e, |
60 | | |
61 | | Invalid = 0xff, |
62 | | } |
63 | | } |
64 | | |
65 | | /// Representation of a DER-encoded (X.690) object |
66 | 7.60k | #[derive(Debug, Clone, PartialEq)] Unexecuted instantiation: <der_parser::ber::ber::BerObject as core::cmp::PartialEq>::ne Unexecuted instantiation: <der_parser::ber::ber::BerObject as core::cmp::PartialEq>::eq |
67 | | pub struct BerObject<'a> { |
68 | | pub header: BerObjectHeader<'a>, |
69 | | pub content: BerObjectContent<'a>, |
70 | | } |
71 | | |
72 | 7.60k | #[derive(Clone, Copy, Debug)] |
73 | | pub struct BerObjectHeader<'a> { |
74 | | pub class: BerClass, |
75 | | pub structured: u8, |
76 | | pub tag: BerTag, |
77 | | pub len: u64, |
78 | | |
79 | | pub raw_tag: Option<&'a [u8]>, |
80 | | } |
81 | | |
82 | 7.60k | #[derive(Debug, Clone, PartialEq)] Unexecuted instantiation: <der_parser::ber::ber::BerObjectContent as core::cmp::PartialEq>::eq Unexecuted instantiation: <der_parser::ber::ber::BerObjectContent as core::cmp::PartialEq>::ne |
83 | | pub enum BerObjectContent<'a> { |
84 | | EndOfContent, |
85 | | Boolean(bool), |
86 | | Integer(&'a [u8]), |
87 | | BitString(u8, BitStringObject<'a>), |
88 | | OctetString(&'a [u8]), |
89 | | Null, |
90 | | Enum(u64), |
91 | | OID(Oid<'a>), |
92 | | RelativeOID(Oid<'a>), |
93 | | NumericString(&'a str), |
94 | | PrintableString(&'a str), |
95 | | IA5String(&'a str), |
96 | | UTF8String(&'a str), |
97 | | T61String(&'a [u8]), |
98 | | |
99 | | BmpString(&'a [u8]), |
100 | | |
101 | | Sequence(Vec<BerObject<'a>>), |
102 | | Set(Vec<BerObject<'a>>), |
103 | | |
104 | | UTCTime(&'a [u8]), |
105 | | GeneralizedTime(&'a [u8]), |
106 | | |
107 | | GeneralString(&'a [u8]), |
108 | | |
109 | | ContextSpecific(BerTag, Option<Box<BerObject<'a>>>), |
110 | | Unknown(BerTag, &'a [u8]), |
111 | | } |
112 | | |
113 | | impl TryFrom<u8> for BerClass { |
114 | | type Error = BerClassFromIntError; |
115 | | |
116 | | #[inline] |
117 | 10.2M | fn try_from(value: u8) -> Result<Self, Self::Error> { |
118 | 10.2M | match value { |
119 | 6.60M | 0b00 => Ok(BerClass::Universal), |
120 | 2.68M | 0b01 => Ok(BerClass::Application), |
121 | 396k | 0b10 => Ok(BerClass::ContextSpecific), |
122 | 550k | 0b11 => Ok(BerClass::Private), |
123 | 0 | _ => Err(BerClassFromIntError(())), |
124 | | } |
125 | 10.2M | } |
126 | | } |
127 | | |
128 | | impl<'a> BerObjectHeader<'a> { |
129 | | /// Test if object class is Universal |
130 | | #[inline] |
131 | 0 | pub fn is_universal(&self) -> bool { |
132 | 0 | self.class == BerClass::Universal |
133 | 0 | } |
134 | | /// Test if object class is Application |
135 | | #[inline] |
136 | 28.4k | pub fn is_application(&self) -> bool { |
137 | 28.4k | self.class == BerClass::Application |
138 | 28.4k | } |
139 | | /// Test if object class is Context-specific |
140 | | #[inline] |
141 | 0 | pub fn is_contextspecific(&self) -> bool { |
142 | 0 | self.class == BerClass::ContextSpecific |
143 | 0 | } |
144 | | /// Test if object class is Private |
145 | | #[inline] |
146 | 0 | pub fn is_private(&self) -> bool { |
147 | 0 | self.class == BerClass::Private |
148 | 0 | } |
149 | | |
150 | | /// Test if object is primitive |
151 | | #[inline] |
152 | 0 | pub fn is_primitive(&self) -> bool { |
153 | 0 | self.structured == 0 |
154 | 0 | } |
155 | | /// Test if object is constructed |
156 | | #[inline] |
157 | 3.91M | pub fn is_constructed(&self) -> bool { |
158 | 3.91M | self.structured == 1 |
159 | 3.91M | } |
160 | | } |
161 | | |
162 | | impl<'a> BerObject<'a> { |
163 | | /// Build a BerObject from a header and content. |
164 | | /// Note: values are not checked, so the tag can be different from the real content, or flags |
165 | | /// can be invalid. |
166 | 4.43M | pub fn from_header_and_content<'hdr>( |
167 | 4.43M | header: BerObjectHeader<'hdr>, |
168 | 4.43M | content: BerObjectContent<'hdr>, |
169 | 4.43M | ) -> BerObject<'hdr> { |
170 | 4.43M | BerObject { header, content } |
171 | 4.43M | } |
172 | | /// Build a BerObject from its content, using default flags (no class, correct tag, |
173 | | /// and structured flag set only for Set and Sequence) |
174 | 5.45k | pub fn from_obj(c: BerObjectContent) -> BerObject { |
175 | 5.45k | let class = BerClass::Universal; |
176 | 5.45k | let tag = c.tag(); |
177 | 5.45k | let structured = match tag { |
178 | 0 | BerTag::Sequence | BerTag::Set => 1, |
179 | 5.45k | _ => 0, |
180 | | }; |
181 | 5.45k | let header = BerObjectHeader { |
182 | 5.45k | class, |
183 | 5.45k | structured, |
184 | 5.45k | tag, |
185 | 5.45k | len: 0, |
186 | 5.45k | raw_tag: None, |
187 | 5.45k | }; |
188 | 5.45k | BerObject { header, content: c } |
189 | 5.45k | } |
190 | | |
191 | | /// Build a DER integer object from a slice containing an encoded integer |
192 | 0 | pub fn from_int_slice(i: &'a [u8]) -> BerObject<'a> { |
193 | 0 | let header = BerObjectHeader { |
194 | 0 | class: BerClass::Universal, |
195 | 0 | structured: 0, |
196 | 0 | tag: BerTag::Integer, |
197 | 0 | len: 0, |
198 | 0 | raw_tag: None, |
199 | 0 | }; |
200 | 0 | BerObject { |
201 | 0 | header, |
202 | 0 | content: BerObjectContent::Integer(i), |
203 | 0 | } |
204 | 0 | } |
205 | | |
206 | | /// Set a tag for the BER object |
207 | 0 | pub fn set_raw_tag(self, raw_tag: Option<&'a [u8]>) -> BerObject { |
208 | 0 | let header = BerObjectHeader { |
209 | 0 | raw_tag, |
210 | 0 | ..self.header |
211 | 0 | }; |
212 | 0 | BerObject { header, ..self } |
213 | 0 | } |
214 | | |
215 | | /// Build a DER sequence object from a vector of DER objects |
216 | 0 | pub fn from_seq(l: Vec<BerObject>) -> BerObject { |
217 | 0 | BerObject::from_obj(BerObjectContent::Sequence(l)) |
218 | 0 | } |
219 | | |
220 | | /// Build a DER set object from a vector of DER objects |
221 | 0 | pub fn from_set(l: Vec<BerObject>) -> BerObject { |
222 | 0 | BerObject::from_obj(BerObjectContent::Set(l)) |
223 | 0 | } |
224 | | |
225 | | /// Build a BER header from this object content |
226 | | #[deprecated( |
227 | | since = "0.5.0", |
228 | | note = "please use `obj.header` or `obj.header.clone()` instead" |
229 | | )] |
230 | 0 | pub fn to_header(&self) -> BerObjectHeader { |
231 | 0 | self.header |
232 | 0 | } |
233 | | |
234 | | /// Attempt to read integer value from DER object. |
235 | | /// This can fail if the object is not an integer, or if it is too large. |
236 | | /// |
237 | | /// ```rust |
238 | | /// # extern crate der_parser; |
239 | | /// # use der_parser::ber::{BerObject,BerObjectContent}; |
240 | | /// let der_int = BerObject::from_int_slice(b"\x01\x00\x01"); |
241 | | /// assert_eq!( |
242 | | /// der_int.as_u64(), |
243 | | /// Ok(0x10001) |
244 | | /// ); |
245 | | /// ``` |
246 | 0 | pub fn as_u64(&self) -> Result<u64, BerError> { |
247 | 0 | self.content.as_u64() |
248 | 0 | } |
249 | | |
250 | | /// Attempt to read integer value from DER object. |
251 | | /// This can fail if the object is not an integer, or if it is too large. |
252 | | /// |
253 | | /// ```rust |
254 | | /// # extern crate der_parser; |
255 | | /// # use der_parser::ber::{BerObject,BerObjectContent}; |
256 | | /// let der_int = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); |
257 | | /// assert_eq!( |
258 | | /// der_int.as_u32(), |
259 | | /// Ok(0x10001) |
260 | | /// ); |
261 | | /// ``` |
262 | 915k | pub fn as_u32(&self) -> Result<u32, BerError> { |
263 | 915k | self.content.as_u32() |
264 | 915k | } |
265 | | |
266 | | /// Attempt to read integer value from DER object. |
267 | | /// This can fail if the object is not a boolean. |
268 | 0 | pub fn as_bool(&self) -> Result<bool, BerError> { |
269 | 0 | self.content.as_bool() |
270 | 0 | } |
271 | | |
272 | | /// Attempt to read an OID value from DER object. |
273 | | /// This can fail if the object is not an OID. |
274 | 0 | pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> { |
275 | 0 | self.content.as_oid() |
276 | 0 | } |
277 | | |
278 | | /// Attempt to read an OID value from DER object. |
279 | | /// This can fail if the object is not an OID. |
280 | 32.1k | pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> { |
281 | 32.1k | self.content.as_oid_val() |
282 | 32.1k | } |
283 | | |
284 | | /// Attempt to read the content from a context-specific DER object. |
285 | | /// This can fail if the object is not context-specific. |
286 | | /// |
287 | | /// Note: the object is cloned. |
288 | 832 | pub fn as_context_specific(&self) -> Result<(BerTag, Option<Box<BerObject<'a>>>), BerError> { |
289 | 832 | self.content.as_context_specific() |
290 | 832 | } |
291 | | |
292 | | /// Attempt to read a reference to a BitString value from DER object. |
293 | | /// This can fail if the object is not an BitString. |
294 | | /// |
295 | | /// Note that this function returns a reference to the BitString. To get an owned value, |
296 | | /// use [`as_bitstring`](struct.BerObject.html#method.as_bitstring) |
297 | 0 | pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> { |
298 | 0 | self.content.as_bitstring_ref() |
299 | 0 | } |
300 | | |
301 | | /// Attempt to read a BitString value from DER object. |
302 | | /// This can fail if the object is not an BitString. |
303 | 0 | pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> { |
304 | 0 | self.content.as_bitstring() |
305 | 0 | } |
306 | | |
307 | | /// Attempt to extract the list of objects from a DER sequence. |
308 | | /// This can fail if the object is not a sequence. |
309 | 0 | pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> { |
310 | 0 | self.content.as_sequence() |
311 | 0 | } |
312 | | |
313 | | /// Attempt to extract the list of objects from a DER set. |
314 | | /// This can fail if the object is not a set. |
315 | 0 | pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> { |
316 | 0 | self.content.as_set() |
317 | 0 | } |
318 | | |
319 | | /// Attempt to get the content from a DER object, as a slice. |
320 | | /// This can fail if the object does not contain a type directly equivalent to a slice (e.g a |
321 | | /// sequence). |
322 | | /// This function mostly concerns string types, integers, or unknown DER objects. |
323 | 65.6k | pub fn as_slice(&self) -> Result<&'a [u8], BerError> { |
324 | 65.6k | self.content.as_slice() |
325 | 65.6k | } |
326 | | |
327 | | /// Attempt to get the content from a DER object, as a str. |
328 | | /// This can fail if the object does not contain a string type. |
329 | | /// |
330 | | /// Only NumericString, PrintableString, UTF8String and IA5String |
331 | | /// are considered here. Other string types can be read using `as_slice`. |
332 | 0 | pub fn as_str(&self) -> Result<&'a str, BerError> { |
333 | 0 | self.content.as_str() |
334 | 0 | } |
335 | | |
336 | | /// Test if object class is Universal |
337 | 0 | pub fn is_universal(&self) -> bool { |
338 | 0 | self.header.class == BerClass::Universal |
339 | 0 | } |
340 | | /// Test if object class is Application |
341 | 0 | pub fn is_application(&self) -> bool { |
342 | 0 | self.header.class == BerClass::Application |
343 | 0 | } |
344 | | /// Test if object class is Context-specific |
345 | 0 | pub fn is_contextspecific(&self) -> bool { |
346 | 0 | self.header.class == BerClass::ContextSpecific |
347 | 0 | } |
348 | | /// Test if object class is Private |
349 | 0 | pub fn is_private(&self) -> bool { |
350 | 0 | self.header.class == BerClass::Private |
351 | 0 | } |
352 | | |
353 | | /// Test if object is primitive |
354 | 0 | pub fn is_primitive(&self) -> bool { |
355 | 0 | self.header.structured == 0 |
356 | 0 | } |
357 | | /// Test if object is constructed |
358 | 0 | pub fn is_constructed(&self) -> bool { |
359 | 0 | self.header.structured == 1 |
360 | 0 | } |
361 | | } |
362 | | |
363 | | /// Build a DER object from an OID. |
364 | | impl<'a> From<Oid<'a>> for BerObject<'a> { |
365 | 0 | fn from(oid: Oid<'a>) -> BerObject<'a> { |
366 | 0 | BerObject::from_obj(BerObjectContent::OID(oid)) |
367 | 0 | } |
368 | | } |
369 | | |
370 | | /// Build a DER object from a BerObjectContent. |
371 | | impl<'a> From<BerObjectContent<'a>> for BerObject<'a> { |
372 | 0 | fn from(obj: BerObjectContent<'a>) -> BerObject<'a> { |
373 | 0 | BerObject::from_obj(obj) |
374 | 0 | } |
375 | | } |
376 | | |
377 | | /// Replacement function for Option.xor (>= 1.37) |
378 | | #[inline] |
379 | | pub fn xor_option<T>(opta: Option<T>, optb: Option<T>) -> Option<T> { |
380 | 0 | match (opta, optb) { |
381 | 0 | (Some(a), None) => Some(a), |
382 | 0 | (None, Some(b)) => Some(b), |
383 | 0 | _ => None, |
384 | | } |
385 | 0 | } |
386 | | |
387 | | /// Compare two BER headers. `len` fields are compared only if both objects have it set (same for `raw_tag`) |
388 | | impl<'a> PartialEq<BerObjectHeader<'a>> for BerObjectHeader<'a> { |
389 | 0 | fn eq(&self, other: &BerObjectHeader) -> bool { |
390 | 0 | self.class == other.class |
391 | 0 | && self.tag == other.tag |
392 | 0 | && self.structured == other.structured |
393 | | && { |
394 | 0 | if self.len != 0 && other.len != 0 { |
395 | 0 | self.len == other.len |
396 | | } else { |
397 | 0 | true |
398 | | } |
399 | | } |
400 | | && { |
401 | | // it tag is present for both, compare it |
402 | 0 | if xor_option(self.raw_tag, other.raw_tag).is_none() { |
403 | 0 | self.raw_tag == other.raw_tag |
404 | | } else { |
405 | 0 | true |
406 | | } |
407 | | } |
408 | 0 | } |
409 | | } |
410 | | |
411 | | impl<'a> BerObjectContent<'a> { |
412 | 4.68k | pub fn as_u64(&self) -> Result<u64, BerError> { |
413 | 4.68k | match *self { |
414 | 4.68k | BerObjectContent::Integer(i) => bytes_to_u64(i), |
415 | 0 | BerObjectContent::Enum(i) => Ok(i as u64), |
416 | 0 | _ => Err(BerError::BerTypeError), |
417 | | } |
418 | 4.68k | } |
419 | | |
420 | 918k | pub fn as_u32(&self) -> Result<u32, BerError> { |
421 | 918k | match *self { |
422 | 908k | BerObjectContent::Integer(i) => bytes_to_u64(i).and_then(|x| { |
423 | 908k | if x > u64::from(std::u32::MAX) { |
424 | 359 | Err(BerError::IntegerTooLarge) |
425 | | } else { |
426 | 908k | Ok(x as u32) |
427 | | } |
428 | 908k | }), |
429 | 40 | BerObjectContent::Enum(i) => { |
430 | 40 | if i > u64::from(std::u32::MAX) { |
431 | 16 | Err(BerError::IntegerTooLarge) |
432 | | } else { |
433 | 24 | Ok(i as u32) |
434 | | } |
435 | | } |
436 | 9.52k | _ => Err(BerError::BerTypeError), |
437 | | } |
438 | 918k | } |
439 | | |
440 | 0 | pub fn as_bool(&self) -> Result<bool, BerError> { |
441 | 0 | match *self { |
442 | 0 | BerObjectContent::Boolean(b) => Ok(b), |
443 | 0 | _ => Err(BerError::BerTypeError), |
444 | | } |
445 | 0 | } |
446 | | |
447 | 45.3k | pub fn as_oid(&self) -> Result<&Oid<'a>, BerError> { |
448 | 45.3k | match *self { |
449 | 45.3k | BerObjectContent::OID(ref o) => Ok(o), |
450 | 0 | BerObjectContent::RelativeOID(ref o) => Ok(o), |
451 | 0 | _ => Err(BerError::BerTypeError), |
452 | | } |
453 | 45.3k | } |
454 | | |
455 | 32.1k | pub fn as_oid_val(&self) -> Result<Oid<'a>, BerError> { |
456 | 32.1k | self.as_oid().map(|o| o.clone()) |
457 | 32.1k | } |
458 | | |
459 | 832 | pub fn as_context_specific(&self) -> Result<(BerTag, Option<Box<BerObject<'a>>>), BerError> { |
460 | 832 | match *self { |
461 | 832 | BerObjectContent::ContextSpecific(u, ref o) => Ok((u, o.clone())), |
462 | 0 | _ => Err(BerError::BerTypeError), |
463 | | } |
464 | 832 | } |
465 | | |
466 | 0 | pub fn as_bitstring_ref(&self) -> Result<&BitStringObject, BerError> { |
467 | 0 | match *self { |
468 | 0 | BerObjectContent::BitString(_, ref b) => Ok(b), |
469 | 0 | _ => Err(BerError::BerTypeError), |
470 | | } |
471 | 0 | } |
472 | | |
473 | 0 | pub fn as_bitstring(&'a self) -> Result<BitStringObject<'a>, BerError> { |
474 | 0 | match *self { |
475 | 0 | BerObjectContent::BitString(_, ref b) => Ok(b.to_owned()), |
476 | 0 | _ => Err(BerError::BerTypeError), |
477 | | } |
478 | 0 | } |
479 | | |
480 | 0 | pub fn as_sequence(&self) -> Result<&Vec<BerObject<'a>>, BerError> { |
481 | 0 | match *self { |
482 | 0 | BerObjectContent::Sequence(ref s) => Ok(s), |
483 | 0 | _ => Err(BerError::BerTypeError), |
484 | | } |
485 | 0 | } |
486 | | |
487 | 0 | pub fn as_set(&self) -> Result<&Vec<BerObject<'a>>, BerError> { |
488 | 0 | match *self { |
489 | 0 | BerObjectContent::Set(ref s) => Ok(s), |
490 | 0 | _ => Err(BerError::BerTypeError), |
491 | | } |
492 | 0 | } |
493 | | |
494 | | #[rustfmt::skip] |
495 | 152k | pub fn as_slice(&self) -> Result<&'a [u8],BerError> { |
496 | 152k | match *self { |
497 | 696 | BerObjectContent::NumericString(s) | |
498 | 4.78k | BerObjectContent::PrintableString(s) | |
499 | 2.03k | BerObjectContent::UTF8String(s) | |
500 | 8.70k | BerObjectContent::IA5String(s) => Ok(s.as_ref()), |
501 | 5.45k | BerObjectContent::Integer(s) | |
502 | 9.50k | BerObjectContent::BitString(_,BitStringObject{data:s}) | |
503 | 34.9k | BerObjectContent::OctetString(s) | |
504 | 1.99k | BerObjectContent::T61String(s) | |
505 | 2.13k | BerObjectContent::BmpString(s) | |
506 | 1.12k | BerObjectContent::GeneralString(s) | |
507 | 109k | BerObjectContent::Unknown(_,s) => Ok(s), |
508 | 34.8k | _ => Err(BerError::BerTypeError), |
509 | | } |
510 | 152k | } |
511 | | |
512 | | #[rustfmt::skip] |
513 | 0 | pub fn as_str(&self) -> Result<&'a str,BerError> { |
514 | 0 | match *self { |
515 | 0 | BerObjectContent::NumericString(s) | |
516 | 0 | BerObjectContent::PrintableString(s) | |
517 | 0 | BerObjectContent::UTF8String(s) | |
518 | 0 | BerObjectContent::IA5String(s) => Ok(s), |
519 | 0 | _ => Err(BerError::BerTypeError), |
520 | | } |
521 | 0 | } |
522 | | |
523 | | #[rustfmt::skip] |
524 | 5.45k | pub fn tag(&self) -> BerTag { |
525 | 5.45k | match *self { |
526 | 0 | BerObjectContent::EndOfContent => BerTag::EndOfContent, |
527 | 282 | BerObjectContent::Boolean(_) => BerTag::Boolean, |
528 | 1.50k | BerObjectContent::Integer(_) => BerTag::Integer, |
529 | 0 | BerObjectContent::BitString(_,_) => BerTag::BitString, |
530 | 0 | BerObjectContent::OctetString(_) => BerTag::OctetString, |
531 | 0 | BerObjectContent::Null => BerTag::Null, |
532 | 1.11k | BerObjectContent::Enum(_) => BerTag::Enumerated, |
533 | 0 | BerObjectContent::OID(_) => BerTag::Oid, |
534 | 194 | BerObjectContent::NumericString(_) => BerTag::NumericString, |
535 | 204 | BerObjectContent::PrintableString(_) => BerTag::PrintableString, |
536 | 377 | BerObjectContent::IA5String(_) => BerTag::Ia5String, |
537 | 194 | BerObjectContent::UTF8String(_) => BerTag::Utf8String, |
538 | 514 | BerObjectContent::RelativeOID(_) => BerTag::RelativeOid, |
539 | 196 | BerObjectContent::T61String(_) => BerTag::T61String, |
540 | 195 | BerObjectContent::BmpString(_) => BerTag::BmpString, |
541 | 0 | BerObjectContent::Sequence(_) => BerTag::Sequence, |
542 | 0 | BerObjectContent::Set(_) => BerTag::Set, |
543 | 199 | BerObjectContent::UTCTime(_) => BerTag::UtcTime, |
544 | 204 | BerObjectContent::GeneralizedTime(_) => BerTag::GeneralizedTime, |
545 | 216 | BerObjectContent::GeneralString(_) => BerTag::GeneralString, |
546 | 55 | BerObjectContent::ContextSpecific(x,_) | |
547 | 55 | BerObjectContent::Unknown(x,_) => x, |
548 | | } |
549 | 5.45k | } |
550 | | } |
551 | | |
552 | | #[cfg(feature = "bigint")] |
553 | | mod bigint { |
554 | | use super::{BerObject, BerObjectContent}; |
555 | | use num_bigint::{BigInt, BigUint, Sign}; |
556 | | |
557 | | impl<'a> BerObject<'a> { |
558 | | pub fn as_bigint(&self) -> Option<BigInt> { |
559 | | match self.content { |
560 | | BerObjectContent::Integer(s) => Some(BigInt::from_bytes_be(Sign::Plus, s)), |
561 | | _ => None, |
562 | | } |
563 | | } |
564 | | |
565 | | pub fn as_biguint(&self) -> Option<BigUint> { |
566 | | match self.content { |
567 | | BerObjectContent::Integer(s) => Some(BigUint::from_bytes_be(s)), |
568 | | _ => None, |
569 | | } |
570 | | } |
571 | | } |
572 | | } |
573 | | |
574 | | // This is a consuming iterator |
575 | | impl<'a> IntoIterator for BerObject<'a> { |
576 | | type Item = BerObject<'a>; |
577 | | type IntoIter = BerObjectIntoIterator<'a>; |
578 | | |
579 | 2.10k | fn into_iter(self) -> Self::IntoIter { |
580 | 2.10k | // match self { |
581 | 2.10k | // BerObjectContent::Sequence(ref v) => (), |
582 | 2.10k | // _ => (), |
583 | 2.10k | // }; |
584 | 2.10k | BerObjectIntoIterator { val: self, idx: 0 } |
585 | 2.10k | } |
586 | | } |
587 | | |
588 | | pub struct BerObjectIntoIterator<'a> { |
589 | | val: BerObject<'a>, |
590 | | idx: usize, |
591 | | } |
592 | | |
593 | | impl<'a> Iterator for BerObjectIntoIterator<'a> { |
594 | | type Item = BerObject<'a>; |
595 | 8.91k | fn next(&mut self) -> Option<BerObject<'a>> { |
596 | | // let result = if self.idx < self.vec.len() { |
597 | | // Some(self.vec[self.idx].clone()) |
598 | | // } else { |
599 | | // None |
600 | | // }; |
601 | 8.91k | let res = match self.val.content { |
602 | 8.91k | BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(v[self.idx].clone()), |
603 | 0 | BerObjectContent::Set(ref v) if self.idx < v.len() => Some(v[self.idx].clone()), |
604 | | _ => { |
605 | 2.10k | if self.idx == 0 { |
606 | 1 | Some(self.val.clone()) |
607 | | } else { |
608 | 2.10k | None |
609 | | } |
610 | | } |
611 | | }; |
612 | 8.91k | self.idx += 1; |
613 | 8.91k | res |
614 | 8.91k | } |
615 | | } |
616 | | |
617 | | // impl<'a> Iterator for BerObjectContent<'a> { |
618 | | // type Item = BerObjectContent<'a>; |
619 | | // |
620 | | // fn next(&mut self) -> Option<BerObjectContent<'a>> { |
621 | | // None |
622 | | // } |
623 | | // } |
624 | | |
625 | | pub struct BerObjectRefIterator<'a> { |
626 | | obj: &'a BerObject<'a>, |
627 | | idx: usize, |
628 | | } |
629 | | |
630 | | impl<'a> Iterator for BerObjectRefIterator<'a> { |
631 | | type Item = &'a BerObject<'a>; |
632 | 0 | fn next(&mut self) -> Option<&'a BerObject<'a>> { |
633 | 0 | let res = match (*self.obj).content { |
634 | 0 | BerObjectContent::Sequence(ref v) if self.idx < v.len() => Some(&v[self.idx]), |
635 | 0 | BerObjectContent::Set(ref v) if self.idx < v.len() => Some(&v[self.idx]), |
636 | 0 | _ => None, |
637 | | }; |
638 | 0 | self.idx += 1; |
639 | 0 | res |
640 | 0 | } |
641 | | } |
642 | | |
643 | | impl<'a> BerObject<'a> { |
644 | 0 | pub fn ref_iter(&'a self) -> BerObjectRefIterator<'a> { |
645 | 0 | BerObjectRefIterator { obj: self, idx: 0 } |
646 | 0 | } |
647 | | } |
648 | | |
649 | | impl<'a> Index<usize> for BerObject<'a> { |
650 | | type Output = BerObject<'a>; |
651 | | |
652 | 0 | fn index(&self, idx: usize) -> &BerObject<'a> { |
653 | 0 | match (*self).content { |
654 | 0 | BerObjectContent::Sequence(ref v) if idx < v.len() => &v[idx], |
655 | 0 | BerObjectContent::Set(ref v) if idx < v.len() => &v[idx], |
656 | 0 | _ => panic!("Try to index BerObjectContent which is not structured"), |
657 | | } |
658 | | // XXX the following |
659 | | // self.ref_iter().nth(idx).unwrap() |
660 | | // fails with: |
661 | | // error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495] |
662 | | // self.ref_iter().nth(idx).unwrap() |
663 | 0 | } |
664 | | } |
665 | | |
666 | | /// BitString wrapper |
667 | 0 | #[derive(Clone, Debug, PartialEq)] Unexecuted instantiation: <der_parser::ber::ber::BitStringObject as core::cmp::PartialEq>::ne Unexecuted instantiation: <der_parser::ber::ber::BitStringObject as core::cmp::PartialEq>::eq |
668 | | pub struct BitStringObject<'a> { |
669 | | pub data: &'a [u8], |
670 | | } |
671 | | |
672 | | impl<'a> BitStringObject<'a> { |
673 | | /// Test if bit `bitnum` is set |
674 | 0 | pub fn is_set(&self, bitnum: usize) -> bool { |
675 | 0 | let byte_pos = bitnum / 8; |
676 | 0 | if byte_pos >= self.data.len() { |
677 | 0 | return false; |
678 | 0 | } |
679 | 0 | let b = 7 - (bitnum % 8); |
680 | 0 | (self.data[byte_pos] & (1 << b)) != 0 |
681 | 0 | } |
682 | | } |
683 | | |
684 | | impl<'a> AsRef<[u8]> for BitStringObject<'a> { |
685 | 0 | fn as_ref(&self) -> &[u8] { |
686 | 0 | self.data |
687 | 0 | } |
688 | | } |
689 | | |
690 | | #[cfg(test)] |
691 | | mod tests { |
692 | | use crate::ber::*; |
693 | | use crate::oid::*; |
694 | | |
695 | | #[test] |
696 | | fn test_der_as_u64() { |
697 | | let der_obj = BerObject::from_int_slice(b"\x01\x00\x02"); |
698 | | assert_eq!(der_obj.as_u64(), Ok(0x10002)); |
699 | | } |
700 | | |
701 | | #[test] |
702 | | fn test_der_seq_iter() { |
703 | | let der_obj = BerObject::from_obj(BerObjectContent::Sequence(vec![ |
704 | | BerObject::from_int_slice(b"\x01\x00\x01"), |
705 | | BerObject::from_int_slice(b"\x01\x00\x00"), |
706 | | ])); |
707 | | let expected_values = vec![ |
708 | | BerObject::from_int_slice(b"\x01\x00\x01"), |
709 | | BerObject::from_int_slice(b"\x01\x00\x00"), |
710 | | ]; |
711 | | |
712 | | for (idx, v) in der_obj.ref_iter().enumerate() { |
713 | | // println!("v: {:?}", v); |
714 | | assert_eq!((*v), expected_values[idx]); |
715 | | } |
716 | | } |
717 | | |
718 | | #[test] |
719 | | fn test_der_from_oid() { |
720 | | let obj: BerObject = Oid::from(&[1, 2]).unwrap().into(); |
721 | | let expected = BerObject::from_obj(BerObjectContent::OID(Oid::from(&[1, 2]).unwrap())); |
722 | | |
723 | | assert_eq!(obj, expected); |
724 | | } |
725 | | |
726 | | #[test] |
727 | | fn test_der_bistringobject() { |
728 | | let obj = BitStringObject { |
729 | | data: &[0x0f, 0x00, 0x40], |
730 | | }; |
731 | | assert!(!obj.is_set(0)); |
732 | | assert!(obj.is_set(7)); |
733 | | assert!(!obj.is_set(9)); |
734 | | assert!(obj.is_set(17)); |
735 | | } |
736 | | |
737 | | #[test] |
738 | | fn test_der_bistringobject_asref() { |
739 | | fn assert_equal<T: AsRef<[u8]>>(s: T, b: &[u8]) { |
740 | | assert_eq!(s.as_ref(), b); |
741 | | } |
742 | | let b: &[u8] = &[0x0f, 0x00, 0x40]; |
743 | | let obj = BitStringObject { data: b }; |
744 | | assert_equal(obj, b); |
745 | | } |
746 | | |
747 | | #[cfg(feature = "bigint")] |
748 | | #[test] |
749 | | fn test_der_to_bigint() { |
750 | | let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); |
751 | | let expected = ::num_bigint::BigInt::from(0x10001); |
752 | | |
753 | | assert_eq!(obj.as_bigint(), Some(expected)); |
754 | | } |
755 | | |
756 | | #[cfg(feature = "bigint")] |
757 | | #[test] |
758 | | fn test_der_to_biguint() { |
759 | | let obj = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01")); |
760 | | let expected = ::num_bigint::BigUint::from(0x10001 as u32); |
761 | | |
762 | | assert_eq!(obj.as_biguint(), Some(expected)); |
763 | | } |
764 | | } |