xref: /aosp_15_r20/external/open-dice/src/dice_test.cc (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
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