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