xref: /aosp_15_r20/external/open-dice/src/template_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/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_Cbor;
31 using dice::test::DeriveFakeInputValue;
32 using dice::test::DiceStateForTest;
33 using dice::test::KeyType_Ed25519;
34 
TEST(DiceOpsTest,KnownAnswerZeroInput)35 TEST(DiceOpsTest, KnownAnswerZeroInput) {
36   DiceStateForTest current_state = {};
37   DiceStateForTest next_state = {};
38   DiceInputValues input_values = {};
39   DiceResult result = DiceMainFlow(
40       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
41       sizeof(next_state.certificate), next_state.certificate,
42       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
43   EXPECT_EQ(kDiceResultOk, result);
44   // Both CDI values and the certificate should be deterministic.
45   EXPECT_EQ(0, memcmp(next_state.cdi_attest,
46                       dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
47   EXPECT_EQ(0, memcmp(next_state.cdi_seal,
48                       dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
49   ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput),
50             next_state.certificate_size);
51   EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_ZeroInput,
52                       next_state.certificate, next_state.certificate_size));
53 }
54 
TEST(DiceOpsTest,KnownAnswerHashOnlyInput)55 TEST(DiceOpsTest, KnownAnswerHashOnlyInput) {
56   DiceStateForTest current_state = {};
57   DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
58   DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
59   DiceStateForTest next_state = {};
60   DiceInputValues input_values = {};
61   DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
62   DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
63                        input_values.authority_hash);
64   input_values.config_type = kDiceConfigTypeInline;
65   DeriveFakeInputValue("inline_config", DICE_INLINE_CONFIG_SIZE,
66                        input_values.config_value);
67 
68   DiceResult result = DiceMainFlow(
69       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
70       sizeof(next_state.certificate), next_state.certificate,
71       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
72   EXPECT_EQ(kDiceResultOk, result);
73   // Both CDI values and the certificate should be deterministic.
74   EXPECT_EQ(
75       0, memcmp(next_state.cdi_attest,
76                 dice::test::kExpectedCdiAttest_HashOnlyInput, DICE_CDI_SIZE));
77   EXPECT_EQ(
78       0, memcmp(next_state.cdi_seal, dice::test::kExpectedCdiSeal_HashOnlyInput,
79                 DICE_CDI_SIZE));
80   ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_HashOnlyInput),
81             next_state.certificate_size);
82   EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_HashOnlyInput,
83                       next_state.certificate, next_state.certificate_size));
84 }
85 
TEST(DiceOpsTest,WithCodeDescriptor)86 TEST(DiceOpsTest, WithCodeDescriptor) {
87   DiceStateForTest current_state = {};
88   DiceStateForTest next_state = {};
89   DiceInputValues input_values = {};
90   uint8_t descriptor[] = {0, 1, 2, 3};
91   input_values.code_descriptor = descriptor;
92   input_values.code_descriptor_size = sizeof(descriptor);
93   DiceResult result = DiceMainFlow(
94       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
95       sizeof(next_state.certificate), next_state.certificate,
96       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
97   EXPECT_EQ(kDiceResultInvalidInput, result);
98 }
99 
TEST(DiceOpsTest,WithConfigDescriptor)100 TEST(DiceOpsTest, WithConfigDescriptor) {
101   DiceStateForTest current_state = {};
102   DiceStateForTest next_state = {};
103   DiceInputValues input_values = {};
104   uint8_t descriptor[] = {0, 1, 2, 3};
105   input_values.config_descriptor = descriptor;
106   input_values.config_descriptor_size = sizeof(descriptor);
107   input_values.config_type = kDiceConfigTypeDescriptor;
108   DiceResult result = DiceMainFlow(
109       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
110       sizeof(next_state.certificate), next_state.certificate,
111       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
112   EXPECT_EQ(kDiceResultInvalidInput, result);
113 }
114 
TEST(DiceOpsTest,WithAuthorityDescriptor)115 TEST(DiceOpsTest, WithAuthorityDescriptor) {
116   DiceStateForTest current_state = {};
117   DiceStateForTest next_state = {};
118   DiceInputValues input_values = {};
119   uint8_t descriptor[] = {0, 1, 2, 3};
120   input_values.authority_descriptor = descriptor;
121   input_values.authority_descriptor_size = sizeof(descriptor);
122   DiceResult result = DiceMainFlow(
123       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
124       sizeof(next_state.certificate), next_state.certificate,
125       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
126   EXPECT_EQ(kDiceResultInvalidInput, result);
127 }
128 
TEST(DiceOpsTest,NonZeroMode)129 TEST(DiceOpsTest, NonZeroMode) {
130   constexpr size_t kModeOffsetInCert = 315;
131   DiceStateForTest current_state = {};
132   DiceStateForTest next_state = {};
133   DiceInputValues input_values = {};
134   input_values.mode = kDiceModeDebug;
135   DiceResult result = DiceMainFlow(
136       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
137       sizeof(next_state.certificate), next_state.certificate,
138       &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
139   EXPECT_EQ(kDiceResultOk, result);
140   EXPECT_EQ(kDiceModeDebug, next_state.certificate[kModeOffsetInCert]);
141 }
142 
TEST(DiceOpsTest,SmallCertBuffer)143 TEST(DiceOpsTest, SmallCertBuffer) {
144   DiceStateForTest current_state = {};
145   DiceStateForTest next_state = {};
146   DiceInputValues input_values = {};
147   DiceResult result = DiceMainFlow(
148       NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
149       12 /*too small*/, next_state.certificate, &next_state.certificate_size,
150       next_state.cdi_attest, next_state.cdi_seal);
151   EXPECT_EQ(kDiceResultBufferTooSmall, result);
152   EXPECT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_ZeroInput),
153             next_state.certificate_size);
154 }
155 
TEST(DiceOpsTest,InvalidConfigType)156 TEST(DiceOpsTest, InvalidConfigType) {
157   DiceStateForTest current_state = {};
158   DiceStateForTest next_state = {};
159   DiceInputValues input_values = {};
160   input_values.config_type = (DiceConfigType)55;
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(kDiceResultInvalidInput, result);
166 }
167 
TEST(DiceOpsTest,PartialCertChain)168 TEST(DiceOpsTest, PartialCertChain) {
169   constexpr size_t kNumLayers = 7;
170   DiceStateForTest states[kNumLayers + 1] = {};
171   DiceInputValues inputs[kNumLayers] = {};
172   for (size_t i = 0; i < kNumLayers; ++i) {
173     char seed[40];
174     pw::string::Format(seed, "code_hash_%zu", i);
175     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
176     pw::string::Format(seed, "authority_hash_%zu", i);
177     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
178     inputs[i].config_type = kDiceConfigTypeInline;
179     pw::string::Format(seed, "inline_config_%zu", i);
180     DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
181     inputs[i].mode = kDiceModeNormal;
182     EXPECT_EQ(
183         kDiceResultOk,
184         DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
185                      &inputs[i], sizeof(states[i + 1].certificate),
186                      states[i + 1].certificate, &states[i + 1].certificate_size,
187                      states[i + 1].cdi_attest, states[i + 1].cdi_seal));
188     char suffix[40];
189     pw::string::Format(suffix, "part_cert_chain_%zu", i);
190   }
191   // Use the first derived CDI cert as the 'root' of partial chain.
192   EXPECT_TRUE(dice::test::VerifyCertificateChain(
193       CertificateType_Cbor, states[1].certificate, states[1].certificate_size,
194       &states[2], kNumLayers - 1, /*is_partial_chain=*/true));
195 }
196 
TEST(DiceOpsTest,FullCertChain)197 TEST(DiceOpsTest, FullCertChain) {
198   constexpr size_t kNumLayers = 7;
199   DiceStateForTest states[kNumLayers + 1] = {};
200   DiceInputValues inputs[kNumLayers] = {};
201   for (size_t i = 0; i < kNumLayers; ++i) {
202     char seed[40];
203     pw::string::Format(seed, "code_hash_%zu", i);
204     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
205     pw::string::Format(seed, "authority_hash_%zu", i);
206     DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
207     inputs[i].config_type = kDiceConfigTypeInline;
208     pw::string::Format(seed, "inline_config_%zu", i);
209     DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
210     inputs[i].mode = kDiceModeNormal;
211     EXPECT_EQ(
212         kDiceResultOk,
213         DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
214                      &inputs[i], sizeof(states[i + 1].certificate),
215                      states[i + 1].certificate, &states[i + 1].certificate_size,
216                      states[i + 1].cdi_attest, states[i + 1].cdi_seal));
217     char suffix[40];
218     pw::string::Format(suffix, "full_cert_chain_%zu", i);
219   }
220   // Use a fake self-signed UDS cert as the 'root'.
221   uint8_t root_certificate[dice::test::kTestCertSize];
222   size_t root_certificate_size = 0;
223   dice::test::CreateFakeUdsCertificate(
224       NULL, states[0].cdi_attest, CertificateType_Cbor, KeyType_Ed25519,
225       root_certificate, &root_certificate_size);
226   EXPECT_TRUE(dice::test::VerifyCertificateChain(
227       CertificateType_Cbor, root_certificate, root_certificate_size, &states[1],
228       kNumLayers, /*is_partial_chain=*/false));
229 }
230 
231 }  // namespace
232