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