xref: /aosp_15_r20/external/open-dice/src/cbor_p384_cert_op_test.cc (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
1 // Copyright 2022 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_P384;
35 
TEST(DiceOpsTest,KnownAnswerZeroInput)36 TEST(DiceOpsTest, KnownAnswerZeroInput) {
37   DiceStateForTest current_state = {};
38   DiceStateForTest next_state = {};
39   DiceInputValues input_values = {};
40   DiceResult result = DiceMainFlow(
41       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
42       sizeof(next_state.certificate), next_state.certificate,
43       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
44   EXPECT_EQ(kDiceResultOk, result);
45   DumpState(CertificateType_Cbor, KeyType_P384, "zero_input", next_state);
46   // The CDI values should be deterministic.
47   ASSERT_EQ(sizeof(next_state.cdi_attest),
48             sizeof(dice::test::kExpectedCdiAttest_ZeroInput));
49   EXPECT_EQ(0, memcmp(next_state.cdi_attest,
50                       dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
51   ASSERT_EQ(sizeof(next_state.cdi_seal),
52             sizeof(dice::test::kExpectedCdiSeal_ZeroInput));
53   EXPECT_EQ(0, memcmp(next_state.cdi_seal,
54                       dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
55   ASSERT_EQ(sizeof(dice::test::kExpectedCborP384Cert_ZeroInput),
56             next_state.certificate_size);
57   // Comparing everything except for the signature, since ECDSA signatures are
58   // not deterministic
59   EXPECT_EQ(0,
60             memcmp(dice::test::kExpectedCborP384Cert_ZeroInput,
61                    next_state.certificate,
62                    next_state.certificate_size - DICE_SIGNATURE_BUFFER_SIZE));
63 }
64 
TEST(DiceOpsTest,KnownAnswerHashOnlyInput)65 TEST(DiceOpsTest, KnownAnswerHashOnlyInput) {
66   DiceStateForTest current_state = {};
67   DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
68   DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
69   DiceStateForTest next_state = {};
70   DiceInputValues input_values = {};
71   DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
72   DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
73                        input_values.authority_hash);
74   input_values.config_type = kDiceConfigTypeInline;
75   DeriveFakeInputValue("inline_config", DICE_INLINE_CONFIG_SIZE,
76                        input_values.config_value);
77 
78   DiceResult result = DiceMainFlow(
79       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
80       sizeof(next_state.certificate), next_state.certificate,
81       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
82   EXPECT_EQ(kDiceResultOk, result);
83   DumpState(CertificateType_Cbor, KeyType_P384, "hash_only_input", next_state);
84   ASSERT_EQ(sizeof(next_state.cdi_attest),
85             sizeof(dice::test::kExpectedCdiAttest_HashOnlyInput));
86   EXPECT_EQ(
87       0, memcmp(next_state.cdi_attest,
88                 dice::test::kExpectedCdiAttest_HashOnlyInput, DICE_CDI_SIZE));
89   ASSERT_EQ(sizeof(next_state.cdi_seal),
90             sizeof(dice::test::kExpectedCdiSeal_HashOnlyInput));
91   EXPECT_EQ(
92       0, memcmp(next_state.cdi_seal, dice::test::kExpectedCdiSeal_HashOnlyInput,
93                 DICE_CDI_SIZE));
94   ASSERT_EQ(sizeof(dice::test::kExpectedCborP384Cert_HashOnlyInput),
95             next_state.certificate_size);
96   EXPECT_EQ(0,
97             memcmp(dice::test::kExpectedCborP384Cert_HashOnlyInput,
98                    next_state.certificate,
99                    next_state.certificate_size - DICE_SIGNATURE_BUFFER_SIZE));
100 }
101 
TEST(DiceOpsTest,KnownAnswerDescriptorInput)102 TEST(DiceOpsTest, KnownAnswerDescriptorInput) {
103   DiceStateForTest current_state = {};
104   DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
105   DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
106 
107   DiceStateForTest next_state = {};
108 
109   DiceInputValues input_values = {};
110   DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
111   uint8_t code_descriptor[100];
112   DeriveFakeInputValue("code_desc", sizeof(code_descriptor), code_descriptor);
113   input_values.code_descriptor = code_descriptor;
114   input_values.code_descriptor_size = sizeof(code_descriptor);
115 
116   uint8_t config_descriptor[40];
117   DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
118                        config_descriptor);
119   input_values.config_descriptor = config_descriptor;
120   input_values.config_descriptor_size = sizeof(config_descriptor);
121   input_values.config_type = kDiceConfigTypeDescriptor;
122 
123   DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
124                        input_values.authority_hash);
125   uint8_t authority_descriptor[65];
126   DeriveFakeInputValue("authority_desc", sizeof(authority_descriptor),
127                        authority_descriptor);
128   input_values.authority_descriptor = authority_descriptor;
129   input_values.authority_descriptor_size = sizeof(authority_descriptor);
130 
131   DiceResult result = DiceMainFlow(
132       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
133       sizeof(next_state.certificate), next_state.certificate,
134       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
135   EXPECT_EQ(kDiceResultOk, result);
136   DumpState(CertificateType_Cbor, KeyType_P384, "descriptor_input", next_state);
137   // Both CDI values and the certificate should be deterministic.
138   EXPECT_EQ(
139       0, memcmp(next_state.cdi_attest,
140                 dice::test::kExpectedCdiAttest_DescriptorInput, DICE_CDI_SIZE));
141   EXPECT_EQ(
142       0, memcmp(next_state.cdi_seal,
143                 dice::test::kExpectedCdiSeal_DescriptorInput, DICE_CDI_SIZE));
144   ASSERT_EQ(sizeof(dice::test::kExpectedCborP384Cert_DescriptorInput),
145             next_state.certificate_size);
146   EXPECT_EQ(0,
147             memcmp(dice::test::kExpectedCborP384Cert_DescriptorInput,
148                    next_state.certificate,
149                    next_state.certificate_size - DICE_SIGNATURE_BUFFER_SIZE));
150 }
151 
TEST(DiceOpsTest,NonZeroMode)152 TEST(DiceOpsTest, NonZeroMode) {
153   constexpr size_t kModeOffsetInCert = 316;
154   DiceStateForTest current_state = {};
155   DiceStateForTest next_state = {};
156   DiceInputValues input_values = {};
157   input_values.mode = kDiceModeDebug;
158   DiceResult result = DiceMainFlow(
159       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
160       sizeof(next_state.certificate), next_state.certificate,
161       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
162   EXPECT_EQ(kDiceResultOk, result);
163   EXPECT_EQ(kDiceModeDebug, next_state.certificate[kModeOffsetInCert]);
164 }
165 
TEST(DiceOpsTest,LargeInputs)166 TEST(DiceOpsTest, LargeInputs) {
167   constexpr uint8_t kBigBuffer[1024 * 1024] = {};
168   DiceStateForTest current_state = {};
169   DiceStateForTest next_state = {};
170   DiceInputValues input_values = {};
171   input_values.code_descriptor = kBigBuffer;
172   input_values.code_descriptor_size = sizeof(kBigBuffer);
173   DiceResult result = DiceMainFlow(
174       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
175       sizeof(next_state.certificate), next_state.certificate,
176       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
177   EXPECT_EQ(kDiceResultBufferTooSmall, result);
178 }
179 
TEST(DiceOpsTest,InvalidConfigType)180 TEST(DiceOpsTest, InvalidConfigType) {
181   DiceStateForTest current_state = {};
182   DiceStateForTest next_state = {};
183   DiceInputValues input_values = {};
184   input_values.config_type = (DiceConfigType)55;
185   DiceResult result = DiceMainFlow(
186       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
187       sizeof(next_state.certificate), next_state.certificate,
188       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
189   EXPECT_EQ(kDiceResultInvalidInput, result);
190 }
191 
TEST(DiceOpsTest,PartialCertChain)192 TEST(DiceOpsTest, PartialCertChain) {
193   constexpr size_t kNumLayers = 7;
194   DiceStateForTest states[kNumLayers + 1] = {};
195   DiceInputValues inputs[kNumLayers] = {};
196   for (size_t i = 0; i < kNumLayers; ++i) {
197     char seed[40];
198     pw::string::Format(seed, "code_hash_%zu", i);
199     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
200     pw::string::Format(seed, "authority_hash_%zu", i);
201     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
202     inputs[i].config_type = kDiceConfigTypeInline;
203     pw::string::Format(seed, "inline_config_%zu", i);
204     DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
205     inputs[i].mode = kDiceModeNormal;
206     EXPECT_EQ(
207         kDiceResultOk,
208         DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
209                      &inputs[i], sizeof(states[i + 1].certificate),
210                      states[i + 1].certificate, &states[i + 1].certificate_size,
211                      states[i + 1].cdi_attest, states[i + 1].cdi_seal));
212     char suffix[40];
213     pw::string::Format(suffix, "part_cert_chain_%zu", i);
214     DumpState(CertificateType_Cbor, KeyType_P384, suffix, states[i + 1]);
215   }
216   // Use the first derived CDI cert as the 'root' of partial chain.
217   EXPECT_TRUE(dice::test::VerifyCertificateChain(
218       CertificateType_Cbor, states[1].certificate, states[1].certificate_size,
219       &states[2], kNumLayers - 1, /*is_partial_chain=*/true));
220 }
221 
TEST(DiceOpsTest,FullCertChain)222 TEST(DiceOpsTest, FullCertChain) {
223   constexpr size_t kNumLayers = 7;
224   DiceStateForTest states[kNumLayers + 1] = {};
225   DiceInputValues inputs[kNumLayers] = {};
226   for (size_t i = 0; i < kNumLayers; ++i) {
227     char seed[40];
228     pw::string::Format(seed, "code_hash_%zu", i);
229     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
230     pw::string::Format(seed, "authority_hash_%zu", i);
231     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
232     inputs[i].config_type = kDiceConfigTypeInline;
233     pw::string::Format(seed, "inline_config_%zu", i);
234     DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
235     inputs[i].mode = kDiceModeNormal;
236     EXPECT_EQ(
237         kDiceResultOk,
238         DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
239                      &inputs[i], sizeof(states[i + 1].certificate),
240                      states[i + 1].certificate, &states[i + 1].certificate_size,
241                      states[i + 1].cdi_attest, states[i + 1].cdi_seal));
242     char suffix[40];
243     pw::string::Format(suffix, "full_cert_chain_%zu", i);
244     DumpState(CertificateType_Cbor, KeyType_P384, suffix, states[i + 1]);
245   }
246   // Use a fake self-signed UDS cert as the 'root'.
247   uint8_t root_certificate[dice::test::kTestCertSize];
248   size_t root_certificate_size = 0;
249   dice::test::CreateFakeUdsCertificate(
250       NULL, states[0].cdi_attest, CertificateType_Cbor, KeyType_P384,
251       root_certificate, &root_certificate_size);
252   EXPECT_TRUE(dice::test::VerifyCertificateChain(
253       CertificateType_Cbor, root_certificate, root_certificate_size, &states[1],
254       kNumLayers, /*is_partial_chain=*/false));
255 }
256 
257 }  // namespace
258