ot_certs/asn1/dice_tcb.rs
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::Result;
6
7use crate::asn1::builder::Builder;
8use crate::asn1::x509::X509;
9use crate::asn1::{Oid, Tag};
10use crate::template::DiceTcbInfoExtension;
11
12impl DiceTcbInfoExtension {
13 // From the DICE specification:
14 // https://trustedcomputinggroup.org/wp-content/uploads/DICE-Attestation-Architecture-r23-final.pdf
15 //
16 // tcg OBJECT IDENTIFIER ::= {2 23 133}
17 // tcg-dice OBJECT IDENTIFIER ::= { tcg platformClass(5) 4 }
18 // tcg-dice-TcbInfo OBJECT IDENTIFIER ::= {tcg-dice 1}
19 // DiceTcbInfo ::== SEQUENCE {
20 // vendor [0] IMPLICIT UTF8String OPTIONAL,
21 // model [1] IMPLICIT UTF8String OPTIONAL,
22 // version [2] IMPLICIT UTF8String OPTIONAL,
23 // svn [3] IMPLICIT INTEGER OPTIONAL,
24 // layer [4] IMPLICIT INTEGER OPTIONAL,
25 // index [5] IMPLICIT INTEGER OPTIONAL,
26 // fwids [6] IMPLICIT FWIDLIST OPTIONAL,
27 // flags [7] IMPLICIT OperationalFlags OPTIONAL,
28 // vendorInfo [8] IMPLICIT OCTET STRING OPTIONAL,
29 // type [9] IMPLICIT OCTET STRING OPTIONAL
30 // }
31 // FWIDLIST ::== SEQUENCE SIZE (1..MAX) OF FWID
32 // FWID ::== SEQUENCE {
33 // hashAlg OBJECT IDENTIFIER,
34 // digest OCTET STRING
35 // }
36 // OperationalFlags ::= BIT STRING {
37 // notConfigured (0),
38 // notSecure (1),
39 // recovery (2),
40 // debug (3)
41 // }
42
43 // Push a raw DICE TCB Info extension data, without the X509 extension header.
44 pub fn push_extension_raw<B: Builder>(&self, builder: &mut B) -> Result<()> {
45 builder.push_seq(Some("dice_tcb_info".into()), |builder| {
46 if let Some(vendor) = &self.vendor {
47 builder.push_string(
48 Some("dice_vendor".into()),
49 &Tag::Context {
50 constructed: false,
51 value: 0,
52 },
53 vendor,
54 )?;
55 }
56 if let Some(model) = &self.model {
57 builder.push_string(
58 Some("dice_model".into()),
59 &Tag::Context {
60 constructed: false,
61 value: 1,
62 },
63 model,
64 )?;
65 }
66 if let Some(version) = &self.version {
67 builder.push_string(
68 Some("dice_version".into()),
69 &Tag::Context {
70 constructed: false,
71 value: 2,
72 },
73 version,
74 )?;
75 }
76 if let Some(svn) = &self.svn {
77 builder.push_integer(
78 Some("dice_svn".into()),
79 &Tag::Context {
80 constructed: false,
81 value: 3,
82 },
83 svn,
84 )?;
85 }
86 if let Some(layer) = &self.layer {
87 builder.push_integer(
88 Some("dice_layer".into()),
89 &Tag::Context {
90 constructed: false,
91 value: 4,
92 },
93 layer,
94 )?;
95 }
96 if let Some(fwids) = &self.fw_ids {
97 builder.push_tag(
98 Some("dice_fwids".into()),
99 &Tag::Context {
100 constructed: true,
101 value: 6,
102 },
103 |builder| {
104 for (idx, fwid) in fwids.iter().enumerate() {
105 builder.push_seq(Some("fwid".into()), |builder| {
106 builder.push_oid(&fwid.hash_algorithm.oid())?;
107 builder.push_octet_string(
108 Some(format!("dice_fwids_{}", idx)),
109 |builder| {
110 builder.push_byte_array(
111 Some(format!("dice_fwids_{}", idx)),
112 &fwid.digest,
113 )
114 },
115 )
116 })?;
117 }
118 Ok(())
119 },
120 )?;
121 }
122 if let Some(flags) = &self.flags {
123 builder.push_bitstring(
124 Some("dice_flags".into()),
125 &Tag::Context {
126 constructed: false,
127 value: 7,
128 },
129 &[
130 flags.not_configured.clone(),
131 flags.not_secure.clone(),
132 flags.recovery.clone(),
133 flags.debug.clone(),
134 ],
135 )?;
136 }
137 Ok(())
138 })
139 }
140
141 // Push a DICE TCB Info X509 extension.
142 pub fn push_extension<B: Builder>(&self, builder: &mut B) -> Result<()> {
143 // Per the DICE specification, the DiceTcbInfo extension SHOULD be marked critical.
144 X509::push_extension(builder, &Oid::DiceTcbInfo, true, |builder| {
145 self.push_extension_raw(builder)
146 })
147 }
148}