xref: /aosp_15_r20/external/open-dice/src/cbor_cert_op_test.cc (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
1 // Copyright 2020 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/dice.h"
22 #include "dice/known_test_values.h"
23 #include "dice/ops.h"
24 #include "dice/ops/trait/cose.h"
25 #include "dice/test_framework.h"
26 #include "dice/test_utils.h"
27 #include "dice/utils.h"
28 #include "pw_string/format.h"
29 
30 namespace {
31 
32 using dice::test::CertificateType_Cbor;
33 using dice::test::DeriveFakeInputValue;
34 using dice::test::DiceStateForTest;
35 using dice::test::KeyType_Ed25519;
36 using dice::test::VerifyCoseSign1;
37 
TEST(DiceOpsTest,KnownAnswerZeroInput)38 TEST(DiceOpsTest, KnownAnswerZeroInput) {
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(kDiceResultOk, result);
47   DumpState(CertificateType_Cbor, KeyType_Ed25519, "zero_input", next_state);
48   // Both CDI values and the certificate should be deterministic.
49   EXPECT_EQ(0, memcmp(next_state.cdi_attest,
50                       dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
51   EXPECT_EQ(0, memcmp(next_state.cdi_seal,
52                       dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
53   ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput),
54             next_state.certificate_size);
55   EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_ZeroInput,
56                       next_state.certificate, next_state.certificate_size));
57 }
58 
TEST(DiceOpsTest,KnownAnswerZeroInputMeasurement)59 TEST(DiceOpsTest, KnownAnswerZeroInputMeasurement) {
60   DiceStateForTest current_state = {};
61   DiceStateForTest next_state = {};
62   DiceInputValues input_values = {};
63   ASSERT_LE(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput) / 2,
64             sizeof(next_state.certificate));
65   DiceResult result = DiceMainFlow(
66       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
67       sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput) / 2,
68       next_state.certificate, &next_state.certificate_size,
69       next_state.cdi_attest, next_state.cdi_seal);
70   EXPECT_EQ(kDiceResultBufferTooSmall, result);
71   EXPECT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput),
72             next_state.certificate_size);
73 }
74 
TEST(DiceOpsTest,KnownAnswerHashOnlyInput)75 TEST(DiceOpsTest, KnownAnswerHashOnlyInput) {
76   DiceStateForTest current_state = {};
77   DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
78   DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
79   DiceStateForTest next_state = {};
80   DiceInputValues input_values = {};
81   DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
82   DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
83                        input_values.authority_hash);
84   input_values.config_type = kDiceConfigTypeInline;
85   DeriveFakeInputValue("inline_config", DICE_INLINE_CONFIG_SIZE,
86                        input_values.config_value);
87 
88   DiceResult result = DiceMainFlow(
89       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
90       sizeof(next_state.certificate), next_state.certificate,
91       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
92   EXPECT_EQ(kDiceResultOk, result);
93   DumpState(CertificateType_Cbor, KeyType_Ed25519, "hash_only_input",
94             next_state);
95   // Both CDI values and the certificate should be deterministic.
96   EXPECT_EQ(
97       0, memcmp(next_state.cdi_attest,
98                 dice::test::kExpectedCdiAttest_HashOnlyInput, DICE_CDI_SIZE));
99   EXPECT_EQ(
100       0, memcmp(next_state.cdi_seal, dice::test::kExpectedCdiSeal_HashOnlyInput,
101                 DICE_CDI_SIZE));
102   ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_HashOnlyInput),
103             next_state.certificate_size);
104   EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_HashOnlyInput,
105                       next_state.certificate, next_state.certificate_size));
106 }
107 
TEST(DiceOpsTest,KnownAnswerDescriptorInput)108 TEST(DiceOpsTest, KnownAnswerDescriptorInput) {
109   DiceStateForTest current_state = {};
110   DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
111   DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
112 
113   DiceStateForTest next_state = {};
114 
115   DiceInputValues input_values = {};
116   DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
117   uint8_t code_descriptor[100];
118   DeriveFakeInputValue("code_desc", sizeof(code_descriptor), code_descriptor);
119   input_values.code_descriptor = code_descriptor;
120   input_values.code_descriptor_size = sizeof(code_descriptor);
121 
122   uint8_t config_descriptor[40];
123   DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
124                        config_descriptor);
125   input_values.config_descriptor = config_descriptor;
126   input_values.config_descriptor_size = sizeof(config_descriptor);
127   input_values.config_type = kDiceConfigTypeDescriptor;
128 
129   DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
130                        input_values.authority_hash);
131   uint8_t authority_descriptor[65];
132   DeriveFakeInputValue("authority_desc", sizeof(authority_descriptor),
133                        authority_descriptor);
134   input_values.authority_descriptor = authority_descriptor;
135   input_values.authority_descriptor_size = sizeof(authority_descriptor);
136 
137   DiceResult result = DiceMainFlow(
138       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
139       sizeof(next_state.certificate), next_state.certificate,
140       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
141   EXPECT_EQ(kDiceResultOk, result);
142   DumpState(CertificateType_Cbor, KeyType_Ed25519, "descriptor_input",
143             next_state);
144   // Both CDI values and the certificate should be deterministic.
145   EXPECT_EQ(
146       0, memcmp(next_state.cdi_attest,
147                 dice::test::kExpectedCdiAttest_DescriptorInput, DICE_CDI_SIZE));
148   EXPECT_EQ(
149       0, memcmp(next_state.cdi_seal,
150                 dice::test::kExpectedCdiSeal_DescriptorInput, DICE_CDI_SIZE));
151   ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_DescriptorInput),
152             next_state.certificate_size);
153   EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_DescriptorInput,
154                       next_state.certificate, next_state.certificate_size));
155 }
156 
TEST(DiceOpsTest,NonZeroMode)157 TEST(DiceOpsTest, NonZeroMode) {
158   constexpr size_t kModeOffsetInCert = 315;
159   DiceStateForTest current_state = {};
160   DiceStateForTest next_state = {};
161   DiceInputValues input_values = {};
162   input_values.mode = kDiceModeDebug;
163   DiceResult result = DiceMainFlow(
164       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
165       sizeof(next_state.certificate), next_state.certificate,
166       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
167   EXPECT_EQ(kDiceResultOk, result);
168   EXPECT_EQ(kDiceModeDebug, next_state.certificate[kModeOffsetInCert]);
169 }
170 
TEST(DiceOpsTest,LargeInputs)171 TEST(DiceOpsTest, LargeInputs) {
172   constexpr uint8_t kBigBuffer[1024 * 1024] = {};
173   DiceStateForTest current_state = {};
174   DiceStateForTest next_state = {};
175   DiceInputValues input_values = {};
176   input_values.code_descriptor = kBigBuffer;
177   input_values.code_descriptor_size = sizeof(kBigBuffer);
178   DiceResult result = DiceMainFlow(
179       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
180       sizeof(next_state.certificate), next_state.certificate,
181       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
182   EXPECT_EQ(kDiceResultBufferTooSmall, result);
183 }
184 
TEST(DiceOpsTest,LargeDescriptor)185 TEST(DiceOpsTest, LargeDescriptor) {
186   DiceStateForTest current_state = {};
187   DiceStateForTest next_state = {};
188   DiceInputValues input_values = {};
189 
190   uint8_t config_descriptor[10 * 1000];
191   DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
192                        config_descriptor);
193   input_values.config_descriptor = config_descriptor;
194   input_values.config_descriptor_size = sizeof(config_descriptor);
195   input_values.config_type = kDiceConfigTypeDescriptor;
196 
197   uint8_t next_certificate[20 * 1000];
198   size_t next_certificate_size = 0;
199   size_t buffer_size = 0;
200 
201   DiceResult result = DiceMainFlow(
202       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
203       buffer_size, next_certificate, &next_certificate_size,
204       next_state.cdi_attest, next_state.cdi_seal);
205   EXPECT_EQ(kDiceResultBufferTooSmall, result);
206 
207   // If this fails, the test is wrong, and we need to make next_certificate
208   // bigger.
209   ASSERT_LE(next_certificate_size, sizeof(next_certificate));
210 
211   buffer_size = next_certificate_size - 1;
212   result = DiceMainFlow(NULL, current_state.cdi_attest, current_state.cdi_seal,
213                         &input_values, buffer_size, next_certificate,
214                         &next_certificate_size, next_state.cdi_attest,
215                         next_state.cdi_seal);
216   EXPECT_EQ(kDiceResultBufferTooSmall, result);
217 
218   buffer_size = next_certificate_size;
219   result = DiceMainFlow(NULL, current_state.cdi_attest, current_state.cdi_seal,
220                         &input_values, buffer_size, next_certificate,
221                         &next_certificate_size, next_state.cdi_attest,
222                         next_state.cdi_seal);
223   EXPECT_EQ(kDiceResultOk, result);
224 }
225 
TEST(DiceOpsTest,InvalidConfigType)226 TEST(DiceOpsTest, InvalidConfigType) {
227   DiceStateForTest current_state = {};
228   DiceStateForTest next_state = {};
229   DiceInputValues input_values = {};
230   input_values.config_type = (DiceConfigType)55;
231   DiceResult result = DiceMainFlow(
232       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
233       sizeof(next_state.certificate), next_state.certificate,
234       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
235   EXPECT_EQ(kDiceResultInvalidInput, result);
236 }
237 
TEST(DiceOpsTest,CoseSignAndEncodeSign1)238 TEST(DiceOpsTest, CoseSignAndEncodeSign1) {
239   DiceStateForTest current_state = {};
240   DiceStateForTest next_state = {};
241   DiceInputValues input_values = {};
242   DiceResult result = DiceMainFlow(
243       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
244       sizeof(next_state.certificate), next_state.certificate,
245       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
246   ASSERT_EQ(kDiceResultOk, result);
247 
248   uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE];
249   result = DiceDeriveCdiPrivateKeySeed(NULL, next_state.cdi_attest,
250                                        private_key_seed);
251   ASSERT_EQ(kDiceResultOk, result);
252 
253   uint8_t private_key[DICE_PRIVATE_KEY_BUFFER_SIZE];
254   uint8_t public_key[DICE_PUBLIC_KEY_BUFFER_SIZE];
255   result = DiceKeypairFromSeed(NULL, kDicePrincipalAuthority, private_key_seed,
256                                public_key, private_key);
257   ASSERT_EQ(kDiceResultOk, result);
258 
259   uint8_t encoded_public_key[DICE_PUBLIC_KEY_BUFFER_SIZE + 32];
260   size_t encoded_public_key_size = 0;
261   result = DiceCoseEncodePublicKey(
262       NULL, kDicePrincipalAuthority, public_key, sizeof(encoded_public_key),
263       encoded_public_key, &encoded_public_key_size);
264   ASSERT_EQ(kDiceResultOk, result);
265 
266   uint8_t payload[500];
267   DeriveFakeInputValue("payload", sizeof(payload), payload);
268 
269   uint8_t aad[100];
270   DeriveFakeInputValue("aad", sizeof(aad), aad);
271 
272   uint8_t sign1[1000];
273   size_t sign1_size;
274   result = DiceCoseSignAndEncodeSign1(NULL, payload, sizeof(payload), aad,
275                                       sizeof(aad), private_key, sizeof(sign1),
276                                       sign1, &sign1_size);
277   ASSERT_EQ(kDiceResultOk, result);
278 
279   EXPECT_TRUE(VerifyCoseSign1(sign1, sign1_size, aad, sizeof(aad),
280                               encoded_public_key, encoded_public_key_size,
281                               payload, sizeof(payload)));
282 }
283 
TEST(DiceOpsTest,PartialCertChain)284 TEST(DiceOpsTest, PartialCertChain) {
285   constexpr size_t kNumLayers = 7;
286   DiceStateForTest states[kNumLayers + 1] = {};
287   DiceInputValues inputs[kNumLayers] = {};
288   for (size_t i = 0; i < kNumLayers; ++i) {
289     char seed[40];
290     pw::string::Format(seed, "code_hash_%zu", i);
291     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
292     pw::string::Format(seed, "authority_hash_%zu", i);
293     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
294     inputs[i].config_type = kDiceConfigTypeInline;
295     pw::string::Format(seed, "inline_config_%zu", i);
296     DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
297     inputs[i].mode = kDiceModeNormal;
298     EXPECT_EQ(
299         kDiceResultOk,
300         DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
301                      &inputs[i], sizeof(states[i + 1].certificate),
302                      states[i + 1].certificate, &states[i + 1].certificate_size,
303                      states[i + 1].cdi_attest, states[i + 1].cdi_seal));
304     char suffix[40];
305     pw::string::Format(suffix, "part_cert_chain_%zu", i);
306     DumpState(CertificateType_Cbor, KeyType_Ed25519, suffix, states[i + 1]);
307   }
308   // Use the first derived CDI cert as the 'root' of partial chain.
309   EXPECT_TRUE(dice::test::VerifyCertificateChain(
310       CertificateType_Cbor, states[1].certificate, states[1].certificate_size,
311       &states[2], kNumLayers - 1, /*is_partial_chain=*/true));
312 }
313 
TEST(DiceOpsTest,FullCertChain)314 TEST(DiceOpsTest, FullCertChain) {
315   constexpr size_t kNumLayers = 7;
316   DiceStateForTest states[kNumLayers + 1] = {};
317   DiceInputValues inputs[kNumLayers] = {};
318   for (size_t i = 0; i < kNumLayers; ++i) {
319     char seed[40];
320     pw::string::Format(seed, "code_hash_%zu", i);
321     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
322     pw::string::Format(seed, "authority_hash_%zu", i);
323     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
324     inputs[i].config_type = kDiceConfigTypeInline;
325     pw::string::Format(seed, "inline_config_%zu", i);
326     DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
327     inputs[i].mode = kDiceModeNormal;
328     EXPECT_EQ(
329         kDiceResultOk,
330         DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
331                      &inputs[i], sizeof(states[i + 1].certificate),
332                      states[i + 1].certificate, &states[i + 1].certificate_size,
333                      states[i + 1].cdi_attest, states[i + 1].cdi_seal));
334     char suffix[40];
335     pw::string::Format(suffix, "full_cert_chain_%zu", i);
336     DumpState(CertificateType_Cbor, KeyType_Ed25519, suffix, states[i + 1]);
337   }
338   // Use a fake self-signed UDS cert as the 'root'.
339   uint8_t root_certificate[dice::test::kTestCertSize];
340   size_t root_certificate_size = 0;
341   dice::test::CreateFakeUdsCertificate(
342       NULL, states[0].cdi_attest, CertificateType_Cbor, KeyType_Ed25519,
343       root_certificate, &root_certificate_size);
344   EXPECT_TRUE(dice::test::VerifyCertificateChain(
345       CertificateType_Cbor, root_certificate, root_certificate_size, &states[1],
346       kNumLayers, /*is_partial_chain=*/false));
347 }
348 
349 }  // namespace
350