matc/util/
asn1.rs

1#![allow(dead_code)]
2
3use std::io::Cursor;
4use std::io::Read;
5use std::io::Result;
6
7use byteorder::ReadBytesExt;
8use byteorder::WriteBytesExt;
9
10#[derive(Debug, Clone)]
11pub enum Class {
12    Universal,
13    Application,
14    ContextSpecific,
15    Private,
16}
17
18#[derive(Debug, Clone)]
19pub struct TagSpec {
20    class: Class,
21    constructed: bool,
22    tag: u16,
23}
24
25pub fn read_tag(cursor: &mut Cursor<&[u8]>) -> Result<u8> {
26    cursor.read_u8()
27}
28
29pub fn read_tag_s(cursor: &mut Cursor<&[u8]>) -> Result<TagSpec> {
30    let first = cursor.read_u8()?;
31    let class = {
32        match first & 0xc0 {
33            0 => Class::Universal,
34            0x40 => Class::Application,
35            0x80 => Class::ContextSpecific,
36            0xc0 => Class::Private,
37            _ => Class::Universal,
38        }
39    };
40    let constructed = (first & 0x20) == 0x20;
41    if (first & 0x1f) != 0x1f {
42        Ok(TagSpec {
43            class,
44            constructed,
45            tag: (first & 0x1f) as u16,
46        })
47    } else {
48        let mut tag: u16 = 0;
49        loop {
50            let next = cursor.read_u8()?;
51            tag <<= 7;
52            tag |= (next & 0x7f) as u16;
53            if next & 0x80 == 0 {
54                break Ok(TagSpec {
55                    class,
56                    constructed,
57                    tag,
58                });
59            }
60        }
61    }
62}
63
64pub fn read_size(cursor: &mut Cursor<&[u8]>) -> Result<usize> {
65    let b1 = cursor.read_u8()? as usize;
66    if b1 & 0x80 == 0 {
67        return Ok(b1);
68    }
69    let size = b1 & 0x7f;
70    let mut out = 0;
71    for _ in 0..size {
72        let c = cursor.read_u8()? as usize;
73        out = (out << 8) + c;
74    }
75    Ok(out)
76}
77
78pub fn read_uint(cursor: &mut Cursor<&[u8]>) -> Result<u32> {
79    read_tag(cursor)?;
80    let size = read_size(cursor)?;
81    let mut out = 0;
82    for _ in 0..size {
83        let c = cursor.read_u8()? as u32;
84        out <<= 8;
85        out |= c;
86    }
87    Ok(out)
88}
89
90pub fn read_string(cursor: &mut Cursor<&[u8]>) -> Result<String> {
91    read_tag(cursor)?;
92    let size = read_size(cursor)?;
93    let mut buf = vec![0; size];
94    cursor.read_exact(&mut buf)?;
95    match std::str::from_utf8(&buf) {
96        Ok(s) => Ok(s.to_owned()),
97        Err(e) => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e)),
98    }
99}
100
101pub fn write_tag(buf: &mut Vec<u8>, tag: u8) -> Result<()> {
102    buf.write_u8(tag)
103}
104
105pub fn write_tag_s(buf: &mut Vec<u8>, class: u8, contructed: bool, tag: u16) -> Result<()> {
106    let mut first = class;
107    if contructed {
108        first |= 0x20
109    }
110    if tag <= 30 {
111        first |= tag as u8;
112        buf.write_u8(first)
113    } else {
114        first |= 0x1f;
115        buf.write_u8(first)?;
116        let mut tmp = tag;
117        while tmp > 0 {
118            if tmp > 0x7f {
119                buf.write_u8((tmp & 0x7f) as u8)?;
120                tmp >>= 7;
121            } else {
122                buf.write_u8(tmp as u8)?;
123                break;
124            }
125        }
126        Ok(())
127    }
128}
129pub fn write_tag_s2(buf: &mut Vec<u8>, ctag: &TagSpec) -> Result<()> {
130    let class = {
131        match ctag.class {
132            Class::Universal => 0,
133            Class::Application => 0x40,
134            Class::ContextSpecific => 0x80,
135            Class::Private => 0xc0,
136        }
137    };
138    write_tag_s(buf, class, ctag.constructed, ctag.tag)
139}
140
141pub fn write_len(buf: &mut Vec<u8>, len: u8) -> Result<()> {
142    buf.write_u8(len)
143}
144
145pub fn write_enum(buf: &mut Vec<u8>, val: u8) -> Result<()> {
146    write_tag(buf, 0xa)?;
147    write_len(buf, 1)?;
148    buf.write_u8(val)
149}
150fn write_octet_string(buf: &mut Vec<u8>, val: &[u8]) -> Result<()> {
151    write_tag(buf, 0x4)?;
152    write_len(buf, val.len() as u8)?;
153    buf.extend_from_slice(val);
154    Ok(())
155}
156fn write_string(buf: &mut Vec<u8>, val: &str) -> Result<()> {
157    write_tag(buf, 0xc)?;
158    let bytes = val.as_bytes();
159    write_len(buf, bytes.len() as u8)?;
160    buf.extend_from_slice(bytes);
161    Ok(())
162}
163fn write_string_with_tag(buf: &mut Vec<u8>, tag: u8, val: &str) -> Result<()> {
164    write_tag(buf, tag)?;
165    let bytes = val.as_bytes();
166    write_len(buf, bytes.len() as u8)?;
167    buf.extend_from_slice(bytes);
168    Ok(())
169}
170fn write_bool(buf: &mut Vec<u8>, val: bool) -> Result<()> {
171    write_tag(buf, 0x1)?;
172    write_len(buf, 1)?;
173    if val {
174        buf.write_u8(0xff)?;
175    } else {
176        buf.write_u8(0)?;
177    }
178    Ok(())
179}
180
181fn write_octet_string_with_tag(buf: &mut Vec<u8>, tag: u8, val: &[u8]) -> Result<()> {
182    write_tag(buf, tag)?;
183    write_len(buf, val.len() as u8)?;
184    buf.extend_from_slice(val);
185    Ok(())
186}
187
188pub fn write_int(buf: &mut Vec<u8>, val: u32) -> Result<()> {
189    write_tag(buf, 0x2)?;
190    if val < 0x80 {
191        write_len(buf, 1)?;
192        buf.write_u8(val as u8)
193    } else if val < 0x8000 {
194        write_len(buf, 2)?;
195        buf.write_u8((val >> 8) as u8)?;
196        buf.write_u8(val as u8)
197    } else if val < 0x800000 {
198        write_len(buf, 3)?;
199        buf.write_u8((val >> 16) as u8)?;
200        buf.write_u8((val >> 8) as u8)?;
201        buf.write_u8(val as u8)
202    } else {
203        Err(std::io::Error::from(std::io::ErrorKind::Unsupported))
204    }
205}
206
207#[derive(Debug, Clone)]
208struct Asn1EncoderStackEntry {
209    pos: usize,
210}
211
212#[derive(Debug, Clone)]
213pub struct Encoder {
214    buffer: Vec<u8>,
215    stack: Vec<Asn1EncoderStackEntry>,
216}
217
218impl Encoder {
219    pub fn new() -> Self {
220        Self {
221            buffer: Vec::new(),
222            stack: Vec::new(),
223        }
224    }
225    pub fn start_seq(&mut self, tag: u8) -> Result<()> {
226        write_tag(&mut self.buffer, tag)?;
227        self.stack.push(Asn1EncoderStackEntry {
228            pos: self.buffer.len() - 1,
229        });
230        write_len(&mut self.buffer, 0)
231    }
232    pub fn fix(&mut self) {
233        while !self.stack.is_empty() {
234            self.end_seq()
235        }
236    }
237    pub fn end_seq(&mut self) {
238        let i = self.stack.pop();
239        if let Some(a) = i {
240            let s = self.buffer.len() - a.pos - 2;
241            //self.buffer[a.pos + 1] = s as u8;
242            if s < 0x80 {
243                self.buffer[a.pos + 1] = s as u8;
244            } else if s <= 0xff {
245                self.buffer[a.pos + 1] = 0x81;
246                self.buffer.insert(a.pos + 2, s as u8);
247            } else {
248                self.buffer[a.pos + 1] = 0x82;
249                self.buffer.insert(a.pos + 2, (s >> 8) as u8);
250                self.buffer.insert(a.pos + 3, s as u8);
251            }
252        }
253    }
254    pub fn write_octet_string(&mut self, val: &[u8]) -> Result<()> {
255        write_octet_string(&mut self.buffer, val)
256    }
257    pub fn write_string(&mut self, val: &str) -> Result<()> {
258        write_string(&mut self.buffer, val)
259    }
260    pub fn write_string_with_tag(&mut self, tag: u8, val: &str) -> Result<()> {
261        write_string_with_tag(&mut self.buffer, tag, val)
262    }
263    pub fn write_octet_string_with_tag(&mut self, tag: u8, val: &[u8]) -> Result<()> {
264        write_octet_string_with_tag(&mut self.buffer, tag, val)
265    }
266    pub fn write_enum(&mut self, val: u8) -> Result<()> {
267        write_enum(&mut self.buffer, val)
268    }
269    pub fn write_int(&mut self, val: u32) -> Result<()> {
270        write_int(&mut self.buffer, val)
271    }
272    pub fn write_bool(&mut self, val: bool) -> Result<()> {
273        write_bool(&mut self.buffer, val)
274    }
275    pub fn write_raw(&mut self, data: &[u8]) {
276        self.buffer.extend_from_slice(data);
277    }
278    pub fn write_oid(&mut self, val: &str) -> Result<()> {
279        match const_oid::ObjectIdentifier::new(val) {
280            Ok(o) => self.write_octet_string_with_tag(0x6, o.as_bytes()),
281            Err(e) => Err(std::io::Error::new(
282                std::io::ErrorKind::InvalidData,
283                format!("can't parse oid {:?}", e),
284            )),
285        }
286    }
287
288    pub fn encode(mut self) -> Vec<u8> {
289        self.fix();
290        self.buffer
291    }
292}
293
294impl Default for Encoder {
295    fn default() -> Self {
296        Self::new()
297    }
298}
299
300#[test]
301fn a_test() {
302    assert_eq!(
303        read_size(&mut std::io::Cursor::new(&[0x82, 0x27, 0x32])).unwrap(),
304        10034
305    );
306    assert_eq!(read_size(&mut std::io::Cursor::new(&[0x08])).unwrap(), 8);
307    let mut buf = Vec::new();
308    write_int(&mut buf, 127).unwrap();
309    assert_eq!(buf, vec![0x02, 0x01, 0x7f]);
310
311    let mut buf = Vec::new();
312    write_int(&mut buf, 128).unwrap();
313    assert_eq!(buf, vec![0x02, 0x02, 0x0, 0x80]);
314
315    let mut buf = Vec::new();
316    write_int(&mut buf, 256).unwrap();
317    assert_eq!(buf, vec![0x02, 0x02, 0x1, 0x0]);
318
319    let mut buf = Vec::new();
320    write_bool(&mut buf, true).unwrap();
321    assert_eq!(buf, vec![0x01, 0x01, 0xff]);
322}
323
324#[test]
325fn tag_test() {
326    let mut buf = Vec::new();
327    write_tag_s(&mut buf, 0xc0, false, 10).unwrap();
328    write_len(&mut buf, 3).unwrap();
329    std::io::Write::write_all(&mut buf, "abc".as_bytes()).unwrap();
330    let mut cursor = Cursor::new(buf.as_ref());
331    println!(
332        "{:?} {:?}",
333        hex::encode(&buf),
334        read_tag_s(&mut cursor).unwrap()
335    );
336
337    let mut buf = Vec::new();
338    write_tag_s(&mut buf, 0xc0, false, 31).unwrap();
339    write_len(&mut buf, 3).unwrap();
340    std::io::Write::write_all(&mut buf, "abc".as_bytes()).unwrap();
341    let mut cursor = Cursor::new(buf.as_ref());
342    println!(
343        "{:?} {:?}",
344        hex::encode(&buf),
345        read_tag_s(&mut cursor).unwrap()
346    );
347
348    let mut buf = Vec::new();
349    write_tag_s(&mut buf, 0xc0, false, 100).unwrap();
350    write_len(&mut buf, 3).unwrap();
351    std::io::Write::write_all(&mut buf, "abc".as_bytes()).unwrap();
352    let mut cursor = Cursor::new(buf.as_ref());
353    println!(
354        "{:?} {:?}",
355        hex::encode(&buf),
356        read_tag_s(&mut cursor).unwrap()
357    );
358}