1 /*
2  * Copyright (C) 2019 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 "UserAuthTests"
18 
19 #include <aidl/Gtest.h>
20 #include <aidl/Vintf.h>
21 #include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
22 #include <aidl/android/hardware/keymaster/VerificationToken.h>
23 #include <android-base/logging.h>
24 #include <android/hardware/identity/IIdentityCredentialStore.h>
25 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
26 #include <binder/IServiceManager.h>
27 #include <binder/ProcessState.h>
28 #include <cppbor.h>
29 #include <cppbor_parse.h>
30 #include <gtest/gtest.h>
31 #include <future>
32 #include <map>
33 #include <utility>
34 
35 #include "VtsIdentityTestUtils.h"
36 
37 namespace android::hardware::identity {
38 
39 using std::endl;
40 using std::make_pair;
41 using std::map;
42 using std::optional;
43 using std::pair;
44 using std::string;
45 using std::tie;
46 using std::vector;
47 
48 using ::android::sp;
49 using ::android::String16;
50 using ::android::binder::Status;
51 
52 using ::android::hardware::keymaster::HardwareAuthToken;
53 using ::android::hardware::keymaster::VerificationToken;
54 
55 class UserAuthTests : public testing::TestWithParam<string> {
56   public:
SetUp()57     virtual void SetUp() override {
58         credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
59                 String16(GetParam().c_str()));
60         ASSERT_NE(credentialStore_, nullptr);
61     }
62 
63     void provisionData();
64     void setupRetrieveData();
65     pair<HardwareAuthToken, VerificationToken> mintTokens(uint64_t challengeForAuthToken,
66                                                           int64_t ageOfAuthTokenMilliSeconds);
67     void retrieveData(HardwareAuthToken authToken, VerificationToken verificationToken,
68                       bool expectSuccess, bool useSessionTranscript);
69 
70     // Set by provisionData
71     SecureAccessControlProfile sacp0_;
72     SecureAccessControlProfile sacp1_;
73     SecureAccessControlProfile sacp2_;
74 
75     vector<uint8_t> encContentUserAuthPerSession_;
76     vector<uint8_t> encContentUserAuthTimeout_;
77     vector<uint8_t> encContentAccessibleByAll_;
78     vector<uint8_t> encContentAccessibleByNone_;
79 
80     vector<uint8_t> credentialData_;
81 
82     // Set by setupRetrieveData().
83     int64_t authChallenge_;
84     cppbor::Map sessionTranscript_;
85     sp<IIdentityCredential> credential_;
86 
87     // Set by retrieveData()
88     bool canGetUserAuthPerSession_;
89     bool canGetUserAuthTimeout_;
90     bool canGetAccessibleByAll_;
91     bool canGetAccessibleByNone_;
92 
93     sp<IIdentityCredentialStore> credentialStore_;
94 };
95 
provisionData()96 void UserAuthTests::provisionData() {
97     string docType = "org.iso.18013-5.2019.mdl";
98     bool testCredential = true;
99     sp<IWritableIdentityCredential> wc;
100     ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
101 
102     vector<uint8_t> attestationApplicationId = {};
103     vector<uint8_t> attestationChallenge = {1};
104     vector<Certificate> certChain;
105     ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
106                                               &certChain)
107                         .isOk());
108 
109     size_t proofOfProvisioningSize = 381;
110     // Not in v1 HAL, may fail
111     wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize);
112 
113     ASSERT_TRUE(wc->startPersonalization(3 /* numAccessControlProfiles */,
114                                          {4} /* numDataElementsPerNamespace */)
115                         .isOk());
116 
117     // Access control profile 0: user auth every session (timeout = 0)
118     ASSERT_TRUE(wc->addAccessControlProfile(0, {}, true, 0, 65 /* secureUserId */, &sacp0_).isOk());
119 
120     // Access control profile 1: user auth, 60 seconds timeout
121     ASSERT_TRUE(
122             wc->addAccessControlProfile(1, {}, true, 60000, 65 /* secureUserId */, &sacp1_).isOk());
123 
124     // Access control profile 2: open access
125     ASSERT_TRUE(wc->addAccessControlProfile(2, {}, false, 0, 0, &sacp2_).isOk());
126 
127     // Data Element: "UserAuth Per Session"
128     ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "UserAuth Per Session", 1).isOk());
129     ASSERT_TRUE(wc->addEntryValue({9}, &encContentUserAuthPerSession_).isOk());
130 
131     // Data Element: "UserAuth Timeout"
132     ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "UserAuth Timeout", 1).isOk());
133     ASSERT_TRUE(wc->addEntryValue({9}, &encContentUserAuthTimeout_).isOk());
134 
135     // Data Element: "Accessible by All"
136     ASSERT_TRUE(wc->beginAddEntry({2}, "ns", "Accessible by All", 1).isOk());
137     ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAll_).isOk());
138 
139     // Data Element: "Accessible by None"
140     ASSERT_TRUE(wc->beginAddEntry({}, "ns", "Accessible by None", 1).isOk());
141     ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByNone_).isOk());
142 
143     vector<uint8_t> proofOfProvisioningSignature;
144     Status status = wc->finishAddingEntries(&credentialData_, &proofOfProvisioningSignature);
145     EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
146 }
147 
148 // From ReaderAuthTest.cpp - TODO: consolidate with VtsIdentityTestUtils.h
149 pair<vector<uint8_t>, vector<uint8_t>> generateReaderKey();
150 vector<uint8_t> generateReaderCert(const vector<uint8_t>& publicKey,
151                                    const vector<uint8_t>& signingKey);
152 RequestDataItem buildRequestDataItem(const string& name, size_t size,
153                                      vector<int32_t> accessControlProfileIds);
154 
calcSessionTranscript(const vector<uint8_t> & ePublicKey)155 cppbor::Map calcSessionTranscript(const vector<uint8_t>& ePublicKey) {
156     auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey);
157     cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
158     vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
159     vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
160     // Let SessionTranscript be a map here (it's an array in EndToEndTest) just
161     // to check that the implementation can deal with either.
162     cppbor::Map sessionTranscript;
163     sessionTranscript.add(42, cppbor::Semantic(24, deviceEngagementBytes));
164     sessionTranscript.add(43, cppbor::Semantic(24, eReaderPubBytes));
165     return sessionTranscript;
166 }
167 
setupRetrieveData()168 void UserAuthTests::setupRetrieveData() {
169     ASSERT_TRUE(credentialStore_
170                         ->getCredential(
171                                 CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
172                                 credentialData_, &credential_)
173                         .isOk());
174 
175     optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
176     optional<vector<uint8_t>> readerEPublicKey =
177             support::ecKeyPairGetPublicKey(readerEKeyPair.value());
178     ASSERT_TRUE(credential_->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
179 
180     vector<uint8_t> eKeyPair;
181     ASSERT_TRUE(credential_->createEphemeralKeyPair(&eKeyPair).isOk());
182     optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
183     sessionTranscript_ = calcSessionTranscript(ePublicKey.value());
184 
185     Status status = credential_->createAuthChallenge(&authChallenge_);
186     EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
187 }
188 
retrieveData(HardwareAuthToken authToken,VerificationToken verificationToken,bool expectSuccess,bool useSessionTranscript)189 void UserAuthTests::retrieveData(HardwareAuthToken authToken, VerificationToken verificationToken,
190                                  bool expectSuccess, bool useSessionTranscript) {
191     canGetUserAuthPerSession_ = false;
192     canGetUserAuthTimeout_ = false;
193     canGetAccessibleByAll_ = false;
194     canGetAccessibleByNone_ = false;
195 
196     vector<uint8_t> itemsRequestBytes;
197     vector<uint8_t> sessionTranscriptBytes;
198     if (useSessionTranscript) {
199         sessionTranscriptBytes = sessionTranscript_.encode();
200 
201         itemsRequestBytes =
202                 cppbor::Map("nameSpaces",
203                             cppbor::Map().add("ns", cppbor::Map()
204                                                             .add("UserAuth Per Session", false)
205                                                             .add("UserAuth Timeout", false)
206                                                             .add("Accessible by All", false)
207                                                             .add("Accessible by None", false)))
208                         .encode();
209         vector<uint8_t> dataToSign = cppbor::Array()
210                                              .add("ReaderAuthentication")
211                                              .add(sessionTranscript_.clone())
212                                              .add(cppbor::Semantic(24, itemsRequestBytes))
213                                              .encode();
214     }
215 
216     // Generate the key that will be used to sign AuthenticatedData.
217     vector<uint8_t> signingKeyBlob;
218     Certificate signingKeyCertificate;
219     ASSERT_TRUE(
220             credential_->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
221 
222     RequestNamespace rns;
223     rns.namespaceName = "ns";
224     rns.items.push_back(buildRequestDataItem("UserAuth Per Session", 1, {0}));
225     rns.items.push_back(buildRequestDataItem("UserAuth Timeout", 1, {1}));
226     rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {2}));
227     rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
228     // OK to fail, not available in v1 HAL
229     credential_->setRequestedNamespaces({rns}).isOk();
230 
231     // OK to fail, not available in v1 HAL
232     credential_->setVerificationToken(verificationToken);
233 
234     Status status = credential_->startRetrieval({sacp0_, sacp1_, sacp2_}, authToken,
235                                                 itemsRequestBytes, signingKeyBlob,
236                                                 sessionTranscriptBytes, {} /* readerSignature */,
237                                                 {4 /* numDataElementsPerNamespace */});
238     if (expectSuccess) {
239         ASSERT_TRUE(status.isOk());
240     } else {
241         ASSERT_FALSE(status.isOk());
242         return;
243     }
244 
245     vector<uint8_t> decrypted;
246 
247     status = credential_->startRetrieveEntryValue("ns", "UserAuth Per Session", 1, {0});
248     if (status.isOk()) {
249         canGetUserAuthPerSession_ = true;
250         ASSERT_TRUE(
251                 credential_->retrieveEntryValue(encContentUserAuthPerSession_, &decrypted).isOk());
252     }
253 
254     status = credential_->startRetrieveEntryValue("ns", "UserAuth Timeout", 1, {1});
255     if (status.isOk()) {
256         canGetUserAuthTimeout_ = true;
257         ASSERT_TRUE(credential_->retrieveEntryValue(encContentUserAuthTimeout_, &decrypted).isOk());
258     }
259 
260     status = credential_->startRetrieveEntryValue("ns", "Accessible by All", 1, {2});
261     if (status.isOk()) {
262         canGetAccessibleByAll_ = true;
263         ASSERT_TRUE(credential_->retrieveEntryValue(encContentAccessibleByAll_, &decrypted).isOk());
264     }
265 
266     status = credential_->startRetrieveEntryValue("ns", "Accessible by None", 1, {});
267     if (status.isOk()) {
268         canGetAccessibleByNone_ = true;
269         ASSERT_TRUE(
270                 credential_->retrieveEntryValue(encContentAccessibleByNone_, &decrypted).isOk());
271     }
272 
273     vector<uint8_t> mac;
274     vector<uint8_t> deviceNameSpaces;
275     ASSERT_TRUE(credential_->finishRetrieval(&mac, &deviceNameSpaces).isOk());
276 }
277 
mintTokens(uint64_t challengeForAuthToken,int64_t ageOfAuthTokenMilliSeconds)278 pair<HardwareAuthToken, VerificationToken> UserAuthTests::mintTokens(
279         uint64_t challengeForAuthToken, int64_t ageOfAuthTokenMilliSeconds) {
280     HardwareAuthToken authToken;
281     VerificationToken verificationToken;
282 
283     uint64_t epochMilliseconds = 1000ULL * 1000ULL * 1000ULL * 1000ULL;
284 
285     authToken.challenge = challengeForAuthToken;
286     authToken.userId = 65;
287     authToken.authenticatorId = 0;
288     authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
289     authToken.timestamp.milliSeconds = epochMilliseconds - ageOfAuthTokenMilliSeconds;
290     authToken.mac.clear();
291     verificationToken.challenge = authChallenge_;
292     verificationToken.timestamp.milliSeconds = epochMilliseconds;
293     verificationToken.securityLevel =
294             ::android::hardware::keymaster::SecurityLevel::TRUSTED_ENVIRONMENT;
295     verificationToken.mac.clear();
296     return make_pair(authToken, verificationToken);
297 }
298 
TEST_P(UserAuthTests,GoodChallenge)299 TEST_P(UserAuthTests, GoodChallenge) {
300     provisionData();
301     setupRetrieveData();
302     auto [authToken, verificationToken] = mintTokens(authChallenge_,  // challengeForAuthToken
303                                                      0);              // ageOfAuthTokenMilliSeconds
304     retrieveData(authToken, verificationToken, true /* expectSuccess */,
305                  true /* useSessionTranscript */);
306     EXPECT_TRUE(canGetUserAuthPerSession_);
307     EXPECT_TRUE(canGetUserAuthTimeout_);
308     EXPECT_TRUE(canGetAccessibleByAll_);
309     EXPECT_FALSE(canGetAccessibleByNone_);
310 }
311 
TEST_P(UserAuthTests,OtherChallenge)312 TEST_P(UserAuthTests, OtherChallenge) {
313     provisionData();
314     setupRetrieveData();
315     uint64_t otherChallenge = authChallenge_ ^ 0x12345678;
316     auto [authToken, verificationToken] = mintTokens(otherChallenge,  // challengeForAuthToken
317                                                      0);              // ageOfAuthTokenMilliSeconds
318     retrieveData(authToken, verificationToken, true /* expectSuccess */,
319                  true /* useSessionTranscript */);
320     EXPECT_FALSE(canGetUserAuthPerSession_);
321     EXPECT_TRUE(canGetUserAuthTimeout_);
322     EXPECT_TRUE(canGetAccessibleByAll_);
323     EXPECT_FALSE(canGetAccessibleByNone_);
324 }
325 
TEST_P(UserAuthTests,NoChallenge)326 TEST_P(UserAuthTests, NoChallenge) {
327     provisionData();
328     setupRetrieveData();
329     auto [authToken, verificationToken] = mintTokens(0,   // challengeForAuthToken
330                                                      0);  // ageOfAuthTokenMilliSeconds
331     retrieveData(authToken, verificationToken, true /* expectSuccess */,
332                  true /* useSessionTranscript */);
333     EXPECT_FALSE(canGetUserAuthPerSession_);
334     EXPECT_TRUE(canGetUserAuthTimeout_);
335     EXPECT_TRUE(canGetAccessibleByAll_);
336     EXPECT_FALSE(canGetAccessibleByNone_);
337 }
338 
TEST_P(UserAuthTests,AuthTokenAgeZero)339 TEST_P(UserAuthTests, AuthTokenAgeZero) {
340     provisionData();
341     setupRetrieveData();
342     auto [authToken, verificationToken] = mintTokens(0,   // challengeForAuthToken
343                                                      0);  // ageOfAuthTokenMilliSeconds
344     retrieveData(authToken, verificationToken, true /* expectSuccess */,
345                  true /* useSessionTranscript */);
346     EXPECT_FALSE(canGetUserAuthPerSession_);
347     EXPECT_TRUE(canGetUserAuthTimeout_);
348     EXPECT_TRUE(canGetAccessibleByAll_);
349     EXPECT_FALSE(canGetAccessibleByNone_);
350 }
351 
TEST_P(UserAuthTests,AuthTokenFromTheFuture)352 TEST_P(UserAuthTests, AuthTokenFromTheFuture) {
353     provisionData();
354     setupRetrieveData();
355     auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
356                                                      -1 * 1000);  // ageOfAuthTokenMilliSeconds
357     retrieveData(authToken, verificationToken, true /* expectSuccess */,
358                  true /* useSessionTranscript */);
359     EXPECT_FALSE(canGetUserAuthPerSession_);
360     EXPECT_FALSE(canGetUserAuthTimeout_);
361     EXPECT_TRUE(canGetAccessibleByAll_);
362     EXPECT_FALSE(canGetAccessibleByNone_);
363 }
364 
TEST_P(UserAuthTests,AuthTokenInsideTimeout)365 TEST_P(UserAuthTests, AuthTokenInsideTimeout) {
366     provisionData();
367     setupRetrieveData();
368     auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
369                                                      30 * 1000);  // ageOfAuthTokenMilliSeconds
370     retrieveData(authToken, verificationToken, true /* expectSuccess */,
371                  true /* useSessionTranscript */);
372     EXPECT_FALSE(canGetUserAuthPerSession_);
373     EXPECT_TRUE(canGetUserAuthTimeout_);
374     EXPECT_TRUE(canGetAccessibleByAll_);
375     EXPECT_FALSE(canGetAccessibleByNone_);
376 }
377 
TEST_P(UserAuthTests,AuthTokenOutsideTimeout)378 TEST_P(UserAuthTests, AuthTokenOutsideTimeout) {
379     provisionData();
380     setupRetrieveData();
381     auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
382                                                      61 * 1000);  // ageOfAuthTokenMilliSeconds
383     retrieveData(authToken, verificationToken, true /* expectSuccess */,
384                  true /* useSessionTranscript */);
385     EXPECT_FALSE(canGetUserAuthPerSession_);
386     EXPECT_FALSE(canGetUserAuthTimeout_);
387     EXPECT_TRUE(canGetAccessibleByAll_);
388     EXPECT_FALSE(canGetAccessibleByNone_);
389 }
390 
391 // The API works even when there's no SessionTranscript / itemsRequest.
392 // Verify that.
TEST_P(UserAuthTests,NoSessionTranscript)393 TEST_P(UserAuthTests, NoSessionTranscript) {
394     provisionData();
395     setupRetrieveData();
396     auto [authToken, verificationToken] = mintTokens(0,          // challengeForAuthToken
397                                                      1 * 1000);  // ageOfAuthTokenMilliSeconds
398     retrieveData(authToken, verificationToken, true /* expectSuccess */,
399                  false /* useSessionTranscript */);
400     EXPECT_FALSE(canGetUserAuthPerSession_);
401     EXPECT_TRUE(canGetUserAuthTimeout_);
402     EXPECT_TRUE(canGetAccessibleByAll_);
403     EXPECT_FALSE(canGetAccessibleByNone_);
404 }
405 
406 // This test verifies that it's possible to do multiple requests as long
407 // as the sessionTranscript doesn't change.
408 //
TEST_P(UserAuthTests,MultipleRequestsSameSessionTranscript)409 TEST_P(UserAuthTests, MultipleRequestsSameSessionTranscript) {
410     provisionData();
411     setupRetrieveData();
412 
413     // First we try with a stale authToken
414     //
415     auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
416                                                      61 * 1000);  // ageOfAuthTokenMilliSeconds
417     retrieveData(authToken, verificationToken, true /* expectSuccess */,
418                  true /* useSessionTranscript */);
419     EXPECT_FALSE(canGetUserAuthPerSession_);
420     EXPECT_FALSE(canGetUserAuthTimeout_);
421     EXPECT_TRUE(canGetAccessibleByAll_);
422     EXPECT_FALSE(canGetAccessibleByNone_);
423 
424     // Then we get a new authToken and try again.
425     tie(authToken, verificationToken) = mintTokens(0,          // challengeForAuthToken
426                                                    5 * 1000);  // ageOfAuthTokenMilliSeconds
427     retrieveData(authToken, verificationToken, true /* expectSuccess */,
428                  true /* useSessionTranscript */);
429     EXPECT_FALSE(canGetUserAuthPerSession_);
430     EXPECT_TRUE(canGetUserAuthTimeout_);
431     EXPECT_TRUE(canGetAccessibleByAll_);
432     EXPECT_FALSE(canGetAccessibleByNone_);
433 }
434 
435 // Like MultipleRequestsSameSessionTranscript but we change the sessionTranscript
436 // between the two calls. This test verifies that change is detected and the
437 // second request fails.
438 //
TEST_P(UserAuthTests,MultipleRequestsSessionTranscriptChanges)439 TEST_P(UserAuthTests, MultipleRequestsSessionTranscriptChanges) {
440     provisionData();
441     setupRetrieveData();
442 
443     // First we try with a stale authToken
444     //
445     auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
446                                                      61 * 1000);  // ageOfAuthTokenMilliSeconds
447     retrieveData(authToken, verificationToken, true /* expectSuccess */,
448                  true /* useSessionTranscript */);
449     EXPECT_FALSE(canGetUserAuthPerSession_);
450     EXPECT_FALSE(canGetUserAuthTimeout_);
451     EXPECT_TRUE(canGetAccessibleByAll_);
452     EXPECT_FALSE(canGetAccessibleByNone_);
453 
454     // Then we get a new authToken and try again.
455     tie(authToken, verificationToken) = mintTokens(0,          // challengeForAuthToken
456                                                    5 * 1000);  // ageOfAuthTokenMilliSeconds
457 
458     // Change sessionTranscript...
459     optional<vector<uint8_t>> eKeyPairNew = support::createEcKeyPair();
460     optional<vector<uint8_t>> ePublicKeyNew = support::ecKeyPairGetPublicKey(eKeyPairNew.value());
461     sessionTranscript_ = calcSessionTranscript(ePublicKeyNew.value());
462 
463     // ... and expect failure.
464     retrieveData(authToken, verificationToken, false /* expectSuccess */,
465                  true /* useSessionTranscript */);
466 }
467 
468 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UserAuthTests);
469 INSTANTIATE_TEST_SUITE_P(
470         Identity, UserAuthTests,
471         testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
472         android::PrintInstanceNameToString);
473 
474 }  // namespace android::hardware::identity
475