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