xref: /aosp_15_r20/hardware/interfaces/security/keymint/aidl/vts/functional/AuthTest.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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         if (alt_uid_ != 0) {
97             gk_->deleteUser(alt_uid_);
98         }
99     }
100 
GatekeeperAvailable()101     bool GatekeeperAvailable() { return (gk_ != nullptr) || (hidl_gk_ != nullptr); }
102 
doEnroll(uint32_t uid,const std::vector<uint8_t> & newPwd,const std::vector<uint8_t> & curHandle={},const std::vector<uint8_t> & curPwd={})103     std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid,
104                                                      const std::vector<uint8_t>& newPwd,
105                                                      const std::vector<uint8_t>& curHandle = {},
106                                                      const std::vector<uint8_t>& curPwd = {}) {
107         if (gk_ != nullptr) {
108             while (true) {
109                 GatekeeperEnrollResponse rsp;
110                 Status status = gk_->enroll(uid, curHandle, curPwd, newPwd, &rsp);
111                 if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
112                     status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
113                     sleep(1);
114                     continue;
115                 }
116                 if (status.isOk()) {
117                     return std::move(rsp);
118                 } else {
119                     GTEST_LOG_(ERROR) << "doEnroll(AIDL) failed: " << status;
120                     return std::nullopt;
121                 }
122             }
123         } else if (hidl_gk_ != nullptr) {
124             while (true) {
125                 HidlGatekeeperResponse rsp;
126                 auto status = hidl_gk_->enroll(
127                         uid, curHandle, curPwd, newPwd,
__anonf6a0e8560102(const HidlGatekeeperResponse& cbRsp) 128                         [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
129                 if (!status.isOk()) {
130                     GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed";
131                     return std::nullopt;
132                 }
133                 if (rsp.code == HidlGatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
134                     sleep(1);
135                     continue;
136                 }
137                 if (rsp.code != HidlGatekeeperStatusCode::STATUS_OK) {
138                     GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed with " << int(rsp.code);
139                     return std::nullopt;
140                 }
141                 // "Parse" the returned data to get at the secure user ID.
142                 if (rsp.data.size() != sizeof(::gatekeeper::password_handle_t)) {
143                     GTEST_LOG_(ERROR)
144                             << "HAL returned password handle of invalid length " << rsp.data.size();
145                     return std::nullopt;
146                 }
147                 const ::gatekeeper::password_handle_t* handle =
148                         reinterpret_cast<const ::gatekeeper::password_handle_t*>(rsp.data.data());
149 
150                 // Translate HIDL response to look like an AIDL response.
151                 GatekeeperEnrollResponse aidl_rsp;
152                 aidl_rsp.statusCode = IGatekeeper::STATUS_OK;
153                 aidl_rsp.data = rsp.data;
154                 aidl_rsp.secureUserId = handle->user_id;
155                 return aidl_rsp;
156             }
157         } else {
158             return std::nullopt;
159         }
160     }
161 
doEnroll(uint32_t uid,const string & newPwd,const std::vector<uint8_t> & curHandle={},const string & curPwd={})162     std::optional<GatekeeperEnrollResponse> doEnroll(uint32_t uid, const string& newPwd,
163                                                      const std::vector<uint8_t>& curHandle = {},
164                                                      const string& curPwd = {}) {
165         return doEnroll(uid, std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
166                         std::vector<uint8_t>(curPwd.begin(), curPwd.end()));
167     }
doEnroll(const string & newPwd)168     std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd) {
169         return doEnroll(uid_, newPwd);
170     }
171 
doVerify(uint32_t uid,uint64_t challenge,const std::vector<uint8_t> & handle,const std::vector<uint8_t> & pwd)172     std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
173                                               const std::vector<uint8_t>& handle,
174                                               const std::vector<uint8_t>& pwd) {
175         if (gk_ != nullptr) {
176             while (true) {
177                 GatekeeperVerifyResponse rsp;
178                 Status status = gk_->verify(uid, challenge, handle, pwd, &rsp);
179                 if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
180                     status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
181                     sleep(1);
182                     continue;
183                 }
184                 if (status.isOk()) {
185                     return rsp.hardwareAuthToken;
186                 } else {
187                     GTEST_LOG_(ERROR) << "doVerify(AIDL) failed: " << status;
188                     return std::nullopt;
189                 }
190             }
191         } else if (hidl_gk_ != nullptr) {
192             while (true) {
193                 HidlGatekeeperResponse rsp;
194                 auto status = hidl_gk_->verify(
195                         uid, challenge, handle, pwd,
196                         [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
197                 if (!status.isOk()) {
198                     GTEST_LOG_(ERROR) << "doVerify(HIDL) failed";
199                     return std::nullopt;
200                 }
201                 if (rsp.code == HidlGatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
202                     sleep(1);
203                     continue;
204                 }
205                 if (rsp.code != HidlGatekeeperStatusCode::STATUS_OK) {
206                     GTEST_LOG_(ERROR) << "doVerify(HIDL) failed with " << int(rsp.code);
207                     return std::nullopt;
208                 }
209                 // "Parse" the returned data to get auth token contents.
210                 if (rsp.data.size() != sizeof(hw_auth_token_t)) {
211                     GTEST_LOG_(ERROR) << "Incorrect size of AuthToken payload.";
212                     return std::nullopt;
213                 }
214                 const hw_auth_token_t* hwAuthToken =
215                         reinterpret_cast<const hw_auth_token_t*>(rsp.data.data());
216                 HardwareAuthToken authToken;
217                 authToken.timestamp.milliSeconds = betoh64(hwAuthToken->timestamp);
218                 authToken.challenge = hwAuthToken->challenge;
219                 authToken.userId = hwAuthToken->user_id;
220                 authToken.authenticatorId = hwAuthToken->authenticator_id;
221                 authToken.authenticatorType = static_cast<HardwareAuthenticatorType>(
222                         betoh32(hwAuthToken->authenticator_type));
223                 authToken.mac.assign(&hwAuthToken->hmac[0], &hwAuthToken->hmac[32]);
224                 return authToken;
225             }
226         } else {
227             return std::nullopt;
228         }
229     }
doVerify(uint32_t uid,uint64_t challenge,const std::vector<uint8_t> & handle,const string & pwd)230     std::optional<HardwareAuthToken> doVerify(uint32_t uid, uint64_t challenge,
231                                               const std::vector<uint8_t>& handle,
232                                               const string& pwd) {
233         return doVerify(uid, challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
234     }
doVerify(uint64_t challenge,const std::vector<uint8_t> & handle,const string & pwd)235     std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
236                                               const std::vector<uint8_t>& handle,
237                                               const string& pwd) {
238         return doVerify(uid_, challenge, handle, pwd);
239     }
240 
241     // 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)242     string ProcessMessage(const vector<uint8_t>& key_blob, KeyPurpose operation,
243                           const string& message, const AuthorizationSet& in_params,
244                           AuthorizationSet* out_params, const HardwareAuthToken& hat) {
245         AuthorizationSet begin_out_params;
246         ErrorCode result = Begin(operation, key_blob, in_params, out_params, hat);
247         EXPECT_EQ(ErrorCode::OK, result);
248         if (result != ErrorCode::OK) {
249             return "";
250         }
251 
252         std::optional<secureclock::TimeStampToken> time_token = std::nullopt;
253         if (timestamp_token_required_ && clock_ != nullptr) {
254             // Ask a secure clock instance for a timestamp, including the per-op challenge.
255             secureclock::TimeStampToken token;
256             EXPECT_EQ(ErrorCode::OK,
257                       GetReturnErrorCode(clock_->generateTimeStamp(challenge_, &token)));
258             time_token = token;
259         }
260 
261         string output;
262         EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &output, hat, time_token));
263         return output;
264     }
265 
EncryptMessage(const vector<uint8_t> & key_blob,const string & message,const AuthorizationSet & in_params,AuthorizationSet * out_params,const HardwareAuthToken & hat)266     string EncryptMessage(const vector<uint8_t>& key_blob, const string& message,
267                           const AuthorizationSet& in_params, AuthorizationSet* out_params,
268                           const HardwareAuthToken& hat) {
269         SCOPED_TRACE("EncryptMessage");
270         return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params, hat);
271     }
272 
DecryptMessage(const vector<uint8_t> & key_blob,const string & ciphertext,const AuthorizationSet & params,const HardwareAuthToken & hat)273     string DecryptMessage(const vector<uint8_t>& key_blob, const string& ciphertext,
274                           const AuthorizationSet& params, const HardwareAuthToken& hat) {
275         SCOPED_TRACE("DecryptMessage");
276         AuthorizationSet out_params;
277         string plaintext =
278                 ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params, hat);
279         EXPECT_TRUE(out_params.empty());
280         return plaintext;
281     }
282 
SignMessage(const vector<uint8_t> & key_blob,const string & message,const AuthorizationSet & in_params,AuthorizationSet * out_params,const HardwareAuthToken & hat)283     string SignMessage(const vector<uint8_t>& key_blob, const string& message,
284                        const AuthorizationSet& in_params, AuthorizationSet* out_params,
285                        const HardwareAuthToken& hat) {
286         SCOPED_TRACE("SignMessage");
287         return ProcessMessage(key_blob, KeyPurpose::SIGN, message, in_params, out_params, hat);
288     }
289 
290   protected:
291     std::shared_ptr<IGatekeeper> gk_;
292     sp<IHidlGatekeeper> hidl_gk_;
293     std::shared_ptr<ISecureClock> clock_;
294     string password_;
295     uint32_t uid_;
296     int64_t sid_;
297     uint32_t alt_uid_;
298     int64_t alt_sid_;
299     std::vector<uint8_t> handle_;
300 };
301 
302 // Test use of a key that requires user-authentication within recent history.
TEST_P(AuthTest,TimeoutAuthentication)303 TEST_P(AuthTest, TimeoutAuthentication) {
304     if (!GatekeeperAvailable()) {
305         GTEST_SKIP() << "No Gatekeeper available";
306     }
307     if (timestamp_token_required_ && clock_ == nullptr) {
308         GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
309     }
310 
311     // Create an AES key that requires authentication within the last 3 seconds.
312     const uint32_t timeout_secs = 3;
313     auto builder = AuthorizationSetBuilder()
314                            .AesEncryptionKey(256)
315                            .BlockMode(BlockMode::ECB)
316                            .Padding(PaddingMode::PKCS7)
317                            .Authorization(TAG_USER_SECURE_ID, sid_)
318                            .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
319                            .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
320     vector<uint8_t> keyblob;
321     vector<KeyCharacteristics> key_characteristics;
322     vector<Certificate> cert_chain;
323     ASSERT_EQ(ErrorCode::OK,
324               GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
325 
326     // Attempt to use the AES key without authentication.
327     const string message = "Hello World!";
328     AuthorizationSet out_params;
329     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
330     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
331               Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
332 
333     // Verify to get a HAT, arbitrary challenge.
334     const uint64_t challenge = 42;
335     const std::optional<HardwareAuthToken> hat = doVerify(challenge, handle_, password_);
336     ASSERT_TRUE(hat.has_value());
337     EXPECT_EQ(hat->userId, sid_);
338 
339     // Adding the auth token makes it possible to use the AES key.
340     const string ciphertext = EncryptMessage(keyblob, message, params, &out_params, hat.value());
341     const string plaintext = DecryptMessage(keyblob, ciphertext, params, hat.value());
342     EXPECT_EQ(message, plaintext);
343 
344     // Altering a single bit in the MAC means no auth.
345     HardwareAuthToken dodgy_hat = hat.value();
346     ASSERT_GT(dodgy_hat.mac.size(), 0);
347     dodgy_hat.mac[0] ^= 0x01;
348     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
349               Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, dodgy_hat));
350 
351     // Wait for long enough that the hardware auth token expires.
352     sleep(timeout_secs + 1);
353 
354     auto begin_result = Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat);
355     if (begin_result == ErrorCode::OK) {
356         // If begin() succeeds despite the out-of-date HAT, that must mean that the KeyMint
357         // device doesn't have its own clock.  In that case, it only detects timeout via a
358         // timestamp token provided on update()/finish()
359         ASSERT_TRUE(timestamp_token_required_);
360 
361         secureclock::TimeStampToken time_token;
362         EXPECT_EQ(ErrorCode::OK,
363                   GetReturnErrorCode(clock_->generateTimeStamp(challenge_, &time_token)));
364 
365         string output;
366         EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
367                   Finish(message, {} /* signature */, &output, hat, time_token));
368     } else {
369         // The KeyMint implementation may have its own clock that can immediately detect timeout.
370         ASSERT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED, begin_result);
371     }
372 }
373 
374 // Test use of a key that requires user-authentication within recent history, but where
375 // the `TimestampToken` provided to the device is unrelated to the in-progress operation.
TEST_P(AuthTest,TimeoutAuthenticationIncorrectTimestampToken)376 TEST_P(AuthTest, TimeoutAuthenticationIncorrectTimestampToken) {
377     if (!GatekeeperAvailable()) {
378         GTEST_SKIP() << "No Gatekeeper available";
379     }
380     if (!timestamp_token_required_) {
381         GTEST_SKIP() << "Test only applies to devices with no secure clock";
382     }
383     if (clock_ == nullptr) {
384         GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
385     }
386 
387     // Create an AES key that requires authentication within the last 3 seconds.
388     const uint32_t timeout_secs = 3;
389     auto builder = AuthorizationSetBuilder()
390                            .AesEncryptionKey(256)
391                            .BlockMode(BlockMode::ECB)
392                            .Padding(PaddingMode::PKCS7)
393                            .Authorization(TAG_USER_SECURE_ID, sid_)
394                            .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
395                            .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
396     vector<uint8_t> keyblob;
397     vector<KeyCharacteristics> key_characteristics;
398     vector<Certificate> cert_chain;
399     ASSERT_EQ(ErrorCode::OK,
400               GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
401 
402     // Verify to get a HAT, arbitrary challenge.
403     const uint64_t challenge = 42;
404     const std::optional<HardwareAuthToken> hat = doVerify(challenge, handle_, password_);
405     ASSERT_TRUE(hat.has_value());
406     EXPECT_EQ(hat->userId, sid_);
407 
408     // KeyMint implementation has no clock, so only detects timeout via timestamp token provided
409     // on update()/finish().  However, for this test we ensure that that the timestamp token has a
410     // *different* challenge value.
411     const string message = "Hello World!";
412     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
413     AuthorizationSet out_params;
414     ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat));
415 
416     secureclock::TimeStampToken time_token;
417     EXPECT_EQ(ErrorCode::OK,
418               GetReturnErrorCode(clock_->generateTimeStamp(challenge_ + 1, &time_token)));
419     string output;
420     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
421               Finish(message, {} /* signature */, &output, hat, time_token));
422 }
423 
424 // Test use of a key with multiple USER_SECURE_ID values.  For variety, use an EC signing key
425 // generated with attestation.
TEST_P(AuthTest,TimeoutAuthenticationMultiSid)426 TEST_P(AuthTest, TimeoutAuthenticationMultiSid) {
427     if (!GatekeeperAvailable()) {
428         GTEST_SKIP() << "No Gatekeeper available";
429     }
430     if (timestamp_token_required_ && clock_ == nullptr) {
431         GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
432     }
433 
434     // Enroll a password for a second user.
435     alt_uid_ = 20001;
436     const string alt_password = "correcthorsebatterystaple2";
437     std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
438     ASSERT_TRUE(rsp.has_value());
439     alt_sid_ = rsp->secureUserId;
440     const std::vector<uint8_t> alt_handle = rsp->data;
441 
442     // Create an attested EC key that requires authentication within the last 3 seconds from either
443     // secure ID. Also allow any authenticator type.
444     const uint32_t timeout_secs = 3;
445     auto builder = AuthorizationSetBuilder()
446                            .EcdsaSigningKey(EcCurve::P_256)
447                            .Digest(Digest::NONE)
448                            .Digest(Digest::SHA_2_256)
449                            .SetDefaultValidity()
450                            .AttestationChallenge("challenge")
451                            .AttestationApplicationId("app_id")
452                            .Authorization(TAG_USER_SECURE_ID, alt_sid_)
453                            .Authorization(TAG_USER_SECURE_ID, sid_)
454                            .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY)
455                            .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
456     vector<uint8_t> keyblob;
457     vector<KeyCharacteristics> key_characteristics;
458     auto result = GenerateKey(builder, &keyblob, &key_characteristics);
459     ASSERT_EQ(ErrorCode::OK, result);
460 
461     // Verify first user to get a HAT that should work.
462     const uint64_t challenge = 42;
463     const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge, handle_, password_);
464     ASSERT_TRUE(hat.has_value());
465     EXPECT_EQ(hat->userId, sid_);
466 
467     const string message = "Hello World!";
468     auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
469     AuthorizationSet out_params;
470     const string signature = SignMessage(keyblob, message, params, &out_params, hat.value());
471 
472     // Verify second user to get a HAT that should work.
473     const uint64_t alt_challenge = 43;
474     const std::optional<HardwareAuthToken> alt_hat =
475             doVerify(alt_uid_, alt_challenge, alt_handle, alt_password);
476     ASSERT_TRUE(alt_hat.has_value());
477     EXPECT_EQ(alt_hat->userId, alt_sid_);
478 
479     const string alt_signature =
480             SignMessage(keyblob, message, params, &out_params, alt_hat.value());
481 }
482 
483 // Test use of a key that requires an auth token for each action on the operation, with
484 // a per-operation challenge value included.
TEST_P(AuthTest,AuthPerOperation)485 TEST_P(AuthTest, AuthPerOperation) {
486     if (!GatekeeperAvailable()) {
487         GTEST_SKIP() << "No Gatekeeper available";
488     }
489 
490     // Create an AES key that requires authentication per-action.
491     auto builder = AuthorizationSetBuilder()
492                            .AesEncryptionKey(256)
493                            .BlockMode(BlockMode::ECB)
494                            .Padding(PaddingMode::PKCS7)
495                            .Authorization(TAG_USER_SECURE_ID, sid_)
496                            .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD);
497     vector<uint8_t> keyblob;
498     vector<KeyCharacteristics> key_characteristics;
499     vector<Certificate> cert_chain;
500     ASSERT_EQ(ErrorCode::OK,
501               GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
502 
503     // Attempt to use the AES key without authentication fails after begin.
504     const string message = "Hello World!";
505     AuthorizationSet out_params;
506     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
507     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
508     string output;
509     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED, Finish(message, {} /* signature */, &output));
510 
511     // Verify to get a HAT, but with an arbitrary challenge.
512     const uint64_t unrelated_challenge = 42;
513     const std::optional<HardwareAuthToken> unrelated_hat =
514             doVerify(unrelated_challenge, handle_, password_);
515     ASSERT_TRUE(unrelated_hat.has_value());
516     EXPECT_EQ(unrelated_hat->userId, sid_);
517 
518     // Attempt to use the AES key with an unrelated authentication fails after begin.
519     EXPECT_EQ(ErrorCode::OK,
520               Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, unrelated_hat.value()));
521     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
522               Finish(message, {} /* signature */, &output, unrelated_hat.value()));
523 
524     // Now get a HAT with the challenge from an in-progress operation.
525     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
526     const std::optional<HardwareAuthToken> hat = doVerify(challenge_, handle_, password_);
527     ASSERT_TRUE(hat.has_value());
528     EXPECT_EQ(hat->userId, sid_);
529     string ciphertext;
530     EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, hat.value()));
531 
532     // Altering a single bit in the MAC means no auth.
533     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
534     std::optional<HardwareAuthToken> dodgy_hat = doVerify(challenge_, handle_, password_);
535     ASSERT_TRUE(dodgy_hat.has_value());
536     EXPECT_EQ(dodgy_hat->userId, sid_);
537     ASSERT_GT(dodgy_hat->mac.size(), 0);
538     dodgy_hat->mac[0] ^= 0x01;
539     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
540               Finish(message, {} /* signature */, &ciphertext, dodgy_hat.value()));
541 }
542 
543 // Test use of a key that requires an auth token for each action on the operation, with
544 // a per-operation challenge value included, with multiple secure IDs allowed.
TEST_P(AuthTest,AuthPerOperationMultiSid)545 TEST_P(AuthTest, AuthPerOperationMultiSid) {
546     if (!GatekeeperAvailable()) {
547         GTEST_SKIP() << "No Gatekeeper available";
548     }
549 
550     // Enroll a password for a second user.
551     alt_uid_ = 20001;
552     const string alt_password = "correcthorsebatterystaple2";
553     std::optional<GatekeeperEnrollResponse> rsp = doEnroll(alt_uid_, alt_password);
554     ASSERT_TRUE(rsp.has_value());
555     alt_sid_ = rsp->secureUserId;
556     const std::vector<uint8_t> alt_handle = rsp->data;
557 
558     // Create an AES key that requires authentication per-action.
559     auto builder = AuthorizationSetBuilder()
560                            .AesEncryptionKey(256)
561                            .BlockMode(BlockMode::ECB)
562                            .Padding(PaddingMode::PKCS7)
563                            .Authorization(TAG_USER_SECURE_ID, sid_)
564                            .Authorization(TAG_USER_SECURE_ID, alt_sid_)
565                            .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::ANY);
566     vector<uint8_t> keyblob;
567     vector<KeyCharacteristics> key_characteristics;
568     vector<Certificate> cert_chain;
569     ASSERT_EQ(ErrorCode::OK,
570               GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
571 
572     // Get a HAT for first user with the challenge from an in-progress operation.
573     const string message = "Hello World!";
574     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
575     AuthorizationSet out_params;
576     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
577     const std::optional<HardwareAuthToken> hat = doVerify(uid_, challenge_, handle_, password_);
578     ASSERT_TRUE(hat.has_value());
579     EXPECT_EQ(hat->userId, sid_);
580     string ciphertext;
581     EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, hat.value()));
582 
583     // Get a HAT for second user with the challenge from an in-progress operation.
584     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
585     const std::optional<HardwareAuthToken> alt_hat =
586             doVerify(alt_uid_, challenge_, alt_handle, alt_password);
587     ASSERT_TRUE(alt_hat.has_value());
588     EXPECT_EQ(alt_hat->userId, alt_sid_);
589     string alt_ciphertext;
590     EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, alt_hat.value()));
591 }
592 
593 // Test use of a key that requires an auth token for each action on the operation, but
594 // which gets passed a HAT of the wrong type
TEST_P(AuthTest,AuthPerOperationWrongAuthType)595 TEST_P(AuthTest, AuthPerOperationWrongAuthType) {
596     if (!GatekeeperAvailable()) {
597         GTEST_SKIP() << "No Gatekeeper available";
598     }
599 
600     // Create an AES key that requires authentication per-action, but with no valid authenticator
601     // types.
602     auto builder =
603             AuthorizationSetBuilder()
604                     .AesEncryptionKey(256)
605                     .BlockMode(BlockMode::ECB)
606                     .Padding(PaddingMode::PKCS7)
607                     .Authorization(TAG_USER_SECURE_ID, sid_)
608                     .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::FINGERPRINT);
609     vector<uint8_t> keyblob;
610     vector<KeyCharacteristics> key_characteristics;
611     vector<Certificate> cert_chain;
612     ASSERT_EQ(ErrorCode::OK,
613               GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
614 
615     // Get a HAT with the challenge from an in-progress operation.
616     const string message = "Hello World!";
617     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
618     AuthorizationSet out_params;
619     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
620     const std::optional<HardwareAuthToken> hat = doVerify(challenge_, handle_, password_);
621     ASSERT_TRUE(hat.has_value());
622     EXPECT_EQ(hat->userId, sid_);
623 
624     // Should fail because auth type doesn't (can't) match.
625     string ciphertext;
626     EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
627               Finish(message, {} /* signature */, &ciphertext, hat.value()));
628 }
629 
630 INSTANTIATE_KEYMINT_AIDL_TEST(AuthTest);
631 
632 }  // namespace aidl::android::hardware::security::keymint::test
633