1#![cfg(feature = "std")]
2use crate::ber::*;
3use crate::oid::Oid;
4use asn1_rs::ASN1DateTime;
5use cookie_factory::bytes::be_u8;
6use cookie_factory::combinator::slice;
7use cookie_factory::gen_simple;
8use cookie_factory::multi::many_ref;
9use cookie_factory::sequence::tuple;
10use cookie_factory::{GenError, SerializeFn};
11use std::io::Write;
12
13fn encode_length<'a, W: Write + 'a, Len: Into<Length>>(len: Len) -> impl SerializeFn<W> + 'a {
14 let l = len.into();
15 move |out| {
16 match l {
17 Length::Definite(sz) => {
18 if sz <= 0x7f {
19 be_u8(sz as u8)(out)
21 } else {
22 let v: Vec<u8> = sz
24 .to_be_bytes()
25 .iter()
26 .cloned()
27 .skip_while(|&b| b == 0)
28 .collect();
29 let b0 = 0b1000_0000 | (v.len() as u8);
30 tuple((be_u8(b0), slice(v)))(out)
31 }
32 }
33 Length::Indefinite => be_u8(0b1000_0000)(out),
34 }
35 }
36}
37
38#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
42pub fn ber_encode_header<'a, 'b: 'a, W: Write + 'a>(hdr: &'b Header) -> impl SerializeFn<W> + 'a {
43 move |out| {
44 let class_u8 = (hdr.class() as u8) << 6;
46 let pc_u8 = (if hdr.constructed() { 1 } else { 0 }) << 5;
47 if hdr.tag().0 >= 30 {
48 unimplemented!();
49 }
50 let byte_0 = class_u8 | pc_u8 | (hdr.tag().0 as u8);
51 tuple((be_u8(byte_0), encode_length(hdr.length())))(out)
53 }
54}
55
56fn ber_encode_oid<'a, W: Write + 'a>(oid: &'a Oid) -> impl SerializeFn<W> + 'a {
57 move |out| {
58 slice(oid.as_bytes())(out)
60 }
61}
62
63fn ber_encode_datetime<'a, W: Write + 'a>(time: &'a ASN1DateTime) -> impl SerializeFn<W> + 'a {
64 move |out| {
65 let s = format!("{}", time);
66 slice(s)(out)
67 }
68}
69
70fn ber_encode_sequence<'a, W: Write + Default + AsRef<[u8]> + 'a>(
71 v: &'a [BerObject],
72) -> impl SerializeFn<W> + 'a {
73 many_ref(v, ber_encode_object)
74}
75
76#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
80pub fn ber_encode_tagged_explicit<'a, W: Write + Default + AsRef<[u8]> + 'a>(
81 tag: Tag,
82 class: Class,
83 obj: &'a BerObject,
84) -> impl SerializeFn<W> + 'a {
85 move |out| {
86 let v = gen_simple(ber_encode_object(obj), W::default())?;
88 let len = v.as_ref().len();
89 let hdr = Header::new(class, true , tag, len.into());
91 let v_hdr = gen_simple(ber_encode_header(&hdr), W::default())?;
92 tuple((slice(v_hdr), slice(v)))(out)
93 }
94}
95
96#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
100pub fn ber_encode_tagged_implicit<'a, W: Write + Default + AsRef<[u8]> + 'a>(
101 tag: Tag,
102 class: Class,
103 obj: &'a BerObject,
104) -> impl SerializeFn<W> + 'a {
105 move |out| {
106 let v = gen_simple(ber_encode_object_content(&obj.content), W::default())?;
108 let len = v.as_ref().len();
110 let hdr = Header::new(class, obj.header.constructed(), tag, len.into());
111 let v_hdr = gen_simple(ber_encode_header(&hdr), W::default())?;
112 tuple((slice(v_hdr), slice(v)))(out)
113 }
114}
115
116fn ber_encode_object_content<'a, W: Write + Default + AsRef<[u8]> + 'a>(
117 c: &'a BerObjectContent,
118) -> impl SerializeFn<W> + 'a {
119 move |out| match c {
120 BerObjectContent::EndOfContent => be_u8(0)(out),
121 BerObjectContent::Boolean(b) => {
122 let b0 = if *b { 0xff } else { 0x00 };
123 be_u8(b0)(out)
124 }
125 BerObjectContent::Integer(s) => slice(s)(out),
126 BerObjectContent::BitString(ignored_bits, s) => {
127 tuple((be_u8(*ignored_bits), slice(s)))(out)
128 }
129 BerObjectContent::OctetString(s) => slice(s)(out),
130 BerObjectContent::Null => Ok(out),
131 BerObjectContent::Enum(i) => {
132 let v: Vec<u8> = i
133 .to_be_bytes()
134 .iter()
135 .cloned()
136 .skip_while(|&b| b == 0)
137 .collect();
138 slice(v)(out)
139 }
140 BerObjectContent::OID(oid) | BerObjectContent::RelativeOID(oid) => ber_encode_oid(oid)(out),
141 BerObjectContent::UTCTime(time) | BerObjectContent::GeneralizedTime(time) => {
142 ber_encode_datetime(time)(out)
143 }
144 BerObjectContent::NumericString(s)
145 | BerObjectContent::GeneralString(s)
146 | BerObjectContent::ObjectDescriptor(s)
147 | BerObjectContent::GraphicString(s)
148 | BerObjectContent::VisibleString(s)
149 | BerObjectContent::PrintableString(s)
150 | BerObjectContent::IA5String(s)
151 | BerObjectContent::T61String(s)
152 | BerObjectContent::VideotexString(s)
153 | BerObjectContent::UTF8String(s) => slice(s)(out),
154 BerObjectContent::BmpString(s) => slice(s)(out),
155 BerObjectContent::UniversalString(s) => slice(s)(out),
156 BerObjectContent::Sequence(v) | BerObjectContent::Set(v) => ber_encode_sequence(v)(out),
157 BerObjectContent::Optional(inner) => {
159 match inner {
161 Some(obj) => ber_encode_object_content(&obj.content)(out),
162 None => slice(&[])(out), }
164 }
165 BerObjectContent::Tagged(_class, _tag, inner) => {
166 ber_encode_object(inner)(out)
169 }
170 BerObjectContent::Unknown(any) => slice(any.data)(out),
171 }
172}
173
174#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
181pub fn ber_encode_object_raw<'a, 'b: 'a, 'c: 'a, W: Write + Default + AsRef<[u8]> + 'a>(
182 hdr: &'b Header,
183 content: &'c BerObjectContent,
184) -> impl SerializeFn<W> + 'a {
185 tuple((ber_encode_header(hdr), ber_encode_object_content(content)))
186}
187
188#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
197pub fn ber_encode_object<'a, 'b: 'a, W: Write + Default + AsRef<[u8]> + 'a>(
198 obj: &'b BerObject,
199) -> impl SerializeFn<W> + 'a {
200 move |out| {
201 let v = gen_simple(ber_encode_object_content(&obj.content), W::default())?;
203 let len = v.as_ref().len();
204 let hdr = obj.header.clone().with_length(len.into());
205 let v_hdr = gen_simple(ber_encode_header(&hdr), W::default())?;
206 tuple((slice(v_hdr), slice(v)))(out)
207 }
208}
209
210impl BerObject<'_> {
211 #[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
220 pub fn to_vec(&self) -> Result<Vec<u8>, GenError> {
221 gen_simple(ber_encode_object(self), Vec::new())
222 }
223}
224
225#[cfg(test)]
226mod test {
227 use super::*;
228 use crate::error::BerResult;
229 use cookie_factory::gen_simple;
230 use hex_literal::hex;
231
232 macro_rules! encode_and_parse {
233 ($obj:ident, $encode:ident, $parse:ident) => {{
234 let v = gen_simple($encode(&$obj), Vec::new()).expect("could not encode");
235 let (_, obj2) = $parse(&v).expect("could not re-parse");
236 assert_eq!($obj, obj2);
237 v
238 }};
239 }
240
241 #[test]
242 fn test_encode_length() {
243 let l = 38;
244 let v = gen_simple(encode_length(l), Vec::new()).expect("could not serialize");
245 assert_eq!(&v[..], &[38]);
246 let l = 201;
247 let v = gen_simple(encode_length(l), Vec::new()).expect("could not serialize");
248 assert_eq!(&v[..], &[129, 201]);
249 let l = 0x1234_5678;
250 let v = gen_simple(encode_length(l), Vec::new()).expect("could not serialize");
251 assert_eq!(&v[..], &[132, 0x12, 0x34, 0x56, 0x78]);
252 }
253
254 #[test]
255 fn test_encode_header() {
256 let bytes = hex!("02 03 01 00 01");
258 let (_, hdr) = ber_read_element_header(&bytes).expect("could not parse");
259 let v = encode_and_parse!(hdr, ber_encode_header, ber_read_element_header);
260 assert_eq!(&v[..], &bytes[..2]);
261 }
262
263 #[test]
264 fn test_encode_bool() {
265 let b_true = BerObject::from_obj(BerObjectContent::Boolean(true));
266 let b_false = BerObject::from_obj(BerObjectContent::Boolean(false));
267 encode_and_parse!(b_true, ber_encode_object, parse_ber_bool);
268 encode_and_parse!(b_false, ber_encode_object, parse_ber_bool);
269 }
270
271 #[test]
272 fn test_encode_integer() {
273 let i = BerObject::from_obj(BerObjectContent::Integer(b"\x01\x00\x01"));
274 encode_and_parse!(i, ber_encode_object, parse_ber_integer);
275 }
276
277 #[test]
278 fn test_encode_bitstring() {
279 let bytes = hex!("03 04 06 6e 5d e0");
280 let b = BerObject::from_obj(BerObjectContent::BitString(
281 6,
282 BitStringObject { data: &bytes[3..] },
283 ));
284 let v = encode_and_parse!(b, ber_encode_object, parse_ber_bitstring);
285 assert_eq!(&v[..], bytes)
286 }
287
288 #[test]
289 fn test_encode_octetstring() {
290 let i = BerObject::from_obj(BerObjectContent::OctetString(b"AAAAA"));
291 let v = encode_and_parse!(i, ber_encode_object, parse_ber_octetstring);
292 assert_eq!(&v[..], hex!("04 05 41 41 41 41 41"))
293 }
294
295 #[test]
296 fn test_encode_enum() {
297 let i = BerObject::from_obj(BerObjectContent::Enum(2));
298 let v = encode_and_parse!(i, ber_encode_object, parse_ber_enum);
299 assert_eq!(&v[..], hex!("0a 01 02"))
300 }
301
302 #[test]
303 fn test_encode_null() {
304 let i = BerObject::from_obj(BerObjectContent::Null);
305 encode_and_parse!(i, ber_encode_object, parse_ber_null);
306 }
307
308 #[test]
309 fn test_encode_oid() {
310 let bytes = hex!("06 09 2A 86 48 86 F7 0D 01 01 05");
311 let obj = BerObject::from_obj(BerObjectContent::OID(
312 Oid::from(&[1, 2, 840, 113_549, 1, 1, 5]).unwrap(),
313 ));
314 let v = encode_and_parse!(obj, ber_encode_object, parse_ber_oid);
315 assert_eq!(&v[..], bytes);
316 }
317
318 #[test]
319 fn test_encode_relative_oid() {
320 let bytes = hex!("0d 04 c2 7b 03 02");
321 let obj = BerObject::from_obj(BerObjectContent::RelativeOID(
322 Oid::from_relative(&[8571, 3, 2]).unwrap(),
323 ));
324 let v = encode_and_parse!(obj, ber_encode_object, parse_ber_relative_oid);
325 assert_eq!(&v[..], bytes);
326 }
327
328 #[test]
329 fn test_encode_sequence() {
330 let bytes = hex!("30 0a 02 03 01 00 01 02 03 01 00 00");
331 let obj = BerObject::from_seq(vec![
332 BerObject::from_int_slice(b"\x01\x00\x01"),
333 BerObject::from_int_slice(b"\x01\x00\x00"),
334 ]);
335 let v = encode_and_parse!(obj, ber_encode_object, parse_ber_sequence);
336 assert_eq!(&v[..], bytes);
337 }
338
339 #[test]
340 fn test_encode_set() {
341 let bytes = hex!("31 0a 02 03 01 00 01 02 03 01 00 00");
342 let obj = BerObject::from_set(vec![
343 BerObject::from_int_slice(b"\x01\x00\x01"),
344 BerObject::from_int_slice(b"\x01\x00\x00"),
345 ]);
346 let v = encode_and_parse!(obj, ber_encode_object, parse_ber_set);
347 assert_eq!(&v[..], bytes);
348 }
349
350 #[test]
351 fn test_encode_tagged_explicit() {
352 fn local_parse(i: &[u8]) -> BerResult {
353 parse_ber_explicit_optional(i, Tag(0), parse_ber_integer)
354 }
355 let bytes = hex!("a0 03 02 01 02");
356 let obj = BerObject::from_int_slice(b"\x02");
357 let v = gen_simple(
358 ber_encode_tagged_explicit(Tag(0), Class::ContextSpecific, &obj),
359 Vec::new(),
360 )
361 .expect("could not encode");
362 let (_, obj2) = local_parse(&v).expect("could not re-parse");
363 let obj2 = obj2
364 .as_optional()
365 .expect("tagged object not found")
366 .expect("optional object empty");
367 let (_class, tag, inner) = obj2.as_tagged().expect("not a tagged object");
368 assert_eq!(tag, Tag(0));
369 assert_eq!(&obj, inner);
370 assert_eq!(&v[..], bytes);
371 }
372
373 #[test]
374 fn test_encode_tagged_implicit() {
375 fn der_read_integer_content<'a>(
376 i: &'a [u8],
377 hdr: &Header,
378 depth: usize,
379 ) -> BerResult<'a, BerObjectContent<'a>> {
380 ber_read_element_content_as(i, Tag::Integer, hdr.length(), false, depth)
381 }
382 fn local_parse(i: &[u8]) -> BerResult<BerObject> {
383 parse_ber_implicit(i, Tag(3), der_read_integer_content)
384 }
385 let obj = BerObject::from_int_slice(b"\x02");
386 let v = gen_simple(
387 ber_encode_tagged_implicit(Tag(3), Class::ContextSpecific, &obj),
388 Vec::new(),
389 )
390 .expect("could not encode");
391 let (_, obj2) = local_parse(&v).expect("could not re-parse");
392 assert_eq!(obj2.header.tag(), Tag(3));
393 assert_eq!(&obj.content, &obj2.content);
394 let bytes = hex!("83 01 02");
395 assert_eq!(&v[..], bytes);
396 }
397 #[test]
398 fn test_encode_tagged_application() {
399 fn local_parse(i: &[u8]) -> BerResult {
400 parse_ber_explicit_optional(i, Tag(2), parse_ber_integer)
401 }
402 let obj = BerObject::from_int_slice(b"\x02");
403 let v = gen_simple(
404 ber_encode_tagged_explicit(Tag(2), Class::Application, &obj),
405 Vec::new(),
406 )
407 .expect("could not encode");
408 let (_, obj2) = local_parse(&v).expect("could not re-parse");
409 let obj2 = obj2
410 .as_optional()
411 .expect("tagged object not found")
412 .expect("optional object empty");
413 let (_class, tag, inner) = obj2.as_tagged().expect("not a tagged object");
414 assert_eq!(tag, Tag(2));
415 assert_eq!(&obj, inner);
416 let bytes = hex!("62 03 02 01 02");
417 assert_eq!(&v[..], bytes);
418 }
419}