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