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