1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include <stddef.h>
16 #include <stdint.h>
17 #include <stdio.h>
18
19 #include <memory>
20
21 #include "dice/config.h"
22 #include "dice/dice.h"
23 #include "dice/known_test_values.h"
24 #include "dice/test_framework.h"
25 #include "dice/test_utils.h"
26 #include "dice/utils.h"
27 #include "pw_string/format.h"
28
29 namespace {
30
31 using dice::test::CertificateType_Cbor;
32 using dice::test::DeriveFakeInputValue;
33 using dice::test::DiceStateForTest;
34 using dice::test::KeyType_Ed25519;
35 using dice::test::KeyType_P256;
36 using dice::test::KeyType_P384;
37
TEST(DiceOpsTest,InvalidContextReturnsError)38 TEST(DiceOpsTest, InvalidContextReturnsError) {
39 DiceStateForTest current_state = {};
40 DiceStateForTest next_state = {};
41 DiceInputValues input_values = {};
42 DiceResult result = DiceMainFlow(
43 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
44 sizeof(next_state.certificate), next_state.certificate,
45 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
46 EXPECT_EQ(kDiceResultInvalidInput, result);
47 }
48
TEST(DiceOpsTest,Ed25519KnownAnswerZeroInput)49 TEST(DiceOpsTest, Ed25519KnownAnswerZeroInput) {
50 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
51 .subject_algorithm = kDiceKeyAlgorithmEd25519};
52 DiceStateForTest current_state = {};
53 DiceStateForTest next_state = {};
54 DiceInputValues input_values = {};
55 DiceResult result = DiceMainFlow(
56 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
57 sizeof(next_state.certificate), next_state.certificate,
58 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
59 EXPECT_EQ(kDiceResultOk, result);
60 DumpState(CertificateType_Cbor, KeyType_Ed25519, "zero_input", next_state);
61 // The CDI values should be deterministic.
62 ASSERT_EQ(sizeof(next_state.cdi_attest),
63 sizeof(dice::test::kExpectedCdiAttest_ZeroInput));
64 EXPECT_EQ(0, memcmp(next_state.cdi_attest,
65 dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
66 ASSERT_EQ(sizeof(next_state.cdi_seal),
67 sizeof(dice::test::kExpectedCdiSeal_ZeroInput));
68 EXPECT_EQ(0, memcmp(next_state.cdi_seal,
69 dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
70 ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput),
71 next_state.certificate_size);
72 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_ZeroInput,
73 next_state.certificate, next_state.certificate_size));
74 }
75
TEST(DiceOpsTest,P256KnownAnswerZeroInput)76 TEST(DiceOpsTest, P256KnownAnswerZeroInput) {
77 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
78 .subject_algorithm = kDiceKeyAlgorithmP256};
79 DiceStateForTest current_state = {};
80 DiceStateForTest next_state = {};
81 DiceInputValues input_values = {};
82 DiceResult result = DiceMainFlow(
83 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
84 sizeof(next_state.certificate), next_state.certificate,
85 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
86 EXPECT_EQ(kDiceResultOk, result);
87 DumpState(CertificateType_Cbor, KeyType_P256, "zero_input", next_state);
88 // The CDI values should be deterministic.
89 ASSERT_EQ(sizeof(next_state.cdi_attest),
90 sizeof(dice::test::kExpectedCdiAttest_ZeroInput));
91 EXPECT_EQ(0, memcmp(next_state.cdi_attest,
92 dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
93 ASSERT_EQ(sizeof(next_state.cdi_seal),
94 sizeof(dice::test::kExpectedCdiSeal_ZeroInput));
95 EXPECT_EQ(0, memcmp(next_state.cdi_seal,
96 dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
97 ASSERT_EQ(sizeof(dice::test::kExpectedCborP256Cert_ZeroInput),
98 next_state.certificate_size);
99 // Comparing everything except for the signature, since ECDSA signatures are
100 // not deterministic
101 constexpr size_t signature_size = 64;
102 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborP256Cert_ZeroInput,
103 next_state.certificate,
104 next_state.certificate_size - signature_size));
105 }
106
TEST(DiceOpsTest,P384KnownAnswerZeroInput)107 TEST(DiceOpsTest, P384KnownAnswerZeroInput) {
108 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
109 .subject_algorithm = kDiceKeyAlgorithmP384};
110 DiceStateForTest current_state = {};
111 DiceStateForTest next_state = {};
112 DiceInputValues input_values = {};
113 DiceResult result = DiceMainFlow(
114 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
115 sizeof(next_state.certificate), next_state.certificate,
116 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
117 EXPECT_EQ(kDiceResultOk, result);
118 DumpState(CertificateType_Cbor, KeyType_P384, "zero_input", next_state);
119 // The CDI values should be deterministic.
120 ASSERT_EQ(sizeof(next_state.cdi_attest),
121 sizeof(dice::test::kExpectedCdiAttest_ZeroInput));
122 EXPECT_EQ(0, memcmp(next_state.cdi_attest,
123 dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
124 ASSERT_EQ(sizeof(next_state.cdi_seal),
125 sizeof(dice::test::kExpectedCdiSeal_ZeroInput));
126 EXPECT_EQ(0, memcmp(next_state.cdi_seal,
127 dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
128 ASSERT_EQ(sizeof(dice::test::kExpectedCborP384Cert_ZeroInput),
129 next_state.certificate_size);
130 // Comparing everything except for the signature, since ECDSA signatures are
131 // not deterministic
132 constexpr size_t signature_size = 96;
133 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborP384Cert_ZeroInput,
134 next_state.certificate,
135 next_state.certificate_size - signature_size));
136 }
137
TEST(DiceOpsTest,Ed25519KnownAnswerHashOnlyInput)138 TEST(DiceOpsTest, Ed25519KnownAnswerHashOnlyInput) {
139 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
140 .subject_algorithm = kDiceKeyAlgorithmEd25519};
141 DiceStateForTest current_state = {};
142 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
143 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
144 DiceStateForTest next_state = {};
145 DiceInputValues input_values = {};
146 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
147 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
148 input_values.authority_hash);
149 input_values.config_type = kDiceConfigTypeInline;
150 DeriveFakeInputValue("inline_config", DICE_INLINE_CONFIG_SIZE,
151 input_values.config_value);
152
153 DiceResult result = DiceMainFlow(
154 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
155 sizeof(next_state.certificate), next_state.certificate,
156 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
157 EXPECT_EQ(kDiceResultOk, result);
158 DumpState(CertificateType_Cbor, KeyType_Ed25519, "hash_only_input",
159 next_state);
160 ASSERT_EQ(sizeof(next_state.cdi_attest),
161 sizeof(dice::test::kExpectedCdiAttest_HashOnlyInput));
162 EXPECT_EQ(
163 0, memcmp(next_state.cdi_attest,
164 dice::test::kExpectedCdiAttest_HashOnlyInput, DICE_CDI_SIZE));
165 ASSERT_EQ(sizeof(next_state.cdi_seal),
166 sizeof(dice::test::kExpectedCdiSeal_HashOnlyInput));
167 EXPECT_EQ(
168 0, memcmp(next_state.cdi_seal, dice::test::kExpectedCdiSeal_HashOnlyInput,
169 DICE_CDI_SIZE));
170 ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_HashOnlyInput),
171 next_state.certificate_size);
172 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_HashOnlyInput,
173 next_state.certificate, next_state.certificate_size));
174 }
175
TEST(DiceOpsTest,P256KnownAnswerHashOnlyInput)176 TEST(DiceOpsTest, P256KnownAnswerHashOnlyInput) {
177 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
178 .subject_algorithm = kDiceKeyAlgorithmP256};
179 DiceStateForTest current_state = {};
180 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
181 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
182 DiceStateForTest next_state = {};
183 DiceInputValues input_values = {};
184 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
185 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
186 input_values.authority_hash);
187 input_values.config_type = kDiceConfigTypeInline;
188 DeriveFakeInputValue("inline_config", DICE_INLINE_CONFIG_SIZE,
189 input_values.config_value);
190
191 DiceResult result = DiceMainFlow(
192 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
193 sizeof(next_state.certificate), next_state.certificate,
194 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
195 EXPECT_EQ(kDiceResultOk, result);
196 DumpState(CertificateType_Cbor, KeyType_P256, "hash_only_input", next_state);
197 ASSERT_EQ(sizeof(next_state.cdi_attest),
198 sizeof(dice::test::kExpectedCdiAttest_HashOnlyInput));
199 EXPECT_EQ(
200 0, memcmp(next_state.cdi_attest,
201 dice::test::kExpectedCdiAttest_HashOnlyInput, DICE_CDI_SIZE));
202 ASSERT_EQ(sizeof(next_state.cdi_seal),
203 sizeof(dice::test::kExpectedCdiSeal_HashOnlyInput));
204 EXPECT_EQ(
205 0, memcmp(next_state.cdi_seal, dice::test::kExpectedCdiSeal_HashOnlyInput,
206 DICE_CDI_SIZE));
207 ASSERT_EQ(sizeof(dice::test::kExpectedCborP256Cert_HashOnlyInput),
208 next_state.certificate_size);
209 constexpr size_t signature_size = 64;
210 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborP256Cert_HashOnlyInput,
211 next_state.certificate,
212 next_state.certificate_size - signature_size));
213 }
214
TEST(DiceOpsTest,P384KnownAnswerHashOnlyInput)215 TEST(DiceOpsTest, P384KnownAnswerHashOnlyInput) {
216 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
217 .subject_algorithm = kDiceKeyAlgorithmP384};
218 DiceStateForTest current_state = {};
219 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
220 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
221 DiceStateForTest next_state = {};
222 DiceInputValues input_values = {};
223 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
224 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
225 input_values.authority_hash);
226 input_values.config_type = kDiceConfigTypeInline;
227 DeriveFakeInputValue("inline_config", DICE_INLINE_CONFIG_SIZE,
228 input_values.config_value);
229
230 DiceResult result = DiceMainFlow(
231 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
232 sizeof(next_state.certificate), next_state.certificate,
233 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
234 EXPECT_EQ(kDiceResultOk, result);
235 DumpState(CertificateType_Cbor, KeyType_P384, "hash_only_input", next_state);
236 ASSERT_EQ(sizeof(next_state.cdi_attest),
237 sizeof(dice::test::kExpectedCdiAttest_HashOnlyInput));
238 EXPECT_EQ(
239 0, memcmp(next_state.cdi_attest,
240 dice::test::kExpectedCdiAttest_HashOnlyInput, DICE_CDI_SIZE));
241 ASSERT_EQ(sizeof(next_state.cdi_seal),
242 sizeof(dice::test::kExpectedCdiSeal_HashOnlyInput));
243 EXPECT_EQ(
244 0, memcmp(next_state.cdi_seal, dice::test::kExpectedCdiSeal_HashOnlyInput,
245 DICE_CDI_SIZE));
246 ASSERT_EQ(sizeof(dice::test::kExpectedCborP384Cert_HashOnlyInput),
247 next_state.certificate_size);
248 constexpr size_t signature_size = 96;
249 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborP384Cert_HashOnlyInput,
250 next_state.certificate,
251 next_state.certificate_size - signature_size));
252 }
253
TEST(DiceOpsTest,Ed25519KnownAnswerDescriptorInput)254 TEST(DiceOpsTest, Ed25519KnownAnswerDescriptorInput) {
255 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
256 .subject_algorithm = kDiceKeyAlgorithmEd25519};
257 DiceStateForTest current_state = {};
258 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
259 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
260
261 DiceStateForTest next_state = {};
262
263 DiceInputValues input_values = {};
264 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
265 uint8_t code_descriptor[100];
266 DeriveFakeInputValue("code_desc", sizeof(code_descriptor), code_descriptor);
267 input_values.code_descriptor = code_descriptor;
268 input_values.code_descriptor_size = sizeof(code_descriptor);
269
270 uint8_t config_descriptor[40];
271 DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
272 config_descriptor);
273 input_values.config_descriptor = config_descriptor;
274 input_values.config_descriptor_size = sizeof(config_descriptor);
275 input_values.config_type = kDiceConfigTypeDescriptor;
276
277 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
278 input_values.authority_hash);
279 uint8_t authority_descriptor[65];
280 DeriveFakeInputValue("authority_desc", sizeof(authority_descriptor),
281 authority_descriptor);
282 input_values.authority_descriptor = authority_descriptor;
283 input_values.authority_descriptor_size = sizeof(authority_descriptor);
284
285 DiceResult result = DiceMainFlow(
286 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
287 sizeof(next_state.certificate), next_state.certificate,
288 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
289 EXPECT_EQ(kDiceResultOk, result);
290 DumpState(CertificateType_Cbor, KeyType_Ed25519, "descriptor_input",
291 next_state);
292 // Both CDI values and the certificate should be deterministic.
293 EXPECT_EQ(
294 0, memcmp(next_state.cdi_attest,
295 dice::test::kExpectedCdiAttest_DescriptorInput, DICE_CDI_SIZE));
296 EXPECT_EQ(
297 0, memcmp(next_state.cdi_seal,
298 dice::test::kExpectedCdiSeal_DescriptorInput, DICE_CDI_SIZE));
299 ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_DescriptorInput),
300 next_state.certificate_size);
301 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_DescriptorInput,
302 next_state.certificate, next_state.certificate_size));
303 }
304
TEST(DiceOpsTest,P256KnownAnswerDescriptorInput)305 TEST(DiceOpsTest, P256KnownAnswerDescriptorInput) {
306 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
307 .subject_algorithm = kDiceKeyAlgorithmP256};
308 DiceStateForTest current_state = {};
309 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
310 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
311
312 DiceStateForTest next_state = {};
313
314 DiceInputValues input_values = {};
315 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
316 uint8_t code_descriptor[100];
317 DeriveFakeInputValue("code_desc", sizeof(code_descriptor), code_descriptor);
318 input_values.code_descriptor = code_descriptor;
319 input_values.code_descriptor_size = sizeof(code_descriptor);
320
321 uint8_t config_descriptor[40];
322 DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
323 config_descriptor);
324 input_values.config_descriptor = config_descriptor;
325 input_values.config_descriptor_size = sizeof(config_descriptor);
326 input_values.config_type = kDiceConfigTypeDescriptor;
327
328 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
329 input_values.authority_hash);
330 uint8_t authority_descriptor[65];
331 DeriveFakeInputValue("authority_desc", sizeof(authority_descriptor),
332 authority_descriptor);
333 input_values.authority_descriptor = authority_descriptor;
334 input_values.authority_descriptor_size = sizeof(authority_descriptor);
335
336 DiceResult result = DiceMainFlow(
337 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
338 sizeof(next_state.certificate), next_state.certificate,
339 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
340 EXPECT_EQ(kDiceResultOk, result);
341 DumpState(CertificateType_Cbor, KeyType_P256, "descriptor_input", next_state);
342 // Both CDI values and the certificate should be deterministic.
343 EXPECT_EQ(
344 0, memcmp(next_state.cdi_attest,
345 dice::test::kExpectedCdiAttest_DescriptorInput, DICE_CDI_SIZE));
346 EXPECT_EQ(
347 0, memcmp(next_state.cdi_seal,
348 dice::test::kExpectedCdiSeal_DescriptorInput, DICE_CDI_SIZE));
349 ASSERT_EQ(sizeof(dice::test::kExpectedCborP256Cert_DescriptorInput),
350 next_state.certificate_size);
351 constexpr size_t signature_size = 64;
352 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborP256Cert_DescriptorInput,
353 next_state.certificate,
354 next_state.certificate_size - signature_size));
355 }
356
TEST(DiceOpsTest,P384KnownAnswerDescriptorInput)357 TEST(DiceOpsTest, P384KnownAnswerDescriptorInput) {
358 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
359 .subject_algorithm = kDiceKeyAlgorithmP384};
360 DiceStateForTest current_state = {};
361 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
362 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
363
364 DiceStateForTest next_state = {};
365
366 DiceInputValues input_values = {};
367 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
368 uint8_t code_descriptor[100];
369 DeriveFakeInputValue("code_desc", sizeof(code_descriptor), code_descriptor);
370 input_values.code_descriptor = code_descriptor;
371 input_values.code_descriptor_size = sizeof(code_descriptor);
372
373 uint8_t config_descriptor[40];
374 DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
375 config_descriptor);
376 input_values.config_descriptor = config_descriptor;
377 input_values.config_descriptor_size = sizeof(config_descriptor);
378 input_values.config_type = kDiceConfigTypeDescriptor;
379
380 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
381 input_values.authority_hash);
382 uint8_t authority_descriptor[65];
383 DeriveFakeInputValue("authority_desc", sizeof(authority_descriptor),
384 authority_descriptor);
385 input_values.authority_descriptor = authority_descriptor;
386 input_values.authority_descriptor_size = sizeof(authority_descriptor);
387
388 DiceResult result = DiceMainFlow(
389 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
390 sizeof(next_state.certificate), next_state.certificate,
391 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
392 EXPECT_EQ(kDiceResultOk, result);
393 DumpState(CertificateType_Cbor, KeyType_P384, "descriptor_input", next_state);
394 // Both CDI values and the certificate should be deterministic.
395 EXPECT_EQ(
396 0, memcmp(next_state.cdi_attest,
397 dice::test::kExpectedCdiAttest_DescriptorInput, DICE_CDI_SIZE));
398 EXPECT_EQ(
399 0, memcmp(next_state.cdi_seal,
400 dice::test::kExpectedCdiSeal_DescriptorInput, DICE_CDI_SIZE));
401 ASSERT_EQ(sizeof(dice::test::kExpectedCborP384Cert_DescriptorInput),
402 next_state.certificate_size);
403 constexpr size_t signature_size = 96;
404 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborP384Cert_DescriptorInput,
405 next_state.certificate,
406 next_state.certificate_size - signature_size));
407 }
408
TEST(DiceOpsTest,Ed25519NonZeroMode)409 TEST(DiceOpsTest, Ed25519NonZeroMode) {
410 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
411 .subject_algorithm = kDiceKeyAlgorithmEd25519};
412 constexpr size_t kModeOffsetInCert = 315;
413 DiceStateForTest current_state = {};
414 DiceStateForTest next_state = {};
415 DiceInputValues input_values = {};
416 input_values.mode = kDiceModeDebug;
417 DiceResult result = DiceMainFlow(
418 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
419 sizeof(next_state.certificate), next_state.certificate,
420 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
421 EXPECT_EQ(kDiceResultOk, result);
422 EXPECT_EQ(kDiceModeDebug, next_state.certificate[kModeOffsetInCert]);
423 }
424
TEST(DiceOpsTest,P256NonZeroMode)425 TEST(DiceOpsTest, P256NonZeroMode) {
426 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
427 .subject_algorithm = kDiceKeyAlgorithmP256};
428 constexpr size_t kModeOffsetInCert = 315;
429 DiceStateForTest current_state = {};
430 DiceStateForTest next_state = {};
431 DiceInputValues input_values = {};
432 input_values.mode = kDiceModeDebug;
433 DiceResult result = DiceMainFlow(
434 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
435 sizeof(next_state.certificate), next_state.certificate,
436 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
437 EXPECT_EQ(kDiceResultOk, result);
438 EXPECT_EQ(kDiceModeDebug, next_state.certificate[kModeOffsetInCert]);
439 }
440
TEST(DiceOpsTest,P384NonZeroMode)441 TEST(DiceOpsTest, P384NonZeroMode) {
442 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
443 .subject_algorithm = kDiceKeyAlgorithmP384};
444 constexpr size_t kModeOffsetInCert = 316;
445 DiceStateForTest current_state = {};
446 DiceStateForTest next_state = {};
447 DiceInputValues input_values = {};
448 input_values.mode = kDiceModeDebug;
449 DiceResult result = DiceMainFlow(
450 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
451 sizeof(next_state.certificate), next_state.certificate,
452 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
453 EXPECT_EQ(kDiceResultOk, result);
454 EXPECT_EQ(kDiceModeDebug, next_state.certificate[kModeOffsetInCert]);
455 }
456
TEST(DiceOpsTest,Ed25519LargeInputs)457 TEST(DiceOpsTest, Ed25519LargeInputs) {
458 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
459 .subject_algorithm = kDiceKeyAlgorithmEd25519};
460 constexpr uint8_t kBigBuffer[1024 * 1024] = {};
461 DiceStateForTest current_state = {};
462 DiceStateForTest next_state = {};
463 DiceInputValues input_values = {};
464 input_values.code_descriptor = kBigBuffer;
465 input_values.code_descriptor_size = sizeof(kBigBuffer);
466 DiceResult result = DiceMainFlow(
467 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
468 sizeof(next_state.certificate), next_state.certificate,
469 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
470 EXPECT_EQ(kDiceResultBufferTooSmall, result);
471 }
472
TEST(DiceOpsTest,P256LargeInputs)473 TEST(DiceOpsTest, P256LargeInputs) {
474 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
475 .subject_algorithm = kDiceKeyAlgorithmP256};
476 constexpr uint8_t kBigBuffer[1024 * 1024] = {};
477 DiceStateForTest current_state = {};
478 DiceStateForTest next_state = {};
479 DiceInputValues input_values = {};
480 input_values.code_descriptor = kBigBuffer;
481 input_values.code_descriptor_size = sizeof(kBigBuffer);
482 DiceResult result = DiceMainFlow(
483 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
484 sizeof(next_state.certificate), next_state.certificate,
485 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
486 EXPECT_EQ(kDiceResultBufferTooSmall, result);
487 }
488
TEST(DiceOpsTest,P384LargeInputs)489 TEST(DiceOpsTest, P384LargeInputs) {
490 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
491 .subject_algorithm = kDiceKeyAlgorithmP384};
492 constexpr uint8_t kBigBuffer[1024 * 1024] = {};
493 DiceStateForTest current_state = {};
494 DiceStateForTest next_state = {};
495 DiceInputValues input_values = {};
496 input_values.code_descriptor = kBigBuffer;
497 input_values.code_descriptor_size = sizeof(kBigBuffer);
498 DiceResult result = DiceMainFlow(
499 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
500 sizeof(next_state.certificate), next_state.certificate,
501 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
502 EXPECT_EQ(kDiceResultBufferTooSmall, result);
503 }
504
TEST(DiceOpsTest,Ed25519InvalidConfigType)505 TEST(DiceOpsTest, Ed25519InvalidConfigType) {
506 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
507 .subject_algorithm = kDiceKeyAlgorithmEd25519};
508 DiceStateForTest current_state = {};
509 DiceStateForTest next_state = {};
510 DiceInputValues input_values = {};
511 input_values.config_type = (DiceConfigType)55;
512 DiceResult result = DiceMainFlow(
513 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
514 sizeof(next_state.certificate), next_state.certificate,
515 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
516 EXPECT_EQ(kDiceResultInvalidInput, result);
517 }
518
TEST(DiceOpsTest,P256InvalidConfigType)519 TEST(DiceOpsTest, P256InvalidConfigType) {
520 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
521 .subject_algorithm = kDiceKeyAlgorithmP256};
522 DiceStateForTest current_state = {};
523 DiceStateForTest next_state = {};
524 DiceInputValues input_values = {};
525 input_values.config_type = (DiceConfigType)55;
526 DiceResult result = DiceMainFlow(
527 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
528 sizeof(next_state.certificate), next_state.certificate,
529 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
530 EXPECT_EQ(kDiceResultInvalidInput, result);
531 }
532
TEST(DiceOpsTest,P384InvalidConfigType)533 TEST(DiceOpsTest, P384InvalidConfigType) {
534 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
535 .subject_algorithm = kDiceKeyAlgorithmP384};
536 DiceStateForTest current_state = {};
537 DiceStateForTest next_state = {};
538 DiceInputValues input_values = {};
539 input_values.config_type = (DiceConfigType)55;
540 DiceResult result = DiceMainFlow(
541 &context, current_state.cdi_attest, current_state.cdi_seal, &input_values,
542 sizeof(next_state.certificate), next_state.certificate,
543 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
544 EXPECT_EQ(kDiceResultInvalidInput, result);
545 }
546
TEST(DiceOpsTest,Ed25519PartialCertChain)547 TEST(DiceOpsTest, Ed25519PartialCertChain) {
548 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
549 .subject_algorithm = kDiceKeyAlgorithmEd25519};
550 constexpr size_t kNumLayers = 7;
551 DiceStateForTest states[kNumLayers + 1] = {};
552 DiceInputValues inputs[kNumLayers] = {};
553 for (size_t i = 0; i < kNumLayers; ++i) {
554 char seed[40];
555 pw::string::Format(seed, "code_hash_%zu", i);
556 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
557 pw::string::Format(seed, "authority_hash_%zu", i);
558 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
559 inputs[i].config_type = kDiceConfigTypeInline;
560 pw::string::Format(seed, "inline_config_%zu", i);
561 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
562 inputs[i].mode = kDiceModeNormal;
563 EXPECT_EQ(
564 kDiceResultOk,
565 DiceMainFlow(&context, states[i].cdi_attest, states[i].cdi_seal,
566 &inputs[i], sizeof(states[i + 1].certificate),
567 states[i + 1].certificate, &states[i + 1].certificate_size,
568 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
569 char suffix[40];
570 pw::string::Format(suffix, "part_cert_chain_%zu", i);
571 DumpState(CertificateType_Cbor, KeyType_Ed25519, suffix, states[i + 1]);
572 }
573 // Use the first derived CDI cert as the 'root' of partial chain.
574 EXPECT_TRUE(dice::test::VerifyCertificateChain(
575 CertificateType_Cbor, states[1].certificate, states[1].certificate_size,
576 &states[2], kNumLayers - 1, /*is_partial_chain=*/true));
577 }
578
TEST(DiceOpsTest,P256PartialCertChain)579 TEST(DiceOpsTest, P256PartialCertChain) {
580 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
581 .subject_algorithm = kDiceKeyAlgorithmP256};
582 constexpr size_t kNumLayers = 7;
583 DiceStateForTest states[kNumLayers + 1] = {};
584 DiceInputValues inputs[kNumLayers] = {};
585 for (size_t i = 0; i < kNumLayers; ++i) {
586 char seed[40];
587 pw::string::Format(seed, "code_hash_%zu", i);
588 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
589 pw::string::Format(seed, "authority_hash_%zu", i);
590 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
591 inputs[i].config_type = kDiceConfigTypeInline;
592 pw::string::Format(seed, "inline_config_%zu", i);
593 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
594 inputs[i].mode = kDiceModeNormal;
595 EXPECT_EQ(
596 kDiceResultOk,
597 DiceMainFlow(&context, states[i].cdi_attest, states[i].cdi_seal,
598 &inputs[i], sizeof(states[i + 1].certificate),
599 states[i + 1].certificate, &states[i + 1].certificate_size,
600 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
601 char suffix[40];
602 pw::string::Format(suffix, "part_cert_chain_%zu", i);
603 DumpState(CertificateType_Cbor, KeyType_P256, suffix, states[i + 1]);
604 }
605 // Use the first derived CDI cert as the 'root' of partial chain.
606 EXPECT_TRUE(dice::test::VerifyCertificateChain(
607 CertificateType_Cbor, states[1].certificate, states[1].certificate_size,
608 &states[2], kNumLayers - 1, /*is_partial_chain=*/true));
609 }
610
TEST(DiceOpsTest,P384PartialCertChain)611 TEST(DiceOpsTest, P384PartialCertChain) {
612 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
613 .subject_algorithm = kDiceKeyAlgorithmP384};
614 constexpr size_t kNumLayers = 7;
615 DiceStateForTest states[kNumLayers + 1] = {};
616 DiceInputValues inputs[kNumLayers] = {};
617 for (size_t i = 0; i < kNumLayers; ++i) {
618 char seed[40];
619 pw::string::Format(seed, "code_hash_%zu", i);
620 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
621 pw::string::Format(seed, "authority_hash_%zu", i);
622 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
623 inputs[i].config_type = kDiceConfigTypeInline;
624 pw::string::Format(seed, "inline_config_%zu", i);
625 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
626 inputs[i].mode = kDiceModeNormal;
627 EXPECT_EQ(
628 kDiceResultOk,
629 DiceMainFlow(&context, states[i].cdi_attest, states[i].cdi_seal,
630 &inputs[i], sizeof(states[i + 1].certificate),
631 states[i + 1].certificate, &states[i + 1].certificate_size,
632 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
633 char suffix[40];
634 pw::string::Format(suffix, "part_cert_chain_%zu", i);
635 DumpState(CertificateType_Cbor, KeyType_P384, suffix, states[i + 1]);
636 }
637 // Use the first derived CDI cert as the 'root' of partial chain.
638 EXPECT_TRUE(dice::test::VerifyCertificateChain(
639 CertificateType_Cbor, states[1].certificate, states[1].certificate_size,
640 &states[2], kNumLayers - 1, /*is_partial_chain=*/true));
641 }
642
TEST(DiceOpsTest,Ed25519FullCertChain)643 TEST(DiceOpsTest, Ed25519FullCertChain) {
644 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmEd25519,
645 .subject_algorithm = kDiceKeyAlgorithmEd25519};
646 constexpr size_t kNumLayers = 7;
647 DiceStateForTest states[kNumLayers + 1] = {};
648 DiceInputValues inputs[kNumLayers] = {};
649 for (size_t i = 0; i < kNumLayers; ++i) {
650 char seed[40];
651 pw::string::Format(seed, "code_hash_%zu", i);
652 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
653 pw::string::Format(seed, "authority_hash_%zu", i);
654 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
655 inputs[i].config_type = kDiceConfigTypeInline;
656 pw::string::Format(seed, "inline_config_%zu", i);
657 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
658 inputs[i].mode = kDiceModeNormal;
659 EXPECT_EQ(
660 kDiceResultOk,
661 DiceMainFlow(&context, states[i].cdi_attest, states[i].cdi_seal,
662 &inputs[i], sizeof(states[i + 1].certificate),
663 states[i + 1].certificate, &states[i + 1].certificate_size,
664 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
665 char suffix[40];
666 pw::string::Format(suffix, "full_cert_chain_%zu", i);
667 DumpState(CertificateType_Cbor, KeyType_Ed25519, suffix, states[i + 1]);
668 }
669 // Use a fake self-signed UDS cert as the 'root'.
670 uint8_t root_certificate[dice::test::kTestCertSize];
671 size_t root_certificate_size = 0;
672 dice::test::CreateFakeUdsCertificate(
673 &context, states[0].cdi_attest, CertificateType_Cbor, KeyType_Ed25519,
674 root_certificate, &root_certificate_size);
675 EXPECT_TRUE(dice::test::VerifyCertificateChain(
676 CertificateType_Cbor, root_certificate, root_certificate_size, &states[1],
677 kNumLayers, /*is_partial_chain=*/false));
678 }
679
TEST(DiceOpsTest,P256FullCertChain)680 TEST(DiceOpsTest, P256FullCertChain) {
681 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP256,
682 .subject_algorithm = kDiceKeyAlgorithmP256};
683 constexpr size_t kNumLayers = 7;
684 DiceStateForTest states[kNumLayers + 1] = {};
685 DiceInputValues inputs[kNumLayers] = {};
686 for (size_t i = 0; i < kNumLayers; ++i) {
687 char seed[40];
688 pw::string::Format(seed, "code_hash_%zu", i);
689 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
690 pw::string::Format(seed, "authority_hash_%zu", i);
691 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
692 inputs[i].config_type = kDiceConfigTypeInline;
693 pw::string::Format(seed, "inline_config_%zu", i);
694 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
695 inputs[i].mode = kDiceModeNormal;
696 EXPECT_EQ(
697 kDiceResultOk,
698 DiceMainFlow(&context, states[i].cdi_attest, states[i].cdi_seal,
699 &inputs[i], sizeof(states[i + 1].certificate),
700 states[i + 1].certificate, &states[i + 1].certificate_size,
701 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
702 char suffix[40];
703 pw::string::Format(suffix, "full_cert_chain_%zu", i);
704 DumpState(CertificateType_Cbor, KeyType_P256, suffix, states[i + 1]);
705 }
706 // Use a fake self-signed UDS cert as the 'root'.
707 uint8_t root_certificate[dice::test::kTestCertSize];
708 size_t root_certificate_size = 0;
709 dice::test::CreateFakeUdsCertificate(
710 &context, states[0].cdi_attest, CertificateType_Cbor, KeyType_P256,
711 root_certificate, &root_certificate_size);
712 EXPECT_TRUE(dice::test::VerifyCertificateChain(
713 CertificateType_Cbor, root_certificate, root_certificate_size, &states[1],
714 kNumLayers, /*is_partial_chain=*/false));
715 }
716
TEST(DiceOpsTest,P384FullCertChain)717 TEST(DiceOpsTest, P384FullCertChain) {
718 DiceContext context{.authority_algorithm = kDiceKeyAlgorithmP384,
719 .subject_algorithm = kDiceKeyAlgorithmP384};
720 constexpr size_t kNumLayers = 7;
721 DiceStateForTest states[kNumLayers + 1] = {};
722 DiceInputValues inputs[kNumLayers] = {};
723 for (size_t i = 0; i < kNumLayers; ++i) {
724 char seed[40];
725 pw::string::Format(seed, "code_hash_%zu", i);
726 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
727 pw::string::Format(seed, "authority_hash_%zu", i);
728 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
729 inputs[i].config_type = kDiceConfigTypeInline;
730 pw::string::Format(seed, "inline_config_%zu", i);
731 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
732 inputs[i].mode = kDiceModeNormal;
733 EXPECT_EQ(
734 kDiceResultOk,
735 DiceMainFlow(&context, states[i].cdi_attest, states[i].cdi_seal,
736 &inputs[i], sizeof(states[i + 1].certificate),
737 states[i + 1].certificate, &states[i + 1].certificate_size,
738 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
739 char suffix[40];
740 pw::string::Format(suffix, "full_cert_chain_%zu", i);
741 DumpState(CertificateType_Cbor, KeyType_P384, suffix, states[i + 1]);
742 }
743 // Use a fake self-signed UDS cert as the 'root'.
744 uint8_t root_certificate[dice::test::kTestCertSize];
745 size_t root_certificate_size = 0;
746 dice::test::CreateFakeUdsCertificate(
747 &context, states[0].cdi_attest, CertificateType_Cbor, KeyType_P384,
748 root_certificate, &root_certificate_size);
749 EXPECT_TRUE(dice::test::VerifyCertificateChain(
750 CertificateType_Cbor, root_certificate, root_certificate_size, &states[1],
751 kNumLayers, /*is_partial_chain=*/false));
752 }
753
754 } // namespace
755