• 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/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