yasna/writer/
mod.rs

1// Copyright 2016 Masaki Hara
2// Copyright 2019 Fortanix, Inc.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10#![forbid(missing_docs)]
11
12use alloc::vec::Vec;
13
14#[cfg(feature = "num-bigint")]
15use num_bigint::{BigUint, BigInt};
16#[cfg(feature = "bit-vec")]
17use bit_vec::BitVec;
18
19use super::{PCBit, Tag};
20use super::tags::{TAG_BOOLEAN,TAG_INTEGER,TAG_OCTETSTRING};
21use super::tags::{TAG_NULL,TAG_OID,TAG_UTF8STRING,TAG_SEQUENCE,TAG_SET,TAG_ENUM,TAG_IA5STRING,TAG_BMPSTRING};
22use super::tags::{TAG_NUMERICSTRING,TAG_PRINTABLESTRING,TAG_VISIBLESTRING};
23use super::models::{ObjectIdentifier,TaggedDerValue};
24#[cfg(feature = "time")]
25use super::models::{UTCTime,GeneralizedTime};
26
27/// Constructs DER-encoded data as `Vec<u8>`.
28///
29/// This function uses the loan pattern: `callback` is called back with
30/// a [`DERWriter`], to which the ASN.1 value is written.
31///
32/// # Examples
33///
34/// ```
35/// use yasna;
36/// let der = yasna::construct_der(|writer| {
37///     writer.write_sequence(|writer| {
38///         writer.next().write_i64(10);
39///         writer.next().write_bool(true);
40///     })
41/// });
42/// assert_eq!(der, vec![48, 6, 2, 1, 10, 1, 1, 255]);
43/// ```
44pub fn construct_der<F>(callback: F) -> Vec<u8>
45        where F: FnOnce(DERWriter) {
46    let mut buf = Vec::new();
47    {
48        let mut writer = DERWriterSeq {
49            buf: &mut buf,
50        };
51        callback(writer.next());
52    }
53    return buf;
54}
55
56/// Tries to construct DER-encoded data as `Vec<u8>`.
57///
58/// Same as [`construct_der`], only that it allows
59/// returning an error from the passed closure.
60///
61/// This function uses the loan pattern: `callback` is called back with
62/// a [`DERWriterSeq`], to which the ASN.1 values are written.
63///
64/// # Examples
65///
66/// ```
67/// use yasna;
68/// let res_ok = yasna::try_construct_der::<_, ()>(|writer| {
69///     writer.write_sequence(|writer| {
70///         writer.next().write_i64(10);
71///         writer.next().write_bool(true);
72///     });
73///     Ok(())
74/// });
75/// let res_err = yasna::try_construct_der::<_, &str>(|writer| {
76///     writer.write_sequence(|writer| {
77///         writer.next().write_i64(10);
78///         writer.next().write_bool(true);
79///         return Err("some error here");
80///     })?;
81///     Ok(())
82/// });
83/// assert_eq!(res_ok, Ok(vec![48, 6, 2, 1, 10, 1, 1, 255]));
84/// assert_eq!(res_err, Err("some error here"));
85/// ```
86pub fn try_construct_der<F, E>(callback: F) -> Result<Vec<u8>, E>
87        where F: FnOnce(DERWriter) -> Result<(), E> {
88    let mut buf = Vec::new();
89    {
90        let mut writer = DERWriterSeq {
91            buf: &mut buf,
92        };
93        callback(writer.next())?;
94    }
95    return Ok(buf);
96}
97
98/// Constructs DER-encoded sequence of data as `Vec<u8>`.
99///
100/// This is similar to [`construct_der`], but this function
101/// accepts more than one ASN.1 values.
102///
103/// This function uses the loan pattern: `callback` is called back with
104/// a [`DERWriterSeq`], to which the ASN.1 values are written.
105///
106/// # Examples
107///
108/// ```
109/// use yasna;
110/// let der = yasna::construct_der_seq(|writer| {
111///     writer.next().write_i64(10);
112///     writer.next().write_bool(true);
113/// });
114/// assert_eq!(der, vec![2, 1, 10, 1, 1, 255]);
115/// ```
116pub fn construct_der_seq<F>(callback: F) -> Vec<u8>
117        where F: FnOnce(&mut DERWriterSeq) {
118    let mut buf = Vec::new();
119    {
120        let mut writer = DERWriterSeq {
121            buf: &mut buf,
122        };
123        callback(&mut writer);
124    }
125    return buf;
126}
127
128/// Tries to construct a DER-encoded sequence of data as `Vec<u8>`.
129///
130/// Same as [`construct_der_seq`], only that it allows
131/// returning an error from the passed closure.
132///
133/// This function uses the loan pattern: `callback` is called back with
134/// a [`DERWriterSeq`], to which the ASN.1 values are written.
135///
136/// # Examples
137///
138/// ```
139/// use yasna;
140/// let res_ok = yasna::try_construct_der_seq::<_, ()>(|writer| {
141///     writer.next().write_i64(10);
142///     writer.next().write_bool(true);
143///     Ok(())
144/// });
145/// let res_err = yasna::try_construct_der_seq::<_, &str>(|writer| {
146///     return Err("some error here");
147/// });
148/// assert_eq!(res_ok, Ok(vec![2, 1, 10, 1, 1, 255]));
149/// assert_eq!(res_err, Err("some error here"));
150/// ```
151pub fn try_construct_der_seq<F, E>(callback: F) -> Result<Vec<u8> , E>
152        where F: FnOnce(&mut DERWriterSeq) -> Result<(), E> {
153    let mut buf = Vec::new();
154    {
155        let mut writer = DERWriterSeq {
156            buf: &mut buf,
157        };
158        callback(&mut writer)?;
159    }
160    return Ok(buf);
161}
162
163/// A writer object that accepts an ASN.1 value.
164///
165/// The two main sources of `DERWriterSeq` are:
166///
167/// - The [`construct_der`] function, the starting point of
168///   DER serialization.
169/// - The [`next`](DERWriterSeq::next) method of [`DERWriterSeq`].
170///
171/// # Examples
172///
173/// ```
174/// use yasna;
175/// let der = yasna::construct_der(|writer| {
176///     writer.write_i64(10)
177/// });
178/// assert_eq!(der, vec![2, 1, 10]);
179/// ```
180#[derive(Debug)]
181pub struct DERWriter<'a> {
182    buf: &'a mut Vec<u8>,
183    implicit_tag: Option<Tag>,
184}
185
186impl<'a> DERWriter<'a> {
187    fn from_buf(buf: &'a mut Vec<u8>) -> Self {
188        return DERWriter {
189            buf,
190            implicit_tag: None,
191        }
192    }
193    /// Writes BER identifier (tag + primitive/constructed) octets.
194    fn write_identifier(&mut self, tag: Tag, pc: PCBit) {
195        let tag = if let Some(tag) = self.implicit_tag { tag } else { tag };
196        self.implicit_tag = None;
197        let classid = tag.tag_class as u8;
198        let pcid = pc as u8;
199        if tag.tag_number < 31 {
200            self.buf.push(
201                (classid << 6) | (pcid << 5) | (tag.tag_number as u8));
202            return;
203        }
204        self.buf.push((classid << 6) | (pcid << 5) | 31);
205        let mut shiftnum = 63; // ceil(64 / 7) * 7 - 7
206        while (tag.tag_number >> shiftnum) == 0 {
207            shiftnum -= 7;
208        }
209        while shiftnum > 0 {
210            self.buf.push(128 | (((tag.tag_number >> shiftnum) & 127) as u8));
211            shiftnum -= 7;
212        }
213        self.buf.push((tag.tag_number & 127) as u8);
214    }
215
216    /// Writes BER length octets.
217    fn write_length(&mut self, length: usize) {
218        let length = length as u64;
219        if length < 128 {
220            self.buf.push(length as u8);
221            return;
222        }
223        let mut shiftnum = 56; // ceil(64 / 8) * 8 - 8
224        while (length >> shiftnum) == 0 {
225            shiftnum -= 8;
226        }
227        self.buf.push(128 | ((shiftnum / 8 + 1) as u8));
228        loop {
229            self.buf.push((length >> shiftnum) as u8);
230            if shiftnum == 0 {
231                break;
232            }
233            shiftnum -= 8;
234        }
235    }
236
237    /// Deals with unknown length procedures.
238    /// This function first marks the current position and
239    /// allocates 3 bytes. Then it calls back `callback`.
240    /// It then calculates the length and moves the written data
241    /// to the actual position. Finally, it writes the length.
242    fn with_length<T, F>(&mut self, callback: F) -> T
243        where F: FnOnce(&mut Self) -> T {
244        let expected_length_length = 3;
245        for _ in 0..3 {
246            self.buf.push(255);
247        }
248        let start_pos = self.buf.len();
249        let result = callback(self);
250        let length = (self.buf.len() - start_pos) as u64;
251        let length_length;
252        let mut shiftnum = 56; // ceil(64 / 8) * 8 - 8
253        if length < 128 {
254            length_length = 1;
255        } else {
256            while (length >> shiftnum) == 0 {
257                shiftnum -= 8;
258            }
259            length_length = shiftnum / 8 + 2;
260        }
261        let new_start_pos;
262        if length_length < expected_length_length {
263            let diff = expected_length_length - length_length;
264            new_start_pos = start_pos - diff;
265            self.buf.drain(new_start_pos .. start_pos);
266        } else if length_length > expected_length_length {
267            let diff = length_length - expected_length_length;
268            new_start_pos = start_pos + diff;
269            for _ in 0..diff { self.buf.insert(start_pos, 0); }
270        } else {
271            new_start_pos = start_pos;
272        }
273        let mut idx = new_start_pos - length_length;
274        if length < 128 {
275            self.buf[idx] = length as u8;
276        } else {
277            self.buf[idx] = 128 | ((shiftnum / 8 + 1) as u8);
278            idx += 1;
279            loop {
280                self.buf[idx] = (length >> shiftnum) as u8;
281                idx += 1;
282                if shiftnum == 0 {
283                    break;
284                }
285                shiftnum -= 8;
286            }
287        }
288        return result;
289    }
290
291    /// Writes `bool` as an ASN.1 BOOLEAN value.
292    ///
293    /// # Examples
294    ///
295    /// ```
296    /// use yasna;
297    /// let der = yasna::construct_der(|writer| {
298    ///     writer.write_bool(true)
299    /// });
300    /// assert_eq!(der, vec![1, 1, 255]);
301    /// ```
302    pub fn write_bool(mut self, val: bool) {
303        self.write_identifier(TAG_BOOLEAN, PCBit::Primitive);
304        self.write_length(1);
305        self.buf.push(if val { 255 } else { 0 });
306    }
307
308    fn write_integer(mut self, tag: Tag, val: i64) {
309        let mut shiftnum = 56;
310        while shiftnum > 0 &&
311                (val >> (shiftnum-1) == 0 || val >> (shiftnum-1) == -1) {
312            shiftnum -= 8;
313        }
314        self.write_identifier(tag, PCBit::Primitive);
315        self.write_length(shiftnum / 8 + 1);
316        loop {
317            self.buf.push((val >> shiftnum) as u8);
318            if shiftnum == 0 {
319                break;
320            }
321            shiftnum -= 8;
322        }
323    }
324
325    /// Writes `i64` as an ASN.1 ENUMERATED value.
326    ///
327    /// # Examples
328    ///
329    /// ```
330    /// use yasna;
331    /// let der = yasna::construct_der(|writer| {
332    ///     writer.write_enum(2)
333    /// });
334    /// assert_eq!(der, vec![10, 1, 2]);
335    /// ```
336    pub fn write_enum(self, val: i64) {
337        self.write_integer(TAG_ENUM, val);
338    }
339
340    /// Writes `i64` as an ASN.1 INTEGER value.
341    ///
342    /// # Examples
343    ///
344    /// ```
345    /// use yasna;
346    /// let der = yasna::construct_der(|writer| {
347    ///     writer.write_i64(1234567890)
348    /// });
349    /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]);
350    /// ```
351    pub fn write_i64(self, val: i64) {
352        self.write_integer(TAG_INTEGER, val);
353    }
354
355    /// Writes `u64` as an ASN.1 INTEGER value.
356    pub fn write_u64(mut self, val: u64) {
357        let mut shiftnum = 64;
358        while shiftnum > 0 && val >> (shiftnum-1) == 0 {
359            shiftnum -= 8;
360        }
361        self.write_identifier(TAG_INTEGER, PCBit::Primitive);
362        self.write_length(shiftnum / 8 + 1);
363        if shiftnum == 64 {
364            self.buf.push(0);
365            shiftnum -= 8;
366        }
367        loop {
368            self.buf.push((val >> shiftnum) as u8);
369            if shiftnum == 0 {
370                break;
371            }
372            shiftnum -= 8;
373        }
374    }
375
376    /// Writes `i32` as an ASN.1 INTEGER value.
377    pub fn write_i32(self, val: i32) {
378        self.write_i64(val as i64)
379    }
380
381    /// Writes `u32` as an ASN.1 INTEGER value.
382    pub fn write_u32(self, val: u32) {
383        self.write_i64(val as i64)
384    }
385
386    /// Writes `i16` as an ASN.1 INTEGER value.
387    pub fn write_i16(self, val: i16) {
388        self.write_i64(val as i64)
389    }
390
391    /// Writes `u16` as an ASN.1 INTEGER value.
392    pub fn write_u16(self, val: u16) {
393        self.write_i64(val as i64)
394    }
395
396    /// Writes `i8` as an ASN.1 INTEGER value.
397    pub fn write_i8(self, val: i8) {
398        self.write_i64(val as i64)
399    }
400
401    /// Writes `u8` as an ASN.1 INTEGER value.
402    pub fn write_u8(self, val: u8) {
403        self.write_i64(val as i64)
404    }
405
406    #[cfg(feature = "num-bigint")]
407    /// Writes `BigInt` as an ASN.1 INTEGER value.
408    ///
409    /// # Examples
410    ///
411    /// ```
412    /// # fn main() {
413    /// use yasna;
414    /// use num_bigint::BigInt;
415    /// let der = yasna::construct_der(|writer| {
416    ///     writer.write_bigint(
417    ///         &BigInt::parse_bytes(b"1234567890", 10).unwrap())
418    /// });
419    /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]);
420    /// # }
421    /// ```
422    ///
423    /// # Features
424    ///
425    /// This method is enabled by `num` feature.
426    ///
427    /// ```toml
428    /// [dependencies]
429    /// yasna = { version = "*", features = ["num-bigint"] }
430    /// ```
431    pub fn write_bigint(self, val: &BigInt) {
432        use num_bigint::Sign;
433        let (sign, mut bytes) = val.to_bytes_be();
434        if sign == Sign::Minus {
435            let mut carry: usize = 1;
436            for b in bytes.iter_mut().rev() {
437                let bval = 255 - (*b as usize);
438                *b = (bval + carry) as u8;
439                carry = (bval + carry) >> 8;
440            }
441        }
442        self.write_bigint_bytes(&bytes, sign != Sign::Minus);
443    }
444
445    /// Writes `&[u8]` and `bool` as an ASN.1 INTEGER value.
446    ///
447    /// The first parameter encodes the bytes of the integer, in big-endian
448    /// byte ordering and two's complement format. The second parameter encodes
449    /// the sign, and is true if the number is non-negative, and false if it is
450    /// negative. Zero is encoded by passing an empty slice.
451    ///
452    /// The number is expected to be in two's complement format, so for example
453    /// `1` is encoded as `[1]` and `-1` as `[255]`.
454    ///
455    /// You don't have to worry about leading bits, meaning that if the leading
456    /// bit of a positive number is not zero, a leading zero byte will be
457    /// encoded by the function. Similarly, if the leading bit of a negative
458    /// number is not one, a leading byte will be added by the function as well.
459    ///
460    /// # Examples
461    ///
462    /// ```
463    /// # fn main() {
464    /// use yasna;
465    /// let der = yasna::construct_der(|writer| {
466    ///     // Encodes 1234567890
467    ///     writer.write_bigint_bytes(&[73, 150, 2, 210], true)
468    /// });
469    /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]);
470    /// # }
471    /// ```
472    pub fn write_bigint_bytes(mut self, bytes: &[u8], positive: bool) {
473        let mut bytes = bytes;
474
475        // Remove leading zero bytes
476        while bytes.get(0) == Some(&0)  {
477            bytes = &bytes[1..];
478        }
479
480        if !positive {
481            // Remove leading 255 bytes
482            // (the order is important here, [255, 0] should be a fixpoint input)
483            while bytes.len() > 1 && bytes[0] == 255 && bytes.get(1).unwrap_or(&0) & 128 != 0 {
484                bytes = &bytes[1..];
485            }
486        }
487
488        self.write_identifier(TAG_INTEGER, PCBit::Primitive);
489        if bytes.len() == 0 || bytes[0] == 0 {
490            self.write_length(1);
491            self.buf.push(0);
492        } else if positive {
493            if bytes[0] >= 128 {
494                self.write_length(bytes.len() + 1);
495                self.buf.push(0);
496            } else {
497                self.write_length(bytes.len());
498            }
499            self.buf.extend_from_slice(&bytes);
500        } else {
501            debug_assert!(bytes[0] != 0);
502            if bytes[0] < 128 {
503                self.write_length(bytes.len() + 1);
504                self.buf.push(255);
505            } else {
506                self.write_length(bytes.len());
507            }
508            self.buf.extend_from_slice(&bytes);
509        }
510    }
511
512    #[cfg(feature = "num-bigint")]
513    /// Writes `BigUint` as an ASN.1 INTEGER value.
514    ///
515    /// # Examples
516    ///
517    /// ```
518    /// # fn main() {
519    /// use yasna;
520    /// use num_bigint::BigUint;
521    /// let der = yasna::construct_der(|writer| {
522    ///     writer.write_biguint(
523    ///         &BigUint::parse_bytes(b"1234567890", 10).unwrap())
524    /// });
525    /// assert_eq!(der, vec![2, 4, 73, 150, 2, 210]);
526    /// # }
527    /// ```
528    ///
529    /// # Features
530    ///
531    /// This method is enabled by `num` feature.
532    ///
533    /// ```toml
534    /// [dependencies]
535    /// yasna = { version = "*", features = ["num-bigint"] }
536    /// ```
537    pub fn write_biguint(mut self, val: &BigUint) {
538        self.write_identifier(TAG_INTEGER, PCBit::Primitive);
539        let mut bytes = val.to_bytes_le();
540        if &bytes == &[0] {
541            self.write_length(1);
542            self.buf.push(0);
543            return;
544        }
545        let byteslen = bytes.len();
546        debug_assert!(bytes[byteslen-1] != 0);
547        if bytes[byteslen-1] >= 128 {
548            self.write_length(byteslen+1);
549            self.buf.push(0);
550        } else {
551            self.write_length(byteslen);
552        }
553        bytes.reverse();
554        self.buf.extend_from_slice(&bytes);
555    }
556
557    #[cfg(feature = "bit-vec")]
558    /// Writes [`BitVec`] as an ASN.1 BITSTRING value.
559    ///
560    /// # Examples
561    ///
562    /// ```
563    /// # fn main() {
564    /// use yasna;
565    /// use bit_vec::BitVec;
566    /// let der = yasna::construct_der(|writer| {
567    ///     writer.write_bitvec(&
568    ///         [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1,
569    ///             0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1]
570    ///         .iter().map(|&i| i != 0).collect())
571    /// });
572    /// assert_eq!(&der, &[3, 5, 3, 206, 213, 116, 24]);
573    /// # }
574    /// ```
575    ///
576    /// # Features
577    ///
578    /// This method is enabled by `bit-vec` feature.
579    ///
580    /// ```toml
581    /// [dependencies]
582    /// yasna = { version = "*", features = ["bit-vec"] }
583    /// ```
584    pub fn write_bitvec(self, bitvec: &BitVec) {
585        let len = bitvec.len();
586        let bytes = bitvec.to_bytes();
587        self.write_bitvec_bytes(&bytes, len);
588    }
589
590    /// Writes `&[u8]` and `usize` as an ASN.1 BITSTRING value.
591    ///
592    /// The `len` parameter represents the number of bits to be encoded.
593    /// This function is similar to `write_bitvec`, with `to_bytes` applied to
594    /// the bitvec, but is available even if the `bit-vec` feature is disabled.
595    ///
596    /// # Examples
597    ///
598    /// ```
599    /// # fn main() {
600    /// use yasna;
601    /// let der_1 = yasna::construct_der(|writer| {
602    ///     writer.write_bitvec_bytes(&[117, 13, 64], 18)
603    /// });
604    /// let der_2 = yasna::construct_der(|writer| {
605    ///     writer.write_bitvec_bytes(&[117, 13, 65], 18)
606    /// });
607    /// assert_eq!(&der_1, &[3, 4, 6, 117, 13, 64]);
608    /// assert_eq!(&der_2, &[3, 4, 6, 117, 13, 64]);
609    /// # }
610    /// ```
611    pub fn write_bitvec_bytes(mut self, bytes: &[u8], len: usize) {
612        use super::tags::TAG_BITSTRING;
613        self.write_identifier(TAG_BITSTRING, PCBit::Primitive);
614        debug_assert!(len <= 8 * bytes.len());
615        debug_assert!(8 * bytes.len() < len + 8);
616        self.write_length(1 + bytes.len());
617        let len_diff = 8 * bytes.len() - len;
618        self.buf.push(len_diff as u8);
619        if bytes.len() > 0 {
620            self.buf.extend_from_slice(&bytes[0 .. bytes.len() - 1]);
621            let mask = !(255u16 >> (8 - len_diff)) as u8;
622            self.buf.push(bytes[bytes.len() - 1] & mask);
623        }
624    }
625
626    /// Writes `&[u8]` as an ASN.1 OCTETSTRING value.
627    ///
628    /// # Examples
629    ///
630    /// ```
631    /// use yasna;
632    /// let der = yasna::construct_der(|writer| {
633    ///     writer.write_bytes(b"Hello!")
634    /// });
635    /// assert_eq!(der, vec![4, 6, 72, 101, 108, 108, 111, 33]);
636    /// ```
637    pub fn write_bytes(mut self, bytes: &[u8]) {
638        self.write_identifier(TAG_OCTETSTRING, PCBit::Primitive);
639        self.write_length(bytes.len());
640        self.buf.extend_from_slice(bytes);
641    }
642
643    /// Writes `&str` as an ASN.1 UTF8String value.
644    ///
645    /// # Examples
646    ///
647    /// ```
648    /// use yasna;
649    /// let der = yasna::construct_der(|writer| {
650    ///     writer.write_utf8_string("Hello!")
651    /// });
652    /// assert_eq!(der, vec![12, 6, 72, 101, 108, 108, 111, 33]);
653    /// ```
654    pub fn write_utf8_string(mut self, string: &str) {
655        self.write_identifier(TAG_UTF8STRING, PCBit::Primitive);
656        self.write_length(string.len());
657        self.buf.extend_from_slice(string.as_bytes());
658    }
659
660    /// Writes `&str` as an ASN.1 IA5String value.
661    ///
662    /// # Examples
663    ///
664    /// ```
665    /// use yasna;
666    /// let der = yasna::construct_der(|writer| {
667    ///     writer.write_ia5_string("Hello!")
668    /// });
669    /// assert_eq!(der, vec![22, 6, 72, 101, 108, 108, 111, 33]);
670    /// ```
671    pub fn write_ia5_string(mut self, string: &str) {
672        assert!(string.is_ascii(), "IA5 string must be ASCII");
673        self.write_identifier(TAG_IA5STRING, PCBit::Primitive);
674        self.write_length(string.len());
675        self.buf.extend_from_slice(string.as_bytes());
676    }
677
678    /// Writes `&str` as an ASN.1 BMPString value.
679    ///
680    /// # Examples
681    ///
682    /// ```
683    /// use yasna;
684    /// let der = yasna::construct_der(|writer| {
685    ///     writer.write_bmp_string("❤πü2?")
686    /// });
687    /// assert_eq!(der, vec![30, 10, 39, 100, 3, 192, 0, 252, 0, 50, 0, 63]);
688    /// ```
689    pub fn write_bmp_string(mut self, string: &str) {
690        let utf16 : Vec<u16> = string.encode_utf16().collect();
691
692        let mut bytes = Vec::with_capacity(utf16.len() * 2);
693        for c in utf16 {
694            bytes.push((c / 256) as u8);
695            bytes.push((c % 256) as u8);
696        }
697
698        self.write_identifier(TAG_BMPSTRING, PCBit::Primitive);
699        self.write_length(bytes.len());
700        self.buf.extend_from_slice(&bytes);
701    }
702
703    /// Writes the ASN.1 NULL value.
704    ///
705    /// # Examples
706    ///
707    /// ```
708    /// use yasna;
709    /// let der = yasna::construct_der(|writer| {
710    ///     writer.write_null()
711    /// });
712    /// assert_eq!(der, vec![5, 0]);
713    /// ```
714    pub fn write_null(mut self) {
715        self.write_identifier(TAG_NULL, PCBit::Primitive);
716        self.write_length(0);
717    }
718
719    /// Writes an ASN.1 object identifier.
720    ///
721    /// # Examples
722    ///
723    /// ```
724    /// use yasna;
725    /// use yasna::models::ObjectIdentifier;
726    /// let der = yasna::construct_der(|writer| {
727    ///     writer.write_oid(&ObjectIdentifier::from_slice(
728    ///         &[1, 2, 840, 113549, 1, 1]))
729    /// });
730    /// assert_eq!(&der, &[6, 8, 42, 134, 72, 134, 247, 13, 1, 1]);
731    /// ```
732    ///
733    /// # Panics
734    ///
735    /// It panics when the OID cannot be canonically encoded in BER.
736    pub fn write_oid(mut self, oid: &ObjectIdentifier) {
737        assert!(oid.components().len() >= 2, "Invalid OID: too short");
738        let id0 = oid.components()[0];
739        let id1 = oid.components()[1];
740        assert!(
741            (id0 < 3) && (id1 < 18446744073709551535) &&
742            (id0 >= 2 || id1 < 40),
743            "Invalid OID {{{} {} ...}}", id0, id1);
744        let subid0 = id0 * 40 + id1;
745        let mut length = 0;
746        for i in 1..oid.components().len() {
747            let mut subid = if i == 1 {
748                subid0
749            } else {
750                oid.components()[i]
751            } | 1;
752            while subid > 0 {
753                length += 1;
754                subid >>= 7;
755            }
756        }
757        self.write_identifier(TAG_OID, PCBit::Primitive);
758        self.write_length(length);
759        for i in 1..oid.components().len() {
760            let subid = if i == 1 {
761                subid0
762            } else {
763                oid.components()[i]
764            };
765            let mut shiftnum = 63; // ceil(64 / 7) * 7 - 7
766            while ((subid|1) >> shiftnum) == 0 {
767                shiftnum -= 7;
768            }
769            while shiftnum > 0 {
770                self.buf.push(128 | ((((subid|1) >> shiftnum) & 127) as u8));
771                shiftnum -= 7;
772            }
773            self.buf.push((subid & 127) as u8);
774        }
775    }
776
777    /// Writes an ASN.1 UTF8String.
778    ///
779    /// # Examples
780    ///
781    /// ```
782    /// use yasna;
783    /// let der = yasna::construct_der(|writer| {
784    ///     writer.write_utf8string("gnaw ροκανίζω 𪘂る")
785    /// });
786    /// assert_eq!(&der, &[
787    ///     12, 29, 103, 110, 97, 119, 32, 207, 129, 206, 191, 206,
788    ///     186, 206, 177, 206, 189, 206, 175, 206, 182, 207,
789    ///     137, 32, 240, 170, 152, 130, 227, 130, 139]);
790    /// ```
791    pub fn write_utf8string(self, string: &str) {
792        self.write_tagged_implicit(TAG_UTF8STRING, |writer| {
793            writer.write_bytes(string.as_bytes())
794        })
795    }
796
797    /// Writes ASN.1 SEQUENCE.
798    ///
799    /// This function uses the loan pattern: `callback` is called back with
800    /// a [`DERWriterSeq`], to which the contents of the
801    /// SEQUENCE is written.
802    ///
803    /// This is equivalent to [`write_sequence_of`](Self::write_sequence_of)
804    /// in behavior.
805    ///
806    /// # Examples
807    ///
808    /// ```
809    /// use yasna;
810    /// let der = yasna::construct_der(|writer| {
811    ///     writer.write_sequence(|writer| {
812    ///         writer.next().write_i64(10);
813    ///         writer.next().write_bool(true);
814    ///     })
815    /// });
816    /// assert_eq!(der, vec![48, 6, 2, 1, 10, 1, 1, 255]);
817    /// ```
818    pub fn write_sequence<T, F>(mut self, callback: F) -> T
819        where F: FnOnce(&mut DERWriterSeq) -> T {
820        self.write_identifier(TAG_SEQUENCE, PCBit::Constructed);
821        return self.with_length(|writer| {
822            callback(&mut DERWriterSeq {
823                buf: writer.buf,
824            })
825        });
826    }
827
828    /// Writes ASN.1 SEQUENCE OF.
829    ///
830    /// This function uses the loan pattern: `callback` is called back with
831    /// a [`DERWriterSeq`], to which the contents of the
832    /// SEQUENCE OF are written.
833    ///
834    /// This is equivalent to [`write_sequence`](Self::write_sequence) in
835    /// behavior.
836    ///
837    /// # Examples
838    ///
839    /// ```
840    /// use yasna;
841    /// let der = yasna::construct_der(|writer| {
842    ///     writer.write_sequence_of(|writer| {
843    ///         for &i in &[10, -129] {
844    ///             writer.next().write_i64(i);
845    ///         }
846    ///     })
847    /// });
848    /// assert_eq!(der, vec![48, 7, 2, 1, 10, 2, 2, 255, 127]);
849    /// ```
850    pub fn write_sequence_of<T, F>(self, callback: F) -> T
851        where F: FnOnce(&mut DERWriterSeq) -> T {
852        self.write_sequence(callback)
853    }
854
855    /// Writes ASN.1 SET.
856    ///
857    /// This function uses the loan pattern: `callback` is called back with
858    /// a [`DERWriterSet`], to which the contents of the
859    /// SET are written.
860    ///
861    /// For SET OF values, use [`write_set_of`](Self::write_set_of) instead.
862    ///
863    /// # Examples
864    ///
865    /// ```
866    /// use yasna;
867    /// let der = yasna::construct_der(|writer| {
868    ///     writer.write_set(|writer| {
869    ///         writer.next().write_i64(10);
870    ///         writer.next().write_bool(true);
871    ///     })
872    /// });
873    /// assert_eq!(der, vec![49, 6, 1, 1, 255, 2, 1, 10]);
874    /// ```
875    pub fn write_set<T, F>(mut self, callback: F) -> T
876        where F: FnOnce(&mut DERWriterSet) -> T {
877        let mut bufs = Vec::new();
878        let result = callback(&mut DERWriterSet {
879            bufs: &mut bufs,
880        });
881        for buf in bufs.iter() {
882            assert!(buf.len() > 0, "Empty output in write_set()");
883        }
884        bufs.sort_by(|buf0, buf1| {
885            let buf00 = buf0[0] & 223;
886            let buf10 = buf1[0] & 223;
887            if buf00 != buf10 || (buf0[0] & 31) != 31 {
888                return buf00.cmp(&buf10);
889            }
890            let len0 = buf0[1..].iter().position(|x| x & 128 == 0).unwrap();
891            let len1 = buf1[1..].iter().position(|x| x & 128 == 0).unwrap();
892            if len0 != len1 {
893                return len0.cmp(&len1);
894            }
895            return buf0[1..].cmp(&buf1[1..]);
896        });
897        // let bufs_len = bufs.iter().map(|buf| buf.len()).sum();
898        let bufs_len = bufs.iter().map(|buf| buf.len()).fold(0, |x, y| x + y);
899        self.write_identifier(TAG_SET, PCBit::Constructed);
900        self.write_length(bufs_len);
901        for buf in bufs.iter() {
902            self.buf.extend_from_slice(buf);
903        }
904        return result;
905    }
906
907    /// Writes ASN.1 SET OF.
908    ///
909    /// This function uses the loan pattern: `callback` is called back with
910    /// a [`DERWriterSet`], to which the contents of the
911    /// SET OF are written.
912    ///
913    /// For SET values, use [`write_set`](Self::write_set) instead.
914    ///
915    /// # Examples
916    ///
917    /// ```
918    /// use yasna;
919    /// let der = yasna::construct_der(|writer| {
920    ///     writer.write_set_of(|writer| {
921    ///         for &i in &[10, -129] {
922    ///             writer.next().write_i64(i);
923    ///         }
924    ///     })
925    /// });
926    /// assert_eq!(der, vec![49, 7, 2, 1, 10, 2, 2, 255, 127]);
927    /// ```
928    pub fn write_set_of<T, F>(mut self, callback: F) -> T
929        where F: FnOnce(&mut DERWriterSet) -> T {
930        let mut bufs = Vec::new();
931        let result = callback(&mut DERWriterSet {
932            bufs: &mut bufs,
933        });
934        for buf in bufs.iter() {
935            assert!(buf.len() > 0, "Empty output in write_set_of()");
936        }
937        bufs.sort();
938        // let bufs_len = bufs.iter().map(|buf| buf.len()).sum();
939        let bufs_len = bufs.iter().map(|buf| buf.len()).fold(0, |x, y| x + y);
940        self.write_identifier(TAG_SET, PCBit::Constructed);
941        self.write_length(bufs_len);
942        for buf in bufs.iter() {
943            self.buf.extend_from_slice(buf);
944        }
945        return result;
946    }
947
948    /// Writes an ASN.1 NumericString.
949    ///
950    /// # Examples
951    ///
952    /// ```
953    /// use yasna;
954    /// let der = yasna::construct_der(|writer| {
955    ///     writer.write_numeric_string("128 256")
956    /// });
957    /// assert_eq!(&der, &[18, 7, 49, 50, 56, 32, 50, 53, 54]);
958    /// ```
959    pub fn write_numeric_string(self, string: &str) {
960        let bytes = string.as_bytes();
961        for &byte in bytes {
962            assert!(byte == b' ' || (b'0' <= byte && byte <= b'9'),
963                "Invalid NumericString: {:?} appeared", byte);
964        }
965        self.write_tagged_implicit(TAG_NUMERICSTRING, |writer| {
966            writer.write_bytes(bytes)
967        });
968    }
969
970    /// Writes an ASN.1 PrintableString.
971    ///
972    /// # Examples
973    ///
974    /// ```
975    /// use yasna;
976    /// let der = yasna::construct_der(|writer| {
977    ///     writer.write_printable_string("Co., Ltd.")
978    /// });
979    /// assert_eq!(&der, &[19, 9, 67, 111, 46, 44, 32, 76, 116, 100, 46]);
980    /// ```
981    pub fn write_printable_string(self, string: &str) {
982        let bytes = string.as_bytes();
983        for &byte in bytes {
984            assert!(
985                byte == b' ' ||
986                (b'\'' <= byte && byte <= b':' && byte != b'*') ||
987                byte == b'=' ||
988                (b'A' <= byte && byte <= b'Z') ||
989                (b'a' <= byte && byte <= b'z'),
990                "Invalid PrintableString: {:?} appeared", byte);
991        }
992        self.write_tagged_implicit(TAG_PRINTABLESTRING, |writer| {
993            writer.write_bytes(bytes)
994        });
995    }
996
997    #[cfg(feature = "time")]
998    /// Writes an ASN.1 UTCTime.
999    ///
1000    /// # Examples
1001    ///
1002    /// ```
1003    /// # fn main() {
1004    /// use yasna;
1005    /// use yasna::models::UTCTime;
1006    /// use time::OffsetDateTime;
1007    /// let der = yasna::construct_der(|writer| {
1008    ///     writer.write_utctime(
1009    ///         &UTCTime::from_datetime(
1010    ///             OffsetDateTime::from_unix_timestamp(378820800).unwrap()))
1011    /// });
1012    /// assert_eq!(&der, &[
1013    ///     23, 13, 56, 50, 48, 49, 48, 50, 49, 50, 48, 48, 48, 48, 90]);
1014    /// # }
1015    /// ```
1016    ///
1017    /// # Features
1018    ///
1019    /// This method is enabled by `time` feature.
1020    ///
1021    /// ```toml
1022    /// [dependencies]
1023    /// yasna = { version = "*", features = ["time"] }
1024    /// ```
1025    pub fn write_utctime(self, datetime: &UTCTime) {
1026        use super::tags::TAG_UTCTIME;
1027        self.write_tagged_implicit(TAG_UTCTIME, |writer| {
1028            writer.write_bytes(&datetime.to_bytes())
1029        });
1030    }
1031
1032    #[cfg(feature = "time")]
1033    /// Writes an ASN.1 GeneralizedTime.
1034    ///
1035    /// # Examples
1036    ///
1037    /// ```
1038    /// # fn main() {
1039    /// use yasna;
1040    /// use yasna::models::GeneralizedTime;
1041    /// use time::OffsetDateTime;
1042    /// let der = yasna::construct_der(|writer| {
1043    ///     writer.write_generalized_time(
1044    ///         &GeneralizedTime::from_datetime(
1045    ///             OffsetDateTime::from_unix_timestamp_nanos(
1046    ///                 500_159_309_724_000_000).unwrap()))
1047    /// });
1048    /// assert_eq!(&der, &[
1049    ///     24, 19, 49, 57, 56, 53, 49, 49, 48, 54, 50,
1050    ///     49, 48, 56, 50, 57, 46, 55, 50, 52, 90]);
1051    /// # }
1052    /// ```
1053    ///
1054    /// # Features
1055    ///
1056    /// This method is enabled by `time` feature.
1057    ///
1058    /// ```toml
1059    /// [dependencies]
1060    /// yasna = { version = "*", features = ["time"] }
1061    /// ```
1062    pub fn write_generalized_time(self, datetime: &GeneralizedTime) {
1063        use super::tags::TAG_GENERALIZEDTIME;
1064        self.write_tagged_implicit(TAG_GENERALIZEDTIME, |writer| {
1065            writer.write_bytes(&datetime.to_bytes())
1066        });
1067    }
1068
1069    /// Writes an ASN.1 VisibleString.
1070    ///
1071    /// # Examples
1072    ///
1073    /// ```
1074    /// use yasna;
1075    /// let der = yasna::construct_der(|writer| {
1076    ///     writer.write_visible_string("Hi!")
1077    /// });
1078    /// assert_eq!(&der, &[26, 3, 72, 105, 33]);
1079    /// ```
1080    pub fn write_visible_string(self, string: &str) {
1081        let bytes = string.as_bytes();
1082        for &byte in bytes {
1083            assert!(b' ' <= byte && byte <= b'~',
1084                "Invalid VisibleString: {:?} appeared", byte);
1085        }
1086        self.write_tagged_implicit(TAG_VISIBLESTRING, |writer| {
1087            writer.write_bytes(bytes)
1088        });
1089    }
1090
1091    /// Writes an (explicitly) tagged value.
1092    ///
1093    /// # Examples
1094    ///
1095    /// ```
1096    /// use yasna::{self,Tag};
1097    /// let der = yasna::construct_der(|writer| {
1098    ///     writer.write_tagged(Tag::context(3), |writer| {
1099    ///         writer.write_i64(10)
1100    ///     })
1101    /// });
1102    /// assert_eq!(der, vec![163, 3, 2, 1, 10]);
1103    /// ```
1104    ///
1105    /// Note: you can achieve the same using
1106    /// [`write_tagged_implicit`](Self::write_tagged_implicit):
1107    ///
1108    /// ```
1109    /// use yasna::{self,Tag};
1110    /// let der = yasna::construct_der(|writer| {
1111    ///     writer.write_tagged_implicit(Tag::context(3), |writer| {
1112    ///         writer.write_sequence(|writer| {
1113    ///             let writer = writer.next();
1114    ///             writer.write_i64(10)
1115    ///         })
1116    ///     })
1117    /// });
1118    /// assert_eq!(der, vec![163, 3, 2, 1, 10]);
1119    /// ```
1120    pub fn write_tagged<T, F>(mut self, tag: Tag, callback: F) -> T
1121        where F: FnOnce(DERWriter) -> T {
1122        self.write_identifier(tag, PCBit::Constructed);
1123        return self.with_length(|writer| {
1124            callback(DERWriter::from_buf(writer.buf))
1125        });
1126    }
1127
1128    /// Writes an implicitly tagged value.
1129    ///
1130    /// # Examples
1131    ///
1132    /// ```
1133    /// use yasna::{self,Tag};
1134    /// let der = yasna::construct_der(|writer| {
1135    ///     writer.write_tagged_implicit(Tag::context(3), |writer| {
1136    ///         writer.write_i64(10)
1137    ///     })
1138    /// });
1139    /// assert_eq!(der, vec![131, 1, 10]);
1140    /// ```
1141    pub fn write_tagged_implicit<T, F>
1142        (mut self, tag: Tag, callback: F) -> T
1143        where F: FnOnce(DERWriter) -> T {
1144        let tag = if let Some(tag) = self.implicit_tag { tag } else { tag };
1145        self.implicit_tag = None;
1146        let mut writer = DERWriter::from_buf(self.buf);
1147        writer.implicit_tag = Some(tag);
1148        return callback(writer);
1149    }
1150
1151    /// Writes the arbitrary tagged DER value in `der`.
1152    ///
1153    /// # Examples
1154    ///
1155    /// ```
1156    /// use yasna;
1157    /// use yasna::models::TaggedDerValue;
1158    /// use yasna::tags::TAG_OCTETSTRING;
1159    /// let tagged_der_value = TaggedDerValue::from_tag_and_bytes(TAG_OCTETSTRING, b"Hello!".to_vec());
1160    /// let der1 = yasna::construct_der(|writer| {
1161    ///     writer.write_tagged_der(&tagged_der_value)
1162    /// });
1163    /// let der2 = yasna::construct_der(|writer| {
1164    ///     writer.write_bytes(b"Hello!")
1165    /// });
1166    /// assert_eq!(der1, der2);
1167    /// ```
1168    pub fn write_tagged_der(mut self, der: &TaggedDerValue) {
1169        self.write_identifier(der.tag(), der.pcbit());
1170        self.write_length(der.value().len());
1171        self.buf.extend_from_slice(der.value());
1172    }
1173
1174    /// Writes `&[u8]` into the DER output buffer directly. Properly encoded tag
1175    /// and length must be included at the start of the passed buffer.
1176    ///
1177    /// # Examples
1178    ///
1179    /// ```
1180    /// use yasna;
1181    /// let raw_der = yasna::construct_der(|writer| {
1182    ///     writer.write_der(b"\x04\x06Hello!")
1183    /// });
1184    /// let der = yasna::construct_der(|writer| {
1185    ///     writer.write_bytes(b"Hello!")
1186    /// });
1187    /// assert_eq!(raw_der, der);
1188    /// ```
1189    pub fn write_der(self, der: &[u8]) {
1190        self.buf.extend_from_slice(der);
1191    }
1192}
1193
1194/// A writer object that accepts ASN.1 values.
1195///
1196/// The main source of this object is the [`write_sequence`][write_sequence]
1197/// method from [`DERWriter`].
1198///
1199/// [write_sequence]: DERWriter::write_sequence
1200///
1201/// # Examples
1202///
1203/// ```
1204/// use yasna;
1205/// let der = yasna::construct_der(|writer| {
1206///     writer.write_sequence(|writer : &mut yasna::DERWriterSeq| {
1207///         writer.next().write_i64(10);
1208///         writer.next().write_bool(true);
1209///     })
1210/// });
1211/// assert_eq!(der, vec![48, 6, 2, 1, 10, 1, 1, 255]);
1212/// ```
1213#[derive(Debug)]
1214pub struct DERWriterSeq<'a> {
1215    buf: &'a mut Vec<u8>,
1216}
1217
1218impl<'a> DERWriterSeq<'a> {
1219    /// Generates a new [`DERWriter`].
1220    pub fn next<'b>(&'b mut self) -> DERWriter<'b> {
1221        return DERWriter::from_buf(self.buf);
1222    }
1223}
1224
1225/// A writer object that accepts ASN.1 values.
1226///
1227/// The main source of this object is the [`write_set`](DERWriter::write_set)
1228/// method from [`DERWriter`].
1229///
1230/// # Examples
1231///
1232/// ```
1233/// use yasna;
1234/// let der = yasna::construct_der(|writer| {
1235///     writer.write_set(|writer : &mut yasna::DERWriterSet| {
1236///         writer.next().write_i64(10);
1237///         writer.next().write_bool(true);
1238///     })
1239/// });
1240/// assert_eq!(der, vec![49, 6, 1, 1, 255, 2, 1, 10]);
1241/// ```
1242#[derive(Debug)]
1243pub struct DERWriterSet<'a> {
1244    bufs: &'a mut Vec<Vec<u8>>,
1245}
1246
1247impl<'a> DERWriterSet<'a> {
1248    /// Generates a new [`DERWriter`].
1249    pub fn next<'b>(&'b mut self) -> DERWriter<'b> {
1250        self.bufs.push(Vec::new());
1251        return DERWriter::from_buf(self.bufs.last_mut().unwrap());
1252    }
1253}
1254
1255#[cfg(test)]
1256mod tests;