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