1 /*
2 * Copyright (C) 2017 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 #include <aidl/android/system/keystore2/IKeystoreOperation.h>
18 #include <aidl/android/system/keystore2/IKeystoreSecurityLevel.h>
19 #include <aidl/android/system/keystore2/IKeystoreService.h>
20 #include <aidl/android/system/keystore2/ResponseCode.h>
21 #include <android/binder_manager.h>
22 #include <android/system/wifi/keystore/1.0/IKeystore.h>
23 #include <binder/IServiceManager.h>
24 #include <cutils/properties.h>
25 #include <gtest/gtest.h>
26 #include <hidl/GtestPrinter.h>
27 #include <hidl/ServiceManagement.h>
28 #include <keymint_support/authorization_set.h>
29 #include <utils/String16.h>
30
31 using namespace std;
32 using namespace ::testing;
33 using namespace android;
34 using android::system::wifi::keystore::V1_0::IKeystore;
35
36 namespace keymint = ::aidl::android::hardware::security::keymint;
37 namespace ks2 = ::aidl::android::system::keystore2;
38
main(int argc,char ** argv)39 int main(int argc, char** argv) {
40 InitGoogleTest(&argc, argv);
41 int status = RUN_ALL_TESTS();
42 return status;
43 }
44
45 namespace {
46
47 enum KeyPurpose {
48 ENCRYPTION,
49 SIGNING,
50 };
51
52 // The fixture for testing the Wifi Keystore HAL
53 class WifiKeystoreHalTest : public TestWithParam<std::string> {
54 protected:
SetUp()55 void SetUp() override {
56 keystore = IKeystore::getService(GetParam());
57 ASSERT_TRUE(keystore);
58
59 ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(kKeystoreServiceName));
60 ks2Service = ks2::IKeystoreService::fromBinder(ks2Binder);
61
62 ASSERT_TRUE(ks2Service);
63 resetState();
64 }
65
TearDown()66 void TearDown() override { resetState(); }
67
isDebuggableBuild()68 bool isDebuggableBuild() {
69 char value[PROPERTY_VALUE_MAX] = {0};
70 property_get("ro.system.build.type", value, "");
71 if (strcmp(value, "userdebug") == 0) {
72 return true;
73 }
74 if (strcmp(value, "eng") == 0) {
75 return true;
76 }
77 return false;
78 }
79
80 /**
81 * Resets the relevant state of the system between tests
82 */
resetState()83 void resetState() {
84 deleteKey(kTestKeyName, true);
85 deleteKey(kTestKeyName, false);
86 }
87
keyDescriptor(const std::string & alias,bool useWifiNamespace)88 ks2::KeyDescriptor keyDescriptor(const std::string& alias, bool useWifiNamespace) {
89 if (useWifiNamespace) {
90 return {
91 .domain = ks2::Domain::SELINUX,
92 .nspace = 102, // Namespace Wifi
93 .alias = alias,
94 .blob = {},
95 };
96 } else {
97 return {
98 .domain = ks2::Domain::APP,
99 .nspace = -1, // ignored - should be -1.
100 .alias = alias,
101 .blob = {},
102 };
103 }
104 }
105
106 /**
107 * Delete a key if it exists.
108 *
109 * @param keyName: name of the key to delete
110 * @param useWifiNamespace: delete the key from the wifi namespace
111 * instead of the process' namespace. (Requires special
112 * privileges on the test's part)
113 *
114 * @return true iff the key existed and is now deleted, false otherwise.
115 */
deleteKey(std::string keyName,bool useWifiNamespace)116 bool deleteKey(std::string keyName, bool useWifiNamespace) {
117 String16 keyName16(keyName.data(), keyName.size());
118 auto rc = ks2Service->deleteKey(keyDescriptor(keyName, useWifiNamespace));
119 if (!rc.isOk() &&
120 rc.getServiceSpecificError() != int32_t(ks2::ResponseCode::KEY_NOT_FOUND)) {
121 cout << "deleteKey: failed binder call" << rc.getDescription() << endl;
122 return false;
123 }
124
125 return true;
126 }
127
128 /**
129 * Generate a key for a specific purpose.
130 *
131 * This generates a key which can be used either for signing
132 * or encryption. The signing key is setup to be used in
133 * the Wifi Keystore HAL's sign() call. The data
134 * about the key returning from its generation is discarded.
135 * If this returns 'true' the key generation has completed
136 * and the key is ready for use.
137 *
138 * @param keyName: name of the key to generate
139 * @param purpose: the purpose the generated key will support
140 * @param useWifiNamespace: generate the key in the wifi namespace
141 * instead of the process' namespace. (Requires special
142 * privileges on the test's part)
143 *
144 * @return true iff the key was successfully generated and is
145 * ready for use, false otherwise.
146 */
generateKey(std::string keyName,KeyPurpose purpose,bool useWifiNamespace)147 bool generateKey(std::string keyName, KeyPurpose purpose, bool useWifiNamespace) {
148 constexpr uint32_t kAESKeySize = 256;
149
150 vector<uint8_t> entropy;
151 keymint::AuthorizationSetBuilder key_parameters;
152 if (purpose == KeyPurpose::SIGNING) {
153 key_parameters.EcdsaSigningKey(kAESKeySize);
154 }
155
156 if (purpose == KeyPurpose::ENCRYPTION) {
157 key_parameters.AesEncryptionKey(kAESKeySize);
158 }
159
160 key_parameters.NoDigestOrPadding()
161 .Authorization(keymint::TAG_BLOCK_MODE, keymint::BlockMode::CBC)
162 .Authorization(keymint::TAG_NO_AUTH_REQUIRED);
163
164 std::shared_ptr<ks2::IKeystoreSecurityLevel> securityLevel;
165
166 fflush(stdout);
167
168 auto rc = ks2Service->getSecurityLevel(keymint::SecurityLevel::TRUSTED_ENVIRONMENT,
169 &securityLevel);
170 if (!rc.isOk()) {
171 cout << "generateKey: Failed to get security level: " << rc.getDescription() << endl;
172 return false;
173 }
174
175 ks2::KeyMetadata keyMetadata;
176
177 rc = securityLevel->generateKey(keyDescriptor(keyName, useWifiNamespace),
178 {} /* attestation key */, key_parameters.vector_data(),
179 0 /* flags */, entropy, &keyMetadata);
180 if (!rc.isOk()) {
181 cout << "generateKey: Failed to generate key: " << rc.getDescription() << endl;
182 return false;
183 }
184
185 return true;
186 }
187
188 constexpr static const char kKeystoreServiceName[] =
189 "android.system.keystore2.IKeystoreService/default";
190 constexpr static const char kTestKeyName[] = "TestKeyName";
191
192 sp<IKeystore> keystore;
193 std::shared_ptr<ks2::IKeystoreService> ks2Service;
194 };
195
TEST_P(WifiKeystoreHalTest,Sign_nullptr_key_name)196 TEST_P(WifiKeystoreHalTest, Sign_nullptr_key_name) {
197 IKeystore::KeystoreStatusCode statusCode;
198
199 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
200 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
201 statusCode = status;
202 return;
203 };
204
205 ::android::hardware::hidl_vec<uint8_t> dataToSign;
206 dataToSign.resize(100);
207 keystore->sign(nullptr, dataToSign, callback);
208 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
209 }
210
TEST_P(WifiKeystoreHalTest,Sign_empty_key_name)211 TEST_P(WifiKeystoreHalTest, Sign_empty_key_name) {
212 IKeystore::KeystoreStatusCode statusCode;
213
214 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
215 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
216 statusCode = status;
217 return;
218 };
219
220 ::android::hardware::hidl_vec<uint8_t> dataToSign;
221 dataToSign.resize(100);
222 keystore->sign("", dataToSign, callback);
223 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
224 }
225
TEST_P(WifiKeystoreHalTest,Sign_empty_data)226 TEST_P(WifiKeystoreHalTest, Sign_empty_data) {
227 if (!isDebuggableBuild()) {
228 GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
229 }
230
231 bool callbackInvoked = false;
232
233 auto callback = [&callbackInvoked](IKeystore::KeystoreStatusCode /*status*/,
234 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
235 // The result is ignored; this callback is a no-op.
236 callbackInvoked = true;
237 return;
238 };
239
240 bool result = generateKey(kTestKeyName, KeyPurpose::SIGNING, true);
241 EXPECT_EQ(result, true);
242
243 // The data to sign is empty. The return code is not important, and the attempt could be
244 // interpreted as valid or an error case. The goal is to determine that the callback
245 // was invokved.
246 ::android::hardware::hidl_vec<uint8_t> dataToSign;
247 keystore->sign(kTestKeyName, dataToSign, callback);
248 EXPECT_EQ(true, callbackInvoked);
249 }
250
TEST_P(WifiKeystoreHalTest,Sign_wrong_key_purpose)251 TEST_P(WifiKeystoreHalTest, Sign_wrong_key_purpose) {
252 if (!isDebuggableBuild()) {
253 GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
254 }
255
256 IKeystore::KeystoreStatusCode statusCode;
257
258 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
259 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
260 statusCode = status;
261 return;
262 };
263
264 // Create a key which cannot sign; any signing attempt should fail.
265 bool result = generateKey(kTestKeyName, KeyPurpose::ENCRYPTION, true);
266 EXPECT_EQ(result, true);
267
268 ::android::hardware::hidl_vec<uint8_t> dataToSign;
269 dataToSign.resize(100);
270 keystore->sign(kTestKeyName, dataToSign, callback);
271 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
272 }
273
TEST_P(WifiKeystoreHalTest,Sign_success)274 TEST_P(WifiKeystoreHalTest, Sign_success) {
275 if (!isDebuggableBuild()) {
276 GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
277 }
278
279 IKeystore::KeystoreStatusCode statusCode;
280
281 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
282 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
283 statusCode = status;
284 return;
285 };
286
287 ::android::hardware::hidl_vec<uint8_t> dataToSign;
288
289 bool result = generateKey(kTestKeyName, KeyPurpose::SIGNING, true);
290 EXPECT_EQ(result, true);
291
292 // With data the signing attempt should succeed
293
294 dataToSign.resize(100);
295 keystore->sign(kTestKeyName, dataToSign, callback);
296 EXPECT_EQ(IKeystore::KeystoreStatusCode::SUCCESS, statusCode);
297
298 result = deleteKey(kTestKeyName, true);
299 EXPECT_EQ(result, true);
300 }
301
TEST_P(WifiKeystoreHalTest,GetBlob_null_key_name)302 TEST_P(WifiKeystoreHalTest, GetBlob_null_key_name) {
303 IKeystore::KeystoreStatusCode statusCode;
304
305 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
306 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
307 statusCode = status;
308 return;
309 };
310
311 // Attempting to get a blob on a non-existent key should fail.
312 statusCode = IKeystore::KeystoreStatusCode::SUCCESS;
313 keystore->getBlob(nullptr, callback);
314 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
315 }
316
TEST_P(WifiKeystoreHalTest,GetBlob_empty_key_name)317 TEST_P(WifiKeystoreHalTest, GetBlob_empty_key_name) {
318 IKeystore::KeystoreStatusCode statusCode;
319
320 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
321 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
322 statusCode = status;
323 return;
324 };
325
326 // Attempting to get a blob on a non-existent key should fail.
327 statusCode = IKeystore::KeystoreStatusCode::SUCCESS;
328 keystore->getBlob("", callback);
329 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
330 }
331
TEST_P(WifiKeystoreHalTest,GetBlob_missing_key)332 TEST_P(WifiKeystoreHalTest, GetBlob_missing_key) {
333 IKeystore::KeystoreStatusCode statusCode;
334
335 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
336 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
337 statusCode = status;
338 return;
339 };
340
341 // Attempting to get a blob on a non-existent key should fail.
342 statusCode = IKeystore::KeystoreStatusCode::SUCCESS;
343 keystore->getBlob(kTestKeyName, callback);
344 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
345 }
346
TEST_P(WifiKeystoreHalTest,GetBlob_wrong_user)347 TEST_P(WifiKeystoreHalTest, GetBlob_wrong_user) {
348 if (!isDebuggableBuild()) {
349 GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
350 }
351
352 IKeystore::KeystoreStatusCode statusCode;
353
354 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
355 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
356 statusCode = status;
357 return;
358 };
359
360 // The HAL is expecting the key to belong to the wifi user.
361 // If the key belongs to another user's space it should fail.
362 bool result = generateKey(kTestKeyName, KeyPurpose::SIGNING, false);
363 EXPECT_EQ(result, true);
364
365 keystore->getBlob(std::string("USRCERT_") + kTestKeyName, callback);
366 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
367
368 result = deleteKey(kTestKeyName, false);
369 EXPECT_EQ(result, true);
370 }
371
TEST_P(WifiKeystoreHalTest,GetBlob_success)372 TEST_P(WifiKeystoreHalTest, GetBlob_success) {
373 if (!isDebuggableBuild()) {
374 GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
375 }
376
377 IKeystore::KeystoreStatusCode statusCode;
378
379 std::string cert;
380 auto callback = [&statusCode, &cert](IKeystore::KeystoreStatusCode status,
381 const ::android::hardware::hidl_vec<uint8_t>& value) {
382 statusCode = status;
383 cert = std::string(reinterpret_cast<const char*>(value.data()),
384 reinterpret_cast<const char*>(value.data()) + value.size());
385 return;
386 };
387
388 // Accessing the key belonging to the wifi user should succeed.
389
390 bool result = generateKey(kTestKeyName, KeyPurpose::SIGNING, true);
391 EXPECT_EQ(result, true);
392
393 keystore->getBlob(std::string("USRCERT_") + kTestKeyName, callback);
394 EXPECT_EQ(IKeystore::KeystoreStatusCode::SUCCESS, statusCode);
395 // Must return PEM encoded certificates.
396 EXPECT_EQ(cert.rfind("-----BEGIN CERTIFICATE-----", 0), 0);
397
398 result = deleteKey(kTestKeyName, true);
399 EXPECT_EQ(result, true);
400 }
401
TEST_P(WifiKeystoreHalTest,GetPublicKey_nullptr_key_name)402 TEST_P(WifiKeystoreHalTest, GetPublicKey_nullptr_key_name) {
403 IKeystore::KeystoreStatusCode statusCode;
404
405 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
406 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
407 statusCode = status;
408 return;
409 };
410
411 // Attempting to export a non-existent key should fail.
412 statusCode = IKeystore::KeystoreStatusCode::SUCCESS;
413 keystore->getPublicKey(nullptr, callback);
414 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
415 }
416
TEST_P(WifiKeystoreHalTest,GetPublicKey_empty_key_name)417 TEST_P(WifiKeystoreHalTest, GetPublicKey_empty_key_name) {
418 IKeystore::KeystoreStatusCode statusCode;
419
420 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
421 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
422 statusCode = status;
423 return;
424 };
425
426 // Attempting to export a non-existent key should fail.
427 statusCode = IKeystore::KeystoreStatusCode::SUCCESS;
428 keystore->getPublicKey("", callback);
429 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
430 }
431
TEST_P(WifiKeystoreHalTest,GetPublicKey_wrong_key_name)432 TEST_P(WifiKeystoreHalTest, GetPublicKey_wrong_key_name) {
433 IKeystore::KeystoreStatusCode statusCode;
434
435 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
436 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
437 statusCode = status;
438 return;
439 };
440
441 // Attempting to export a non-existent key should fail.
442 statusCode = IKeystore::KeystoreStatusCode::SUCCESS;
443 keystore->getPublicKey(kTestKeyName, callback);
444 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
445 }
446
TEST_P(WifiKeystoreHalTest,GetPublicKey_wrong_user)447 TEST_P(WifiKeystoreHalTest, GetPublicKey_wrong_user) {
448 if (!isDebuggableBuild()) {
449 GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
450 }
451
452 IKeystore::KeystoreStatusCode statusCode;
453
454 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
455 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
456 statusCode = status;
457 return;
458 };
459
460 // The HAL is expecting the key to belong to the wifi user.
461 // If the key belongs to another user's space (e.g. root) it should
462 // not be accessible and should fail.
463
464 bool result = generateKey(kTestKeyName, KeyPurpose::SIGNING, false);
465 EXPECT_EQ(result, true);
466
467 keystore->getPublicKey(kTestKeyName, callback);
468 EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
469
470 result = deleteKey(kTestKeyName, false);
471 EXPECT_EQ(result, true);
472 }
473
TEST_P(WifiKeystoreHalTest,GetPublicKey_success)474 TEST_P(WifiKeystoreHalTest, GetPublicKey_success) {
475 if (!isDebuggableBuild()) {
476 GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
477 }
478
479 IKeystore::KeystoreStatusCode statusCode;
480
481 auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
482 const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
483 statusCode = status;
484 return;
485 };
486
487 // Accessing the key belonging to the wifi uid should succeed.
488
489 bool result = generateKey(kTestKeyName, KeyPurpose::SIGNING, true);
490 EXPECT_EQ(result, true);
491
492 keystore->getPublicKey(kTestKeyName, callback);
493 EXPECT_EQ(IKeystore::KeystoreStatusCode::SUCCESS, statusCode);
494
495 result = deleteKey(kTestKeyName, true);
496 EXPECT_EQ(result, true);
497 }
498
499 INSTANTIATE_TEST_SUITE_P(
500 PerInstance, WifiKeystoreHalTest,
501 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeystore::descriptor)),
502 android::hardware::PrintInstanceNameToString);
503
504 } // namespace
505