Skip to content

Commit b2be6a6

Browse files
authored
Implement TCG DICE TCB Info X509 Extension (#28)
Implement the TCG DICE TCB Info and Multi TCB Info X509 Extensions as defined in https://trustedcomputinggroup.org/wp-content/uploads/DICE-Attestation-Architecture-Version-1.1-Revision-18_pub.pdf
1 parent 2466091 commit b2be6a6

File tree

6 files changed

+1005
-1
lines changed

6 files changed

+1005
-1
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ set(LIBNAT20_SOURCES
4141
# Add the core library source files here.
4242
src/core/asn1.c
4343
src/core/oid.c
44+
src/core/x509_ext_tcg_dice_tcb_info.c
4445
src/core/x509.c
4546
)
4647

@@ -50,13 +51,15 @@ set(LIBNAT20_PUB_HEADERS
5051
include/nat20/asn1.h
5152
include/nat20/crypto.h
5253
include/nat20/oid.h
54+
include/nat20/x509_ext_tcg_dice_tcb_info.h
5355
include/nat20/x509.h
5456
)
5557

5658
set(LIBNAT20_TEST_SOURCES
5759
# Add test source files here.
5860
src/core/test/test.cpp
5961
src/core/test/asn1.cpp
62+
src/core/test/x509_ext_tcg_dice_tcb_info.cpp
6063
)
6164

6265
set(LIBNAT20_DOC_PAGES

include/nat20/oid.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* @sa N20_ASN1_DEFINE_OID
3838
* @sa N20_ASN1_DECLARE_OID
3939
*/
40-
#define N20_ASN1_MAX_OID_ELEMENTS 7
40+
#define N20_ASN1_MAX_OID_ELEMENTS 10
4141

4242
/**
4343
* @brief Structure representing an object identifier.
@@ -129,6 +129,11 @@ N20_ASN1_DECLARE_OID(OID_EC_PUBLIC_KEY);
129129
N20_ASN1_DECLARE_OID(OID_SECP256R1);
130130
N20_ASN1_DECLARE_OID(OID_SECP384R1);
131131

132+
N20_ASN1_DECLARE_OID(OID_SHA224);
133+
N20_ASN1_DECLARE_OID(OID_SHA256);
134+
N20_ASN1_DECLARE_OID(OID_SHA384);
135+
N20_ASN1_DECLARE_OID(OID_SHA512);
136+
132137
N20_ASN1_DECLARE_OID(OID_ECDSA_WITH_SHA224);
133138
N20_ASN1_DECLARE_OID(OID_ECDSA_WITH_SHA256);
134139
N20_ASN1_DECLARE_OID(OID_ECDSA_WITH_SHA384);
@@ -144,4 +149,7 @@ N20_ASN1_DECLARE_OID(OID_COMMON_NAME);
144149
N20_ASN1_DECLARE_OID(OID_BASIC_CONSTRAINTS);
145150
N20_ASN1_DECLARE_OID(OID_KEY_USAGE);
146151

152+
N20_ASN1_DECLARE_OID(OID_TCG_DICE_TCB_INFO);
153+
N20_ASN1_DECLARE_OID(OID_TCG_DICE_MULTI_TCB_INFO);
154+
147155
/** @} */
Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
/*
2+
* Copyright 2025 Aurora Operations, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/** @file */
18+
19+
#pragma once
20+
21+
#include <nat20/asn1.h>
22+
#include <nat20/oid.h>
23+
#include <stddef.h>
24+
#include <stdint.h>
25+
26+
#ifdef __cplusplus
27+
extern "C" {
28+
#endif
29+
30+
/**
31+
* @defgroup n20_x509_ext_tcg_dice_tcb_info_operational_flags_macros TCG DICE TCB Info Operational
32+
* Flags Macros.
33+
*
34+
* These macros set the corresponding flags in the operational flags (and mask)
35+
* bit mask of @ref n20_x509_ext_tcg_dice_tcb_info_operational_flags_t.
36+
* Each macro takes a pointer to an instance of
37+
* @ref n20_x509_ext_tcg_dice_tcb_info_operational_flags_t as its argument.
38+
*
39+
* See TCG DICE Attestation Architecture Version 1.1, Section 6.1.1.1.
40+
*
41+
* # Example
42+
*
43+
* @code{.c}
44+
* n20_x509_ext_tcg_dice_tcb_info_operational_flags_t operational_flags = {0};
45+
* N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_SECURE(&operational_flags);
46+
* @endcode
47+
* @{
48+
*/
49+
50+
/**
51+
* @brief The target environment is not configured for normal operation.
52+
*/
53+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_CONFIGURED(operational_flags) \
54+
(operational_flags)->operational_flags_mask[0] |= 0x80
55+
/**
56+
* @brief The target environment is not secure.
57+
*/
58+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_SECURE(operational_flags) \
59+
(operational_flags)->operational_flags_mask[0] |= 0x40
60+
/**
61+
* @brief The target environment is recovering (e.g. from a failure).
62+
*/
63+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_RECOVERY(operational_flags) \
64+
(operational_flags)->operational_flags_mask[0] |= 0x20
65+
/**
66+
* @brief The target environment can be debuged.
67+
*/
68+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_DEBUG(operational_flags) \
69+
(operational_flags)->operational_flags_mask[0] |= 0x10
70+
/**
71+
* @brief The target environment is vulnerable to replay attack.
72+
*/
73+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_REPLAY_PROTECTED( \
74+
operational_flags) \
75+
(operational_flags)->operational_flags_mask[0] |= 0x08
76+
/**
77+
* @brief The target environment is vulneerable to modification by unauthorized updates.
78+
*/
79+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_INTEGRITY_PROTECTED( \
80+
operational_flags) \
81+
(operational_flags)->operational_flags_mask[0] |= 0x04
82+
/**
83+
* @brief The target environment is not measured after being loaded into memory.
84+
*/
85+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_RUNTIME_MEASURED( \
86+
operational_flags) \
87+
(operational_flags)->operational_flags_mask[0] |= 0x02
88+
/**
89+
* @brief The target environment is mutable.
90+
*/
91+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_IMMUTABLE(operational_flags) \
92+
(operational_flags)->operational_flags_mask[0] |= 0x01
93+
/**
94+
* @brief – The Target Environment measurements are not measurements of a Trusted Computing Base
95+
* (TCB).
96+
*/
97+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_TCB(operational_flags) \
98+
(operational_flags)->operational_flags_mask[1] |= 0x80
99+
/**
100+
* @brief Used to force a fixed width of for the OperationalFlags (and OperationalFlagsMask) bit
101+
* string.
102+
*/
103+
#define N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_FIXED_WIDTH(operational_flags) \
104+
(operational_flags)->operational_flags_mask[3] |= 0x01
105+
/**
106+
* @}
107+
*/
108+
109+
/**
110+
* @brief TCG DICE TCB Info Operational Flags.
111+
*
112+
* This type is used to populate the TCB Info Operational Flags and Operational Flags Mask
113+
* ASN.1 bitstrings.
114+
*
115+
* Always zero initialize instances of this structure and
116+
* set the flags using the @ref n20_x509_ext_tcg_dice_tcb_info_operational_flags_macros.
117+
*
118+
* # Example
119+
*
120+
* @code{.c}
121+
* n20_x509_ext_tcg_dice_tcb_info_operational_flags_t operational_flags = {0};
122+
* N20_X509_EXT_TCG_DICE_TCB_INFO_OPERATIONAL_FLAGS_SET_NOT_SECURE(&operational_flags);
123+
* @endcode
124+
*
125+
* (See TCG DICE Attestation Architecture Version 1.1, Section 6.1.1.1.)
126+
*/
127+
typedef struct n20_x509_ext_tcg_dice_tcb_info_operational_flags_s {
128+
/**
129+
* @brief The operational flags mask.
130+
*
131+
* Use the @ref n20_x509_ext_tcg_dice_tcb_info_operational_flags_macros to set the individual
132+
* bits of the operation flags mask. As described in
133+
* @ref n20_x509_ext_tcg_dice_tcb_info_operational_flags_t, there is no need to access this
134+
* field directly.
135+
*/
136+
uint8_t operational_flags_mask[4];
137+
} n20_x509_ext_tcg_dice_tcb_info_operational_flags_t;
138+
139+
/**
140+
* @brief TCG DICE TCB FW ID.
141+
*
142+
* (See TCG DICE Attestation Architecture Version 1.1, Section 6.1.1.)
143+
*/
144+
typedef struct n20_x509_ext_tcg_dice_tcb_info_fwid_s {
145+
/**
146+
* @brief Hash algorithm OID of the algorithm used to generate the digest.
147+
*/
148+
n20_asn1_object_identifier_t hash_algo;
149+
/**
150+
* @brief Digest of firmware, initialization values, or other settings of the Target
151+
* Environment.
152+
*
153+
* If the digest buffer is NULL, no digest is added to the extension.
154+
*/
155+
n20_asn1_slice_t digest;
156+
} n20_x509_ext_tcg_dice_tcb_info_fwid_t;
157+
158+
/**
159+
* @brief List of TCG DICE FWIDs.
160+
*
161+
* If the list is NULL, no FWIDs are inserted into the TCG DICE TCB Info extension.
162+
*/
163+
typedef struct n20_x509_ext_tcg_dice_tcb_info_fwid_list_s {
164+
/**
165+
* @brief List of FWIDs to include in the TCG DICE TCB Info extension.
166+
*/
167+
n20_x509_ext_tcg_dice_tcb_info_fwid_t const *list;
168+
/**
169+
* @brief Number of FWIDs in the list.
170+
*/
171+
size_t count;
172+
} n20_x509_ext_tcg_dice_tcb_info_fwid_list_t;
173+
174+
/**
175+
* @brief TCG DICE TCB Info X509 extension context.
176+
*
177+
* This is the context expected by
178+
* @ref n20_x509_ext_tcg_dice_tcb_info_content.
179+
* An instance of this object must be passed to the callback.
180+
* This is typically done using @ref n20_x509_extension by
181+
* initializing @ref n20_x509_extension_t.content_cb with
182+
* @ref n20_x509_ext_tcg_dice_tcb_info_content and setting
183+
* @ref n20_x509_extension_t.context to an instance of this
184+
* struct.
185+
*
186+
* (See TCG DICE Attestation Architecture Version 1.1, Section 6.1.1.)
187+
* @sa OID_TCG_DICE_TCB_INFO
188+
*/
189+
typedef struct n20_x509_ext_tcg_dice_tcb_info_s {
190+
/**
191+
* @brief The entity that created the measurement of the Target Environment.
192+
*
193+
* Must be a nul terminated UTF-8 encoded string.
194+
*
195+
* If NULL, vendor is not included in the generated extension.
196+
*/
197+
char const *vendor;
198+
/**
199+
* @brief The product name associated with the measurement of the Target Environment.
200+
*
201+
* Must be a nul terminated UTF-8 encoded string.
202+
*
203+
* If NULL, model is not included in the generated extension.
204+
*/
205+
char const *model;
206+
/**
207+
* @brief The revision string associated with the Target Environment.
208+
*
209+
* Must be a nul terminated UTF-8 encoded string.
210+
*
211+
* If NULL, version is not included in the generated extension.
212+
*/
213+
char const *version;
214+
/**
215+
* @brief The security version number associated with the Target Environment.
216+
*/
217+
int64_t svn;
218+
/**
219+
* @brief The DICE layer associated with this measurement of the Target Environment.
220+
*/
221+
int64_t layer;
222+
/**
223+
* @brief A value that distinguishes different instances of the same type of Target Environment.
224+
*/
225+
int64_t index;
226+
/**
227+
* @brief List of FWIDs to include in the extension.
228+
*
229+
* @sa n20_x509_ext_tcg_dice_tcb_info_fwid_list_t
230+
*/
231+
n20_x509_ext_tcg_dice_tcb_info_fwid_list_t fwids;
232+
/**
233+
* @brief A list of flags that enumerate potentially simultaneous operational states of the
234+
* Target Environment.
235+
*
236+
* @sa n20_x509_ext_tcg_dice_tcb_info_operational_flags_t
237+
*/
238+
n20_x509_ext_tcg_dice_tcb_info_operational_flags_t flags;
239+
/**
240+
* @brief Used to commumicate which bits in @ref flags are meaningful.
241+
*
242+
* When a bit is set here, the bit at the corresponding position in @ref flags is meaninful to
243+
* the verifier.
244+
*
245+
* @sa n20_x509_ext_tcg_dice_tcb_info_operational_flags_t
246+
*/
247+
n20_x509_ext_tcg_dice_tcb_info_operational_flags_t flags_mask;
248+
/**
249+
* @brief Vendor supplied values that encode vendor, model, or device specific state.
250+
*
251+
* If vender_info.buffer is NULL vendor info is not included in the generated extension.
252+
*/
253+
n20_asn1_slice_t vendor_info;
254+
/**
255+
* @brief A machine readable description of the measurement.
256+
*
257+
* If type.buffer is NULL, type is not included in the generated extension.
258+
*/
259+
n20_asn1_slice_t type;
260+
} n20_x509_ext_tcg_dice_tcb_info_t;
261+
262+
/**
263+
* @brief Renders the value of a TCG DICE TCB Info X509 extension.
264+
*
265+
* The function expects a pointer to an instance of
266+
* @ref n20_x509_ext_tcg_dice_tcb_info_t as @ref context argument.
267+
*
268+
* If @ref context is NULL, nothing is rendered, which would leave
269+
* the resulting TCG DICE TCB Info extension malformed.
270+
*
271+
* This function is typically not used directly but instead
272+
* passed to @ref n20_x509_extension by initializing an
273+
* instance of @ref n20_x509_extensions_t
274+
* (See @ref n20_x509_extension for an example).
275+
*/
276+
extern void n20_x509_ext_tcg_dice_tcb_info_content(n20_asn1_stream_t *const s, void *context);
277+
278+
/**
279+
* @brief TCG DICE Multi TCB Info X509 extension context.
280+
*
281+
* This is the context expected by
282+
* @ref n20_x509_ext_tcg_dice_multi_tcb_info_content.
283+
* An instance of this object must be passed to the callback.
284+
* This is typically done using @ref n20_x509_extension by
285+
* initializing @ref n20_x509_extension_t.content_cb with
286+
* @ref n20_x509_ext_tcg_dice_multi_tcb_info_content and setting
287+
* @ref n20_x509_extension_t.context to an instance of this
288+
* struct.
289+
*
290+
* (See TCG DICE Attestation Architecture Version 1.1, Section 6.1.2.)
291+
* @sa OID_TCG_DICE_MULTI_TCB_INFO
292+
*/
293+
typedef struct n20_x509_ext_tcg_dice_multi_tcb_info_s {
294+
/**
295+
* @brief List of TCB Info to include in the extension.
296+
*
297+
* If NULL, no list is rendered in the extension.
298+
*
299+
* @sa n20_x509_ext_tcg_dice_tcb_info_t
300+
*/
301+
n20_x509_ext_tcg_dice_tcb_info_t const *list;
302+
/**
303+
* @brief Number of elements in the list.
304+
*/
305+
size_t count;
306+
} n20_x509_ext_tcg_dice_multi_tcb_info_t;
307+
308+
/**
309+
* @brief Renders the value of a TCG DICE Multi TCB Info X509 extension.
310+
*
311+
* The function expects a pointer to an instance of
312+
* @ref n20_x509_ext_tcg_dice_multi_tcb_info_t as @ref context argument.
313+
*
314+
* If @ref context is NULL, or the list is NULL or number of elements in the list is 0, nothing is
315+
* rendered, which would leave the resulting TCG DICE Multi TCB Info extension malformed.
316+
*
317+
* This function is typically not used directly but instead
318+
* passed to @ref n20_x509_extension by initializing an
319+
* instance of @ref n20_x509_extensions_t
320+
* (See @ref n20_x509_extension for an example).
321+
*/
322+
extern void n20_x509_ext_tcg_dice_multi_tcb_info_content(n20_asn1_stream_t *const s, void *context);
323+
324+
#ifdef __cplusplus
325+
}
326+
#endif

src/core/oid.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ N20_ASN1_DEFINE_OID(OID_SECP256R1, 1, 2, 840, 10045, 3, 1, 7);
2828
/* Also known as NIST P-384 */
2929
N20_ASN1_DEFINE_OID(OID_SECP384R1, 1, 3, 132, 0, 34);
3030

31+
N20_ASN1_DEFINE_OID(OID_SHA224, 2, 16, 840, 1, 101, 3, 4, 2, 4);
32+
N20_ASN1_DEFINE_OID(OID_SHA256, 2, 16, 840, 1, 101, 3, 4, 2, 1);
33+
N20_ASN1_DEFINE_OID(OID_SHA384, 2, 16, 840, 1, 101, 3, 4, 2, 2);
34+
N20_ASN1_DEFINE_OID(OID_SHA512, 2, 16, 840, 1, 101, 3, 4, 2, 3);
35+
3136
N20_ASN1_DEFINE_OID(OID_ECDSA_WITH_SHA224, 1, 2, 840, 10045, 4, 3, 1);
3237
N20_ASN1_DEFINE_OID(OID_ECDSA_WITH_SHA256, 1, 2, 840, 10045, 4, 3, 2);
3338
N20_ASN1_DEFINE_OID(OID_ECDSA_WITH_SHA384, 1, 2, 840, 10045, 4, 3, 3);
@@ -42,3 +47,6 @@ N20_ASN1_DEFINE_OID(OID_COMMON_NAME, 2, 5, 4, 3);
4247

4348
N20_ASN1_DEFINE_OID(OID_BASIC_CONSTRAINTS, 2, 5, 29, 19);
4449
N20_ASN1_DEFINE_OID(OID_KEY_USAGE, 2, 5, 29, 15);
50+
51+
N20_ASN1_DEFINE_OID(OID_TCG_DICE_TCB_INFO, 2, 23, 133, 5, 4, 1);
52+
N20_ASN1_DEFINE_OID(OID_TCG_DICE_MULTI_TCB_INFO, 2, 23, 133, 5, 4, 5);

0 commit comments

Comments
 (0)