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