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,mac)63 TEST_F(swbcc, mac) {
64 int rc;
65 uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
66 size_t cose_sign1_size = 0;
67
68 memset(cose_sign1, 0, sizeof(cose_sign1));
69
70 rc = swbcc_sign_key(_state->s, true, HWBCC_ALGORITHM_ED25519,
71 test_data.data(), test_data.size(), test_aad,
72 sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
73 &cose_sign1_size);
74 ASSERT_EQ(rc, 0);
75
76 ASSERT_GT(cose_sign1_size, 0);
77 /* TODO: Check contents of cose_sign1. */
78
79 test_abort:;
80 }
81
TEST_F(swbcc,bcc)82 TEST_F(swbcc, bcc) {
83 int rc;
84 uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
85 size_t bcc_size = 0;
86 std::vector<PubKey> keys;
87 uint8_t* dk_pub_key;
88 uint8_t* km_pub_key;
89
90 memset(bcc, 0, sizeof(bcc));
91
92 rc = swbcc_get_bcc(_state->s, true, bcc, sizeof(bcc), &bcc_size);
93 ASSERT_EQ(rc, 0);
94 ASSERT_GT(bcc_size, 0);
95
96 ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys), true);
97
98 /* Only a degenerate self-signed BCC is currently supported. */
99 ASSERT_EQ(keys.size(), 2);
100
101 dk_pub_key = keys[0].data();
102 km_pub_key = keys[1].data();
103 ASSERT_EQ(memcmp(dk_pub_key, km_pub_key, ED25519_PUBLIC_KEY_LEN), 0);
104
105 test_abort:;
106 }
107
108 /* Check that test mode yields different output every time */
TEST(hwbcc,protected_data_test_mode)109 TEST(hwbcc, protected_data_test_mode) {
110 int rc;
111 uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
112 size_t cose_sign1_size;
113 uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
114 size_t bcc_size;
115 std::vector<PubKey> keys1;
116 std::vector<PubKey> keys2;
117
118 /* Get first set of keys */
119 memset(cose_sign1, 0, sizeof(cose_sign1));
120 memset(bcc, 0, sizeof(bcc));
121
122 rc = hwbcc_get_protected_data(
123 true, HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
124 test_aad, sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
125 &cose_sign1_size, bcc, sizeof(bcc), &bcc_size);
126 ASSERT_EQ(rc, 0);
127
128 ASSERT_GT(cose_sign1_size, 0);
129 ASSERT_GT(bcc_size, 0);
130
131 ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys1), true);
132
133 /* Get second set of keys */
134 memset(cose_sign1, 0, sizeof(cose_sign1));
135 memset(bcc, 0, sizeof(bcc));
136
137 rc = hwbcc_get_protected_data(
138 true, HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
139 test_aad, sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
140 &cose_sign1_size, bcc, sizeof(bcc), &bcc_size);
141 ASSERT_EQ(rc, 0);
142
143 ASSERT_GT(cose_sign1_size, 0);
144 ASSERT_GT(bcc_size, 0);
145
146 ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys2), true);
147
148 /* The two sets of keys must be different in test mode. */
149 ASSERT_NE(memcmp(keys1[0].data(), keys2[0].data(), ED25519_PUBLIC_KEY_LEN),
150 0);
151 ASSERT_NE(memcmp(keys1[1].data(), keys2[1].data(), ED25519_PUBLIC_KEY_LEN),
152 0);
153
154 test_abort:;
155 }
156
157 /*
158 * Macro to enable test cases for generic ARM64 platform only.
159 * (This includes generic_arm32 targets too).
160 */
161 #if defined(PLATFORM_GENERIC_ARM64)
162 #define GENERIC_ARM64_PLATFORM_ONLY_TEST(name) name
163 #else
164 #define GENERIC_ARM64_PLATFORM_ONLY_TEST(name) DISABLED_##name
165 #endif
166
167 /*
168 * Device key is hard-coded on emulator targets, i.e. BCC keys are fixed too.
169 * We test that BCC keys don't change to make sure that we don't accidentally
170 * change the key derivation procedure.
171 */
172 static const uint8_t emulator_pub_key[ED25519_PUBLIC_KEY_LEN] = {
173 0xc0, 0xdd, 0x6c, 0xf4, 0x3e, 0x66, 0x15, 0xc7, 0x4d, 0x23, 0xb8,
174 0x96, 0x11, 0x11, 0xc9, 0x88, 0x07, 0x92, 0x2c, 0x8f, 0x32, 0xf6,
175 0x79, 0x85, 0x86, 0x36, 0xad, 0xbd, 0x20, 0xf0, 0x9b, 0x21};
176
TEST(hwbcc,GENERIC_ARM64_PLATFORM_ONLY_TEST (protected_data))177 TEST(hwbcc, GENERIC_ARM64_PLATFORM_ONLY_TEST(protected_data)) {
178 int rc;
179 uint8_t cose_sign1[HWBCC_MAX_RESP_PAYLOAD_SIZE];
180 size_t cose_sign1_size;
181 uint8_t bcc[HWBCC_MAX_RESP_PAYLOAD_SIZE];
182 size_t bcc_size;
183 std::vector<PubKey> keys;
184 uint8_t* dk_pub_key;
185 uint8_t* km_pub_key;
186
187 memset(cose_sign1, 0, sizeof(cose_sign1));
188 memset(bcc, 0, sizeof(bcc));
189
190 rc = hwbcc_get_protected_data(
191 false, HWBCC_ALGORITHM_ED25519, test_data.data(), test_data.size(),
192 test_aad, sizeof(test_aad), cose_sign1, sizeof(cose_sign1),
193 &cose_sign1_size, bcc, sizeof(bcc), &bcc_size);
194 ASSERT_EQ(rc, 0);
195
196 ASSERT_GT(cose_sign1_size, 0);
197 ASSERT_GT(bcc_size, 0);
198
199 ASSERT_EQ(validate_bcc_impl(bcc, bcc_size, &keys), true);
200 ASSERT_EQ(keys.size(), 2);
201
202 dk_pub_key = keys[0].data();
203 km_pub_key = keys[1].data();
204 ASSERT_EQ(memcmp(emulator_pub_key, dk_pub_key, ED25519_PUBLIC_KEY_LEN), 0);
205 ASSERT_EQ(memcmp(dk_pub_key, km_pub_key, ED25519_PUBLIC_KEY_LEN), 0);
206
207 test_abort:;
208 }
209
210 static const uint8_t emulator_cdi_attest[DICE_CDI_SIZE] = {
211 0x44, 0x26, 0x69, 0x94, 0x02, 0x34, 0x1c, 0xc8, 0x1d, 0x93, 0xc7,
212 0xb8, 0x47, 0xaf, 0x55, 0xe8, 0xde, 0x8e, 0x79, 0x4c, 0x1b, 0x0f,
213 0xea, 0x99, 0x7f, 0x91, 0x83, 0x83, 0x7f, 0x26, 0x7f, 0x93};
214
215 static const uint8_t emulator_cdi_seal[DICE_CDI_SIZE] = {
216 0xf7, 0xe5, 0xb0, 0x2b, 0xd0, 0xfa, 0x4d, 0x5b, 0xfa, 0xd8, 0x16,
217 0x24, 0xfa, 0xc8, 0x50, 0xac, 0x4f, 0x1a, 0x3d, 0xb4, 0xbc, 0x02,
218 0xc9, 0xfd, 0xeb, 0xfe, 0x26, 0xfc, 0x28, 0x98, 0x5b, 0xe8,
219 };
220
221 /**
222 * Test the two CDIs: CDI_Attest and CDI_Seal; and the UDS included
223 * in the BCC, all of which are retrieved from get_dice_artifacts, with those
224 * values specific to ARM64 emulator, given that the hwkey for the emulator
225 * is hardcoded.
226 */
TEST(hwbcc,GENERIC_ARM64_PLATFORM_ONLY_TEST (test_get_dice_artifacts))227 TEST(hwbcc, GENERIC_ARM64_PLATFORM_ONLY_TEST(test_get_dice_artifacts)) {
228 int rc;
229 uint8_t dice_artifacts[HWBCC_MAX_RESP_PAYLOAD_SIZE];
230 size_t dice_artifacts_size;
231 CDI next_cdi_attest;
232 CDI next_cdi_seal;
233
234 /**
235 * dice_artifacts expects the following CBOR encoded structure.
236 * Since the implementation of hwbcc_get_dice_artifacts serves only the
237 * non-secure world, Bcc is not present in the returned dice_artifacts.
238 * We calculate the expected size, including CBOR header sizes.
239 * BccHandover = {
240 * 1 : bstr .size 32, // CDI_Attest
241 * 2 : bstr .size 32, // CDI_Seal
242 * ? 3 : Bcc, // Cert_Chain
243 * }
244 * Bcc = [
245 * PubKeyEd25519, // UDS
246 * + BccEntry, // Root -> leaf
247 * ]
248 */
249 size_t bcc_handover_size = 2 * DICE_CDI_SIZE + 7 /*CBOR tags*/;
250
251 memset(dice_artifacts, 0, sizeof(dice_artifacts));
252
253 rc = hwbcc_get_dice_artifacts(0, dice_artifacts, sizeof(dice_artifacts),
254 &dice_artifacts_size);
255
256 ASSERT_EQ(rc, 0);
257 ASSERT_GT(dice_artifacts_size, 0);
258
259 ASSERT_EQ(dice_artifacts_size, bcc_handover_size);
260
261 ASSERT_EQ(validate_bcc_handover_impl(dice_artifacts, dice_artifacts_size,
262 &next_cdi_attest, &next_cdi_seal),
263 true);
264 if (system_state_app_loading_unlocked()) {
265 ASSERT_EQ(memcmp(emulator_cdi_attest, next_cdi_attest.data(),
266 DICE_CDI_SIZE),
267 0);
268 ASSERT_EQ(
269 memcmp(emulator_cdi_seal, next_cdi_seal.data(), DICE_CDI_SIZE),
270 0);
271 }
272
273 test_abort:;
274 }
275
276 /**
277 * Test that ns_deprivilege does not block the calls to hwbcc from Trusty Apps
278 * such as this test TA.
279 */
TEST(hwbcc,test_ns_deprivilege)280 TEST(hwbcc, test_ns_deprivilege) {
281 int rc;
282 uint8_t dice_artifacts[HWBCC_MAX_RESP_PAYLOAD_SIZE];
283 size_t dice_artifacts_size;
284
285 rc = hwbcc_ns_deprivilege();
286 ASSERT_EQ(rc, 0);
287
288 /* ns_deprivilege should not block calls from secure world. */
289 memset(dice_artifacts, 0, sizeof(dice_artifacts));
290 dice_artifacts_size = 0;
291 rc = hwbcc_get_dice_artifacts(0, dice_artifacts, sizeof(dice_artifacts),
292 &dice_artifacts_size);
293 ASSERT_EQ(rc, 0);
294
295 test_abort:;
296 }
297
298 PORT_TEST(hwbcc, "com.android.trusty.hwbcc.test");
299