1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define TLOG_TAG "hwbcc-test"
18 
19 #include <cppbor.h>
20 #include <cppbor_parse.h>
21 #include <dice/config.h>
22 #include <dice/dice.h>
23 #include <lib/hwbcc/client/hwbcc.h>
24 #include <lib/hwbcc/common/common.h>
25 #include <lib/hwbcc/common/swbcc.h>
26 #include <lib/system_state/system_state.h>
27 #include <openssl/curve25519.h>
28 #include <trusty_unittest.h>
29 #include <uapi/err.h>
30 
31 #include <array>
32 #include <vector>
33 
34 typedef struct {
35     swbcc_session_t s;
36 } swbcc_t;
37 
38 /* UUID of this test TA: {0e109d31-8bbe-47d6-bb47-e1dd08910e16} */
39 static const struct uuid self_uuid = {
40         0x0e109d31,
41         0x8bbe,
42         0x47d6,
43         {0xbb, 0x47, 0xe1, 0xdd, 0x08, 0x91, 0x0e, 0x16},
44 };
45 
46 static const std::array<uint8_t, HWBCC_MAX_DATA_TO_SIGN_SIZE> test_data = {};
47 
48 static const uint8_t test_aad[] = {0xcf, 0xe1, 0x89, 0x39, 0xb1,
49                                    0x72, 0xbf, 0x4f, 0xa8, 0x0f};
50 
TEST_F_SETUP(swbcc)51 TEST_F_SETUP(swbcc) {
52     _state->s = 0;
53     int rc = swbcc_init(&_state->s, &self_uuid);
54     ASSERT_EQ(rc, 0);
55 
56 test_abort:;
57 }
58 
TEST_F_TEARDOWN(swbcc)59 TEST_F_TEARDOWN(swbcc) {
60     swbcc_close(_state->s);
61 }
62 
TEST_F(swbcc,get_client)63 TEST_F(swbcc, get_client) {
64     struct uuid client;
65     swbcc_get_client(_state->s, &client);
66     ASSERT_EQ(memcmp(&client, &self_uuid, sizeof(struct uuid)), 0);
67 
68 test_abort:;
69 }
70 
TEST_F(swbcc,mac)71 TEST_F(swbcc, mac) {
72     int rc;
73     uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
74     size_t cose_sign1_size = 0;
75 
76     memset(cose_sign1, 0, sizeof(cose_sign1));
77 
78     rc = swbcc_sign_key(_state->s, true, HWBCC_ALGORITHM_ED25519,
79                         test_data.data(), test_data.size(), test_aad,
80                         sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
81                         &cose_sign1_size);
82     ASSERT_EQ(rc, 0);
83 
84     ASSERT_GT(cose_sign1_size, 0);
85     /* TODO: Check contents of cose_sign1. */
86 
87 test_abort:;
88 }
89 
TEST_F(swbcc,bcc)90 TEST_F(swbcc, bcc) {
91     int rc;
92     uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
93     size_t bcc_size = 0;
94     std::vector<PubKey> keys;
95     uint8_t* dk_pub_key;
96     uint8_t* km_pub_key;
97 
98     memset(bcc, 0, sizeof(bcc));
99 
100     rc = swbcc_get_bcc(_state->s, true, bcc, sizeof(bcc), &bcc_size);
101     ASSERT_EQ(rc, 0);
102     ASSERT_GT(bcc_size, 0);
103 
104     ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys), true);
105 
106     /* Only a degenerate self-signed BCC is currently supported. */
107     ASSERT_EQ(keys.size(), 2);
108 
109     dk_pub_key = keys[0].data();
110     km_pub_key = keys[1].data();
111     ASSERT_EQ(memcmp(dk_pub_key, km_pub_key, ED25519_PUBLIC_KEY_LEN), 0);
112 
113 test_abort:;
114 }
115 
116 /* Check that test mode yields different output every time */
TEST(hwbcc,protected_data_test_mode)117 TEST(hwbcc, protected_data_test_mode) {
118     int rc;
119     uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
120     size_t cose_sign1_size;
121     uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
122     size_t bcc_size;
123     std::vector<PubKey> keys1;
124     std::vector<PubKey> keys2;
125 
126     /* Get first set of keys */
127     memset(cose_sign1, 0, sizeof(cose_sign1));
128     memset(bcc, 0, sizeof(bcc));
129 
130     rc = hwbcc_get_protected_data(
131             true, HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
132             test_aad, sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
133             &cose_sign1_size, bcc, sizeof(bcc), &bcc_size);
134     ASSERT_EQ(rc, 0);
135 
136     ASSERT_GT(cose_sign1_size, 0);
137     ASSERT_GT(bcc_size, 0);
138 
139     ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys1), true);
140 
141     /* Get second set of keys */
142     memset(cose_sign1, 0, sizeof(cose_sign1));
143     memset(bcc, 0, sizeof(bcc));
144 
145     rc = hwbcc_get_protected_data(
146             true, HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
147             test_aad, sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
148             &cose_sign1_size, bcc, sizeof(bcc), &bcc_size);
149     ASSERT_EQ(rc, 0);
150 
151     ASSERT_GT(cose_sign1_size, 0);
152     ASSERT_GT(bcc_size, 0);
153 
154     ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys2), true);
155 
156     /* The two sets of keys must be different in test mode. */
157     ASSERT_NE(memcmp(keys1[0].data(), keys2[0].data(), ED25519_PUBLIC_KEY_LEN),
158               0);
159     ASSERT_NE(memcmp(keys1[1].data(), keys2[1].data(), ED25519_PUBLIC_KEY_LEN),
160               0);
161 
162 test_abort:;
163 }
164 
165 /*
166  * Macro to enable test cases for generic ARM64 platform only.
167  * (This includes generic_arm32 targets too).
168  */
169 #if defined(PLATFORM_GENERIC_ARM64)
170 #define GENERIC_ARM64_PLATFORM_ONLY_TEST(name) name
171 #else
172 #define GENERIC_ARM64_PLATFORM_ONLY_TEST(name) DISABLED_##name
173 #endif
174 
175 /*
176  * Device key is hard-coded on emulator targets, i.e. BCC keys are fixed too.
177  * We test that BCC keys don't change to make sure that we don't accidentally
178  * change the key derivation procedure.
179  */
180 static const uint8_t emulator_pub_key[ED25519_PUBLIC_KEY_LEN] = {
181         0xc0, 0xdd, 0x6c, 0xf4, 0x3e, 0x66, 0x15, 0xc7, 0x4d, 0x23, 0xb8,
182         0x96, 0x11, 0x11, 0xc9, 0x88, 0x07, 0x92, 0x2c, 0x8f, 0x32, 0xf6,
183         0x79, 0x85, 0x86, 0x36, 0xad, 0xbd, 0x20, 0xf0, 0x9b, 0x21};
184 
TEST(hwbcc,GENERIC_ARM64_PLATFORM_ONLY_TEST (protected_data))185 TEST(hwbcc, GENERIC_ARM64_PLATFORM_ONLY_TEST(protected_data)) {
186     int rc;
187     uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
188     size_t cose_sign1_size;
189     uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
190     size_t bcc_size;
191     std::vector<PubKey> keys;
192     uint8_t* dk_pub_key;
193     uint8_t* km_pub_key;
194 
195     memset(cose_sign1, 0, sizeof(cose_sign1));
196     memset(bcc, 0, sizeof(bcc));
197 
198     rc = hwbcc_get_protected_data(
199             false, HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
200             test_aad, sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
201             &cose_sign1_size, bcc, sizeof(bcc), &bcc_size);
202     ASSERT_EQ(rc, 0);
203 
204     ASSERT_GT(cose_sign1_size, 0);
205     ASSERT_GT(bcc_size, 0);
206 
207     ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys), true);
208     ASSERT_EQ(keys.size(), 2);
209 
210     dk_pub_key = keys[0].data();
211     km_pub_key = keys[1].data();
212     ASSERT_EQ(memcmp(emulator_pub_key, dk_pub_key, ED25519_PUBLIC_KEY_LEN), 0);
213     ASSERT_EQ(memcmp(dk_pub_key, km_pub_key, ED25519_PUBLIC_KEY_LEN), 0);
214 
215 test_abort:;
216 }
217 
218 static const uint8_t emulator_cdi_attest[DICE_CDI_SIZE] = {
219         0x44, 0x26, 0x69, 0x94, 0x02, 0x34, 0x1c, 0xc8, 0x1d, 0x93, 0xc7,
220         0xb8, 0x47, 0xaf, 0x55, 0xe8, 0xde, 0x8e, 0x79, 0x4c, 0x1b, 0x0f,
221         0xea, 0x99, 0x7f, 0x91, 0x83, 0x83, 0x7f, 0x26, 0x7f, 0x93};
222 
223 static const uint8_t emulator_cdi_seal[DICE_CDI_SIZE] = {
224         0xf7, 0xe5, 0xb0, 0x2b, 0xd0, 0xfa, 0x4d, 0x5b, 0xfa, 0xd8, 0x16,
225         0x24, 0xfa, 0xc8, 0x50, 0xac, 0x4f, 0x1a, 0x3d, 0xb4, 0xbc, 0x02,
226         0xc9, 0xfd, 0xeb, 0xfe, 0x26, 0xfc, 0x28, 0x98, 0x5b, 0xe8,
227 };
228 
229 /**
230  * Test the two CDIs: CDI_Attest and CDI_Seal; and the UDS included
231  * in the BCC, all of which are retrieved from get_dice_artifacts, with those
232  * values specific to ARM64 emulator, given that the hwkey for the emulator
233  * is hardcoded.
234  */
TEST(hwbcc,GENERIC_ARM64_PLATFORM_ONLY_TEST (test_get_dice_artifacts))235 TEST(hwbcc, GENERIC_ARM64_PLATFORM_ONLY_TEST(test_get_dice_artifacts)) {
236     int rc;
237     uint8_t dice_artifacts[HWBCC_MAX_RESP_PAYLOAD_SIZE];
238     size_t dice_artifacts_size;
239     CDI next_cdi_attest;
240     CDI next_cdi_seal;
241 
242     /**
243      * dice_artifacts expects the following CBOR encoded structure.
244      * Since the implementation of hwbcc_get_dice_artifacts serves only the
245      * non-secure world, Bcc is not present in the returned dice_artifacts.
246      * We calculate the expected size, including CBOR header sizes.
247      * BccHandover = {
248      *      1 : bstr .size 32,	// CDI_Attest
249      *      2 : bstr .size 32,	// CDI_Seal
250      *      ? 3 : Bcc,          // Cert_Chain
251      * }
252      * Bcc = [
253      *      PubKeyEd25519, // UDS
254      *      + BccEntry,    // Root -> leaf
255      *  ]
256      */
257     size_t bcc_handover_size = 2 * DICE_CDI_SIZE + 7 /*CBOR tags*/;
258 
259     memset(dice_artifacts, 0, sizeof(dice_artifacts));
260 
261     rc = hwbcc_get_dice_artifacts(0, dice_artifacts, sizeof(dice_artifacts),
262                                   &dice_artifacts_size);
263 
264     ASSERT_EQ(rc, 0);
265     ASSERT_GT(dice_artifacts_size, 0);
266 
267     ASSERT_EQ(dice_artifacts_size, bcc_handover_size);
268 
269     ASSERT_EQ(validate_bcc_handover_impl(dice_artifacts, dice_artifacts_size,
270                                          &next_cdi_attest, &next_cdi_seal),
271               true);
272     if (system_state_app_loading_unlocked()) {
273         ASSERT_EQ(memcmp(emulator_cdi_attest, next_cdi_attest.data(),
274                          DICE_CDI_SIZE),
275                   0);
276         ASSERT_EQ(
277                 memcmp(emulator_cdi_seal, next_cdi_seal.data(), DICE_CDI_SIZE),
278                 0);
279     }
280 
281 test_abort:;
282 }
283 
284 /**
285  * Test that ns_deprivilege does not block the calls to hwbcc from Trusty Apps
286  * such as this test TA.
287  */
TEST(hwbcc,test_ns_deprivilege)288 TEST(hwbcc, test_ns_deprivilege) {
289     int rc;
290     uint8_t dice_artifacts[HWBCC_MAX_RESP_PAYLOAD_SIZE];
291     size_t dice_artifacts_size;
292 
293     rc = hwbcc_ns_deprivilege();
294     ASSERT_EQ(rc, 0);
295 
296     /* ns_deprivilege should not block calls from secure world. */
297     memset(dice_artifacts, 0, sizeof(dice_artifacts));
298     dice_artifacts_size = 0;
299     rc = hwbcc_get_dice_artifacts(0, dice_artifacts, sizeof(dice_artifacts),
300                                   &dice_artifacts_size);
301     ASSERT_EQ(rc, 0);
302 
303 test_abort:;
304 }
305 
306 PORT_TEST(hwbcc, "com.android.trusty.hwbcc.test");
307