1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "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
32 #include "Util.h"
33
34 namespace android::hardware::identity {
35
36 using std::endl;
37 using std::map;
38 using std::optional;
39 using std::string;
40 using std::vector;
41
42 using ::android::sp;
43 using ::android::String16;
44 using ::android::binder::Status;
45
46 class IdentityCredentialTests : public testing::TestWithParam<string> {
47 public:
SetUp()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
TEST_P(IdentityCredentialTests,verifyAttestationWithEmptyChallenge)57 TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
58 Status result;
59
60 HardwareInformation hwInfo;
61 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
62
63 sp<IWritableIdentityCredential> writableCredential;
64 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
65 false /* testCredential */));
66
67 vector<uint8_t> attestationChallenge;
68 vector<Certificate> attestationCertificate;
69 vector<uint8_t> attestationApplicationId = {};
70 result = writableCredential->getAttestationCertificate(
71 attestationApplicationId, attestationChallenge, &attestationCertificate);
72
73 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());
77 }
78
TEST_P(IdentityCredentialTests,verifyAttestationSuccessWithChallenge)79 TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
80 Status result;
81
82 HardwareInformation hwInfo;
83 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
84
85 sp<IWritableIdentityCredential> writableCredential;
86 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
87 false /* testCredential */));
88
89 string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
90 vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
91 vector<Certificate> attestationCertificate;
92 vector<uint8_t> attestationApplicationId = {1};
93
94 result = writableCredential->getAttestationCertificate(
95 attestationApplicationId, attestationChallenge, &attestationCertificate);
96
97 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
98 << endl;
99
100 test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
101 attestationApplicationId, false);
102 }
103
TEST_P(IdentityCredentialTests,verifyAttestationDoubleCallFails)104 TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
105 Status result;
106
107 sp<IWritableIdentityCredential> writableCredential;
108 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
109 false /* testCredential */));
110
111 string challenge = "NotSoRandomChallenge1";
112 test_utils::AttestationData attData(writableCredential, challenge,
113 {1} /* atteestationApplicationId */);
114 test_utils::validateAttestationCertificate(attData.attestationCertificate,
115 attData.attestationChallenge,
116 attData.attestationApplicationId, false);
117
118 string challenge2 = "NotSoRandomChallenge2";
119 test_utils::AttestationData attData2(writableCredential, challenge2,
120 {} /* atteestationApplicationId */);
121 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
TEST_P(IdentityCredentialTests,verifyStartPersonalization)127 TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
128 Status result;
129 sp<IWritableIdentityCredential> writableCredential;
130 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
131 false /* testCredential */));
132
133 // First call should go through
134 const vector<int32_t> entryCounts = {2, 4};
135 writableCredential->setExpectedProofOfProvisioningSize(123456);
136 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
TEST_P(IdentityCredentialTests,verifyStartPersonalizationMin)150 TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
151 Status result;
152 sp<IWritableIdentityCredential> writableCredential;
153 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
154 false /* testCredential */));
155
156 // Verify minimal number of profile count and entry count
157 const vector<int32_t> entryCounts = {1, 1};
158 writableCredential->setExpectedProofOfProvisioningSize(123456);
159 result = writableCredential->startPersonalization(1, entryCounts);
160 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
161 << endl;
162 }
163
TEST_P(IdentityCredentialTests,verifyStartPersonalizationOne)164 TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
165 Status result;
166 sp<IWritableIdentityCredential> writableCredential;
167 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
168 false /* testCredential */));
169
170 // Verify minimal number of profile count and entry count
171 const vector<int32_t> entryCounts = {1};
172 writableCredential->setExpectedProofOfProvisioningSize(123456);
173 result = writableCredential->startPersonalization(1, entryCounts);
174 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
175 << endl;
176 }
177
TEST_P(IdentityCredentialTests,verifyStartPersonalizationLarge)178 TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
179 Status result;
180 sp<IWritableIdentityCredential> writableCredential;
181 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
182 false /* testCredential */));
183
184 // Verify set a large number of profile count and entry count is ok
185 const vector<int32_t> entryCounts = {255};
186 writableCredential->setExpectedProofOfProvisioningSize(123456);
187 result = writableCredential->startPersonalization(25, entryCounts);
188 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
189 << endl;
190 }
191
TEST_P(IdentityCredentialTests,verifyProfileNumberMismatchShouldFail)192 TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
193 Status result;
194 sp<IWritableIdentityCredential> writableCredential;
195 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
196 false /* testCredential */));
197
198 // Enter mismatched entry and profile numbers
199 const vector<int32_t> entryCounts = {5, 6};
200 writableCredential->setExpectedProofOfProvisioningSize(123456);
201 result = writableCredential->startPersonalization(5, entryCounts);
202 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
203 << endl;
204
205 optional<vector<uint8_t>> readerCertificate = test_utils::generateReaderCertificate("12345");
206 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 =
215 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
216 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
224 // startPersonalization, and begintest_utils::addEntry was not called.
225 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
TEST_P(IdentityCredentialTests,verifyDuplicateProfileId)231 TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
232 Status result;
233 sp<IWritableIdentityCredential> writableCredential;
234 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
235 false /* testCredential */));
236
237 const vector<int32_t> entryCounts = {3, 6};
238 writableCredential->setExpectedProofOfProvisioningSize(123456);
239 result = writableCredential->startPersonalization(3, entryCounts);
240 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;
256 int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
257 result = writableCredential->addAccessControlProfile(
258 testProfile.id, cert, testProfile.userAuthenticationRequired,
259 testProfile.timeoutMillis, secureUserId, &profile);
260
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
TEST_P(IdentityCredentialTests,verifyOneProfileAndEntryPass)287 TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
288 Status result;
289
290 HardwareInformation hwInfo;
291 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
292
293 sp<IWritableIdentityCredential> writableCredential;
294 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
295 false /* testCredential */));
296
297 string challenge = "NotSoRandomChallenge1";
298 test_utils::AttestationData attData(writableCredential, challenge,
299 {} /* atteestationApplicationId */);
300 EXPECT_TRUE(attData.result.isOk())
301 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
302
303 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
304 ASSERT_TRUE(readerCertificate1);
305
306 const vector<int32_t> entryCounts = {1u};
307 size_t expectedPoPSize = 185 + readerCertificate1.value().size();
308 // 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
314 const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
315
316 optional<vector<SecureAccessControlProfile>> secureProfiles =
317 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
318 ASSERT_TRUE(secureProfiles);
319
320 const vector<test_utils::TestEntryData> testEntries1 = {
321 {"Name Space", "Last name", string("Turing"), vector<int32_t>{1}},
322 };
323
324 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
325 for (const auto& entry : testEntries1) {
326 ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
327 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);
341 string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
342 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"
359 " 'accessControlProfiles' : [1, ],\n"
360 " },\n"
361 " ],\n"
362 " },\n"
363 " false,\n"
364 "]",
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
TEST_P(IdentityCredentialTests,verifyManyProfilesAndEntriesPass)375 TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
376 Status result;
377
378 HardwareInformation hwInfo;
379 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
380
381 sp<IWritableIdentityCredential> writableCredential;
382 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
383 false /* testCredential */));
384
385 string challenge = "NotSoRandomChallenge";
386 test_utils::AttestationData attData(writableCredential, challenge,
387 {} /* atteestationApplicationId */);
388 EXPECT_TRUE(attData.result.isOk())
389 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
390
391 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
392 ASSERT_TRUE(readerCertificate1);
393
394 optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
395 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};
402 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);
407 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
408 << endl;
409
410 optional<vector<SecureAccessControlProfile>> secureProfiles =
411 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
412 ASSERT_TRUE(secureProfiles);
413
414 vector<uint8_t> portraitImage1;
415 test_utils::setImageData(portraitImage1);
416
417 vector<uint8_t> portraitImage2;
418 test_utils::setImageData(portraitImage2);
419
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) {
436 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
437 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);
451 string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(),
452 32, //
453 {"readerCertificate"});
454 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"
524 " false,\n"
525 "]",
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
TEST_P(IdentityCredentialTests,verifyEmptyNameSpaceMixedWithNonEmptyWorks)536 TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
537 Status result;
538
539 HardwareInformation hwInfo;
540 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
541
542 sp<IWritableIdentityCredential> writableCredential;
543 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
544 false /* testCredential */));
545
546 string challenge = "NotSoRandomChallenge";
547 test_utils::AttestationData attData(writableCredential, challenge,
548 {} /* atteestationApplicationId */);
549 ASSERT_TRUE(attData.result.isOk())
550 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
551
552 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
553 ASSERT_TRUE(readerCertificate1);
554
555 optional<vector<uint8_t>> readerCertificate2 =
556 test_utils::generateReaderCertificate("123456987987987987987987");
557 ASSERT_TRUE(readerCertificate2);
558
559 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);
565 result = writableCredential->startPersonalization(3, entryCounts);
566 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
567 << endl;
568
569 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 =
574 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
575 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) {
587 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
588 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
TEST_P(IdentityCredentialTests,verifyInterleavingEntryNameSpaceOrderingFails)600 TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
601 Status result;
602
603 HardwareInformation hwInfo;
604 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
605
606 sp<IWritableIdentityCredential> writableCredential;
607 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
608 false /* testCredential */));
609
610 string challenge = "NotSoRandomChallenge";
611 test_utils::AttestationData attData(writableCredential, challenge,
612 {} /* atteestationApplicationId */);
613 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};
621 writableCredential->setExpectedProofOfProvisioningSize(123456);
622 result = writableCredential->startPersonalization(3, entryCounts);
623 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
624 << endl;
625
626 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
627 ASSERT_TRUE(readerCertificate1);
628
629 optional<vector<uint8_t>> readerCertificate2 =
630 test_utils::generateReaderCertificate("123456987987987987987987");
631 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 =
638 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
639 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) {
649 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
650 encryptedBlobs, true));
651 }
652 const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
653 vector<int32_t>{0, 1}};
654
655 EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
656 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) {
667 EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
668 encryptedBlobs, false));
669 }
670
671 vector<uint8_t> credentialData;
672 vector<uint8_t> proofOfProvisioningSignature;
673 result =
674 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
675
676 // should fail because test_utils::addEntry should have failed earlier.
677 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
TEST_P(IdentityCredentialTests,verifyAccessControlProfileIdOutOfRange)683 TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
684 sp<IWritableIdentityCredential> writableCredential;
685 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
686 false /* testCredential */));
687
688 const vector<int32_t> entryCounts = {1};
689 writableCredential->setExpectedProofOfProvisioningSize(123456);
690 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
719 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IdentityCredentialTests);
720 INSTANTIATE_TEST_SUITE_P(
721 Identity, IdentityCredentialTests,
722 testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
723 android::PrintInstanceNameToString);
724
725 } // namespace android::hardware::identity
726