1use anyhow::{Result, bail, ensure};
10use num_bigint_dig::BigUint;
11
12use crate::asn1::builder::Builder;
13use crate::asn1::{Oid, Tag};
14use crate::template::{Value, Variable};
15
16impl Tag {
17 pub fn to_der(&self) -> Result<Vec<u8>> {
19 const ASN1_TAG_CLASS_CONTEXT: u8 = 2 << 6;
20 const ASN1_TAG_FORM_PRIMITIVE: u8 = 0 << 5;
21 const ASN1_TAG_FORM_CONSTRUCTED: u8 = 1 << 5;
22 let tag = match self {
26 Tag::Boolean => 0x01,
27 Tag::BitString => 0x03,
28 Tag::GeneralizedTime => 0x018,
29 Tag::Integer => 0x02,
30 Tag::OctetString => 0x04,
31 Tag::Oid => 0x06,
32 Tag::PrintableString => 0x13,
33 Tag::Sequence => 0x30,
34 Tag::Set => 0x31,
35 Tag::Utf8String => 0x0c,
36 &Tag::Context { constructed, value } => {
37 ensure!(value <= 30, "tag number above 30 are not supported for now");
39 let constructed = if constructed {
40 ASN1_TAG_FORM_CONSTRUCTED
41 } else {
42 ASN1_TAG_FORM_PRIMITIVE
43 };
44 ASN1_TAG_CLASS_CONTEXT | constructed | (value as u8)
45 }
46 };
47 Ok(vec![tag])
48 }
49}
50
51pub struct Der {
52 output: Vec<u8>,
53}
54
55impl Der {
56 fn new() -> Der {
57 Der { output: Vec::new() }
58 }
59
60 pub fn generate(build: impl FnOnce(&mut Self) -> Result<()>) -> Result<Vec<u8>> {
61 let mut der = Der::new();
62 build(&mut der)?;
63 Ok(der.output)
64 }
65
66 pub fn encode_size(size: usize) -> Vec<u8> {
67 let mut encoded = Vec::<u8>::new();
69 if size <= 0x7f {
70 encoded.push(size as u8);
71 } else {
72 let mut remaining = size;
73 while remaining != 0 {
74 encoded.push((remaining & 0xff) as u8);
75 remaining >>= 8;
76 }
77 encoded.push(0x80 | (encoded.len() as u8));
78 encoded.reverse();
79 }
80 encoded
81 }
82
83 fn get_value_or_error<T>(val: &Value<T>) -> Result<&T> {
84 match val {
85 Value::Literal(x) => Ok(x),
86 Value::Variable(Variable { name, .. }) => bail!(
87 "cannot push value of variable {name}: the DER generator does not support variables"
88 ),
89 }
90 }
91
92 fn push_bytes(&mut self, val: &[u8]) -> Result<()> {
94 self.output.extend(val);
95 Ok(())
96 }
97}
98
99impl Builder for Der {
100 fn push_byte(&mut self, val: u8) -> Result<()> {
102 self.output.push(val);
103 Ok(())
104 }
105
106 fn push_boolean(&mut self, tag: &Tag, val: &Value<bool>) -> Result<()> {
108 let val = Self::get_value_or_error(val)?;
109 let val = if *val { 0xffu8 } else { 0x00u8 };
110 self.push_tag(None, tag, |builder| builder.push_byte(val))
111 }
112
113 fn push_integer(
116 &mut self,
117 _name_hint: Option<String>,
118 tag: &Tag,
119 val: &Value<BigUint>,
120 ) -> Result<()> {
121 let mut bytes = Self::get_value_or_error(val)?.to_bytes_be();
122 if (bytes[0] >> 7) == 1 {
125 bytes.insert(0, 0x00);
126 }
127 let val = Value::Literal(bytes);
128 self.push_tag(None, tag, |builder| builder.push_byte_array(None, &val))
129 }
130
131 fn push_integer_pad(
135 &mut self,
136 _name_hint: Option<String>,
137 val: &Value<BigUint>,
138 size: usize,
139 ) -> Result<()> {
140 let val = Self::get_value_or_error(val)?;
141 let mut bytes = val.to_bytes_be();
142 while bytes.len() < size {
143 bytes.insert(0, 0x0);
144 }
145 let val = Value::Literal(bytes);
146 self.push_byte_array(None, &val)
147 }
148
149 fn push_byte_array(&mut self, _name_hint: Option<String>, val: &Value<Vec<u8>>) -> Result<()> {
152 let val = Self::get_value_or_error(val)?;
153 self.output.extend(val);
154 Ok(())
155 }
156
157 fn push_string(
159 &mut self,
160 _name_hint: Option<String>,
161 str_type: &Tag,
162 val: &Value<String>,
163 ) -> Result<()> {
164 let val = Self::get_value_or_error(val)?;
165 let val = Value::Literal(val.as_bytes().to_vec());
166 self.push_tag(None, str_type, |builder| {
167 builder.push_byte_array(None, &val)
168 })
169 }
170
171 fn push_oid(&mut self, oid: &Oid) -> Result<()> {
173 let val = Value::Literal(oid.to_der()?);
174 self.push_tag(None, &Tag::Oid, |builder| {
175 builder.push_byte_array(None, &val)
176 })
177 }
178
179 fn push_bitstring(
180 &mut self,
181 name_hint: Option<String>,
182 tag: &Tag,
183 bits: &[Value<bool>],
184 ) -> Result<()> {
185 let bits = bits
186 .iter()
187 .map(Self::get_value_or_error)
188 .collect::<Result<Vec<_>>>()?;
189 let nr_bytes = bits.len().div_ceil(8);
192 let mut bytes = vec![0u8; nr_bytes];
193 for (i, bit) in bits.iter().enumerate() {
194 bytes[i / 8] |= (**bit as u8) << (7 - (i % 8));
195 }
196
197 self.push_as_bit_string(None, tag, bytes.len() * 8 - bits.len(), |builder| {
198 builder.push_byte_array(name_hint.clone(), &Value::Literal(bytes.clone()))
199 })
200 }
201
202 fn push_tag(
205 &mut self,
206 _name_hint: Option<String>,
207 tag: &Tag,
208 build: impl FnOnce(&mut Self) -> Result<()>,
209 ) -> Result<()> {
210 let mut content = Der::new();
211 build(&mut content)?;
212 self.push_bytes(&tag.to_der()?)?;
214 if content.output.len() <= 0x7f {
216 self.push_byte(content.output.len() as u8)?;
217 } else {
218 let len = content.output.len();
219 let bytes = Self::encode_size(len);
220 self.push_bytes(&bytes)?;
221 }
222 self.push_bytes(&content.output)
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230 use num_traits::FromPrimitive;
231
232 #[test]
233 fn test_asn1_der_byte() -> Result<()> {
234 let der = Der::generate(|builder| builder.push_byte(0xa5))?;
235 const RESULT: &[u8] = &[0xa5];
236 assert_eq!(&der, RESULT);
237 Ok(())
238 }
239
240 #[test]
241 fn test_asn1_der_byte_array() -> Result<()> {
242 let bytes: Vec<u8> = vec![0x12, 0x34, 0x56, 0x78];
243 let der =
244 Der::generate(|builder| builder.push_byte_array(None, &Value::Literal(bytes.clone())))?;
245 assert_eq!(der, bytes);
246 Ok(())
247 }
248
249 #[test]
250 fn test_asn1_der_boolean() -> Result<()> {
251 let der = Der::generate(|builder| {
252 builder.push_boolean(&Tag::Boolean, &Value::Literal(true))?;
253 builder.push_boolean(&Tag::Integer, &Value::Literal(false))
254 })?;
255 const RESULT: &[u8] = &[
256 0x01, 0x01, 0xff, 0x02, 0x01, 0x00,
259 ];
260 assert_eq!(&der, RESULT);
261 Ok(())
262 }
263
264 #[test]
265 fn test_asn1_der_integer() -> Result<()> {
266 let der = Der::generate(|builder| {
267 builder.push_integer(
268 None,
269 &Tag::Integer,
270 &Value::Literal(BigUint::from_u32(0).unwrap()),
271 )?;
272 builder.push_integer(
273 None,
274 &Tag::Integer,
275 &Value::Literal(BigUint::from_u32(0x1234).unwrap()),
276 )?;
277 builder.push_integer(
278 None,
279 &Tag::OctetString,
280 &Value::Literal(BigUint::from_u32(0x8000).unwrap()),
281 )
282 })?;
283 const RESULT: &[u8] = &[
284 0x02, 0x01, 0x0,
286 0x02, 0x02, 0x12, 0x34,
288 0x04, 0x03, 0x00, 0x80, 0x00,
290 ];
291 assert_eq!(&der, RESULT);
292 Ok(())
293 }
294
295 #[test]
296 fn test_asn1_der_integer_pad() -> Result<()> {
297 let der = Der::generate(|builder| {
298 builder.push_integer_pad(
299 None,
300 &Value::Literal(BigUint::from_u32(0x1234).unwrap()),
301 2,
302 )?;
303 builder.push_integer_pad(None, &Value::Literal(BigUint::from_u32(0x1234).unwrap()), 4)
304 })?;
305 const RESULT: &[u8] = &[
306 0x12, 0x34, 0x00, 0x00, 0x12, 0x34,
309 ];
310 assert_eq!(&der, RESULT);
311 Ok(())
312 }
313
314 #[test]
315 fn test_asn1_der_string() -> Result<()> {
316 let der = Der::generate(|builder| {
317 builder.push_string(
318 None,
319 &Tag::PrintableString,
320 &Value::Literal("lowRISC".into()),
321 )?;
322 builder.push_string(None, &Tag::Utf8String, &Value::Literal("OpenTitan".into()))?;
323 builder.push_string(None, &Tag::OctetString, &Value::Literal("".into()))
324 })?;
325 const RESULT: &[u8] = &[
326 0x13, 0x07, 0x6c, 0x6f, 0x77, 0x52, 0x49, 0x53, 0x43,
328 0x0c, 0x09, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x69, 0x74, 0x61, 0x6e,
330 0x04, 0x00,
332 ];
333 assert_eq!(&der, RESULT);
334 Ok(())
335 }
336
337 #[test]
338 fn test_asn1_der_oid() -> Result<()> {
339 let der = Der::generate(|builder| builder.push_oid(&Oid::Custom("2.999.3".into())))?;
340 const RESULT: &[u8] = &[
341 0x06, 0x03, 0x88, 0x037, 0x03,
343 ];
344 assert_eq!(&der, RESULT);
345 Ok(())
346 }
347
348 #[test]
349 fn test_asn1_der_bitstring() -> Result<()> {
350 let der = Der::generate(|builder| {
351 builder.push_bitstring(None, &Tag::BitString, &[])?;
352 builder.push_bitstring(None, &Tag::BitString, &[Value::Literal(true)])?;
353 builder.push_bitstring(None, &Tag::OctetString, &[Value::Literal(false)])?;
354 builder.push_bitstring(
355 None,
356 &Tag::BitString,
357 &[
358 true, false, true, true, false, false, false, false, true, false, false, true,
359 ]
360 .into_iter()
361 .map(Value::Literal)
362 .collect::<Vec<_>>(),
363 )
364 })?;
365 const RESULT: &[u8] = &[
366 0x03, 0x01, 0x0, 0x03, 0x02, 0x7, 0x80, 0x04, 0x02, 0x7, 0x00,
370 0x03, 0x03, 0x04, 0b10110000, 0b10010000,
372 ];
373 assert_eq!(&der, RESULT);
374 Ok(())
375 }
376
377 #[test]
378 fn test_asn1_der_tag() -> Result<()> {
379 let bytes_empty: (&[u8], &[u8]) = (&[], &[0x00]);
381 let bytes_short: (&[u8], &[u8]) = (&[0xa5u8; 0x7f], &[0x7f]);
382 let bytes_long_1a: (&[u8], &[u8]) = (&[0xb6u8; 0x80], &[0x81, 0x80]);
383 let bytes_long_1b: (&[u8], &[u8]) = (&[0xc7u8; 0xff], &[0x81, 0xff]);
384 let bytes_long_2a: (&[u8], &[u8]) = (&[0xd8u8; 0x100], &[0x82, 0x01, 0x00]);
385 let bytes_long_2b: (&[u8], &[u8]) = (&[0xe9u8; 0xffff], &[0x82, 0xff, 0xff]);
386 let seq = [
387 bytes_empty,
388 bytes_short,
389 bytes_long_1a,
390 bytes_long_1b,
391 bytes_long_2a,
392 bytes_long_2b,
393 ];
394 let der = Der::generate(|builder| {
395 for (bytes, _) in seq {
396 builder.push_tag(None, &Tag::Sequence, |builder| {
397 builder.push_byte_array(None, &Value::Literal(bytes.to_vec()))
398 })?;
399 }
400 Ok(())
401 })?;
402 let mut result = Vec::<u8>::new();
403 for (bytes, len_enc) in seq {
404 result.push(0x30); result.extend(len_enc);
406 result.extend(bytes);
407 }
408 assert_eq!(der, result);
409 Ok(())
410 }
411}