1use anyhow::{Context, Result, bail, ensure};
9use hex::{FromHex, ToHex};
10use indexmap::IndexMap;
11use num_bigint_dig::{BigUint, ToBigUint};
12use num_traits::Num;
13use serde::{Deserialize, Serialize};
14
15use crate::template::{
16 BasicConstraints, Certificate, CertificateExtension, Conversion, DiceTcbInfoExtension,
17 DiceTcbInfoFlags, EcPublicKey, EcPublicKeyInfo, EcdsaSignature, FirmwareId, KeyUsage,
18 Signature, SizeRange, SubjectPublicKeyInfo, Template, Value, Variable, VariableType,
19};
20
21#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
24#[serde(untagged)]
25pub enum SubstValue {
26 ByteArray(Vec<u8>),
27 Uint32(u32),
28 String(String),
29 Boolean(bool),
30}
31
32#[derive(Clone, Debug, Default, Deserialize, Serialize)]
35pub struct SubstData {
36 #[serde(flatten)]
37 pub values: IndexMap<String, SubstValue>,
38}
39
40impl SubstData {
41 pub fn new() -> SubstData {
42 SubstData {
43 values: IndexMap::new(),
44 }
45 }
46
47 pub fn to_json(&self) -> Result<String> {
48 Ok(serde_json::to_string(&self)?)
49 }
50
51 pub fn from_json(content: &str) -> Result<SubstData> {
52 Ok(serde_json::from_str(content)?)
53 }
54}
55
56pub trait Subst: Sized {
59 fn subst(&self, data: &SubstData) -> Result<Self>;
62}
63
64impl SubstValue {
65 pub fn parse(&self, var_type: &VariableType) -> Result<SubstValue> {
69 match *var_type {
70 VariableType::ByteArray { .. } => self.parse_as_byte_array(var_type.size()),
71 VariableType::Integer { .. } => self.parse_as_integer(var_type.size()),
72 VariableType::String { .. } => self.parse_as_string(var_type.size()),
73 VariableType::Boolean => self.parse_as_boolean(),
74 }
75 }
76
77 fn parse_as_byte_array(&self, size: usize) -> Result<SubstValue> {
78 match self {
79 SubstValue::ByteArray(bytes) => {
80 ensure!(
81 size == 0 || bytes.len() == size,
82 "expected a byte array of size {size} but got {} bytes",
83 bytes.len()
84 );
85 Ok(self.clone())
86 }
87 SubstValue::String(s) => {
88 let bytes = Vec::<u8>::from_hex(s)
91 .with_context(|| format!("cannot parse {s} as an hexstring"))?;
92 ensure!(
93 size == 0 || bytes.len() == size,
94 "expected a byte array of size {size} but got {} bytes",
95 bytes.len()
96 );
97 Ok(SubstValue::ByteArray(bytes))
98 }
99 _ => bail!("cannot parse value {self:?} as a byte-array"),
100 }
101 }
102
103 fn parse_as_integer(&self, size: usize) -> Result<SubstValue> {
104 match self {
105 SubstValue::ByteArray(bytes) => {
106 ensure!(
108 size == 0 || bytes.len() <= size,
109 "expected an integer that fits on {size} bytes but it uses {} bytes",
110 bytes.len()
111 );
112 Ok(self.clone())
113 }
114 SubstValue::String(s) => {
115 let (radix, s) = s
117 .strip_prefix("0x")
118 .map_or_else(|| (10, s.as_str()), |s| (16, s));
119 let val = BigUint::from_str_radix(s, radix)
120 .with_context(|| format!("cannot parse {s} as an integer"))?;
121 let bytes = val.to_bytes_be();
122 ensure!(
123 size == 0 || bytes.len() <= size,
124 "expected an integer that fits on {size} bytes but it uses {} bytes",
125 bytes.len()
126 );
127 Ok(SubstValue::ByteArray(bytes))
128 }
129 SubstValue::Uint32(x) => {
130 let bigint = x.to_biguint().expect("cannot convert a i32 to BigInt");
131 let bytes = bigint.to_bytes_be();
132 ensure!(
133 size == 0 || bytes.len() <= size,
134 "expected an integer that fits on {size} bytes but it uses {} bytes",
135 bytes.len()
136 );
137 Ok(SubstValue::ByteArray(bytes))
138 }
139 _ => bail!("cannot parse value {self:?} as an integer"),
140 }
141 }
142
143 fn parse_as_string(&self, size: usize) -> Result<SubstValue> {
144 match self {
145 SubstValue::String(s) => {
146 ensure!(
147 size == 0 || s.len() <= size,
148 "expected a string of at most {size} bytes but it uses {} bytes",
149 s.len()
150 );
151 Ok(self.clone())
152 }
153 _ => bail!("cannot parse value {self:?} as a string"),
154 }
155 }
156
157 fn parse_as_boolean(&self) -> Result<SubstValue> {
158 Ok(match self {
159 SubstValue::Boolean(_) => self.clone(),
160 SubstValue::String(s) => match s.as_str() {
161 "true" => SubstValue::Boolean(true),
162 "false" => SubstValue::Boolean(false),
163 _ => bail!("cannot parse string '{s}' as a boolean, used either 'true' or 'false'"),
164 },
165 _ => bail!("cannot parse value {self:?} as a boolean"),
166 })
167 }
168}
169
170impl Subst for Template {
171 fn subst(&self, data: &SubstData) -> Result<Template> {
187 let mut variables = self.variables.clone();
190 let mut new_data = SubstData::new();
191 for (var_name, val) in data.values.iter() {
192 let Some(var_type) = variables.shift_remove(var_name) else {
193 continue;
195 };
196 new_data.values.insert(var_name.clone(), val.parse(&var_type).with_context(
197 || format!("cannot parse content of substitution variable {var_name} according to the type {var_type:?} specified in the template ")
198 )?);
199 }
200 Ok(Template {
201 name: self.name.clone(),
202 variables,
203 certificate: self.certificate.subst(&new_data)?,
204 })
205 }
206}
207
208pub trait ConvertValue<T>
211where
212 Self: Sized,
213{
214 fn convert(&self, convert: &Option<Conversion>) -> Result<T>;
218 fn unconvert(val: &T) -> Result<Self>;
222}
223
224impl ConvertValue<Vec<u8>> for SubstValue {
225 fn convert(&self, convert: &Option<Conversion>) -> Result<Vec<u8>> {
226 let val = self.parse(&VariableType::ByteArray {
229 size: SizeRange::ExactSize(0),
230 tweak_msb: None,
231 })?;
232 let SubstValue::ByteArray(bytes) = val else {
234 bail!("cannot substitute a byte-array field with value {:?}", self);
235 };
236 ensure!(
237 convert.is_none(),
238 "substitution of a byte-array field with a byte-array value cannot specify a conversion"
239 );
240 Ok(bytes.clone())
241 }
242
243 fn unconvert(val: &Vec<u8>) -> Result<SubstValue> {
244 Ok(SubstValue::ByteArray(val.clone()))
245 }
246}
247
248impl ConvertValue<BigUint> for SubstValue {
249 fn convert(&self, convert: &Option<Conversion>) -> Result<BigUint> {
250 let val = self.parse(&VariableType::Integer {
252 size: SizeRange::ExactSize(0),
253 })?;
254 match val {
255 SubstValue::ByteArray(bytes) => {
256 match convert {
258 None | Some(Conversion::BigEndian) => Ok(BigUint::from_bytes_be(&bytes)),
259 _ => bail!(
260 "substitution of an integer field with a byte-array cannot specify conversion {:?}",
261 convert
262 ),
263 }
264 }
265 _ => bail!("cannot substitute an integer field with value {:?}", self),
266 }
267 }
268
269 fn unconvert(val: &BigUint) -> Result<SubstValue> {
270 Ok(SubstValue::ByteArray(val.to_bytes_be()))
272 }
273}
274
275impl ConvertValue<String> for SubstValue {
276 fn convert(&self, convert: &Option<Conversion>) -> Result<String> {
277 match self {
278 SubstValue::String(x) => {
279 ensure!(
281 convert.is_none(),
282 "substitution of a string field with a string value cannot specify a conversion"
283 );
284 Ok(x.clone())
285 }
286 SubstValue::ByteArray(bytes) => match convert {
287 Some(Conversion::LowercaseHex) => Ok(bytes.encode_hex::<String>()),
288 _ => bail!(
289 "substitution of a string field with a byte-array cannot specify conversion {:?}",
290 convert
291 ),
292 },
293 _ => bail!("cannot substitute a string field with value {:?}", self),
294 }
295 }
296
297 fn unconvert(val: &String) -> Result<SubstValue> {
298 Ok(SubstValue::String(val.clone()))
300 }
301}
302
303impl ConvertValue<bool> for SubstValue {
304 fn convert(&self, convert: &Option<Conversion>) -> Result<bool> {
305 let SubstValue::Boolean(b) = self else {
306 bail!("cannot substitute a boolean field with value {:?}", self)
307 };
308 ensure!(
310 convert.is_none(),
311 "substitution of a boolean field with a boolean value cannot specify a conversion"
312 );
313 Ok(*b)
314 }
315
316 fn unconvert(val: &bool) -> Result<SubstValue> {
317 Ok(SubstValue::Boolean(*val))
319 }
320}
321
322impl<T> Subst for Value<T>
323where
324 Value<T>: Clone,
325 SubstValue: ConvertValue<T>,
326{
327 fn subst(&self, data: &SubstData) -> Result<Value<T>> {
328 match self {
329 Value::Literal(_) => Ok(self.clone()),
330 Value::Variable(Variable { name, convert }) => match data.values.get(name) {
331 None => Ok(self.clone()),
332 Some(val) => Ok(Value::Literal(val.convert(convert)?)),
333 },
334 }
335 }
336}
337
338impl Subst for Certificate {
339 fn subst(&self, data: &SubstData) -> Result<Certificate> {
340 Ok(Certificate {
341 serial_number: self
342 .serial_number
343 .subst(data)
344 .context("cannot substitute serial number")?,
345 not_before: self
346 .not_before
347 .subst(data)
348 .context("cannot substitute not_before")?,
349 not_after: self
350 .not_after
351 .subst(data)
352 .context("cannot substitute not_after")?,
353 issuer: self
354 .issuer
355 .subst(data)
356 .context("cannot substitute issuer")?,
357 subject: self
358 .subject
359 .subst(data)
360 .context("cannot substitute subject")?,
361 subject_public_key_info: self
362 .subject_public_key_info
363 .subst(data)
364 .context("cannot substitute subject public key info")?,
365 authority_key_identifier: self
366 .authority_key_identifier
367 .subst(data)
368 .context("cannot substitute authority key id")?,
369 subject_key_identifier: self
370 .subject_key_identifier
371 .subst(data)
372 .context("cannot substitute subject key id")?,
373 basic_constraints: self
374 .basic_constraints
375 .subst(data)
376 .context("cannot substitute basic constraints")?,
377 key_usage: self
378 .key_usage
379 .subst(data)
380 .context("cannot substitute key usage")?,
381 private_extensions: self
382 .private_extensions
383 .iter()
384 .map(|ext| ext.subst(data))
385 .collect::<Result<Vec<_>>>()
386 .context("cannot substitute in extensions")?,
387 signature: self
388 .signature
389 .subst(data)
390 .context("cannot substitute signature")?,
391
392 subject_alt_name: self
393 .subject_alt_name
394 .subst(data)
395 .context("cannot substitute subject alt name")?,
396 })
397 }
398}
399
400impl Subst for BasicConstraints {
401 fn subst(&self, data: &SubstData) -> Result<BasicConstraints> {
402 Ok(BasicConstraints {
403 ca: self.ca.subst(data)?,
404 })
405 }
406}
407
408impl Subst for CertificateExtension {
409 fn subst(&self, data: &SubstData) -> Result<CertificateExtension> {
410 match self {
411 CertificateExtension::DiceTcbInfo(dice) => Ok(CertificateExtension::DiceTcbInfo(
412 dice.subst(data)
413 .context("cannot substitute in DICE extension")?,
414 )),
415 }
416 }
417}
418
419impl Subst for DiceTcbInfoExtension {
420 fn subst(&self, data: &SubstData) -> Result<DiceTcbInfoExtension> {
421 Ok(DiceTcbInfoExtension {
422 model: self
423 .model
424 .subst(data)
425 .context("cannot substitute DICE model")?,
426 vendor: self
427 .vendor
428 .subst(data)
429 .context("cannot substitute DICE vendor")?,
430 version: self
431 .version
432 .subst(data)
433 .context("cannot substitute DICE version")?,
434 svn: self.svn.subst(data).context("cannot substitute DICE svn")?,
435 layer: self
436 .layer
437 .subst(data)
438 .context("cannot substitute DICE layer")?,
439 fw_ids: self
440 .fw_ids
441 .subst(data)
442 .context("cannot substitute DICE firmware ids")?,
443 flags: self
444 .flags
445 .subst(data)
446 .context("cannot substitute DICE flags")?,
447 })
448 }
449}
450
451impl Subst for FirmwareId {
452 fn subst(&self, data: &SubstData) -> Result<FirmwareId> {
453 Ok(FirmwareId {
454 hash_algorithm: self.hash_algorithm,
455 digest: self.digest.subst(data)?,
456 })
457 }
458}
459
460impl Subst for DiceTcbInfoFlags {
461 fn subst(&self, data: &SubstData) -> Result<DiceTcbInfoFlags> {
462 Ok(DiceTcbInfoFlags {
463 not_configured: self
464 .not_configured
465 .subst(data)
466 .context("cannot substitute not_configured flag")?,
467 not_secure: self
468 .not_secure
469 .subst(data)
470 .context("cannot substitute not_configured flag")?,
471 recovery: self
472 .recovery
473 .subst(data)
474 .context("cannot substitute not_configured flag")?,
475 debug: self
476 .debug
477 .subst(data)
478 .context("cannot substitute not_configured flag")?,
479 })
480 }
481}
482
483impl Subst for KeyUsage {
484 fn subst(&self, data: &SubstData) -> Result<KeyUsage> {
485 Ok(KeyUsage {
486 digital_signature: self
487 .digital_signature
488 .subst(data)
489 .context("cannot substitute digital signature key usage")?,
490 key_agreement: self
491 .key_agreement
492 .subst(data)
493 .context("cannot substitute key agreement")?,
494 cert_sign: self
495 .cert_sign
496 .subst(data)
497 .context("cannot substitute cert sign")?,
498 })
499 }
500}
501
502impl Subst for SubjectPublicKeyInfo {
503 fn subst(&self, data: &SubstData) -> Result<SubjectPublicKeyInfo> {
504 match self {
505 SubjectPublicKeyInfo::EcPublicKey(ec) => {
506 Ok(SubjectPublicKeyInfo::EcPublicKey(ec.subst(data)?))
507 }
508 }
509 }
510}
511
512impl Subst for EcPublicKeyInfo {
513 fn subst(&self, data: &SubstData) -> Result<EcPublicKeyInfo> {
514 Ok(EcPublicKeyInfo {
515 curve: self.curve.clone(),
516 public_key: self.public_key.subst(data)?,
517 })
518 }
519}
520
521impl Subst for EcPublicKey {
522 fn subst(&self, data: &SubstData) -> Result<EcPublicKey> {
523 Ok(EcPublicKey {
524 x: self.x.subst(data)?,
525 y: self.y.subst(data)?,
526 })
527 }
528}
529
530impl Subst for Signature {
531 fn subst(&self, data: &SubstData) -> Result<Signature> {
532 match self {
533 Signature::EcdsaWithSha256 { value } => Ok(Signature::EcdsaWithSha256 {
534 value: value.subst(data)?,
535 }),
536 }
537 }
538}
539
540impl Subst for EcdsaSignature {
541 fn subst(&self, data: &SubstData) -> Result<EcdsaSignature> {
542 Ok(EcdsaSignature {
543 r: self.r.subst(data)?,
544 s: self.s.subst(data)?,
545 })
546 }
547}
548
549impl<T> Subst for Option<T>
550where
551 T: Subst,
552{
553 fn subst(&self, data: &SubstData) -> Result<Option<T>> {
554 self.as_ref().map(|x| x.subst(data)).transpose()
555 }
556}
557
558impl<T> Subst for Vec<T>
559where
560 T: Subst,
561{
562 fn subst(&self, data: &SubstData) -> Result<Vec<T>> {
563 self.iter()
564 .map(|x| x.subst(data))
565 .collect::<Result<Vec<_>>>()
566 }
567}
568
569impl<K, V> Subst for IndexMap<K, V>
570where
571 K: Clone + Eq + std::hash::Hash,
572 V: Subst,
573{
574 fn subst(&self, data: &SubstData) -> Result<IndexMap<K, V>> {
575 self.iter()
576 .map(|(k, v)| Ok((k.clone(), v.subst(data)?)))
577 .collect::<Result<IndexMap<K, V>>>()
578 }
579}
580
581#[cfg(test)]
582mod tests {
583 use super::*;
584
585 #[test]
587 fn parse_byte_array() {
588 let byte_array = SubstValue::ByteArray(vec![0xde, 0xad, 0xbe, 0xef]);
589 assert_eq!(
591 byte_array
592 .parse(&VariableType::ByteArray {
593 size: SizeRange::ExactSize(0),
594 tweak_msb: None
595 })
596 .unwrap(),
597 byte_array
598 );
599 assert_eq!(
600 byte_array
601 .parse(&VariableType::ByteArray {
602 size: SizeRange::ExactSize(4),
603 tweak_msb: None
604 })
605 .unwrap(),
606 byte_array
607 );
608 assert!(
609 byte_array
610 .parse(&VariableType::ByteArray {
611 size: SizeRange::ExactSize(3),
612 tweak_msb: None
613 })
614 .is_err()
615 );
616 assert!(
618 byte_array
619 .parse(&VariableType::ByteArray {
620 size: SizeRange::ExactSize(5),
621 tweak_msb: None
622 })
623 .is_err()
624 );
625
626 let byte_array_str = SubstValue::String("deadbeef".into());
628 assert_eq!(
630 byte_array_str
631 .parse(&VariableType::ByteArray {
632 size: SizeRange::ExactSize(0),
633 tweak_msb: None
634 })
635 .unwrap(),
636 byte_array
637 );
638 assert_eq!(
639 byte_array_str
640 .parse(&VariableType::ByteArray {
641 size: SizeRange::ExactSize(4),
642 tweak_msb: None
643 })
644 .unwrap(),
645 byte_array
646 );
647 assert!(
648 byte_array_str
649 .parse(&VariableType::ByteArray {
650 size: SizeRange::ExactSize(3),
651 tweak_msb: None
652 })
653 .is_err()
654 );
655 assert!(
657 byte_array_str
658 .parse(&VariableType::ByteArray {
659 size: SizeRange::ExactSize(5),
660 tweak_msb: None
661 })
662 .is_err()
663 );
664 }
665
666 #[test]
668 fn parse_integers() {
669 let byte_array = SubstValue::ByteArray(vec![0x3f, 0x2e, 0x1d, 0x0c]);
671 let byte_array_str_hex = SubstValue::String("0x3f2e1d0c".to_string());
673 let byte_array_str_dec = SubstValue::String("1059986700".to_string());
674 let byte_array_int = SubstValue::Uint32(0x3f2e1d0c);
676
677 for val in [
678 &byte_array,
679 &byte_array_int,
680 &byte_array_str_hex,
681 &byte_array_str_dec,
682 ] {
683 assert_eq!(
685 val.parse(&VariableType::Integer {
686 size: SizeRange::ExactSize(0),
687 })
688 .unwrap(),
689 byte_array
690 );
691 assert_eq!(
692 val.parse(&VariableType::Integer {
693 size: SizeRange::ExactSize(4),
694 })
695 .unwrap(),
696 byte_array
697 );
698 assert_eq!(
700 val.parse(&VariableType::Integer {
701 size: SizeRange::ExactSize(5),
702 })
703 .unwrap(),
704 byte_array
705 );
706 assert!(
708 val.parse(&VariableType::Integer {
709 size: SizeRange::ExactSize(3),
710 })
711 .is_err()
712 );
713 }
714 }
715
716 #[test]
718 fn parse_strings() {
719 let s = SubstValue::String("OpenTitan".into());
721 assert_eq!(
723 s.parse(&VariableType::String {
724 size: SizeRange::ExactSize(0),
725 })
726 .unwrap(),
727 s
728 );
729 assert_eq!(
730 s.parse(&VariableType::String {
731 size: SizeRange::ExactSize(9),
732 })
733 .unwrap(),
734 s
735 );
736 assert_eq!(
738 s.parse(&VariableType::String {
739 size: SizeRange::ExactSize(10),
740 })
741 .unwrap(),
742 s
743 );
744 assert!(
745 s.parse(&VariableType::String {
746 size: SizeRange::ExactSize(8),
747 })
748 .is_err()
749 );
750 }
751
752 #[test]
754 fn parse_booleans() {
755 for b in [false, true] {
756 let b_val = SubstValue::Boolean(b);
757 assert_eq!(b_val.parse(&VariableType::Boolean).unwrap(), b_val);
758 let b_str = SubstValue::String(format!("{b}"));
759 assert_eq!(b_str.parse(&VariableType::Boolean).unwrap(), b_val);
760 }
761 }
762
763 #[test]
765 fn convert_to_byte_array() {
766 let byte_array = vec![0xde, 0xad, 0xbe, 0xef, 0x13, 0x24, 0x35];
770 let array_val = SubstValue::ByteArray(byte_array.clone());
771 let conv_none: Result<Vec<u8>> = array_val.convert(&None);
772 let conv_lowercase: Result<Vec<u8>> = array_val.convert(&Some(Conversion::LowercaseHex));
773 let conv_bigendian: Result<Vec<u8>> = array_val.convert(&Some(Conversion::BigEndian));
774
775 assert_eq!(conv_none.unwrap(), byte_array);
776 assert!(conv_lowercase.is_err());
777 assert!(conv_bigendian.is_err());
778 }
780
781 #[test]
783 fn convert_to_string() {
784 let s = "OpenTitan".to_string();
786 let s_val = SubstValue::String(s.clone());
787 let conv_none: Result<String> = s_val.convert(&None);
788 let conv_lowercase: Result<String> = s_val.convert(&Some(Conversion::LowercaseHex));
789 let conv_bigendian: Result<String> = s_val.convert(&Some(Conversion::BigEndian));
790
791 assert_eq!(conv_none.unwrap(), s);
792 assert!(conv_lowercase.is_err());
793 assert!(conv_bigendian.is_err());
794
795 let byte_array = vec![0x0e, 0xad, 0xbe, 0xef, 0x13, 0x24, 0x35];
798 let array_hexstr = "0eadbeef132435".to_string();
799 let array_val = SubstValue::ByteArray(byte_array);
800 let conv_none: Result<String> = array_val.convert(&None);
801 let conv_lowercase: Result<String> = array_val.convert(&Some(Conversion::LowercaseHex));
802 let conv_bigendian: Result<String> = array_val.convert(&Some(Conversion::BigEndian));
803
804 assert!(conv_none.is_err());
805 assert_eq!(conv_lowercase.unwrap(), array_hexstr);
806 assert!(conv_bigendian.is_err());
807 }
808
809 #[test]
811 fn convert_to_integer() {
812 let byte_array = vec![0xde, 0xad, 0xbe, 0xef, 0x13, 0x24, 0x35];
816 let array_val = SubstValue::ByteArray(byte_array.clone());
817 let array_int = BigUint::from_bytes_be(&byte_array);
818 let conv_none: Result<BigUint> = array_val.convert(&None);
819 let conv_lowercase: Result<BigUint> = array_val.convert(&Some(Conversion::LowercaseHex));
820 let conv_bigendian: Result<BigUint> = array_val.convert(&Some(Conversion::BigEndian));
821
822 assert_eq!(conv_none.unwrap(), array_int);
823 assert!(conv_lowercase.is_err());
824 assert_eq!(conv_bigendian.unwrap(), array_int);
825 }
826
827 #[test]
829 fn convert_to_boolean() {
830 let b = false;
832 let b_val = SubstValue::Boolean(b);
833 let conv_none: Result<bool> = b_val.convert(&None);
834 let conv_lowercase: Result<bool> = b_val.convert(&Some(Conversion::LowercaseHex));
835 let conv_bigendian: Result<bool> = b_val.convert(&Some(Conversion::BigEndian));
836
837 assert_eq!(conv_none.unwrap(), b);
838 assert!(conv_lowercase.is_err());
839 assert!(conv_bigendian.is_err());
840 }
841}