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