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;