xref: /aosp_15_r20/hardware/interfaces/identity/aidl/vts/EndToEndTests.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright (C) 2019 The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "VtsHalIdentityEndToEndTest"
17*4d7e907cSAndroid Build Coastguard Worker 
18*4d7e907cSAndroid Build Coastguard Worker #include <aidl/Gtest.h>
19*4d7e907cSAndroid Build Coastguard Worker #include <aidl/Vintf.h>
20*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
21*4d7e907cSAndroid Build Coastguard Worker #include <android/hardware/identity/IIdentityCredentialStore.h>
22*4d7e907cSAndroid Build Coastguard Worker #include <android/hardware/identity/support/IdentityCredentialSupport.h>
23*4d7e907cSAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <binder/ProcessState.h>
25*4d7e907cSAndroid Build Coastguard Worker #include <cppbor.h>
26*4d7e907cSAndroid Build Coastguard Worker #include <cppbor_parse.h>
27*4d7e907cSAndroid Build Coastguard Worker #include <gtest/gtest.h>
28*4d7e907cSAndroid Build Coastguard Worker #include <future>
29*4d7e907cSAndroid Build Coastguard Worker #include <map>
30*4d7e907cSAndroid Build Coastguard Worker #include <tuple>
31*4d7e907cSAndroid Build Coastguard Worker 
32*4d7e907cSAndroid Build Coastguard Worker #include "Util.h"
33*4d7e907cSAndroid Build Coastguard Worker 
34*4d7e907cSAndroid Build Coastguard Worker namespace android::hardware::identity {
35*4d7e907cSAndroid Build Coastguard Worker 
36*4d7e907cSAndroid Build Coastguard Worker using std::endl;
37*4d7e907cSAndroid Build Coastguard Worker using std::make_tuple;
38*4d7e907cSAndroid Build Coastguard Worker using std::map;
39*4d7e907cSAndroid Build Coastguard Worker using std::optional;
40*4d7e907cSAndroid Build Coastguard Worker using std::string;
41*4d7e907cSAndroid Build Coastguard Worker using std::tuple;
42*4d7e907cSAndroid Build Coastguard Worker using std::vector;
43*4d7e907cSAndroid Build Coastguard Worker 
44*4d7e907cSAndroid Build Coastguard Worker using ::android::sp;
45*4d7e907cSAndroid Build Coastguard Worker using ::android::String16;
46*4d7e907cSAndroid Build Coastguard Worker using ::android::binder::Status;
47*4d7e907cSAndroid Build Coastguard Worker 
48*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::keymaster::HardwareAuthToken;
49*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::keymaster::VerificationToken;
50*4d7e907cSAndroid Build Coastguard Worker 
51*4d7e907cSAndroid Build Coastguard Worker using test_utils::validateAttestationCertificate;
52*4d7e907cSAndroid Build Coastguard Worker 
53*4d7e907cSAndroid Build Coastguard Worker class EndToEndTests : public testing::TestWithParam<std::string> {
54*4d7e907cSAndroid Build Coastguard Worker   public:
SetUp()55*4d7e907cSAndroid Build Coastguard Worker     virtual void SetUp() override {
56*4d7e907cSAndroid Build Coastguard Worker         credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
57*4d7e907cSAndroid Build Coastguard Worker                 String16(GetParam().c_str()));
58*4d7e907cSAndroid Build Coastguard Worker         ASSERT_NE(credentialStore_, nullptr);
59*4d7e907cSAndroid Build Coastguard Worker         halApiVersion_ = credentialStore_->getInterfaceVersion();
60*4d7e907cSAndroid Build Coastguard Worker     }
61*4d7e907cSAndroid Build Coastguard Worker 
62*4d7e907cSAndroid Build Coastguard Worker     sp<IIdentityCredentialStore> credentialStore_;
63*4d7e907cSAndroid Build Coastguard Worker     int halApiVersion_;
64*4d7e907cSAndroid Build Coastguard Worker };
65*4d7e907cSAndroid Build Coastguard Worker 
TEST_P(EndToEndTests,hardwareInformation)66*4d7e907cSAndroid Build Coastguard Worker TEST_P(EndToEndTests, hardwareInformation) {
67*4d7e907cSAndroid Build Coastguard Worker     HardwareInformation info;
68*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credentialStore_->getHardwareInformation(&info).isOk());
69*4d7e907cSAndroid Build Coastguard Worker     ASSERT_GT(info.credentialStoreName.size(), 0);
70*4d7e907cSAndroid Build Coastguard Worker     ASSERT_GT(info.credentialStoreAuthorName.size(), 0);
71*4d7e907cSAndroid Build Coastguard Worker     ASSERT_GE(info.dataChunkSize, 256);
72*4d7e907cSAndroid Build Coastguard Worker }
73*4d7e907cSAndroid Build Coastguard Worker 
74*4d7e907cSAndroid Build Coastguard Worker tuple<bool, string, vector<uint8_t>, vector<uint8_t>, vector<uint8_t>>
extractFromTestCredentialData(const vector<uint8_t> & credentialData)75*4d7e907cSAndroid Build Coastguard Worker extractFromTestCredentialData(const vector<uint8_t>& credentialData) {
76*4d7e907cSAndroid Build Coastguard Worker     string docType;
77*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> storageKey;
78*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> credentialPrivKey;
79*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> sha256Pop;
80*4d7e907cSAndroid Build Coastguard Worker 
81*4d7e907cSAndroid Build Coastguard Worker     auto [item, _, message] = cppbor::parse(credentialData);
82*4d7e907cSAndroid Build Coastguard Worker     if (item == nullptr) {
83*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
84*4d7e907cSAndroid Build Coastguard Worker     }
85*4d7e907cSAndroid Build Coastguard Worker 
86*4d7e907cSAndroid Build Coastguard Worker     const cppbor::Array* arrayItem = item->asArray();
87*4d7e907cSAndroid Build Coastguard Worker     if (arrayItem == nullptr || arrayItem->size() != 3) {
88*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
89*4d7e907cSAndroid Build Coastguard Worker     }
90*4d7e907cSAndroid Build Coastguard Worker 
91*4d7e907cSAndroid Build Coastguard Worker     const cppbor::Tstr* docTypeItem = (*arrayItem)[0]->asTstr();
92*4d7e907cSAndroid Build Coastguard Worker     const cppbor::Bool* testCredentialItem =
93*4d7e907cSAndroid Build Coastguard Worker             ((*arrayItem)[1]->asSimple() != nullptr ? ((*arrayItem)[1]->asSimple()->asBool())
94*4d7e907cSAndroid Build Coastguard Worker                                                     : nullptr);
95*4d7e907cSAndroid Build Coastguard Worker     const cppbor::Bstr* encryptedCredentialKeysItem = (*arrayItem)[2]->asBstr();
96*4d7e907cSAndroid Build Coastguard Worker     if (docTypeItem == nullptr || testCredentialItem == nullptr ||
97*4d7e907cSAndroid Build Coastguard Worker         encryptedCredentialKeysItem == nullptr) {
98*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
99*4d7e907cSAndroid Build Coastguard Worker     }
100*4d7e907cSAndroid Build Coastguard Worker 
101*4d7e907cSAndroid Build Coastguard Worker     docType = docTypeItem->value();
102*4d7e907cSAndroid Build Coastguard Worker 
103*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> hardwareBoundKey = support::getTestHardwareBoundKey();
104*4d7e907cSAndroid Build Coastguard Worker     const vector<uint8_t>& encryptedCredentialKeys = encryptedCredentialKeysItem->value();
105*4d7e907cSAndroid Build Coastguard Worker     const vector<uint8_t> docTypeVec(docType.begin(), docType.end());
106*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> decryptedCredentialKeys =
107*4d7e907cSAndroid Build Coastguard Worker             support::decryptAes128Gcm(hardwareBoundKey, encryptedCredentialKeys, docTypeVec);
108*4d7e907cSAndroid Build Coastguard Worker     if (!decryptedCredentialKeys) {
109*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
110*4d7e907cSAndroid Build Coastguard Worker     }
111*4d7e907cSAndroid Build Coastguard Worker 
112*4d7e907cSAndroid Build Coastguard Worker     auto [dckItem, dckPos, dckMessage] = cppbor::parse(decryptedCredentialKeys.value());
113*4d7e907cSAndroid Build Coastguard Worker     if (dckItem == nullptr) {
114*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
115*4d7e907cSAndroid Build Coastguard Worker     }
116*4d7e907cSAndroid Build Coastguard Worker     const cppbor::Array* dckArrayItem = dckItem->asArray();
117*4d7e907cSAndroid Build Coastguard Worker     if (dckArrayItem == nullptr) {
118*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
119*4d7e907cSAndroid Build Coastguard Worker     }
120*4d7e907cSAndroid Build Coastguard Worker     if (dckArrayItem->size() < 2) {
121*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
122*4d7e907cSAndroid Build Coastguard Worker     }
123*4d7e907cSAndroid Build Coastguard Worker     const cppbor::Bstr* storageKeyItem = (*dckArrayItem)[0]->asBstr();
124*4d7e907cSAndroid Build Coastguard Worker     const cppbor::Bstr* credentialPrivKeyItem = (*dckArrayItem)[1]->asBstr();
125*4d7e907cSAndroid Build Coastguard Worker     if (storageKeyItem == nullptr || credentialPrivKeyItem == nullptr) {
126*4d7e907cSAndroid Build Coastguard Worker         return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
127*4d7e907cSAndroid Build Coastguard Worker     }
128*4d7e907cSAndroid Build Coastguard Worker     storageKey = storageKeyItem->value();
129*4d7e907cSAndroid Build Coastguard Worker     credentialPrivKey = credentialPrivKeyItem->value();
130*4d7e907cSAndroid Build Coastguard Worker     if (dckArrayItem->size() == 3) {
131*4d7e907cSAndroid Build Coastguard Worker         const cppbor::Bstr* sha256PopItem = (*dckArrayItem)[2]->asBstr();
132*4d7e907cSAndroid Build Coastguard Worker         if (sha256PopItem == nullptr) {
133*4d7e907cSAndroid Build Coastguard Worker             return make_tuple(false, docType, storageKey, credentialPrivKey, sha256Pop);
134*4d7e907cSAndroid Build Coastguard Worker         }
135*4d7e907cSAndroid Build Coastguard Worker         sha256Pop = sha256PopItem->value();
136*4d7e907cSAndroid Build Coastguard Worker     }
137*4d7e907cSAndroid Build Coastguard Worker     return make_tuple(true, docType, storageKey, credentialPrivKey, sha256Pop);
138*4d7e907cSAndroid Build Coastguard Worker }
139*4d7e907cSAndroid Build Coastguard Worker 
TEST_P(EndToEndTests,createAndRetrieveCredential)140*4d7e907cSAndroid Build Coastguard Worker TEST_P(EndToEndTests, createAndRetrieveCredential) {
141*4d7e907cSAndroid Build Coastguard Worker     // First, generate a key-pair for the reader since its public key will be
142*4d7e907cSAndroid Build Coastguard Worker     // part of the request data.
143*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> readerKey;
144*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerCertificate =
145*4d7e907cSAndroid Build Coastguard Worker             test_utils::generateReaderCertificate("1234", &readerKey);
146*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(readerCertificate);
147*4d7e907cSAndroid Build Coastguard Worker 
148*4d7e907cSAndroid Build Coastguard Worker     // Make the portrait image really big (just shy of 256 KiB) to ensure that
149*4d7e907cSAndroid Build Coastguard Worker     // the chunking code gets exercised.
150*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> portraitImage;
151*4d7e907cSAndroid Build Coastguard Worker     test_utils::setImageData(portraitImage);
152*4d7e907cSAndroid Build Coastguard Worker 
153*4d7e907cSAndroid Build Coastguard Worker     // Access control profiles:
154*4d7e907cSAndroid Build Coastguard Worker     const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
155*4d7e907cSAndroid Build Coastguard Worker                                                           {0, readerCertificate.value(), false, 0},
156*4d7e907cSAndroid Build Coastguard Worker                                                           // Profile 1 (no authentication)
157*4d7e907cSAndroid Build Coastguard Worker                                                           {1, {}, false, 0}};
158*4d7e907cSAndroid Build Coastguard Worker 
159*4d7e907cSAndroid Build Coastguard Worker     // It doesn't matter since no user auth is needed in this particular test,
160*4d7e907cSAndroid Build Coastguard Worker     // but for good measure, clear out the tokens we pass to the HAL.
161*4d7e907cSAndroid Build Coastguard Worker     HardwareAuthToken authToken;
162*4d7e907cSAndroid Build Coastguard Worker     VerificationToken verificationToken;
163*4d7e907cSAndroid Build Coastguard Worker     authToken.challenge = 0;
164*4d7e907cSAndroid Build Coastguard Worker     authToken.userId = 0;
165*4d7e907cSAndroid Build Coastguard Worker     authToken.authenticatorId = 0;
166*4d7e907cSAndroid Build Coastguard Worker     authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
167*4d7e907cSAndroid Build Coastguard Worker     authToken.timestamp.milliSeconds = 0;
168*4d7e907cSAndroid Build Coastguard Worker     authToken.mac.clear();
169*4d7e907cSAndroid Build Coastguard Worker     verificationToken.challenge = 0;
170*4d7e907cSAndroid Build Coastguard Worker     verificationToken.timestamp.milliSeconds = 0;
171*4d7e907cSAndroid Build Coastguard Worker     verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
172*4d7e907cSAndroid Build Coastguard Worker     verificationToken.mac.clear();
173*4d7e907cSAndroid Build Coastguard Worker 
174*4d7e907cSAndroid Build Coastguard Worker     // Here's the actual test data:
175*4d7e907cSAndroid Build Coastguard Worker     const vector<test_utils::TestEntryData> testEntries = {
176*4d7e907cSAndroid Build Coastguard Worker             {"PersonalData", "Last name", string("Turing"), vector<int32_t>{0, 1}},
177*4d7e907cSAndroid Build Coastguard Worker             {"PersonalData", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
178*4d7e907cSAndroid Build Coastguard Worker             {"PersonalData", "First name", string("Alan"), vector<int32_t>{0, 1}},
179*4d7e907cSAndroid Build Coastguard Worker             {"PersonalData", "Home address", string("Maida Vale, London, England"),
180*4d7e907cSAndroid Build Coastguard Worker              vector<int32_t>{0}},
181*4d7e907cSAndroid Build Coastguard Worker             {"Image", "Portrait image", portraitImage, vector<int32_t>{0, 1}},
182*4d7e907cSAndroid Build Coastguard Worker     };
183*4d7e907cSAndroid Build Coastguard Worker     const vector<int32_t> testEntriesEntryCounts = {static_cast<int32_t>(testEntries.size() - 1),
184*4d7e907cSAndroid Build Coastguard Worker                                                     1u};
185*4d7e907cSAndroid Build Coastguard Worker     HardwareInformation hwInfo;
186*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
187*4d7e907cSAndroid Build Coastguard Worker 
188*4d7e907cSAndroid Build Coastguard Worker     string cborPretty;
189*4d7e907cSAndroid Build Coastguard Worker     sp<IWritableIdentityCredential> writableCredential;
190*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
191*4d7e907cSAndroid Build Coastguard Worker                                                     true /* testCredential */));
192*4d7e907cSAndroid Build Coastguard Worker 
193*4d7e907cSAndroid Build Coastguard Worker     string challenge = "attestationChallenge";
194*4d7e907cSAndroid Build Coastguard Worker     test_utils::AttestationData attData(writableCredential, challenge,
195*4d7e907cSAndroid Build Coastguard Worker                                         {1} /* atteestationApplicationId */);
196*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(attData.result.isOk())
197*4d7e907cSAndroid Build Coastguard Worker             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
198*4d7e907cSAndroid Build Coastguard Worker 
199*4d7e907cSAndroid Build Coastguard Worker     validateAttestationCertificate(attData.attestationCertificate, attData.attestationChallenge,
200*4d7e907cSAndroid Build Coastguard Worker                                    attData.attestationApplicationId, true);
201*4d7e907cSAndroid Build Coastguard Worker 
202*4d7e907cSAndroid Build Coastguard Worker     // This is kinda of a hack but we need to give the size of
203*4d7e907cSAndroid Build Coastguard Worker     // ProofOfProvisioning that we'll expect to receive.
204*4d7e907cSAndroid Build Coastguard Worker     const int32_t expectedProofOfProvisioningSize = 262861 - 326 + readerCertificate.value().size();
205*4d7e907cSAndroid Build Coastguard Worker     // OK to fail, not available in v1 HAL
206*4d7e907cSAndroid Build Coastguard Worker     writableCredential->setExpectedProofOfProvisioningSize(expectedProofOfProvisioningSize);
207*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(
208*4d7e907cSAndroid Build Coastguard Worker             writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts)
209*4d7e907cSAndroid Build Coastguard Worker                     .isOk());
210*4d7e907cSAndroid Build Coastguard Worker 
211*4d7e907cSAndroid Build Coastguard Worker     optional<vector<SecureAccessControlProfile>> secureProfiles =
212*4d7e907cSAndroid Build Coastguard Worker             test_utils::addAccessControlProfiles(writableCredential, testProfiles);
213*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(secureProfiles);
214*4d7e907cSAndroid Build Coastguard Worker 
215*4d7e907cSAndroid Build Coastguard Worker     // Uses TestEntryData* pointer as key and values are the encrypted blobs. This
216*4d7e907cSAndroid Build Coastguard Worker     // is a little hacky but it works well enough.
217*4d7e907cSAndroid Build Coastguard Worker     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
218*4d7e907cSAndroid Build Coastguard Worker 
219*4d7e907cSAndroid Build Coastguard Worker     for (const auto& entry : testEntries) {
220*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
221*4d7e907cSAndroid Build Coastguard Worker                                          encryptedBlobs, true));
222*4d7e907cSAndroid Build Coastguard Worker     }
223*4d7e907cSAndroid Build Coastguard Worker 
224*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> credentialData;
225*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> proofOfProvisioningSignature;
226*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(
227*4d7e907cSAndroid Build Coastguard Worker             writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature)
228*4d7e907cSAndroid Build Coastguard Worker                     .isOk());
229*4d7e907cSAndroid Build Coastguard Worker 
230*4d7e907cSAndroid Build Coastguard Worker     // Validate the proofOfProvisioning which was returned
231*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> proofOfProvisioning =
232*4d7e907cSAndroid Build Coastguard Worker             support::coseSignGetPayload(proofOfProvisioningSignature);
233*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(proofOfProvisioning);
234*4d7e907cSAndroid Build Coastguard Worker     cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
235*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(
236*4d7e907cSAndroid Build Coastguard Worker             "[\n"
237*4d7e907cSAndroid Build Coastguard Worker             "  'ProofOfProvisioning',\n"
238*4d7e907cSAndroid Build Coastguard Worker             "  'org.iso.18013-5.2019.mdl',\n"
239*4d7e907cSAndroid Build Coastguard Worker             "  [\n"
240*4d7e907cSAndroid Build Coastguard Worker             "    {\n"
241*4d7e907cSAndroid Build Coastguard Worker             "      'id' : 0,\n"
242*4d7e907cSAndroid Build Coastguard Worker             "      'readerCertificate' : <not printed>,\n"
243*4d7e907cSAndroid Build Coastguard Worker             "    },\n"
244*4d7e907cSAndroid Build Coastguard Worker             "    {\n"
245*4d7e907cSAndroid Build Coastguard Worker             "      'id' : 1,\n"
246*4d7e907cSAndroid Build Coastguard Worker             "    },\n"
247*4d7e907cSAndroid Build Coastguard Worker             "  ],\n"
248*4d7e907cSAndroid Build Coastguard Worker             "  {\n"
249*4d7e907cSAndroid Build Coastguard Worker             "    'PersonalData' : [\n"
250*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
251*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'Last name',\n"
252*4d7e907cSAndroid Build Coastguard Worker             "        'value' : 'Turing',\n"
253*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, 1, ],\n"
254*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
255*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
256*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'Birth date',\n"
257*4d7e907cSAndroid Build Coastguard Worker             "        'value' : '19120623',\n"
258*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, 1, ],\n"
259*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
260*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
261*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'First name',\n"
262*4d7e907cSAndroid Build Coastguard Worker             "        'value' : 'Alan',\n"
263*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, 1, ],\n"
264*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
265*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
266*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'Home address',\n"
267*4d7e907cSAndroid Build Coastguard Worker             "        'value' : 'Maida Vale, London, England',\n"
268*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, ],\n"
269*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
270*4d7e907cSAndroid Build Coastguard Worker             "    ],\n"
271*4d7e907cSAndroid Build Coastguard Worker             "    'Image' : [\n"
272*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
273*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'Portrait image',\n"
274*4d7e907cSAndroid Build Coastguard Worker             "        'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
275*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, 1, ],\n"
276*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
277*4d7e907cSAndroid Build Coastguard Worker             "    ],\n"
278*4d7e907cSAndroid Build Coastguard Worker             "  },\n"
279*4d7e907cSAndroid Build Coastguard Worker             "  true,\n"
280*4d7e907cSAndroid Build Coastguard Worker             "]",
281*4d7e907cSAndroid Build Coastguard Worker             cborPretty);
282*4d7e907cSAndroid Build Coastguard Worker 
283*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
284*4d7e907cSAndroid Build Coastguard Worker             attData.attestationCertificate[0].encodedCertificate);
285*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credentialPubKey);
286*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
287*4d7e907cSAndroid Build Coastguard Worker                                                  {},  // Additional data
288*4d7e907cSAndroid Build Coastguard Worker                                                  credentialPubKey.value()));
289*4d7e907cSAndroid Build Coastguard Worker     writableCredential = nullptr;
290*4d7e907cSAndroid Build Coastguard Worker 
291*4d7e907cSAndroid Build Coastguard Worker     // Extract doctype, storage key, and credentialPrivKey from credentialData... this works
292*4d7e907cSAndroid Build Coastguard Worker     // only because we asked for a test-credential meaning that the HBK is all zeroes.
293*4d7e907cSAndroid Build Coastguard Worker     auto [exSuccess, exDocType, exStorageKey, exCredentialPrivKey, exSha256Pop] =
294*4d7e907cSAndroid Build Coastguard Worker             extractFromTestCredentialData(credentialData);
295*4d7e907cSAndroid Build Coastguard Worker 
296*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exSuccess);
297*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(exDocType, "org.iso.18013-5.2019.mdl");
298*4d7e907cSAndroid Build Coastguard Worker     // ... check that the public key derived from the private key matches what was
299*4d7e907cSAndroid Build Coastguard Worker     // in the certificate.
300*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> exCredentialKeyPair =
301*4d7e907cSAndroid Build Coastguard Worker             support::ecPrivateKeyToKeyPair(exCredentialPrivKey);
302*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exCredentialKeyPair);
303*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> exCredentialPubKey =
304*4d7e907cSAndroid Build Coastguard Worker             support::ecKeyPairGetPublicKey(exCredentialKeyPair.value());
305*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exCredentialPubKey);
306*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(exCredentialPubKey.value(), credentialPubKey.value());
307*4d7e907cSAndroid Build Coastguard Worker 
308*4d7e907cSAndroid Build Coastguard Worker     // Starting with API version 3 (feature version 202101) we require SHA-256(ProofOfProvisioning)
309*4d7e907cSAndroid Build Coastguard Worker     // to be in CredentialKeys (which is stored encrypted in CredentialData). Check
310*4d7e907cSAndroid Build Coastguard Worker     // that it's there with the expected value.
311*4d7e907cSAndroid Build Coastguard Worker     if (halApiVersion_ >= 3) {
312*4d7e907cSAndroid Build Coastguard Worker         ASSERT_EQ(exSha256Pop, support::sha256(proofOfProvisioning.value()));
313*4d7e907cSAndroid Build Coastguard Worker     }
314*4d7e907cSAndroid Build Coastguard Worker 
315*4d7e907cSAndroid Build Coastguard Worker     // Now that the credential has been provisioned, read it back and check the
316*4d7e907cSAndroid Build Coastguard Worker     // correct data is returned.
317*4d7e907cSAndroid Build Coastguard Worker     sp<IIdentityCredential> credential;
318*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credentialStore_
319*4d7e907cSAndroid Build Coastguard Worker                         ->getCredential(
320*4d7e907cSAndroid Build Coastguard Worker                                 CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
321*4d7e907cSAndroid Build Coastguard Worker                                 credentialData, &credential)
322*4d7e907cSAndroid Build Coastguard Worker                         .isOk());
323*4d7e907cSAndroid Build Coastguard Worker     ASSERT_NE(credential, nullptr);
324*4d7e907cSAndroid Build Coastguard Worker 
325*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerEphemeralKeyPair = support::createEcKeyPair();
326*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(readerEphemeralKeyPair);
327*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerEphemeralPublicKey =
328*4d7e907cSAndroid Build Coastguard Worker             support::ecKeyPairGetPublicKey(readerEphemeralKeyPair.value());
329*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential->setReaderEphemeralPublicKey(readerEphemeralPublicKey.value()).isOk());
330*4d7e907cSAndroid Build Coastguard Worker 
331*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> ephemeralKeyPair;
332*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential->createEphemeralKeyPair(&ephemeralKeyPair).isOk());
333*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> ephemeralPublicKey = support::ecKeyPairGetPublicKey(ephemeralKeyPair);
334*4d7e907cSAndroid Build Coastguard Worker 
335*4d7e907cSAndroid Build Coastguard Worker     // Calculate requestData field and sign it with the reader key.
336*4d7e907cSAndroid Build Coastguard Worker     auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ephemeralPublicKey.value());
337*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(getXYSuccess);
338*4d7e907cSAndroid Build Coastguard Worker     cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
339*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
340*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
341*4d7e907cSAndroid Build Coastguard Worker     cppbor::Array sessionTranscript = cppbor::Array()
342*4d7e907cSAndroid Build Coastguard Worker                                               .add(cppbor::SemanticTag(24, deviceEngagementBytes))
343*4d7e907cSAndroid Build Coastguard Worker                                               .add(cppbor::SemanticTag(24, eReaderPubBytes));
344*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
345*4d7e907cSAndroid Build Coastguard Worker 
346*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> itemsRequestBytes =
347*4d7e907cSAndroid Build Coastguard Worker             cppbor::Map("nameSpaces",
348*4d7e907cSAndroid Build Coastguard Worker                         cppbor::Map()
349*4d7e907cSAndroid Build Coastguard Worker                                 .add("PersonalData", cppbor::Map()
350*4d7e907cSAndroid Build Coastguard Worker                                                              .add("Last name", false)
351*4d7e907cSAndroid Build Coastguard Worker                                                              .add("Birth date", false)
352*4d7e907cSAndroid Build Coastguard Worker                                                              .add("First name", false)
353*4d7e907cSAndroid Build Coastguard Worker                                                              .add("Home address", true))
354*4d7e907cSAndroid Build Coastguard Worker                                 .add("Image", cppbor::Map().add("Portrait image", false)))
355*4d7e907cSAndroid Build Coastguard Worker                     .encode();
356*4d7e907cSAndroid Build Coastguard Worker     cborPretty = cppbor::prettyPrint(itemsRequestBytes, 32, {"EphemeralPublicKey"});
357*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(
358*4d7e907cSAndroid Build Coastguard Worker             "{\n"
359*4d7e907cSAndroid Build Coastguard Worker             "  'nameSpaces' : {\n"
360*4d7e907cSAndroid Build Coastguard Worker             "    'PersonalData' : {\n"
361*4d7e907cSAndroid Build Coastguard Worker             "      'Last name' : false,\n"
362*4d7e907cSAndroid Build Coastguard Worker             "      'Birth date' : false,\n"
363*4d7e907cSAndroid Build Coastguard Worker             "      'First name' : false,\n"
364*4d7e907cSAndroid Build Coastguard Worker             "      'Home address' : true,\n"
365*4d7e907cSAndroid Build Coastguard Worker             "    },\n"
366*4d7e907cSAndroid Build Coastguard Worker             "    'Image' : {\n"
367*4d7e907cSAndroid Build Coastguard Worker             "      'Portrait image' : false,\n"
368*4d7e907cSAndroid Build Coastguard Worker             "    },\n"
369*4d7e907cSAndroid Build Coastguard Worker             "  },\n"
370*4d7e907cSAndroid Build Coastguard Worker             "}",
371*4d7e907cSAndroid Build Coastguard Worker             cborPretty);
372*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> encodedReaderAuthentication =
373*4d7e907cSAndroid Build Coastguard Worker             cppbor::Array()
374*4d7e907cSAndroid Build Coastguard Worker                     .add("ReaderAuthentication")
375*4d7e907cSAndroid Build Coastguard Worker                     .add(sessionTranscript.clone())
376*4d7e907cSAndroid Build Coastguard Worker                     .add(cppbor::SemanticTag(24, itemsRequestBytes))
377*4d7e907cSAndroid Build Coastguard Worker                     .encode();
378*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> encodedReaderAuthenticationBytes =
379*4d7e907cSAndroid Build Coastguard Worker             cppbor::SemanticTag(24, encodedReaderAuthentication).encode();
380*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerSignature =
381*4d7e907cSAndroid Build Coastguard Worker             support::coseSignEcDsa(readerKey, {},                     // content
382*4d7e907cSAndroid Build Coastguard Worker                                    encodedReaderAuthenticationBytes,  // detached content
383*4d7e907cSAndroid Build Coastguard Worker                                    readerCertificate.value());
384*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(readerSignature);
385*4d7e907cSAndroid Build Coastguard Worker 
386*4d7e907cSAndroid Build Coastguard Worker     // Generate the key that will be used to sign AuthenticatedData.
387*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> signingKeyBlob;
388*4d7e907cSAndroid Build Coastguard Worker     Certificate signingKeyCertificate;
389*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
390*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> signingPubKey =
391*4d7e907cSAndroid Build Coastguard Worker             support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
392*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(signingPubKey);
393*4d7e907cSAndroid Build Coastguard Worker     test_utils::verifyAuthKeyCertificate(signingKeyCertificate.encodedCertificate);
394*4d7e907cSAndroid Build Coastguard Worker 
395*4d7e907cSAndroid Build Coastguard Worker     // Since we're using a test-credential we know storageKey meaning we can get the
396*4d7e907cSAndroid Build Coastguard Worker     // private key. Do this, derive the public key from it, and check this matches what
397*4d7e907cSAndroid Build Coastguard Worker     // is in the certificate...
398*4d7e907cSAndroid Build Coastguard Worker     const vector<uint8_t> exDocTypeVec(exDocType.begin(), exDocType.end());
399*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> exSigningPrivKey =
400*4d7e907cSAndroid Build Coastguard Worker             support::decryptAes128Gcm(exStorageKey, signingKeyBlob, exDocTypeVec);
401*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exSigningPrivKey);
402*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> exSigningKeyPair =
403*4d7e907cSAndroid Build Coastguard Worker             support::ecPrivateKeyToKeyPair(exSigningPrivKey.value());
404*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exSigningKeyPair);
405*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> exSigningPubKey =
406*4d7e907cSAndroid Build Coastguard Worker             support::ecKeyPairGetPublicKey(exSigningKeyPair.value());
407*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exSigningPubKey);
408*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(exSigningPubKey.value(), signingPubKey.value());
409*4d7e907cSAndroid Build Coastguard Worker 
410*4d7e907cSAndroid Build Coastguard Worker     vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
411*4d7e907cSAndroid Build Coastguard Worker     // OK to fail, not available in v1 HAL
412*4d7e907cSAndroid Build Coastguard Worker     credential->setRequestedNamespaces(requestedNamespaces);
413*4d7e907cSAndroid Build Coastguard Worker     // OK to fail, not available in v1 HAL
414*4d7e907cSAndroid Build Coastguard Worker     credential->setVerificationToken(verificationToken);
415*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential
416*4d7e907cSAndroid Build Coastguard Worker                         ->startRetrieval(secureProfiles.value(), authToken, itemsRequestBytes,
417*4d7e907cSAndroid Build Coastguard Worker                                          signingKeyBlob, sessionTranscriptEncoded,
418*4d7e907cSAndroid Build Coastguard Worker                                          readerSignature.value(), testEntriesEntryCounts)
419*4d7e907cSAndroid Build Coastguard Worker                         .isOk());
420*4d7e907cSAndroid Build Coastguard Worker 
421*4d7e907cSAndroid Build Coastguard Worker     for (const auto& entry : testEntries) {
422*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential
423*4d7e907cSAndroid Build Coastguard Worker                             ->startRetrieveEntryValue(entry.nameSpace, entry.name,
424*4d7e907cSAndroid Build Coastguard Worker                                                       entry.valueCbor.size(), entry.profileIds)
425*4d7e907cSAndroid Build Coastguard Worker                             .isOk());
426*4d7e907cSAndroid Build Coastguard Worker 
427*4d7e907cSAndroid Build Coastguard Worker         auto it = encryptedBlobs.find(&entry);
428*4d7e907cSAndroid Build Coastguard Worker         ASSERT_NE(it, encryptedBlobs.end());
429*4d7e907cSAndroid Build Coastguard Worker         const vector<vector<uint8_t>>& encryptedChunks = it->second;
430*4d7e907cSAndroid Build Coastguard Worker 
431*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> content;
432*4d7e907cSAndroid Build Coastguard Worker         for (const auto& encryptedChunk : encryptedChunks) {
433*4d7e907cSAndroid Build Coastguard Worker             vector<uint8_t> chunk;
434*4d7e907cSAndroid Build Coastguard Worker             ASSERT_TRUE(credential->retrieveEntryValue(encryptedChunk, &chunk).isOk());
435*4d7e907cSAndroid Build Coastguard Worker             content.insert(content.end(), chunk.begin(), chunk.end());
436*4d7e907cSAndroid Build Coastguard Worker         }
437*4d7e907cSAndroid Build Coastguard Worker         EXPECT_EQ(content, entry.valueCbor);
438*4d7e907cSAndroid Build Coastguard Worker 
439*4d7e907cSAndroid Build Coastguard Worker         // TODO: also use |exStorageKey| to decrypt data and check it's the same as whatt
440*4d7e907cSAndroid Build Coastguard Worker         // the HAL returns...
441*4d7e907cSAndroid Build Coastguard Worker     }
442*4d7e907cSAndroid Build Coastguard Worker 
443*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> mac;
444*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> ecdsaSignature;
445*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> deviceNameSpacesEncoded;
446*4d7e907cSAndroid Build Coastguard Worker     // API version 5 (feature version 202301) returns both MAC and ECDSA signature.
447*4d7e907cSAndroid Build Coastguard Worker     if (halApiVersion_ >= 5) {
448*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential
449*4d7e907cSAndroid Build Coastguard Worker                             ->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
450*4d7e907cSAndroid Build Coastguard Worker                                                            &ecdsaSignature)
451*4d7e907cSAndroid Build Coastguard Worker                             .isOk());
452*4d7e907cSAndroid Build Coastguard Worker         ASSERT_GT(ecdsaSignature.size(), 0);
453*4d7e907cSAndroid Build Coastguard Worker     } else {
454*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
455*4d7e907cSAndroid Build Coastguard Worker     }
456*4d7e907cSAndroid Build Coastguard Worker     cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
457*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(
458*4d7e907cSAndroid Build Coastguard Worker             "{\n"
459*4d7e907cSAndroid Build Coastguard Worker             "  'PersonalData' : {\n"
460*4d7e907cSAndroid Build Coastguard Worker             "    'Last name' : 'Turing',\n"
461*4d7e907cSAndroid Build Coastguard Worker             "    'Birth date' : '19120623',\n"
462*4d7e907cSAndroid Build Coastguard Worker             "    'First name' : 'Alan',\n"
463*4d7e907cSAndroid Build Coastguard Worker             "    'Home address' : 'Maida Vale, London, England',\n"
464*4d7e907cSAndroid Build Coastguard Worker             "  },\n"
465*4d7e907cSAndroid Build Coastguard Worker             "  'Image' : {\n"
466*4d7e907cSAndroid Build Coastguard Worker             "    'Portrait image' : <bstr size=262134 "
467*4d7e907cSAndroid Build Coastguard Worker             "sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
468*4d7e907cSAndroid Build Coastguard Worker             "  },\n"
469*4d7e907cSAndroid Build Coastguard Worker             "}",
470*4d7e907cSAndroid Build Coastguard Worker             cborPretty);
471*4d7e907cSAndroid Build Coastguard Worker 
472*4d7e907cSAndroid Build Coastguard Worker     string docType = "org.iso.18013-5.2019.mdl";
473*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerEphemeralPrivateKey =
474*4d7e907cSAndroid Build Coastguard Worker             support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
475*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> eMacKey =
476*4d7e907cSAndroid Build Coastguard Worker             support::calcEMacKey(readerEphemeralPrivateKey.value(),  // Private Key
477*4d7e907cSAndroid Build Coastguard Worker                                  signingPubKey.value(),              // Public Key
478*4d7e907cSAndroid Build Coastguard Worker                                  cppbor::SemanticTag(24, sessionTranscript.encode())
479*4d7e907cSAndroid Build Coastguard Worker                                          .encode());  // SessionTranscriptBytes
480*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> calculatedMac =
481*4d7e907cSAndroid Build Coastguard Worker             support::calcMac(sessionTranscript.encode(),  // SessionTranscript
482*4d7e907cSAndroid Build Coastguard Worker                              docType,                     // DocType
483*4d7e907cSAndroid Build Coastguard Worker                              deviceNameSpacesEncoded,     // DeviceNamespaces
484*4d7e907cSAndroid Build Coastguard Worker                              eMacKey.value());            // EMacKey
485*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(calculatedMac);
486*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(mac, calculatedMac);
487*4d7e907cSAndroid Build Coastguard Worker 
488*4d7e907cSAndroid Build Coastguard Worker     if (ecdsaSignature.size() > 0) {
489*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> encodedDeviceAuthentication =
490*4d7e907cSAndroid Build Coastguard Worker                 cppbor::Array()
491*4d7e907cSAndroid Build Coastguard Worker                         .add("DeviceAuthentication")
492*4d7e907cSAndroid Build Coastguard Worker                         .add(sessionTranscript.clone())
493*4d7e907cSAndroid Build Coastguard Worker                         .add(docType)
494*4d7e907cSAndroid Build Coastguard Worker                         .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
495*4d7e907cSAndroid Build Coastguard Worker                         .encode();
496*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> deviceAuthenticationBytes =
497*4d7e907cSAndroid Build Coastguard Worker                 cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
498*4d7e907cSAndroid Build Coastguard Worker         EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
499*4d7e907cSAndroid Build Coastguard Worker                                                      deviceAuthenticationBytes,  // Detached content
500*4d7e907cSAndroid Build Coastguard Worker                                                      signingPubKey.value()));
501*4d7e907cSAndroid Build Coastguard Worker     }
502*4d7e907cSAndroid Build Coastguard Worker 
503*4d7e907cSAndroid Build Coastguard Worker     // Also perform an additional empty request. This is what mDL applications
504*4d7e907cSAndroid Build Coastguard Worker     // are envisioned to do - one call to get the data elements, another to get
505*4d7e907cSAndroid Build Coastguard Worker     // an empty DeviceSignedItems and corresponding MAC.
506*4d7e907cSAndroid Build Coastguard Worker     //
507*4d7e907cSAndroid Build Coastguard Worker     credential->setRequestedNamespaces({});  // OK to fail, not available in v1 HAL
508*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential
509*4d7e907cSAndroid Build Coastguard Worker                         ->startRetrieval(
510*4d7e907cSAndroid Build Coastguard Worker                                 secureProfiles.value(), authToken, {},         // itemsRequestBytes
511*4d7e907cSAndroid Build Coastguard Worker                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
512*4d7e907cSAndroid Build Coastguard Worker                                 testEntriesEntryCounts)
513*4d7e907cSAndroid Build Coastguard Worker                         .isOk());
514*4d7e907cSAndroid Build Coastguard Worker     // API version 5 (feature version 202301) returns both MAC and ECDSA signature.
515*4d7e907cSAndroid Build Coastguard Worker     if (halApiVersion_ >= 5) {
516*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential
517*4d7e907cSAndroid Build Coastguard Worker                             ->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
518*4d7e907cSAndroid Build Coastguard Worker                                                            &ecdsaSignature)
519*4d7e907cSAndroid Build Coastguard Worker                             .isOk());
520*4d7e907cSAndroid Build Coastguard Worker         ASSERT_GT(ecdsaSignature.size(), 0);
521*4d7e907cSAndroid Build Coastguard Worker     } else {
522*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
523*4d7e907cSAndroid Build Coastguard Worker     }
524*4d7e907cSAndroid Build Coastguard Worker     cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
525*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ("{}", cborPretty);
526*4d7e907cSAndroid Build Coastguard Worker     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
527*4d7e907cSAndroid Build Coastguard Worker     calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
528*4d7e907cSAndroid Build Coastguard Worker                                      docType,                     // DocType
529*4d7e907cSAndroid Build Coastguard Worker                                      deviceNameSpacesEncoded,     // DeviceNamespaces
530*4d7e907cSAndroid Build Coastguard Worker                                      eMacKey.value());            // EMacKey
531*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(calculatedMac);
532*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(mac, calculatedMac);
533*4d7e907cSAndroid Build Coastguard Worker 
534*4d7e907cSAndroid Build Coastguard Worker     if (ecdsaSignature.size() > 0) {
535*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> encodedDeviceAuthentication =
536*4d7e907cSAndroid Build Coastguard Worker                 cppbor::Array()
537*4d7e907cSAndroid Build Coastguard Worker                         .add("DeviceAuthentication")
538*4d7e907cSAndroid Build Coastguard Worker                         .add(sessionTranscript.clone())
539*4d7e907cSAndroid Build Coastguard Worker                         .add(docType)
540*4d7e907cSAndroid Build Coastguard Worker                         .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
541*4d7e907cSAndroid Build Coastguard Worker                         .encode();
542*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> deviceAuthenticationBytes =
543*4d7e907cSAndroid Build Coastguard Worker                 cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
544*4d7e907cSAndroid Build Coastguard Worker         EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
545*4d7e907cSAndroid Build Coastguard Worker                                                      deviceAuthenticationBytes,  // Detached content
546*4d7e907cSAndroid Build Coastguard Worker                                                      signingPubKey.value()));
547*4d7e907cSAndroid Build Coastguard Worker     }
548*4d7e907cSAndroid Build Coastguard Worker 
549*4d7e907cSAndroid Build Coastguard Worker     // Some mDL apps might send a request but with a single empty
550*4d7e907cSAndroid Build Coastguard Worker     // namespace. Check that too.
551*4d7e907cSAndroid Build Coastguard Worker     RequestNamespace emptyRequestNS;
552*4d7e907cSAndroid Build Coastguard Worker     emptyRequestNS.namespaceName = "PersonalData";
553*4d7e907cSAndroid Build Coastguard Worker     credential->setRequestedNamespaces({emptyRequestNS});  // OK to fail, not available in v1 HAL
554*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential
555*4d7e907cSAndroid Build Coastguard Worker                         ->startRetrieval(
556*4d7e907cSAndroid Build Coastguard Worker                                 secureProfiles.value(), authToken, {},         // itemsRequestBytes
557*4d7e907cSAndroid Build Coastguard Worker                                 signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
558*4d7e907cSAndroid Build Coastguard Worker                                 testEntriesEntryCounts)
559*4d7e907cSAndroid Build Coastguard Worker                         .isOk());
560*4d7e907cSAndroid Build Coastguard Worker     // API version 5 (feature version 202301) returns both MAC and ECDSA signature.
561*4d7e907cSAndroid Build Coastguard Worker     if (halApiVersion_ >= 5) {
562*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential
563*4d7e907cSAndroid Build Coastguard Worker                             ->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
564*4d7e907cSAndroid Build Coastguard Worker                                                            &ecdsaSignature)
565*4d7e907cSAndroid Build Coastguard Worker                             .isOk());
566*4d7e907cSAndroid Build Coastguard Worker         ASSERT_GT(ecdsaSignature.size(), 0);
567*4d7e907cSAndroid Build Coastguard Worker     } else {
568*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
569*4d7e907cSAndroid Build Coastguard Worker     }
570*4d7e907cSAndroid Build Coastguard Worker     cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
571*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ("{}", cborPretty);
572*4d7e907cSAndroid Build Coastguard Worker     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
573*4d7e907cSAndroid Build Coastguard Worker     calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
574*4d7e907cSAndroid Build Coastguard Worker                                      docType,                     // DocType
575*4d7e907cSAndroid Build Coastguard Worker                                      deviceNameSpacesEncoded,     // DeviceNamespaces
576*4d7e907cSAndroid Build Coastguard Worker                                      eMacKey.value());            // EMacKey
577*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(calculatedMac);
578*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(mac, calculatedMac);
579*4d7e907cSAndroid Build Coastguard Worker 
580*4d7e907cSAndroid Build Coastguard Worker     if (ecdsaSignature.size() > 0) {
581*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> encodedDeviceAuthentication =
582*4d7e907cSAndroid Build Coastguard Worker                 cppbor::Array()
583*4d7e907cSAndroid Build Coastguard Worker                         .add("DeviceAuthentication")
584*4d7e907cSAndroid Build Coastguard Worker                         .add(sessionTranscript.clone())
585*4d7e907cSAndroid Build Coastguard Worker                         .add(docType)
586*4d7e907cSAndroid Build Coastguard Worker                         .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
587*4d7e907cSAndroid Build Coastguard Worker                         .encode();
588*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> deviceAuthenticationBytes =
589*4d7e907cSAndroid Build Coastguard Worker                 cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
590*4d7e907cSAndroid Build Coastguard Worker         EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
591*4d7e907cSAndroid Build Coastguard Worker                                                      deviceAuthenticationBytes,  // Detached content
592*4d7e907cSAndroid Build Coastguard Worker                                                      signingPubKey.value()));
593*4d7e907cSAndroid Build Coastguard Worker     }
594*4d7e907cSAndroid Build Coastguard Worker }
595*4d7e907cSAndroid Build Coastguard Worker 
TEST_P(EndToEndTests,noSessionEncryption)596*4d7e907cSAndroid Build Coastguard Worker TEST_P(EndToEndTests, noSessionEncryption) {
597*4d7e907cSAndroid Build Coastguard Worker     if (halApiVersion_ < 5) {
598*4d7e907cSAndroid Build Coastguard Worker         GTEST_SKIP() << "Need HAL API version 5, have " << halApiVersion_;
599*4d7e907cSAndroid Build Coastguard Worker     }
600*4d7e907cSAndroid Build Coastguard Worker 
601*4d7e907cSAndroid Build Coastguard Worker     const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (no authentication)
602*4d7e907cSAndroid Build Coastguard Worker                                                           {0, {}, false, 0}};
603*4d7e907cSAndroid Build Coastguard Worker 
604*4d7e907cSAndroid Build Coastguard Worker     HardwareAuthToken authToken;
605*4d7e907cSAndroid Build Coastguard Worker     VerificationToken verificationToken;
606*4d7e907cSAndroid Build Coastguard Worker     authToken.challenge = 0;
607*4d7e907cSAndroid Build Coastguard Worker     authToken.userId = 0;
608*4d7e907cSAndroid Build Coastguard Worker     authToken.authenticatorId = 0;
609*4d7e907cSAndroid Build Coastguard Worker     authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
610*4d7e907cSAndroid Build Coastguard Worker     authToken.timestamp.milliSeconds = 0;
611*4d7e907cSAndroid Build Coastguard Worker     authToken.mac.clear();
612*4d7e907cSAndroid Build Coastguard Worker     verificationToken.challenge = 0;
613*4d7e907cSAndroid Build Coastguard Worker     verificationToken.timestamp.milliSeconds = 0;
614*4d7e907cSAndroid Build Coastguard Worker     verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
615*4d7e907cSAndroid Build Coastguard Worker     verificationToken.mac.clear();
616*4d7e907cSAndroid Build Coastguard Worker 
617*4d7e907cSAndroid Build Coastguard Worker     // Here's the actual test data:
618*4d7e907cSAndroid Build Coastguard Worker     const vector<test_utils::TestEntryData> testEntries = {
619*4d7e907cSAndroid Build Coastguard Worker             {"PersonalData", "Last name", string("Turing"), vector<int32_t>{0}},
620*4d7e907cSAndroid Build Coastguard Worker             {"PersonalData", "Birth date", string("19120623"), vector<int32_t>{0}},
621*4d7e907cSAndroid Build Coastguard Worker             {"PersonalData", "First name", string("Alan"), vector<int32_t>{0}},
622*4d7e907cSAndroid Build Coastguard Worker     };
623*4d7e907cSAndroid Build Coastguard Worker     const vector<int32_t> testEntriesEntryCounts = {3};
624*4d7e907cSAndroid Build Coastguard Worker     HardwareInformation hwInfo;
625*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
626*4d7e907cSAndroid Build Coastguard Worker 
627*4d7e907cSAndroid Build Coastguard Worker     string cborPretty;
628*4d7e907cSAndroid Build Coastguard Worker     sp<IWritableIdentityCredential> writableCredential;
629*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
630*4d7e907cSAndroid Build Coastguard Worker                                                     true /* testCredential */));
631*4d7e907cSAndroid Build Coastguard Worker 
632*4d7e907cSAndroid Build Coastguard Worker     string challenge = "attestationChallenge";
633*4d7e907cSAndroid Build Coastguard Worker     test_utils::AttestationData attData(writableCredential, challenge,
634*4d7e907cSAndroid Build Coastguard Worker                                         {1} /* atteestationApplicationId */);
635*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(attData.result.isOk())
636*4d7e907cSAndroid Build Coastguard Worker             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
637*4d7e907cSAndroid Build Coastguard Worker 
638*4d7e907cSAndroid Build Coastguard Worker     // This is kinda of a hack but we need to give the size of
639*4d7e907cSAndroid Build Coastguard Worker     // ProofOfProvisioning that we'll expect to receive.
640*4d7e907cSAndroid Build Coastguard Worker     const int32_t expectedProofOfProvisioningSize = 230;
641*4d7e907cSAndroid Build Coastguard Worker     // OK to fail, not available in v1 HAL
642*4d7e907cSAndroid Build Coastguard Worker     writableCredential->setExpectedProofOfProvisioningSize(expectedProofOfProvisioningSize);
643*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(
644*4d7e907cSAndroid Build Coastguard Worker             writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts)
645*4d7e907cSAndroid Build Coastguard Worker                     .isOk());
646*4d7e907cSAndroid Build Coastguard Worker 
647*4d7e907cSAndroid Build Coastguard Worker     optional<vector<SecureAccessControlProfile>> secureProfiles =
648*4d7e907cSAndroid Build Coastguard Worker             test_utils::addAccessControlProfiles(writableCredential, testProfiles);
649*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(secureProfiles);
650*4d7e907cSAndroid Build Coastguard Worker 
651*4d7e907cSAndroid Build Coastguard Worker     // Uses TestEntryData* pointer as key and values are the encrypted blobs. This
652*4d7e907cSAndroid Build Coastguard Worker     // is a little hacky but it works well enough.
653*4d7e907cSAndroid Build Coastguard Worker     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
654*4d7e907cSAndroid Build Coastguard Worker 
655*4d7e907cSAndroid Build Coastguard Worker     for (const auto& entry : testEntries) {
656*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
657*4d7e907cSAndroid Build Coastguard Worker                                          encryptedBlobs, true));
658*4d7e907cSAndroid Build Coastguard Worker     }
659*4d7e907cSAndroid Build Coastguard Worker 
660*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> credentialData;
661*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> proofOfProvisioningSignature;
662*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(
663*4d7e907cSAndroid Build Coastguard Worker             writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature)
664*4d7e907cSAndroid Build Coastguard Worker                     .isOk());
665*4d7e907cSAndroid Build Coastguard Worker 
666*4d7e907cSAndroid Build Coastguard Worker     // Validate the proofOfProvisioning which was returned
667*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> proofOfProvisioning =
668*4d7e907cSAndroid Build Coastguard Worker             support::coseSignGetPayload(proofOfProvisioningSignature);
669*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(proofOfProvisioning);
670*4d7e907cSAndroid Build Coastguard Worker     cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
671*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(
672*4d7e907cSAndroid Build Coastguard Worker             "[\n"
673*4d7e907cSAndroid Build Coastguard Worker             "  'ProofOfProvisioning',\n"
674*4d7e907cSAndroid Build Coastguard Worker             "  'org.iso.18013-5.2019.mdl',\n"
675*4d7e907cSAndroid Build Coastguard Worker             "  [\n"
676*4d7e907cSAndroid Build Coastguard Worker             "    {\n"
677*4d7e907cSAndroid Build Coastguard Worker             "      'id' : 0,\n"
678*4d7e907cSAndroid Build Coastguard Worker             "    },\n"
679*4d7e907cSAndroid Build Coastguard Worker             "  ],\n"
680*4d7e907cSAndroid Build Coastguard Worker             "  {\n"
681*4d7e907cSAndroid Build Coastguard Worker             "    'PersonalData' : [\n"
682*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
683*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'Last name',\n"
684*4d7e907cSAndroid Build Coastguard Worker             "        'value' : 'Turing',\n"
685*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, ],\n"
686*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
687*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
688*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'Birth date',\n"
689*4d7e907cSAndroid Build Coastguard Worker             "        'value' : '19120623',\n"
690*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, ],\n"
691*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
692*4d7e907cSAndroid Build Coastguard Worker             "      {\n"
693*4d7e907cSAndroid Build Coastguard Worker             "        'name' : 'First name',\n"
694*4d7e907cSAndroid Build Coastguard Worker             "        'value' : 'Alan',\n"
695*4d7e907cSAndroid Build Coastguard Worker             "        'accessControlProfiles' : [0, ],\n"
696*4d7e907cSAndroid Build Coastguard Worker             "      },\n"
697*4d7e907cSAndroid Build Coastguard Worker             "    ],\n"
698*4d7e907cSAndroid Build Coastguard Worker             "  },\n"
699*4d7e907cSAndroid Build Coastguard Worker             "  true,\n"
700*4d7e907cSAndroid Build Coastguard Worker             "]",
701*4d7e907cSAndroid Build Coastguard Worker             cborPretty);
702*4d7e907cSAndroid Build Coastguard Worker 
703*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
704*4d7e907cSAndroid Build Coastguard Worker             attData.attestationCertificate[0].encodedCertificate);
705*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credentialPubKey);
706*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
707*4d7e907cSAndroid Build Coastguard Worker                                                  {},  // Additional data
708*4d7e907cSAndroid Build Coastguard Worker                                                  credentialPubKey.value()));
709*4d7e907cSAndroid Build Coastguard Worker     writableCredential = nullptr;
710*4d7e907cSAndroid Build Coastguard Worker 
711*4d7e907cSAndroid Build Coastguard Worker     // Extract doctype, storage key, and credentialPrivKey from credentialData... this works
712*4d7e907cSAndroid Build Coastguard Worker     // only because we asked for a test-credential meaning that the HBK is all zeroes.
713*4d7e907cSAndroid Build Coastguard Worker     auto [exSuccess, exDocType, exStorageKey, exCredentialPrivKey, exSha256Pop] =
714*4d7e907cSAndroid Build Coastguard Worker             extractFromTestCredentialData(credentialData);
715*4d7e907cSAndroid Build Coastguard Worker 
716*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exSuccess);
717*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(exDocType, "org.iso.18013-5.2019.mdl");
718*4d7e907cSAndroid Build Coastguard Worker     // ... check that the public key derived from the private key matches what was
719*4d7e907cSAndroid Build Coastguard Worker     // in the certificate.
720*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> exCredentialKeyPair =
721*4d7e907cSAndroid Build Coastguard Worker             support::ecPrivateKeyToKeyPair(exCredentialPrivKey);
722*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exCredentialKeyPair);
723*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> exCredentialPubKey =
724*4d7e907cSAndroid Build Coastguard Worker             support::ecKeyPairGetPublicKey(exCredentialKeyPair.value());
725*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(exCredentialPubKey);
726*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(exCredentialPubKey.value(), credentialPubKey.value());
727*4d7e907cSAndroid Build Coastguard Worker 
728*4d7e907cSAndroid Build Coastguard Worker     sp<IIdentityCredential> credential;
729*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credentialStore_
730*4d7e907cSAndroid Build Coastguard Worker                         ->getCredential(
731*4d7e907cSAndroid Build Coastguard Worker                                 CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
732*4d7e907cSAndroid Build Coastguard Worker                                 credentialData, &credential)
733*4d7e907cSAndroid Build Coastguard Worker                         .isOk());
734*4d7e907cSAndroid Build Coastguard Worker     ASSERT_NE(credential, nullptr);
735*4d7e907cSAndroid Build Coastguard Worker 
736*4d7e907cSAndroid Build Coastguard Worker     // Calculate sessionTranscript, make something that resembles what you'd use for
737*4d7e907cSAndroid Build Coastguard Worker     // an over-the-Internet presentation not using mdoc session encryption.
738*4d7e907cSAndroid Build Coastguard Worker     cppbor::Array sessionTranscript =
739*4d7e907cSAndroid Build Coastguard Worker             cppbor::Array()
740*4d7e907cSAndroid Build Coastguard Worker                     .add(cppbor::Null())  // DeviceEngagementBytes isn't used.
741*4d7e907cSAndroid Build Coastguard Worker                     .add(cppbor::Null())  // EReaderKeyBytes isn't used.
742*4d7e907cSAndroid Build Coastguard Worker                     .add(cppbor::Array()  // Proprietary handover structure follows.
743*4d7e907cSAndroid Build Coastguard Worker                                  .add(cppbor::Tstr("TestHandover"))
744*4d7e907cSAndroid Build Coastguard Worker                                  .add(cppbor::Bstr(vector<uint8_t>{1, 2, 3}))
745*4d7e907cSAndroid Build Coastguard Worker                                  .add(cppbor::Bstr(vector<uint8_t>{9, 8, 7, 6})));
746*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
747*4d7e907cSAndroid Build Coastguard Worker 
748*4d7e907cSAndroid Build Coastguard Worker     // Generate the key that will be used to sign AuthenticatedData.
749*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> signingKeyBlob;
750*4d7e907cSAndroid Build Coastguard Worker     Certificate signingKeyCertificate;
751*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
752*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> signingPubKey =
753*4d7e907cSAndroid Build Coastguard Worker             support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
754*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(signingPubKey);
755*4d7e907cSAndroid Build Coastguard Worker     test_utils::verifyAuthKeyCertificate(signingKeyCertificate.encodedCertificate);
756*4d7e907cSAndroid Build Coastguard Worker 
757*4d7e907cSAndroid Build Coastguard Worker     vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
758*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential->setRequestedNamespaces(requestedNamespaces).isOk());
759*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(credential->setVerificationToken(verificationToken).isOk());
760*4d7e907cSAndroid Build Coastguard Worker     Status status = credential->startRetrieval(
761*4d7e907cSAndroid Build Coastguard Worker             secureProfiles.value(), authToken, {} /* itemsRequestBytes*/, signingKeyBlob,
762*4d7e907cSAndroid Build Coastguard Worker             sessionTranscriptEncoded, {} /* readerSignature */, testEntriesEntryCounts);
763*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
764*4d7e907cSAndroid Build Coastguard Worker 
765*4d7e907cSAndroid Build Coastguard Worker     for (const auto& entry : testEntries) {
766*4d7e907cSAndroid Build Coastguard Worker         ASSERT_TRUE(credential
767*4d7e907cSAndroid Build Coastguard Worker                             ->startRetrieveEntryValue(entry.nameSpace, entry.name,
768*4d7e907cSAndroid Build Coastguard Worker                                                       entry.valueCbor.size(), entry.profileIds)
769*4d7e907cSAndroid Build Coastguard Worker                             .isOk());
770*4d7e907cSAndroid Build Coastguard Worker 
771*4d7e907cSAndroid Build Coastguard Worker         auto it = encryptedBlobs.find(&entry);
772*4d7e907cSAndroid Build Coastguard Worker         ASSERT_NE(it, encryptedBlobs.end());
773*4d7e907cSAndroid Build Coastguard Worker         const vector<vector<uint8_t>>& encryptedChunks = it->second;
774*4d7e907cSAndroid Build Coastguard Worker 
775*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> content;
776*4d7e907cSAndroid Build Coastguard Worker         for (const auto& encryptedChunk : encryptedChunks) {
777*4d7e907cSAndroid Build Coastguard Worker             vector<uint8_t> chunk;
778*4d7e907cSAndroid Build Coastguard Worker             ASSERT_TRUE(credential->retrieveEntryValue(encryptedChunk, &chunk).isOk());
779*4d7e907cSAndroid Build Coastguard Worker             content.insert(content.end(), chunk.begin(), chunk.end());
780*4d7e907cSAndroid Build Coastguard Worker         }
781*4d7e907cSAndroid Build Coastguard Worker         EXPECT_EQ(content, entry.valueCbor);
782*4d7e907cSAndroid Build Coastguard Worker     }
783*4d7e907cSAndroid Build Coastguard Worker 
784*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> mac;
785*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> ecdsaSignature;
786*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> deviceNameSpacesEncoded;
787*4d7e907cSAndroid Build Coastguard Worker     status = credential->finishRetrievalWithSignature(&mac, &deviceNameSpacesEncoded,
788*4d7e907cSAndroid Build Coastguard Worker                                                       &ecdsaSignature);
789*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
790*4d7e907cSAndroid Build Coastguard Worker     // MACing should NOT work since we're not using session encryption
791*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(0, mac.size());
792*4d7e907cSAndroid Build Coastguard Worker 
793*4d7e907cSAndroid Build Coastguard Worker     // ECDSA signatures should work, however. Check this.
794*4d7e907cSAndroid Build Coastguard Worker     ASSERT_GT(ecdsaSignature.size(), 0);
795*4d7e907cSAndroid Build Coastguard Worker 
796*4d7e907cSAndroid Build Coastguard Worker     cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
797*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(
798*4d7e907cSAndroid Build Coastguard Worker             "{\n"
799*4d7e907cSAndroid Build Coastguard Worker             "  'PersonalData' : {\n"
800*4d7e907cSAndroid Build Coastguard Worker             "    'Last name' : 'Turing',\n"
801*4d7e907cSAndroid Build Coastguard Worker             "    'Birth date' : '19120623',\n"
802*4d7e907cSAndroid Build Coastguard Worker             "    'First name' : 'Alan',\n"
803*4d7e907cSAndroid Build Coastguard Worker             "  },\n"
804*4d7e907cSAndroid Build Coastguard Worker             "}",
805*4d7e907cSAndroid Build Coastguard Worker             cborPretty);
806*4d7e907cSAndroid Build Coastguard Worker 
807*4d7e907cSAndroid Build Coastguard Worker     string docType = "org.iso.18013-5.2019.mdl";
808*4d7e907cSAndroid Build Coastguard Worker 
809*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> encodedDeviceAuthentication =
810*4d7e907cSAndroid Build Coastguard Worker             cppbor::Array()
811*4d7e907cSAndroid Build Coastguard Worker                     .add("DeviceAuthentication")
812*4d7e907cSAndroid Build Coastguard Worker                     .add(sessionTranscript.clone())
813*4d7e907cSAndroid Build Coastguard Worker                     .add(docType)
814*4d7e907cSAndroid Build Coastguard Worker                     .add(cppbor::SemanticTag(24, deviceNameSpacesEncoded))
815*4d7e907cSAndroid Build Coastguard Worker                     .encode();
816*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> deviceAuthenticationBytes =
817*4d7e907cSAndroid Build Coastguard Worker             cppbor::SemanticTag(24, encodedDeviceAuthentication).encode();
818*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(support::coseCheckEcDsaSignature(ecdsaSignature,
819*4d7e907cSAndroid Build Coastguard Worker                                                  deviceAuthenticationBytes,  // Detached content
820*4d7e907cSAndroid Build Coastguard Worker                                                  signingPubKey.value()));
821*4d7e907cSAndroid Build Coastguard Worker }
822*4d7e907cSAndroid Build Coastguard Worker 
823*4d7e907cSAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EndToEndTests);
824*4d7e907cSAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
825*4d7e907cSAndroid Build Coastguard Worker         Identity, EndToEndTests,
826*4d7e907cSAndroid Build Coastguard Worker         testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
827*4d7e907cSAndroid Build Coastguard Worker         android::PrintInstanceNameToString);
828*4d7e907cSAndroid Build Coastguard Worker 
829*4d7e907cSAndroid Build Coastguard Worker }  // namespace android::hardware::identity
830*4d7e907cSAndroid Build Coastguard Worker 
main(int argc,char ** argv)831*4d7e907cSAndroid Build Coastguard Worker int main(int argc, char** argv) {
832*4d7e907cSAndroid Build Coastguard Worker     ::testing::InitGoogleTest(&argc, argv);
833*4d7e907cSAndroid Build Coastguard Worker     ::android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
834*4d7e907cSAndroid Build Coastguard Worker     ::android::ProcessState::self()->startThreadPool();
835*4d7e907cSAndroid Build Coastguard Worker     return RUN_ALL_TESTS();
836*4d7e907cSAndroid Build Coastguard Worker }
837