• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 LOG_TAG "keymint_1_test"
18 #include <cutils/log.h>
19 
20 #include <iostream>
21 #include <optional>
22 
23 #include "KeyMintAidlTestBase.h"
24 
25 #include <aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.h>
26 #include <aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.h>
27 #include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
28 #include <aidl/android/hardware/security/secureclock/ISecureClock.h>
29 #include <android-base/logging.h>
30 #include <android/binder_manager.h>
31 
32 using aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
33 using aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
34 using aidl::android::hardware::gatekeeper::IGatekeeper;
35 using aidl::android::hardware::security::keymint::HardwareAuthToken;
36 using aidl::android::hardware::security::secureclock::ISecureClock;
37 
38 #include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
39 #include <android/hardware/gatekeeper/1.0/types.h>
40 #include <gatekeeper/password_handle.h>  // for password_handle_t
41 #include <hardware/hw_auth_token.h>
42 
43 using ::android::sp;
44 using IHidlGatekeeper = ::android::hardware::gatekeeper::V1_0::IGatekeeper;
45 using HidlGatekeeperResponse = ::android::hardware::gatekeeper::V1_0::GatekeeperResponse;
46 using HidlGatekeeperStatusCode = ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
47 
48 namespace aidl::android::hardware::security::keymint::test {
49 
50 class AuthTest : public KeyMintAidlTestBase {
51   public:
SetUp()52     void SetUp() {
53         KeyMintAidlTestBase::SetUp();
54 
55         // Find the default Gatekeeper instance.
56         string gk_name = string(IGatekeeper::descriptor) + "/default";
57         if (AServiceManager_isDeclared(gk_name.c_str())) {
58             // Enroll a user with AIDL Gatekeeper.
59             ::ndk::SpAIBinder binder(AServiceManager_waitForService(gk_name.c_str()));
60             gk_ = IGatekeeper::fromBinder(binder);
61         } else {
62             // Prior to Android U, Gatekeeper was HIDL not AIDL and so may not be present.
63             // Try to enroll user with HIDL Gatekeeper instead.
64             string gk_name = "default";
65             hidl_gk_ = IHidlGatekeeper::getService(gk_name.c_str());
66             if (hidl_gk_ == nullptr) {
67                 std::cerr << "No HIDL Gatekeeper instance for '" << gk_name << "' found.\n";
68                 return;
69             }
70             std::cerr << "No AIDL Gatekeeper instance for '" << gk_name << "' found, using HIDL.\n";
71         }
72 
73         // If the device needs timestamps, find the default ISecureClock instance.
74         if (timestamp_token_required_) {
75             string clock_name = string(ISecureClock::descriptor) + "/default";
76             if (AServiceManager_isDeclared(clock_name.c_str())) {
77                 ::ndk::SpAIBinder binder(AServiceManager_waitForService(clock_name.c_str()));
78                 clock_ = ISecureClock::fromBinder(binder);
79             } else {
80                 std::cerr << "No ISecureClock instance for '" << clock_name << "' found.\n";
81             }
82         }
83 
84         // Enroll a password for a user.
85         uid_ = 10001;
86         password_ = "correcthorsebatterystaple";
87         std::optional<GatekeeperEnrollResponse> rsp = doEnroll(password_);
88         ASSERT_TRUE(rsp.has_value());
89         sid_ = rsp->secureUserId;
90         handle_ = rsp->data;
91     }
92 
TearDown()93     void TearDown() {
94         if (gk_ == nullptr) return;
95         gk_->deleteUser(uid_);
96     }
97 
GatekeeperAvailable()98     bool GatekeeperAvailable() { return (gk_ != nullptr) || (hidl_gk_ != nullptr); }
99 
doEnroll(const std::vector<uint8_t> & newPwd,const std::vector<uint8_t> & curHandle={},const std::vector<uint8_t> & curPwd={})100     std::optional<GatekeeperEnrollResponse> doEnroll(const std::vector<uint8_t>& newPwd,
101                                                      const std::vector<uint8_t>& curHandle = {},
102                                                      const std::vector<uint8_t>& curPwd = {}) {
103         if (gk_ != nullptr) {
104             while (true) {
105                 GatekeeperEnrollResponse rsp;
106                 Status status = gk_->enroll(uid_, curHandle, curPwd, newPwd, &rsp);
107                 if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
108                     status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
109                     sleep(1);
110                     continue;
111                 }
112                 if (status.isOk()) {
113                     return std::move(rsp);
114                 } else {
115                     GTEST_LOG_(ERROR) << "doEnroll(AIDL) failed: " << status;
116                     return std::nullopt;
117                 }
118             }
119         } else if (hidl_gk_ != nullptr) {
120             while (true) {
121                 HidlGatekeeperResponse rsp;
122                 auto status = hidl_gk_->enroll(
123                         uid_, curHandle, curPwd, newPwd,
__anon6c3d41050102(const HidlGatekeeperResponse& cbRsp) 124                         [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
125                 if (!status.isOk()) {
126                     GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed";
127                     return std::nullopt;
128                 }
129                 if (rsp.code == HidlGatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
130                     sleep(1);
131                     continue;
132                 }
133                 if (rsp.code != HidlGatekeeperStatusCode::STATUS_OK) {
134                     GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed with " << int(rsp.code);
135                     return std::nullopt;
136                 }
137                 // "Parse" the returned data to get at the secure user ID.
138                 if (rsp.data.size() != sizeof(::gatekeeper::password_handle_t)) {
139                     GTEST_LOG_(ERROR)
140                             << "HAL returned password handle of invalid length " << rsp.data.size();
141                     return std::nullopt;
142                 }
143                 const ::gatekeeper::password_handle_t* handle =
144                         reinterpret_cast<const ::gatekeeper::password_handle_t*>(rsp.data.data());
145 
146                 // Translate HIDL response to look like an AIDL response.
147                 GatekeeperEnrollResponse aidl_rsp;
148                 aidl_rsp.statusCode = IGatekeeper::STATUS_OK;
149                 aidl_rsp.data = rsp.data;
150                 aidl_rsp.secureUserId = handle->user_id;
151                 return aidl_rsp;
152             }
153         } else {
154             return std::nullopt;
155         }
156     }
157 
doEnroll(const string & newPwd,const std::vector<uint8_t> & curHandle={},const string & curPwd={})158     std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd,
159                                                      const std::vector<uint8_t>& curHandle = {},
160                                                      const string& curPwd = {}) {
161         return doEnroll(std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
162                         std::vector<uint8_t>(curPwd.begin(), curPwd.end()));
163     }
164 
doVerify(uint64_t challenge,const std::vector<uint8_t> & handle,const std::vector<uint8_t> & pwd)165     std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
166                                               const std::vector<uint8_t>& handle,
167                                               const std::vector<uint8_t>& pwd) {
168         if (gk_ != nullptr) {
169             while (true) {
170                 GatekeeperVerifyResponse rsp;
171                 Status status = gk_->verify(uid_, challenge, handle, pwd, &rsp);
172                 if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
173                     status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
174                     sleep(1);
175                     continue;
176                 }
177                 if (status.isOk()) {
178                     return rsp.hardwareAuthToken;
179                 } else {
180                     GTEST_LOG_(ERROR) << "doVerify(AIDL) failed: " << status;
181                     return std::nullopt;
182                 }
183             }
184         } else if (hidl_gk_ != nullptr) {
185             while (true) {
186                 HidlGatekeeperResponse rsp;
187                 auto status = hidl_gk_->verify(
188                         uid_, challenge, handle, pwd,
189                         [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
190                 if (!status.isOk()) {
191                     GTEST_LOG_(ERROR) << "doVerify(HIDL) failed";
192                     return std::nullopt;
193                 }
194                 if (rsp.code == HidlGatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
195                     sleep(1);
196                     continue;
197                 }
198                 if (rsp.code != HidlGatekeeperStatusCode::STATUS_OK) {
199                     GTEST_LOG_(ERROR) << "doVerify(HIDL) failed with " << int(rsp.code);
200                     return std::nullopt;
201                 }
202                 // "Parse" the returned data to get auth token contents.
203                 if (rsp.data.size() != sizeof(hw_auth_token_t)) {
204                     GTEST_LOG_(ERROR) << "Incorrect size of AuthToken payload.";
205                     return std::nullopt;
206                 }
207                 const hw_auth_token_t* hwAuthToken =
208                         reinterpret_cast<const hw_auth_token_t*>(rsp.data.data());
209                 HardwareAuthToken authToken;
210                 authToken.timestamp.milliSeconds = betoh64(hwAuthToken->timestamp);
211                 authToken.challenge = hwAuthToken->challenge;
212                 authToken.userId = hwAuthToken->user_id;
213                 authToken.authenticatorId = hwAuthToken->authenticator_id;
214                 authToken.authenticatorType = static_cast<HardwareAuthenticatorType>(
215                         betoh32(hwAuthToken->authenticator_type));
216                 authToken.mac.assign(&hwAuthToken->hmac[0], &hwAuthToken->hmac[32]);
217                 return authToken;
218             }
219         } else {
220             return std::nullopt;
221         }
222     }
doVerify(uint64_t challenge,const std::vector<uint8_t> & handle,const string & pwd)223     std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
224                                               const std::vector<uint8_t>& handle,
225                                               const string& pwd) {
226         return doVerify(challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
227     }
228 
229     // Variants of the base class methods but with authentication information included.
ProcessMessage(const vector<uint8_t> & key_blob,KeyPurpose operation,const string & message,const AuthorizationSet & in_params,AuthorizationSet * out_params,const HardwareAuthToken & hat)230     string ProcessMessage(const vector<uint8_t>& key_blob, KeyPurpose operation,
231                           const string& message, const AuthorizationSet& in_params,
232                           AuthorizationSet* out_params, const HardwareAuthToken& hat) {
233         AuthorizationSet begin_out_params;
234         ErrorCode result = Begin(operation, key_blob, in_params, out_params, hat);
235         EXPECT_EQ(ErrorCode::OK, result);
236         if (result != ErrorCode::OK) {
237             return "";
238         }
239 
240         std::optional<secureclock::TimeStampToken> time_token = std::nullopt;
241         if (timestamp_token_required_ && clock_ != nullptr) {
242             // Ask a secure clock instance for a timestamp, including the per-op challenge.
243             secureclock::TimeStampToken token;
244             EXPECT_EQ(ErrorCode::OK,
245                       GetReturnErrorCode(clock_->generateTimeStamp(challenge_, &token)));
246             time_token = token;
247         }
248 
249         string output;
250         EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &output, hat, time_token));
251         return output;
252     }
253 
EncryptMessage(const vector<uint8_t> & key_blob,const string & message,const AuthorizationSet & in_params,AuthorizationSet * out_params,const HardwareAuthToken & hat)254     string EncryptMessage(const vector<uint8_t>& key_blob, const string& message,
255                           const AuthorizationSet& in_params, AuthorizationSet* out_params,
256                           const HardwareAuthToken& hat) {
257         SCOPED_TRACE("EncryptMessage");
258         return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params, hat);
259     }
260 
DecryptMessage(const vector<uint8_t> & key_blob,const string & ciphertext,const AuthorizationSet & params,const HardwareAuthToken & hat)261     string DecryptMessage(const vector<uint8_t>& key_blob, const string& ciphertext,
262                           const AuthorizationSet& params, const HardwareAuthToken& hat) {
263         SCOPED_TRACE("DecryptMessage");
264         AuthorizationSet out_params;
265         string plaintext =
266                 ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params, hat);
267         EXPECT_TRUE(out_params.empty());
268         return plaintext;
269     }
270 
271   protected:
272     std::shared_ptr<IGatekeeper> gk_;
273     sp<IHidlGatekeeper> hidl_gk_;
274     std::shared_ptr<ISecureClock> clock_;
275     string password_;
276     uint32_t uid_;
277     int64_t sid_;
278     std::vector<uint8_t> handle_;
279 };
280 
281 // Test use of a key that requires user-authentication within recent history.
TEST_P(AuthTest,TimeoutAuthentication)282 TEST_P(AuthTest, TimeoutAuthentication) {
283     if (!GatekeeperAvailable()) {
284         GTEST_SKIP() << "No Gatekeeper available";
285     }
286     if (timestamp_token_required_ && clock_ == nullptr) {
287         GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
288     }
289 
290     // Create an AES key that requires authentication within the last 3 seconds.
291     const uint32_t timeout_secs = 3;
292     auto builder = AuthorizationSetBuilder()
293                            .AesEncryptionKey(256)
294                            .BlockMode(BlockMode::ECB)
295                            .Padding(PaddingMode::PKCS7)
296                            .Authorization(TAG_USER_SECURE_ID, sid_)
297                            .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
298                            .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
299     vector<uint8_t> keyblob;
300     vector<KeyCharacteristics> key_characteristics;
301     vector<Certificate> cert_chain;
302     ASSERT_EQ(ErrorCode::OK,
303               GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
304 
305     // Attempt to use the AES key without authentication.
306     const string message = "Hello World!";
307     AuthorizationSet out_params;
308     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
309     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
310               Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
311 
312     // Verify to get a HAT, arbitrary challenge.
313     const uint64_t challenge = 42;
314     const std::optional<HardwareAuthToken> hat = doVerify(challenge, handle_, password_);
315     ASSERT_TRUE(hat.has_value());
316     EXPECT_EQ(hat->userId, sid_);
317 
318     // Adding the auth token makes it possible to use the AES key.
319     const string ciphertext = EncryptMessage(keyblob, message, params, &out_params, hat.value());
320     const string plaintext = DecryptMessage(keyblob, ciphertext, params, hat.value());
321     EXPECT_EQ(message, plaintext);
322 
323     // Altering a single bit in the MAC means no auth.
324     HardwareAuthToken dodgy_hat = hat.value();
325     ASSERT_GT(dodgy_hat.mac.size(), 0);
326     dodgy_hat.mac[0] ^= 0x01;
327     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
328               Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, dodgy_hat));
329 
330     // Wait for long enough that the hardware auth token expires.
331     sleep(timeout_secs + 1);
332 
333     auto begin_result = Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat);
334     if (begin_result == ErrorCode::OK) {
335         // If begin() succeeds despite the out-of-date HAT, that must mean that the KeyMint
336         // device doesn't have its own clock.  In that case, it only detects timeout via a
337         // timestamp token provided on update()/finish()
338         ASSERT_TRUE(timestamp_token_required_);
339 
340         secureclock::TimeStampToken time_token;
341         EXPECT_EQ(ErrorCode::OK,
342                   GetReturnErrorCode(clock_->generateTimeStamp(challenge_, &time_token)));
343 
344         string output;
345         EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
346                   Finish(message, {} /* signature */, &output, hat, time_token));
347     } else {
348         // The KeyMint implementation may have its own clock that can immediately detect timeout.
349         ASSERT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED, begin_result);
350     }
351 }
352 
353 // Test use of a key that requires an auth token for each action on the operation, with
354 // a per-operation challenge value included.
TEST_P(AuthTest,AuthPerOperation)355 TEST_P(AuthTest, AuthPerOperation) {
356     if (!GatekeeperAvailable()) {
357         GTEST_SKIP() << "No Gatekeeper available";
358     }
359 
360     // Create an AES key that requires authentication per-action.
361     auto builder = AuthorizationSetBuilder()
362                            .AesEncryptionKey(256)
363                            .BlockMode(BlockMode::ECB)
364                            .Padding(PaddingMode::PKCS7)
365                            .Authorization(TAG_USER_SECURE_ID, sid_)
366                            .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD);
367     vector<uint8_t> keyblob;
368     vector<KeyCharacteristics> key_characteristics;
369     vector<Certificate> cert_chain;
370     ASSERT_EQ(ErrorCode::OK,
371               GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
372 
373     // Attempt to use the AES key without authentication fails after begin.
374     const string message = "Hello World!";
375     AuthorizationSet out_params;
376     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
377     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
378     string output;
379     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED, Finish(message, {} /* signature */, &output));
380 
381     // Verify to get a HAT, but with an arbitrary challenge.
382     const uint64_t unrelated_challenge = 42;
383     const std::optional<HardwareAuthToken> unrelated_hat =
384             doVerify(unrelated_challenge, handle_, password_);
385     ASSERT_TRUE(unrelated_hat.has_value());
386     EXPECT_EQ(unrelated_hat->userId, sid_);
387 
388     // Attempt to use the AES key with an unrelated authentication fails after begin.
389     EXPECT_EQ(ErrorCode::OK,
390               Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, unrelated_hat.value()));
391     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
392               Finish(message, {} /* signature */, &output, unrelated_hat.value()));
393 
394     // Now get a HAT with the challenge from an in-progress operation.
395     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
396     const std::optional<HardwareAuthToken> hat = doVerify(challenge_, handle_, password_);
397     ASSERT_TRUE(hat.has_value());
398     EXPECT_EQ(hat->userId, sid_);
399     string ciphertext;
400     EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, hat.value()));
401 
402     // Altering a single bit in the MAC means no auth.
403     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
404     std::optional<HardwareAuthToken> dodgy_hat = doVerify(challenge_, handle_, password_);
405     ASSERT_TRUE(dodgy_hat.has_value());
406     EXPECT_EQ(dodgy_hat->userId, sid_);
407     ASSERT_GT(dodgy_hat->mac.size(), 0);
408     dodgy_hat->mac[0] ^= 0x01;
409     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
410               Finish(message, {} /* signature */, &ciphertext, hat.value()));
411 }
412 
413 INSTANTIATE_KEYMINT_AIDL_TEST(AuthTest);
414 
415 }  // namespace aidl::android::hardware::security::keymint::test
416