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