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