• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 "PresentationSessionTests"
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 "Util.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 PresentationSessionTests : 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         halApiVersion_ = credentialStore_->getInterfaceVersion();
62     }
63 
64     void provisionData();
65 
66     void provisionSingleDocument(const string& docType, vector<uint8_t>* outCredentialData,
67                                  vector<uint8_t>* outCredentialPubKey);
68 
69     // Set by provisionData
70     vector<uint8_t> credential1Data_;
71     vector<uint8_t> credential1PubKey_;
72     vector<uint8_t> credential2Data_;
73     vector<uint8_t> credential2PubKey_;
74 
75     sp<IIdentityCredentialStore> credentialStore_;
76     int halApiVersion_;
77 };
78 
provisionData()79 void PresentationSessionTests::provisionData() {
80     provisionSingleDocument("org.iso.18013-5.2019.mdl", &credential1Data_, &credential1PubKey_);
81     provisionSingleDocument("org.blah.OtherhDocTypeXX", &credential2Data_, &credential2PubKey_);
82 }
83 
provisionSingleDocument(const string & docType,vector<uint8_t> * outCredentialData,vector<uint8_t> * outCredentialPubKey)84 void PresentationSessionTests::provisionSingleDocument(const string& docType,
85                                                        vector<uint8_t>* outCredentialData,
86                                                        vector<uint8_t>* outCredentialPubKey) {
87     bool testCredential = true;
88     sp<IWritableIdentityCredential> wc;
89     ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
90 
91     vector<uint8_t> attestationApplicationId;
92     vector<uint8_t> attestationChallenge = {1};
93     vector<Certificate> certChain;
94     ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
95                                               &certChain)
96                         .isOk());
97 
98     optional<vector<uint8_t>> optCredentialPubKey =
99             support::certificateChainGetTopMostKey(certChain[0].encodedCertificate);
100     ASSERT_TRUE(optCredentialPubKey);
101     *outCredentialPubKey = optCredentialPubKey.value();
102 
103     size_t proofOfProvisioningSize = 106;
104     // Not in v1 HAL, may fail
105     wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize);
106 
107     ASSERT_TRUE(wc->startPersonalization(1 /* numAccessControlProfiles */,
108                                          {1} /* numDataElementsPerNamespace */)
109                         .isOk());
110 
111     // Access control profile 0: open access - don't care about the returned SACP
112     SecureAccessControlProfile sacp;
113     ASSERT_TRUE(wc->addAccessControlProfile(1, {}, false, 0, 0, &sacp).isOk());
114 
115     // Single entry - don't care about the returned encrypted data
116     ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Some Data", 1).isOk());
117     vector<uint8_t> encryptedData;
118     ASSERT_TRUE(wc->addEntryValue({9}, &encryptedData).isOk());
119 
120     vector<uint8_t> proofOfProvisioningSignature;
121     Status status = wc->finishAddingEntries(outCredentialData, &proofOfProvisioningSignature);
122     EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
123 }
124 
125 // This checks that any methods called on an IIdentityCredential obtained via a session
126 // returns STATUS_FAILED except for startRetrieval(), startRetrieveEntryValue(),
127 // retrieveEntryValue(), finishRetrieval(), setRequestedNamespaces(), setVerificationToken()
128 //
TEST_P(PresentationSessionTests,returnsFailureOnUnsupportedMethods)129 TEST_P(PresentationSessionTests, returnsFailureOnUnsupportedMethods) {
130     if (halApiVersion_ < 4) {
131         GTEST_SKIP() << "Need HAL API version 4, have " << halApiVersion_;
132     }
133 
134     provisionData();
135 
136     sp<IPresentationSession> session;
137     ASSERT_TRUE(credentialStore_
138                         ->createPresentationSession(
139                                 CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
140                                 &session)
141                         .isOk());
142 
143     sp<IIdentityCredential> credential;
144     ASSERT_TRUE(session->getCredential(credential1Data_, &credential).isOk());
145 
146     Status result;
147 
148     vector<uint8_t> signatureProofOfDeletion;
149     result = credential->deleteCredential(&signatureProofOfDeletion);
150     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
151     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
152 
153     vector<uint8_t> ephemeralKeyPair;
154     result = credential->createEphemeralKeyPair(&ephemeralKeyPair);
155     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
156     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
157 
158     result = credential->setReaderEphemeralPublicKey({});
159     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
160     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
161 
162     int64_t authChallenge;
163     result = credential->createAuthChallenge(&authChallenge);
164     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
165     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
166 
167     Certificate certificate;
168     vector<uint8_t> signingKeyBlob;
169     result = credential->generateSigningKeyPair(&signingKeyBlob, &certificate);
170     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
171     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
172 
173     result = credential->deleteCredentialWithChallenge({}, &signatureProofOfDeletion);
174     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
175     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
176 
177     vector<uint8_t> signatureProofOfOwnership;
178     result = credential->proveOwnership({}, &signatureProofOfOwnership);
179     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
180     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
181 
182     sp<IWritableIdentityCredential> writableCredential;
183     result = credential->updateCredential(&writableCredential);
184     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
185     EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
186 }
187 
188 // TODO: need to add tests to check that the returned IIdentityCredential works
189 //       as intended.
190 
191 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresentationSessionTests);
192 INSTANTIATE_TEST_SUITE_P(
193         Identity, PresentationSessionTests,
194         testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
195         android::PrintInstanceNameToString);
196 
197 }  // namespace android::hardware::identity
198