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 "dice/dice.h"
16
17 #include "dice/known_test_values.h"
18 #include "dice/test_framework.h"
19 #include "dice/utils.h"
20 #include "openssl/crypto.h"
21 #include "openssl/digest.h"
22 #include "openssl/hkdf.h"
23 #include "openssl/sha.h"
24
25 namespace {
26
27 const size_t kFakeCertSize = 200;
28
29 struct FakeDiceOps {
FakeDiceOps__anon13ecbba90111::FakeDiceOps30 FakeDiceOps() { CRYPTO_library_init(); }
31
32 // DiceOps calls to |hash| forward here.
Hash__anon13ecbba90111::FakeDiceOps33 DiceResult Hash(const uint8_t* input, size_t input_size,
34 uint8_t output[DICE_HASH_SIZE]) {
35 SHA512(input, input_size, output);
36 hash_count_++;
37 return hash_result_;
38 }
39
40 // DiceOps calls to |kdf| forward here.
Kdf__anon13ecbba90111::FakeDiceOps41 DiceResult Kdf(size_t length, const uint8_t* ikm, size_t ikm_size,
42 const uint8_t* salt, size_t salt_size, const uint8_t* info,
43 size_t info_size, uint8_t* output) {
44 HKDF(output, length, EVP_sha512(), ikm, ikm_size, salt, salt_size, info,
45 info_size);
46 kdf_count_++;
47 return kdf_result_;
48 }
49
50 // DiceOps calls to |generate_certificate| forward here.
GenerateCertificate__anon13ecbba90111::FakeDiceOps51 DiceResult GenerateCertificate(
52 const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
53 const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
54 const DiceInputValues* input_values, size_t certificate_buffer_size,
55 uint8_t* certificate, size_t* certificate_actual_size) {
56 const uint8_t kFakeCert[kFakeCertSize] = {};
57 (void)subject_private_key_seed;
58 (void)authority_private_key_seed;
59 (void)input_values;
60 generate_certificate_count_++;
61 if (certificate_buffer_size < kFakeCertSize) {
62 *certificate_actual_size = kFakeCertSize;
63 return kDiceResultBufferTooSmall;
64 }
65 *certificate_actual_size = kFakeCertSize;
66 memcpy(certificate, kFakeCert, kFakeCertSize);
67 return generate_certificate_result_;
68 }
69
70 // Set these in a test to induce errors.
71 DiceResult hash_result_ = kDiceResultOk;
72 DiceResult kdf_result_ = kDiceResultOk;
73 DiceResult generate_certificate_result_ = kDiceResultOk;
74
75 // These will be incremented on every DiceOps call.
76 int hash_count_ = 0;
77 int kdf_count_ = 0;
78 int generate_certificate_count_ = 0;
79 };
80
81 extern "C" {
82 // These callbacks forward to a FakeDiceOps instance.
DiceHash(void * context,const uint8_t * input,size_t input_size,uint8_t output[DICE_HASH_SIZE])83 DiceResult DiceHash(void* context, const uint8_t* input, size_t input_size,
84 uint8_t output[DICE_HASH_SIZE]) {
85 return reinterpret_cast<FakeDiceOps*>(context)->Hash(input, input_size,
86 output);
87 }
88
DiceKdf(void * context,size_t length,const uint8_t * ikm,size_t ikm_size,const uint8_t * salt,size_t salt_size,const uint8_t * info,size_t info_size,uint8_t * output)89 DiceResult DiceKdf(void* context, size_t length, const uint8_t* ikm,
90 size_t ikm_size, const uint8_t* salt, size_t salt_size,
91 const uint8_t* info, size_t info_size, uint8_t* output) {
92 return reinterpret_cast<FakeDiceOps*>(context)->Kdf(
93 length, ikm, ikm_size, salt, salt_size, info, info_size, output);
94 }
95
DiceGenerateCertificate(void * context,const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const DiceInputValues * input_values,size_t certificate_buffer_size,uint8_t * certificate,size_t * certificate_actual_size)96 DiceResult DiceGenerateCertificate(
97 void* context,
98 const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
99 const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
100 const DiceInputValues* input_values, size_t certificate_buffer_size,
101 uint8_t* certificate, size_t* certificate_actual_size) {
102 return reinterpret_cast<FakeDiceOps*>(context)->GenerateCertificate(
103 subject_private_key_seed, authority_private_key_seed, input_values,
104 certificate_buffer_size, certificate, certificate_actual_size);
105 }
106 }
107
108 struct DiceStateForTest {
109 uint8_t cdi_attest[DICE_CDI_SIZE];
110 uint8_t cdi_seal[DICE_CDI_SIZE];
111 uint8_t certificate[kFakeCertSize + 10];
112 size_t certificate_size;
113 };
114
TEST(DiceTest,KnownAnswer)115 TEST(DiceTest, KnownAnswer) {
116 FakeDiceOps ops;
117 DiceStateForTest current_state = {};
118 DiceStateForTest next_state = {};
119 DiceInputValues input_values = {};
120 DiceResult result = DiceMainFlow(
121 &ops, current_state.cdi_attest, current_state.cdi_seal, &input_values,
122 sizeof(next_state.certificate), next_state.certificate,
123 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
124 EXPECT_EQ(kDiceResultOk, result);
125 EXPECT_EQ(0, memcmp(next_state.cdi_attest,
126 dice::test::kExpectedCdiAttest_ZeroInput, DICE_CDI_SIZE));
127 EXPECT_EQ(0, memcmp(next_state.cdi_seal,
128 dice::test::kExpectedCdiSeal_ZeroInput, DICE_CDI_SIZE));
129 EXPECT_EQ(kFakeCertSize, next_state.certificate_size);
130 }
131
TEST(DiceTest,HashFail)132 TEST(DiceTest, HashFail) {
133 FakeDiceOps ops;
134 ops.hash_result_ = kDiceResultPlatformError;
135 DiceStateForTest current_state = {};
136 DiceStateForTest next_state = {};
137 DiceInputValues input_values = {};
138 DiceResult result = DiceMainFlow(
139 &ops, 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(kDiceResultPlatformError, result);
143 }
144
TEST(DiceTest,KdfFail)145 TEST(DiceTest, KdfFail) {
146 FakeDiceOps ops;
147 ops.kdf_result_ = kDiceResultPlatformError;
148 DiceStateForTest current_state = {};
149 DiceStateForTest next_state = {};
150 DiceInputValues input_values = {};
151 DiceResult result = DiceMainFlow(
152 &ops, current_state.cdi_attest, current_state.cdi_seal, &input_values,
153 sizeof(next_state.certificate), next_state.certificate,
154 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
155 EXPECT_EQ(kDiceResultPlatformError, result);
156 }
157
TEST(DiceTest,CertFail)158 TEST(DiceTest, CertFail) {
159 FakeDiceOps ops;
160 ops.generate_certificate_result_ = kDiceResultPlatformError;
161 DiceStateForTest current_state = {};
162 DiceStateForTest next_state = {};
163 DiceInputValues input_values = {};
164 DiceResult result = DiceMainFlow(
165 &ops, current_state.cdi_attest, current_state.cdi_seal, &input_values,
166 sizeof(next_state.certificate), next_state.certificate,
167 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
168 EXPECT_EQ(kDiceResultPlatformError, result);
169 }
170
TEST(DiceTest,CertTooSmall)171 TEST(DiceTest, CertTooSmall) {
172 FakeDiceOps ops;
173 DiceStateForTest current_state = {};
174 DiceStateForTest next_state = {};
175 DiceInputValues input_values = {};
176 DiceResult result = DiceMainFlow(
177 &ops, current_state.cdi_attest, current_state.cdi_seal, &input_values,
178 kFakeCertSize - 1, next_state.certificate, &next_state.certificate_size,
179 next_state.cdi_attest, next_state.cdi_seal);
180 EXPECT_EQ(kDiceResultBufferTooSmall, result);
181 EXPECT_EQ(next_state.certificate_size, kFakeCertSize);
182 }
183
TEST(DiceTest,NoExtraneousOps)184 TEST(DiceTest, NoExtraneousOps) {
185 FakeDiceOps ops;
186 DiceStateForTest current_state = {};
187 DiceStateForTest next_state = {};
188 DiceInputValues input_values = {};
189 DiceResult result = DiceMainFlow(
190 &ops, current_state.cdi_attest, current_state.cdi_seal, &input_values,
191 sizeof(next_state.certificate), next_state.certificate,
192 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
193 EXPECT_EQ(kDiceResultOk, result);
194 // These are brittle, but can act as an effective check that we're not
195 // regressing in how many expensive operations we call.
196 EXPECT_LE(ops.hash_count_, 2);
197 EXPECT_LE(ops.kdf_count_, 4);
198 EXPECT_LE(ops.generate_certificate_count_, 1);
199 }
200
TEST(DiceTest,NoCertParamsPreservesCDIs)201 TEST(DiceTest, NoCertParamsPreservesCDIs) {
202 FakeDiceOps ops;
203 DiceStateForTest current_state = {};
204 DiceStateForTest next_state = {};
205 DiceStateForTest next_state_no_cert = {};
206 DiceInputValues input_values = {};
207 DiceResult result = DiceMainFlow(
208 &ops, current_state.cdi_attest, current_state.cdi_seal, &input_values,
209 sizeof(next_state.certificate), next_state.certificate,
210 &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal);
211 result = DiceMainFlow(
212 &ops, current_state.cdi_attest, current_state.cdi_seal, &input_values, 0,
213 NULL, NULL, next_state_no_cert.cdi_attest, next_state_no_cert.cdi_seal);
214 EXPECT_EQ(kDiceResultOk, result);
215 EXPECT_EQ(0, memcmp(next_state.cdi_attest, next_state_no_cert.cdi_attest,
216 DICE_CDI_SIZE));
217 EXPECT_EQ(0, memcmp(next_state.cdi_seal, next_state_no_cert.cdi_seal,
218 DICE_CDI_SIZE));
219 }
220
221 } // namespace
222