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