• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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