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