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