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