blob: bc37020293850894a6bda5f9b6479c9107666b53 [file] [log] [blame]
Selene Huang92b61d62020-03-04 02:24:16 -08001/*
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 "VtsIWritableIdentityCredentialTests"
18
19#include <aidl/Gtest.h>
20#include <aidl/Vintf.h>
21#include <android-base/logging.h>
22#include <android/hardware/identity/IIdentityCredentialStore.h>
23#include <android/hardware/identity/support/IdentityCredentialSupport.h>
24#include <binder/IServiceManager.h>
25#include <binder/ProcessState.h>
26#include <cppbor.h>
27#include <cppbor_parse.h>
28#include <gtest/gtest.h>
29#include <future>
30#include <map>
31
David Zeuthen49f2d252020-10-16 11:27:24 -040032#include "Util.h"
Selene Huang92b61d62020-03-04 02:24:16 -080033
34namespace android::hardware::identity {
35
36using std::endl;
37using std::map;
38using std::optional;
39using std::string;
40using std::vector;
41
42using ::android::sp;
43using ::android::String16;
44using ::android::binder::Status;
45
46class IdentityCredentialTests : public testing::TestWithParam<string> {
47 public:
48 virtual void SetUp() override {
49 credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
50 String16(GetParam().c_str()));
51 ASSERT_NE(credentialStore_, nullptr);
52 }
53
54 sp<IIdentityCredentialStore> credentialStore_;
55};
56
57TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
58 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -070059
60 HardwareInformation hwInfo;
61 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
62
Selene Huang92b61d62020-03-04 02:24:16 -080063 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -040064 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
65 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -080066
67 vector<uint8_t> attestationChallenge;
68 vector<Certificate> attestationCertificate;
69 vector<uint8_t> attestationApplicationId = {};
70 result = writableCredential->getAttestationCertificate(
71 attestationApplicationId, attestationChallenge, &attestationCertificate);
72
David Zeuthenef739512020-06-03 13:24:52 -040073 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
74 << endl;
75 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
76 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
Selene Huang92b61d62020-03-04 02:24:16 -080077}
78
79TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
80 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -070081
82 HardwareInformation hwInfo;
83 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
84
Selene Huang92b61d62020-03-04 02:24:16 -080085 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -040086 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
87 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -080088
89 string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
90 vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
91 vector<Certificate> attestationCertificate;
David Zeuthen34abaae2020-10-26 20:26:36 -040092 vector<uint8_t> attestationApplicationId = {1};
Selene Huang92b61d62020-03-04 02:24:16 -080093
94 result = writableCredential->getAttestationCertificate(
95 attestationApplicationId, attestationChallenge, &attestationCertificate);
96
97 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
98 << endl;
99
David Zeuthen34abaae2020-10-26 20:26:36 -0400100 test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
101 attestationApplicationId, false);
Selene Huang92b61d62020-03-04 02:24:16 -0800102}
103
104TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
105 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -0700106
Selene Huang92b61d62020-03-04 02:24:16 -0800107 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400108 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
109 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800110
111 string challenge = "NotSoRandomChallenge1";
David Zeuthen34abaae2020-10-26 20:26:36 -0400112 test_utils::AttestationData attData(writableCredential, challenge,
113 {1} /* atteestationApplicationId */);
114 test_utils::validateAttestationCertificate(attData.attestationCertificate,
115 attData.attestationChallenge,
116 attData.attestationApplicationId, false);
Selene Huang92b61d62020-03-04 02:24:16 -0800117
118 string challenge2 = "NotSoRandomChallenge2";
David Zeuthen34abaae2020-10-26 20:26:36 -0400119 test_utils::AttestationData attData2(writableCredential, challenge2,
120 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800121 EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
122 << attData2.result.exceptionMessage() << endl;
123 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
124 EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, attData2.result.serviceSpecificErrorCode());
125}
126
127TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
128 Status result;
129 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400130 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
131 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800132
133 // First call should go through
134 const vector<int32_t> entryCounts = {2, 4};
David Zeuthenef739512020-06-03 13:24:52 -0400135 writableCredential->setExpectedProofOfProvisioningSize(123456);
Selene Huang92b61d62020-03-04 02:24:16 -0800136 result = writableCredential->startPersonalization(5, entryCounts);
137 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
138 << endl;
139
140 // Call personalization again to check if repeat call is allowed.
141 result = writableCredential->startPersonalization(7, entryCounts);
142
143 // Second call to startPersonalization should have failed.
144 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
145 << endl;
146 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
147 EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
148}
149
150TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
151 Status result;
152 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400153 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
154 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800155
156 // Verify minimal number of profile count and entry count
157 const vector<int32_t> entryCounts = {1, 1};
David Zeuthenef739512020-06-03 13:24:52 -0400158 writableCredential->setExpectedProofOfProvisioningSize(123456);
159 result = writableCredential->startPersonalization(1, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800160 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
161 << endl;
162}
163
164TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
165 Status result;
166 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400167 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
168 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800169
170 // Verify minimal number of profile count and entry count
171 const vector<int32_t> entryCounts = {1};
David Zeuthenef739512020-06-03 13:24:52 -0400172 writableCredential->setExpectedProofOfProvisioningSize(123456);
173 result = writableCredential->startPersonalization(1, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800174 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
175 << endl;
176}
177
178TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
179 Status result;
180 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400181 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
182 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800183
184 // Verify set a large number of profile count and entry count is ok
David Zeuthen630de2a2020-05-11 14:04:54 -0400185 const vector<int32_t> entryCounts = {255};
David Zeuthenef739512020-06-03 13:24:52 -0400186 writableCredential->setExpectedProofOfProvisioningSize(123456);
187 result = writableCredential->startPersonalization(25, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800188 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
189 << endl;
190}
191
192TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
193 Status result;
194 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400195 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
196 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800197
198 // Enter mismatched entry and profile numbers
199 const vector<int32_t> entryCounts = {5, 6};
David Zeuthenef739512020-06-03 13:24:52 -0400200 writableCredential->setExpectedProofOfProvisioningSize(123456);
201 result = writableCredential->startPersonalization(5, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800202 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
203 << endl;
204
Selene Huangcab019a2020-03-11 04:37:48 -0700205 optional<vector<uint8_t>> readerCertificate = test_utils::generateReaderCertificate("12345");
Selene Huang92b61d62020-03-04 02:24:16 -0800206 ASSERT_TRUE(readerCertificate);
207
208 const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
209 {1, readerCertificate.value(), false, 0},
210 {2, readerCertificate.value(), true, 1},
211 // Profile 4 (no authentication)
212 {4, {}, false, 0}};
213
214 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700215 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800216 ASSERT_TRUE(secureProfiles);
217
218 vector<uint8_t> credentialData;
219 vector<uint8_t> proofOfProvisioningSignature;
220 result =
221 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
222
223 // finishAddingEntries should fail because the number of addAccessControlProfile mismatched with
Selene Huangcab019a2020-03-11 04:37:48 -0700224 // startPersonalization, and begintest_utils::addEntry was not called.
Selene Huang92b61d62020-03-04 02:24:16 -0800225 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
226 << endl;
227 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
228 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
229}
230
231TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
232 Status result;
233 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400234 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
235 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800236
237 const vector<int32_t> entryCounts = {3, 6};
David Zeuthenef739512020-06-03 13:24:52 -0400238 writableCredential->setExpectedProofOfProvisioningSize(123456);
239 result = writableCredential->startPersonalization(3, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800240 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
241 << endl;
242
243 const vector<test_utils::TestProfile> testProfiles = {// first profile should go though
244 {1, {}, true, 2},
245 // same id, different
246 // authentication requirement
247 {1, {}, true, 1},
248 // same id, different certificate
249 {1, {}, false, 0}};
250
251 bool expectOk = true;
252 for (const auto& testProfile : testProfiles) {
253 SecureAccessControlProfile profile;
254 Certificate cert;
255 cert.encodedCertificate = testProfile.readerCertificate;
David Zeuthenef739512020-06-03 13:24:52 -0400256 int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
Selene Huang92b61d62020-03-04 02:24:16 -0800257 result = writableCredential->addAccessControlProfile(
258 testProfile.id, cert, testProfile.userAuthenticationRequired,
David Zeuthenef739512020-06-03 13:24:52 -0400259 testProfile.timeoutMillis, secureUserId, &profile);
Selene Huang92b61d62020-03-04 02:24:16 -0800260
261 if (expectOk) {
262 expectOk = false;
263 // for profile should be allowed though as there are no duplications
264 // yet.
265 ASSERT_TRUE(result.isOk())
266 << result.exceptionCode() << "; " << result.exceptionMessage()
267 << "test profile id = " << testProfile.id << endl;
268
269 ASSERT_EQ(testProfile.id, profile.id);
270 ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
271 ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
272 ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
273 ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
274 } else {
275 // should not allow duplicate id profiles.
276 ASSERT_FALSE(result.isOk())
277 << result.exceptionCode() << "; " << result.exceptionMessage()
278 << ". Test profile id = " << testProfile.id
279 << ", timeout=" << testProfile.timeoutMillis << endl;
280 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
281 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA,
282 result.serviceSpecificErrorCode());
283 }
284 }
285}
286
287TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
288 Status result;
289
290 HardwareInformation hwInfo;
291 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
292
293 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400294 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
295 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800296
297 string challenge = "NotSoRandomChallenge1";
David Zeuthen34abaae2020-10-26 20:26:36 -0400298 test_utils::AttestationData attData(writableCredential, challenge,
299 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800300 EXPECT_TRUE(attData.result.isOk())
301 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
302
Selene Huangcab019a2020-03-11 04:37:48 -0700303 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800304 ASSERT_TRUE(readerCertificate1);
305
David Zeuthen28edb102020-04-28 18:54:55 -0400306 const vector<int32_t> entryCounts = {1u};
David Zeuthen34abaae2020-10-26 20:26:36 -0400307 size_t expectedPoPSize = 185 + readerCertificate1.value().size();
David Zeuthen28edb102020-04-28 18:54:55 -0400308 // OK to fail, not available in v1 HAL
309 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
310 result = writableCredential->startPersonalization(1, entryCounts);
311 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
312 << endl;
313
Selene Huang92b61d62020-03-04 02:24:16 -0800314 const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
315
316 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700317 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800318 ASSERT_TRUE(secureProfiles);
319
320 const vector<test_utils::TestEntryData> testEntries1 = {
David Zeuthen34abaae2020-10-26 20:26:36 -0400321 {"Name Space", "Last name", string("Turing"), vector<int32_t>{1}},
Selene Huang92b61d62020-03-04 02:24:16 -0800322 };
323
324 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
325 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700326 ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800327 encryptedBlobs, true));
328 }
329
330 vector<uint8_t> credentialData;
331 vector<uint8_t> proofOfProvisioningSignature;
332 result =
333 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
334
335 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
336 << endl;
337
338 optional<vector<uint8_t>> proofOfProvisioning =
339 support::coseSignGetPayload(proofOfProvisioningSignature);
340 ASSERT_TRUE(proofOfProvisioning);
Max Biresa3c7f4c2021-04-09 08:56:40 -0700341 string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
Selene Huang92b61d62020-03-04 02:24:16 -0800342 EXPECT_EQ(
343 "[\n"
344 " 'ProofOfProvisioning',\n"
345 " 'org.iso.18013-5.2019.mdl',\n"
346 " [\n"
347 " {\n"
348 " 'id' : 1,\n"
349 " 'readerCertificate' : <not printed>,\n"
350 " 'userAuthenticationRequired' : true,\n"
351 " 'timeoutMillis' : 1,\n"
352 " },\n"
353 " ],\n"
354 " {\n"
355 " 'Name Space' : [\n"
356 " {\n"
357 " 'name' : 'Last name',\n"
358 " 'value' : 'Turing',\n"
David Zeuthen34abaae2020-10-26 20:26:36 -0400359 " 'accessControlProfiles' : [1, ],\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800360 " },\n"
361 " ],\n"
362 " },\n"
David Zeuthen34abaae2020-10-26 20:26:36 -0400363 " false,\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800364 "]",
365 cborPretty);
366
367 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
368 attData.attestationCertificate[0].encodedCertificate);
369 ASSERT_TRUE(credentialPubKey);
370 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
371 {}, // Additional data
372 credentialPubKey.value()));
373}
374
375TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
376 Status result;
377
378 HardwareInformation hwInfo;
379 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
380
381 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400382 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
383 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800384
385 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400386 test_utils::AttestationData attData(writableCredential, challenge,
387 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800388 EXPECT_TRUE(attData.result.isOk())
389 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
390
Selene Huangcab019a2020-03-11 04:37:48 -0700391 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800392 ASSERT_TRUE(readerCertificate1);
393
Selene Huangcab019a2020-03-11 04:37:48 -0700394 optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
Selene Huang92b61d62020-03-04 02:24:16 -0800395 ASSERT_TRUE(readerCertificate2);
396
397 const vector<test_utils::TestProfile> testProfiles = {
398 {1, readerCertificate1.value(), true, 1},
399 {2, readerCertificate2.value(), true, 2},
400 };
401 const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
David Zeuthen28edb102020-04-28 18:54:55 -0400402 size_t expectedPoPSize =
403 525021 + readerCertificate1.value().size() + readerCertificate2.value().size();
404 // OK to fail, not available in v1 HAL
405 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
406 result = writableCredential->startPersonalization(testProfiles.size(), entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800407 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
408 << endl;
409
410 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700411 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800412 ASSERT_TRUE(secureProfiles);
413
414 vector<uint8_t> portraitImage1;
Selene Huangcab019a2020-03-11 04:37:48 -0700415 test_utils::setImageData(portraitImage1);
Selene Huang92b61d62020-03-04 02:24:16 -0800416
417 vector<uint8_t> portraitImage2;
Selene Huangcab019a2020-03-11 04:37:48 -0700418 test_utils::setImageData(portraitImage2);
Selene Huang92b61d62020-03-04 02:24:16 -0800419
420 const vector<test_utils::TestEntryData> testEntries1 = {
421 {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
422 {"Name Space2", "Home address", string("Maida Vale, London, England"),
423 vector<int32_t>{1}},
424 {"Name Space2", "Work address", string("Maida Vale2, London, England"),
425 vector<int32_t>{2}},
426 {"Name Space2", "Trailer address", string("Maida, London, England"),
427 vector<int32_t>{1}},
428 {"Image", "Portrait image", portraitImage1, vector<int32_t>{1}},
429 {"Image2", "Work image", portraitImage2, vector<int32_t>{1, 2}},
430 {"Name Space3", "xyzw", string("random stuff"), vector<int32_t>{1, 2}},
431 {"Name Space3", "Something", string("Some string"), vector<int32_t>{2}},
432 };
433
434 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
435 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700436 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800437 encryptedBlobs, true));
438 }
439
440 vector<uint8_t> credentialData;
441 vector<uint8_t> proofOfProvisioningSignature;
442 result =
443 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
444
445 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
446 << endl;
447
448 optional<vector<uint8_t>> proofOfProvisioning =
449 support::coseSignGetPayload(proofOfProvisioningSignature);
450 ASSERT_TRUE(proofOfProvisioning);
Max Biresa3c7f4c2021-04-09 08:56:40 -0700451 string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(),
452 32, //
453 {"readerCertificate"});
Selene Huang92b61d62020-03-04 02:24:16 -0800454 EXPECT_EQ(
455 "[\n"
456 " 'ProofOfProvisioning',\n"
457 " 'org.iso.18013-5.2019.mdl',\n"
458 " [\n"
459 " {\n"
460 " 'id' : 1,\n"
461 " 'readerCertificate' : <not printed>,\n"
462 " 'userAuthenticationRequired' : true,\n"
463 " 'timeoutMillis' : 1,\n"
464 " },\n"
465 " {\n"
466 " 'id' : 2,\n"
467 " 'readerCertificate' : <not printed>,\n"
468 " 'userAuthenticationRequired' : true,\n"
469 " 'timeoutMillis' : 2,\n"
470 " },\n"
471 " ],\n"
472 " {\n"
473 " 'Name Space 1' : [\n"
474 " {\n"
475 " 'name' : 'Last name',\n"
476 " 'value' : 'Turing',\n"
477 " 'accessControlProfiles' : [1, 2, ],\n"
478 " },\n"
479 " ],\n"
480 " 'Name Space2' : [\n"
481 " {\n"
482 " 'name' : 'Home address',\n"
483 " 'value' : 'Maida Vale, London, England',\n"
484 " 'accessControlProfiles' : [1, ],\n"
485 " },\n"
486 " {\n"
487 " 'name' : 'Work address',\n"
488 " 'value' : 'Maida Vale2, London, England',\n"
489 " 'accessControlProfiles' : [2, ],\n"
490 " },\n"
491 " {\n"
492 " 'name' : 'Trailer address',\n"
493 " 'value' : 'Maida, London, England',\n"
494 " 'accessControlProfiles' : [1, ],\n"
495 " },\n"
496 " ],\n"
497 " 'Image' : [\n"
498 " {\n"
499 " 'name' : 'Portrait image',\n"
500 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
501 " 'accessControlProfiles' : [1, ],\n"
502 " },\n"
503 " ],\n"
504 " 'Image2' : [\n"
505 " {\n"
506 " 'name' : 'Work image',\n"
507 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
508 " 'accessControlProfiles' : [1, 2, ],\n"
509 " },\n"
510 " ],\n"
511 " 'Name Space3' : [\n"
512 " {\n"
513 " 'name' : 'xyzw',\n"
514 " 'value' : 'random stuff',\n"
515 " 'accessControlProfiles' : [1, 2, ],\n"
516 " },\n"
517 " {\n"
518 " 'name' : 'Something',\n"
519 " 'value' : 'Some string',\n"
520 " 'accessControlProfiles' : [2, ],\n"
521 " },\n"
522 " ],\n"
523 " },\n"
David Zeuthen34abaae2020-10-26 20:26:36 -0400524 " false,\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800525 "]",
526 cborPretty);
527
528 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
529 attData.attestationCertificate[0].encodedCertificate);
530 ASSERT_TRUE(credentialPubKey);
531 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
532 {}, // Additional data
533 credentialPubKey.value()));
534}
535
536TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
537 Status result;
538
539 HardwareInformation hwInfo;
540 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
541
542 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400543 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
544 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800545
546 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400547 test_utils::AttestationData attData(writableCredential, challenge,
548 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800549 ASSERT_TRUE(attData.result.isOk())
550 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
551
Selene Huangcab019a2020-03-11 04:37:48 -0700552 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800553 ASSERT_TRUE(readerCertificate1);
554
555 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700556 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800557 ASSERT_TRUE(readerCertificate2);
558
David Zeuthen28edb102020-04-28 18:54:55 -0400559 const vector<int32_t> entryCounts = {2u, 2u};
560 size_t expectedPoPSize =
561 377 + readerCertificate1.value().size() + readerCertificate2.value().size();
562 ;
563 // OK to fail, not available in v1 HAL
564 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
David Zeuthenef739512020-06-03 13:24:52 -0400565 result = writableCredential->startPersonalization(3, entryCounts);
David Zeuthen28edb102020-04-28 18:54:55 -0400566 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
567 << endl;
568
Selene Huang92b61d62020-03-04 02:24:16 -0800569 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
570 {1, readerCertificate2.value(), true, 1},
571 {2, {}, false, 0}};
572
573 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700574 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800575 ASSERT_TRUE(secureProfiles);
576
577 const vector<test_utils::TestEntryData> testEntries1 = {
578 // test empty name space
579 {"", "t name", string("Turing"), vector<int32_t>{2}},
580 {"", "Birth", string("19120623"), vector<int32_t>{2}},
581 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
582 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
583 };
584
585 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
586 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700587 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800588 encryptedBlobs, true));
589 }
590
591 vector<uint8_t> credentialData;
592 vector<uint8_t> proofOfProvisioningSignature;
593 result =
594 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
595
596 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
597 << endl;
598}
599
600TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
601 Status result;
602
603 HardwareInformation hwInfo;
604 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
605
606 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400607 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
608 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800609
610 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400611 test_utils::AttestationData attData(writableCredential, challenge,
612 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800613 ASSERT_TRUE(attData.result.isOk())
614 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
615
616 // Enter mismatched entry and profile numbers.
617 // Technically the 2nd name space of "Name Space" occurs intermittently, 2
618 // before "Image" and 2 after image, which is not correct. All of same name
619 // space should occur together. Let's see if this fails.
620 const vector<int32_t> entryCounts = {2u, 1u, 2u};
David Zeuthenef739512020-06-03 13:24:52 -0400621 writableCredential->setExpectedProofOfProvisioningSize(123456);
622 result = writableCredential->startPersonalization(3, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800623 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
624 << endl;
625
Selene Huangcab019a2020-03-11 04:37:48 -0700626 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800627 ASSERT_TRUE(readerCertificate1);
628
629 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700630 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800631 ASSERT_TRUE(readerCertificate2);
632
633 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
634 {1, readerCertificate2.value(), true, 1},
635 {2, {}, false, 0}};
636
637 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700638 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800639 ASSERT_TRUE(secureProfiles);
640
641 const vector<test_utils::TestEntryData> testEntries1 = {
642 // test empty name space
643 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
644 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
645 };
646
647 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
648 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700649 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800650 encryptedBlobs, true));
651 }
652 const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
653 vector<int32_t>{0, 1}};
654
Selene Huangcab019a2020-03-11 04:37:48 -0700655 EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800656 encryptedBlobs, true));
657
658 // We expect this to fail because the namespace is out of order, all "Name Space"
659 // should have been called together
660 const vector<test_utils::TestEntryData> testEntries3 = {
661 {"Name Space", "First name", string("Alan"), vector<int32_t>{0, 1}},
662 {"Name Space", "Home address", string("Maida Vale, London, England"),
663 vector<int32_t>{0}},
664 };
665
666 for (const auto& entry : testEntries3) {
Selene Huangcab019a2020-03-11 04:37:48 -0700667 EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800668 encryptedBlobs, false));
669 }
670
671 vector<uint8_t> credentialData;
672 vector<uint8_t> proofOfProvisioningSignature;
673 result =
674 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
675
Selene Huangcab019a2020-03-11 04:37:48 -0700676 // should fail because test_utils::addEntry should have failed earlier.
Selene Huang92b61d62020-03-04 02:24:16 -0800677 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
678 << endl;
679 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
680 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
681}
682
David Zeuthena0796e92020-04-27 15:24:55 -0400683TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
684 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400685 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
686 false /* testCredential */));
David Zeuthena0796e92020-04-27 15:24:55 -0400687
688 const vector<int32_t> entryCounts = {1};
David Zeuthenef739512020-06-03 13:24:52 -0400689 writableCredential->setExpectedProofOfProvisioningSize(123456);
David Zeuthena0796e92020-04-27 15:24:55 -0400690 Status result = writableCredential->startPersonalization(1, entryCounts);
691 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
692 << endl;
693
694 SecureAccessControlProfile profile;
695
696 // This should fail because the id is >= 32
697 result = writableCredential->addAccessControlProfile(32, // id
698 {}, // readerCertificate
699 false, // userAuthenticationRequired
700 0, // timeoutMillis
701 42, // secureUserId
702 &profile);
703 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
704 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
705 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
706
707 // This should fail because the id is < 0
708 result = writableCredential->addAccessControlProfile(-1, // id
709 {}, // readerCertificate
710 false, // userAuthenticationRequired
711 0, // timeoutMillis
712 42, // secureUserId
713 &profile);
714 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
715 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
716 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
717}
718
Dan Shiba4d5322020-07-28 13:09:30 -0700719GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IdentityCredentialTests);
Selene Huang92b61d62020-03-04 02:24:16 -0800720INSTANTIATE_TEST_SUITE_P(
721 Identity, IdentityCredentialTests,
722 testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
723 android::PrintInstanceNameToString);
724
725} // namespace android::hardware::identity