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/ops.h"
24 #include "dice/ops/trait/cose.h"
25 #include "dice/test_framework.h"
26 #include "dice/test_utils.h"
27 #include "dice/utils.h"
28 #include "pw_string/format.h"
29
30 namespace {
31
32 using dice::test::CertificateType_Cbor;
33 using dice::test::DeriveFakeInputValue;
34 using dice::test::DiceStateForTest;
35 using dice::test::KeyType_Ed25519;
36 using dice::test::VerifyCoseSign1;
37
TEST(DiceOpsTest,KnownAnswerZeroInput)38 TEST(DiceOpsTest, KnownAnswerZeroInput) {
39 DiceStateForTest current_state = {};
40 DiceStateForTest next_state = {};
41 DiceInputValues input_values = {};
42 DiceResult result = DiceMainFlow(
43 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
44 sizeof(next_state.certificate), next_state.certificate,
45 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
46 EXPECT_EQ(kDiceResultOk, result);
47 DumpState(CertificateType_Cbor, KeyType_Ed25519, "android_zero_input",
48 next_state);
49 // Both CDI values and the certificate should be deterministic.
50 EXPECT_EQ(0, memcmp(next_state.cdi_attest,
51 dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
52 EXPECT_EQ(0, memcmp(next_state.cdi_seal,
53 dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
54 ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_AndroidZeroInput),
55 next_state.certificate_size);
56 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_AndroidZeroInput,
57 next_state.certificate, next_state.certificate_size));
58 }
59
TEST(DiceOpsTest,KnownAnswerZeroInputMeasurement)60 TEST(DiceOpsTest, KnownAnswerZeroInputMeasurement) {
61 DiceStateForTest current_state = {};
62 DiceStateForTest next_state = {};
63 DiceInputValues input_values = {};
64 ASSERT_LE(sizeof(dice::test::kExpectedCborEd25519Cert_AndroidZeroInput) / 2,
65 sizeof(next_state.certificate));
66 DiceResult result = DiceMainFlow(
67 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
68 sizeof(dice::test::kExpectedCborEd25519Cert_AndroidZeroInput) / 2,
69 next_state.certificate, &next_state.certificate_size,
70 next_state.cdi_attest, next_state.cdi_seal);
71 EXPECT_EQ(kDiceResultBufferTooSmall, result);
72 EXPECT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_AndroidZeroInput),
73 next_state.certificate_size);
74 }
75
TEST(DiceOpsTest,KnownAnswerHashOnlyInput)76 TEST(DiceOpsTest, KnownAnswerHashOnlyInput) {
77 DiceStateForTest current_state = {};
78 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
79 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
80 DiceStateForTest next_state = {};
81 DiceInputValues input_values = {};
82 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
83 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
84 input_values.authority_hash);
85 input_values.config_type = kDiceConfigTypeInline;
86 DeriveFakeInputValue("inline_config", DICE_INLINE_CONFIG_SIZE,
87 input_values.config_value);
88
89 DiceResult result = DiceMainFlow(
90 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
91 sizeof(next_state.certificate), next_state.certificate,
92 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
93 EXPECT_EQ(kDiceResultOk, result);
94 DumpState(CertificateType_Cbor, KeyType_Ed25519, "android_hash_only_input",
95 next_state);
96 // Both CDI values and the certificate should be deterministic.
97 EXPECT_EQ(
98 0, memcmp(next_state.cdi_attest,
99 dice::test::kExpectedCdiAttest_HashOnlyInput, DICE_CDI_SIZE));
100 EXPECT_EQ(
101 0, memcmp(next_state.cdi_seal, dice::test::kExpectedCdiSeal_HashOnlyInput,
102 DICE_CDI_SIZE));
103 ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_AndroidHashOnlyInput),
104 next_state.certificate_size);
105 EXPECT_EQ(0, memcmp(dice::test::kExpectedCborEd25519Cert_AndroidHashOnlyInput,
106 next_state.certificate, next_state.certificate_size));
107 }
108
TEST(DiceOpsTest,KnownAnswerDescriptorInput)109 TEST(DiceOpsTest, KnownAnswerDescriptorInput) {
110 DiceStateForTest current_state = {};
111 DeriveFakeInputValue("cdi_attest", DICE_CDI_SIZE, current_state.cdi_attest);
112 DeriveFakeInputValue("cdi_seal", DICE_CDI_SIZE, current_state.cdi_seal);
113
114 DiceStateForTest next_state = {};
115
116 DiceInputValues input_values = {};
117 DeriveFakeInputValue("code_hash", DICE_HASH_SIZE, input_values.code_hash);
118 uint8_t code_descriptor[100];
119 DeriveFakeInputValue("code_desc", sizeof(code_descriptor), code_descriptor);
120 input_values.code_descriptor = code_descriptor;
121 input_values.code_descriptor_size = sizeof(code_descriptor);
122
123 uint8_t config_descriptor[40];
124 DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
125 config_descriptor);
126 input_values.config_descriptor = config_descriptor;
127 input_values.config_descriptor_size = sizeof(config_descriptor);
128 input_values.config_type = kDiceConfigTypeDescriptor;
129
130 DeriveFakeInputValue("authority_hash", DICE_HASH_SIZE,
131 input_values.authority_hash);
132 uint8_t authority_descriptor[65];
133 DeriveFakeInputValue("authority_desc", sizeof(authority_descriptor),
134 authority_descriptor);
135 input_values.authority_descriptor = authority_descriptor;
136 input_values.authority_descriptor_size = sizeof(authority_descriptor);
137
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 DumpState(CertificateType_Cbor, KeyType_Ed25519, "android_descriptor_input",
144 next_state);
145 // Both CDI values and the certificate should be deterministic.
146 EXPECT_EQ(
147 0, memcmp(next_state.cdi_attest,
148 dice::test::kExpectedCdiAttest_DescriptorInput, DICE_CDI_SIZE));
149 EXPECT_EQ(
150 0, memcmp(next_state.cdi_seal,
151 dice::test::kExpectedCdiSeal_DescriptorInput, DICE_CDI_SIZE));
152 ASSERT_EQ(sizeof(dice::test::kExpectedCborEd25519Cert_AndroidDescriptorInput),
153 next_state.certificate_size);
154 EXPECT_EQ(0,
155 memcmp(dice::test::kExpectedCborEd25519Cert_AndroidDescriptorInput,
156 next_state.certificate, next_state.certificate_size));
157 }
158
TEST(DiceOpsTest,NonZeroMode)159 TEST(DiceOpsTest, NonZeroMode) {
160 constexpr size_t kModeOffsetInCert = 315;
161 DiceStateForTest current_state = {};
162 DiceStateForTest next_state = {};
163 DiceInputValues input_values = {};
164 input_values.mode = kDiceModeDebug;
165 DiceResult result = DiceMainFlow(
166 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
167 sizeof(next_state.certificate), next_state.certificate,
168 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
169 EXPECT_EQ(kDiceResultOk, result);
170 EXPECT_EQ(kDiceModeDebug, next_state.certificate[kModeOffsetInCert]);
171 }
172
TEST(DiceOpsTest,LargeInputs)173 TEST(DiceOpsTest, LargeInputs) {
174 constexpr uint8_t kBigBuffer[1024 * 1024] = {};
175 DiceStateForTest current_state = {};
176 DiceStateForTest next_state = {};
177 DiceInputValues input_values = {};
178 input_values.code_descriptor = kBigBuffer;
179 input_values.code_descriptor_size = sizeof(kBigBuffer);
180 DiceResult result = DiceMainFlow(
181 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
182 sizeof(next_state.certificate), next_state.certificate,
183 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
184 EXPECT_EQ(kDiceResultBufferTooSmall, result);
185 }
186
TEST(DiceOpsTest,LargeDescriptor)187 TEST(DiceOpsTest, LargeDescriptor) {
188 DiceStateForTest current_state = {};
189 DiceStateForTest next_state = {};
190 DiceInputValues input_values = {};
191
192 uint8_t config_descriptor[10 * 1000];
193 DeriveFakeInputValue("config_desc", sizeof(config_descriptor),
194 config_descriptor);
195 input_values.config_descriptor = config_descriptor;
196 input_values.config_descriptor_size = sizeof(config_descriptor);
197 input_values.config_type = kDiceConfigTypeDescriptor;
198
199 uint8_t next_certificate[20 * 1000];
200 size_t next_certificate_size = 0;
201 size_t buffer_size = 0;
202
203 DiceResult result = DiceMainFlow(
204 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
205 buffer_size, next_certificate, &next_certificate_size,
206 next_state.cdi_attest, next_state.cdi_seal);
207 EXPECT_EQ(kDiceResultBufferTooSmall, result);
208
209 // If this fails, the test is wrong, and we need to make next_certificate
210 // bigger.
211 ASSERT_LE(next_certificate_size, sizeof(next_certificate));
212
213 buffer_size = next_certificate_size - 1;
214 result = DiceMainFlow(NULL, current_state.cdi_attest, current_state.cdi_seal,
215 &input_values, buffer_size, next_certificate,
216 &next_certificate_size, next_state.cdi_attest,
217 next_state.cdi_seal);
218 EXPECT_EQ(kDiceResultBufferTooSmall, result);
219
220 buffer_size = next_certificate_size;
221 result = DiceMainFlow(NULL, current_state.cdi_attest, current_state.cdi_seal,
222 &input_values, buffer_size, next_certificate,
223 &next_certificate_size, next_state.cdi_attest,
224 next_state.cdi_seal);
225 EXPECT_EQ(kDiceResultOk, result);
226 }
227
TEST(DiceOpsTest,InvalidConfigType)228 TEST(DiceOpsTest, InvalidConfigType) {
229 DiceStateForTest current_state = {};
230 DiceStateForTest next_state = {};
231 DiceInputValues input_values = {};
232 input_values.config_type = (DiceConfigType)55;
233 DiceResult result = DiceMainFlow(
234 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
235 sizeof(next_state.certificate), next_state.certificate,
236 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
237 EXPECT_EQ(kDiceResultInvalidInput, result);
238 }
239
TEST(DiceOpsTest,CoseSignAndEncodeSign1)240 TEST(DiceOpsTest, CoseSignAndEncodeSign1) {
241 DiceStateForTest current_state = {};
242 DiceStateForTest next_state = {};
243 DiceInputValues input_values = {};
244 DiceResult result = DiceMainFlow(
245 NULL, current_state.cdi_attest, current_state.cdi_seal, &input_values,
246 sizeof(next_state.certificate), next_state.certificate,
247 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
248 ASSERT_EQ(kDiceResultOk, result);
249
250 uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE];
251 result = DiceDeriveCdiPrivateKeySeed(NULL, next_state.cdi_attest,
252 private_key_seed);
253 ASSERT_EQ(kDiceResultOk, result);
254
255 uint8_t private_key[DICE_PRIVATE_KEY_BUFFER_SIZE];
256 uint8_t public_key[DICE_PUBLIC_KEY_BUFFER_SIZE];
257 result = DiceKeypairFromSeed(NULL, kDicePrincipalAuthority, private_key_seed,
258 public_key, private_key);
259 ASSERT_EQ(kDiceResultOk, result);
260
261 uint8_t encoded_public_key[DICE_PUBLIC_KEY_BUFFER_SIZE + 32];
262 size_t encoded_public_key_size = 0;
263 result = DiceCoseEncodePublicKey(
264 NULL, kDicePrincipalAuthority, public_key, sizeof(encoded_public_key),
265 encoded_public_key, &encoded_public_key_size);
266 ASSERT_EQ(kDiceResultOk, result);
267
268 uint8_t payload[500];
269 DeriveFakeInputValue("payload", sizeof(payload), payload);
270
271 uint8_t aad[100];
272 DeriveFakeInputValue("aad", sizeof(aad), aad);
273
274 uint8_t sign1[1000];
275 size_t sign1_size;
276 result = DiceCoseSignAndEncodeSign1(NULL, payload, sizeof(payload), aad,
277 sizeof(aad), private_key, sizeof(sign1),
278 sign1, &sign1_size);
279 ASSERT_EQ(kDiceResultOk, result);
280
281 EXPECT_TRUE(VerifyCoseSign1(sign1, sign1_size, aad, sizeof(aad),
282 encoded_public_key, encoded_public_key_size,
283 payload, sizeof(payload)));
284 }
285
TEST(DiceOpsTest,PartialCertChain)286 TEST(DiceOpsTest, PartialCertChain) {
287 constexpr size_t kNumLayers = 7;
288 DiceStateForTest states[kNumLayers + 1] = {};
289 DiceInputValues inputs[kNumLayers] = {};
290 for (size_t i = 0; i < kNumLayers; ++i) {
291 char seed[40];
292 pw::string::Format(seed, "code_hash_%zu", i);
293 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
294 pw::string::Format(seed, "authority_hash_%zu", i);
295 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
296 inputs[i].config_type = kDiceConfigTypeInline;
297 pw::string::Format(seed, "inline_config_%zu", i);
298 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
299 inputs[i].mode = kDiceModeNormal;
300 EXPECT_EQ(
301 kDiceResultOk,
302 DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
303 &inputs[i], sizeof(states[i + 1].certificate),
304 states[i + 1].certificate, &states[i + 1].certificate_size,
305 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
306 char suffix[40];
307 pw::string::Format(suffix, "part_cert_chain_%zu", i);
308 DumpState(CertificateType_Cbor, KeyType_Ed25519, suffix, states[i + 1]);
309 }
310 // Use the first derived CDI cert as the 'root' of partial chain.
311 EXPECT_TRUE(dice::test::VerifyCertificateChain(
312 CertificateType_Cbor, states[1].certificate, states[1].certificate_size,
313 &states[2], kNumLayers - 1, /*is_partial_chain=*/true));
314 }
315
TEST(DiceOpsTest,FullCertChain)316 TEST(DiceOpsTest, FullCertChain) {
317 constexpr size_t kNumLayers = 7;
318 DiceStateForTest states[kNumLayers + 1] = {};
319 DiceInputValues inputs[kNumLayers] = {};
320 for (size_t i = 0; i < kNumLayers; ++i) {
321 char seed[40];
322 pw::string::Format(seed, "code_hash_%zu", i);
323 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].code_hash);
324 pw::string::Format(seed, "authority_hash_%zu", i);
325 DeriveFakeInputValue(seed, DICE_HASH_SIZE, inputs[i].authority_hash);
326 inputs[i].config_type = kDiceConfigTypeInline;
327 pw::string::Format(seed, "inline_config_%zu", i);
328 DeriveFakeInputValue(seed, DICE_INLINE_CONFIG_SIZE, inputs[i].config_value);
329 inputs[i].mode = kDiceModeNormal;
330 EXPECT_EQ(
331 kDiceResultOk,
332 DiceMainFlow(/*context=*/NULL, states[i].cdi_attest, states[i].cdi_seal,
333 &inputs[i], sizeof(states[i + 1].certificate),
334 states[i + 1].certificate, &states[i + 1].certificate_size,
335 states[i + 1].cdi_attest, states[i + 1].cdi_seal));
336 char suffix[40];
337 pw::string::Format(suffix, "full_cert_chain_%zu", i);
338 DumpState(CertificateType_Cbor, KeyType_Ed25519, suffix, states[i + 1]);
339 }
340 // Use a fake self-signed UDS cert as the 'root'.
341 uint8_t root_certificate[dice::test::kTestCertSize];
342 size_t root_certificate_size = 0;
343 dice::test::CreateFakeUdsCertificate(
344 NULL, states[0].cdi_attest, CertificateType_Cbor, KeyType_Ed25519,
345 root_certificate, &root_certificate_size);
346 EXPECT_TRUE(dice::test::VerifyCertificateChain(
347 CertificateType_Cbor, root_certificate, root_certificate_size, &states[1],
348 kNumLayers, /*is_partial_chain=*/false));
349 }
350
351 } // namespace
352