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 "VtsIdentityTestUtils.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 = {3000};
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 =
342 support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
343 EXPECT_EQ(
344 "[\n"
345 " 'ProofOfProvisioning',\n"
346 " 'org.iso.18013-5.2019.mdl',\n"
347 " [\n"
348 " {\n"
349 " 'id' : 1,\n"
350 " 'readerCertificate' : <not printed>,\n"
351 " 'userAuthenticationRequired' : true,\n"
352 " 'timeoutMillis' : 1,\n"
353 " },\n"
354 " ],\n"
355 " {\n"
356 " 'Name Space' : [\n"
357 " {\n"
358 " 'name' : 'Last name',\n"
359 " 'value' : 'Turing',\n"
360 " 'accessControlProfiles' : [1, ],\n"
361 " },\n"
362 " ],\n"
363 " },\n"
364 " false,\n"
365 "]",
366 cborPretty);
367
368 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
369 attData.attestationCertificate[0].encodedCertificate);
370 ASSERT_TRUE(credentialPubKey);
371 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
372 {}, // Additional data
373 credentialPubKey.value()));
374 }
375
TEST_P(IdentityCredentialTests,verifyManyProfilesAndEntriesPass)376 TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
377 Status result;
378
379 HardwareInformation hwInfo;
380 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
381
382 sp<IWritableIdentityCredential> writableCredential;
383 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
384 false /* testCredential */));
385
386 string challenge = "NotSoRandomChallenge";
387 test_utils::AttestationData attData(writableCredential, challenge,
388 {} /* atteestationApplicationId */);
389 EXPECT_TRUE(attData.result.isOk())
390 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
391
392 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
393 ASSERT_TRUE(readerCertificate1);
394
395 optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
396 ASSERT_TRUE(readerCertificate2);
397
398 const vector<test_utils::TestProfile> testProfiles = {
399 {1, readerCertificate1.value(), true, 1},
400 {2, readerCertificate2.value(), true, 2},
401 };
402 const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
403 size_t expectedPoPSize =
404 525021 + readerCertificate1.value().size() + readerCertificate2.value().size();
405 // OK to fail, not available in v1 HAL
406 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
407 result = writableCredential->startPersonalization(testProfiles.size(), entryCounts);
408 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
409 << endl;
410
411 optional<vector<SecureAccessControlProfile>> secureProfiles =
412 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
413 ASSERT_TRUE(secureProfiles);
414
415 vector<uint8_t> portraitImage1;
416 test_utils::setImageData(portraitImage1);
417
418 vector<uint8_t> portraitImage2;
419 test_utils::setImageData(portraitImage2);
420
421 const vector<test_utils::TestEntryData> testEntries1 = {
422 {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
423 {"Name Space2", "Home address", string("Maida Vale, London, England"),
424 vector<int32_t>{1}},
425 {"Name Space2", "Work address", string("Maida Vale2, London, England"),
426 vector<int32_t>{2}},
427 {"Name Space2", "Trailer address", string("Maida, London, England"),
428 vector<int32_t>{1}},
429 {"Image", "Portrait image", portraitImage1, vector<int32_t>{1}},
430 {"Image2", "Work image", portraitImage2, vector<int32_t>{1, 2}},
431 {"Name Space3", "xyzw", string("random stuff"), vector<int32_t>{1, 2}},
432 {"Name Space3", "Something", string("Some string"), vector<int32_t>{2}},
433 };
434
435 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
436 for (const auto& entry : testEntries1) {
437 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
438 encryptedBlobs, true));
439 }
440
441 vector<uint8_t> credentialData;
442 vector<uint8_t> proofOfProvisioningSignature;
443 result =
444 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
445
446 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
447 << endl;
448
449 optional<vector<uint8_t>> proofOfProvisioning =
450 support::coseSignGetPayload(proofOfProvisioningSignature);
451 ASSERT_TRUE(proofOfProvisioning);
452 string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(),
453 32, //
454 {"readerCertificate"});
455 EXPECT_EQ(
456 "[\n"
457 " 'ProofOfProvisioning',\n"
458 " 'org.iso.18013-5.2019.mdl',\n"
459 " [\n"
460 " {\n"
461 " 'id' : 1,\n"
462 " 'readerCertificate' : <not printed>,\n"
463 " 'userAuthenticationRequired' : true,\n"
464 " 'timeoutMillis' : 1,\n"
465 " },\n"
466 " {\n"
467 " 'id' : 2,\n"
468 " 'readerCertificate' : <not printed>,\n"
469 " 'userAuthenticationRequired' : true,\n"
470 " 'timeoutMillis' : 2,\n"
471 " },\n"
472 " ],\n"
473 " {\n"
474 " 'Name Space 1' : [\n"
475 " {\n"
476 " 'name' : 'Last name',\n"
477 " 'value' : 'Turing',\n"
478 " 'accessControlProfiles' : [1, 2, ],\n"
479 " },\n"
480 " ],\n"
481 " 'Name Space2' : [\n"
482 " {\n"
483 " 'name' : 'Home address',\n"
484 " 'value' : 'Maida Vale, London, England',\n"
485 " 'accessControlProfiles' : [1, ],\n"
486 " },\n"
487 " {\n"
488 " 'name' : 'Work address',\n"
489 " 'value' : 'Maida Vale2, London, England',\n"
490 " 'accessControlProfiles' : [2, ],\n"
491 " },\n"
492 " {\n"
493 " 'name' : 'Trailer address',\n"
494 " 'value' : 'Maida, London, England',\n"
495 " 'accessControlProfiles' : [1, ],\n"
496 " },\n"
497 " ],\n"
498 " 'Image' : [\n"
499 " {\n"
500 " 'name' : 'Portrait image',\n"
501 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
502 " 'accessControlProfiles' : [1, ],\n"
503 " },\n"
504 " ],\n"
505 " 'Image2' : [\n"
506 " {\n"
507 " 'name' : 'Work image',\n"
508 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
509 " 'accessControlProfiles' : [1, 2, ],\n"
510 " },\n"
511 " ],\n"
512 " 'Name Space3' : [\n"
513 " {\n"
514 " 'name' : 'xyzw',\n"
515 " 'value' : 'random stuff',\n"
516 " 'accessControlProfiles' : [1, 2, ],\n"
517 " },\n"
518 " {\n"
519 " 'name' : 'Something',\n"
520 " 'value' : 'Some string',\n"
521 " 'accessControlProfiles' : [2, ],\n"
522 " },\n"
523 " ],\n"
524 " },\n"
525 " false,\n"
526 "]",
527 cborPretty);
528
529 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
530 attData.attestationCertificate[0].encodedCertificate);
531 ASSERT_TRUE(credentialPubKey);
532 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
533 {}, // Additional data
534 credentialPubKey.value()));
535 }
536
TEST_P(IdentityCredentialTests,verifyEmptyNameSpaceMixedWithNonEmptyWorks)537 TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
538 Status result;
539
540 HardwareInformation hwInfo;
541 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
542
543 sp<IWritableIdentityCredential> writableCredential;
544 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
545 false /* testCredential */));
546
547 string challenge = "NotSoRandomChallenge";
548 test_utils::AttestationData attData(writableCredential, challenge,
549 {} /* atteestationApplicationId */);
550 ASSERT_TRUE(attData.result.isOk())
551 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
552
553 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
554 ASSERT_TRUE(readerCertificate1);
555
556 optional<vector<uint8_t>> readerCertificate2 =
557 test_utils::generateReaderCertificate("123456987987987987987987");
558 ASSERT_TRUE(readerCertificate2);
559
560 const vector<int32_t> entryCounts = {2u, 2u};
561 size_t expectedPoPSize =
562 377 + readerCertificate1.value().size() + readerCertificate2.value().size();
563 ;
564 // OK to fail, not available in v1 HAL
565 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
566 result = writableCredential->startPersonalization(3, entryCounts);
567 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
568 << endl;
569
570 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
571 {1, readerCertificate2.value(), true, 1},
572 {2, {}, false, 0}};
573
574 optional<vector<SecureAccessControlProfile>> secureProfiles =
575 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
576 ASSERT_TRUE(secureProfiles);
577
578 const vector<test_utils::TestEntryData> testEntries1 = {
579 // test empty name space
580 {"", "t name", string("Turing"), vector<int32_t>{2}},
581 {"", "Birth", string("19120623"), vector<int32_t>{2}},
582 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
583 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
584 };
585
586 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
587 for (const auto& entry : testEntries1) {
588 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
589 encryptedBlobs, true));
590 }
591
592 vector<uint8_t> credentialData;
593 vector<uint8_t> proofOfProvisioningSignature;
594 result =
595 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
596
597 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
598 << endl;
599 }
600
TEST_P(IdentityCredentialTests,verifyInterleavingEntryNameSpaceOrderingFails)601 TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
602 Status result;
603
604 HardwareInformation hwInfo;
605 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
606
607 sp<IWritableIdentityCredential> writableCredential;
608 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
609 false /* testCredential */));
610
611 string challenge = "NotSoRandomChallenge";
612 test_utils::AttestationData attData(writableCredential, challenge,
613 {} /* atteestationApplicationId */);
614 ASSERT_TRUE(attData.result.isOk())
615 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
616
617 // Enter mismatched entry and profile numbers.
618 // Technically the 2nd name space of "Name Space" occurs intermittently, 2
619 // before "Image" and 2 after image, which is not correct. All of same name
620 // space should occur together. Let's see if this fails.
621 const vector<int32_t> entryCounts = {2u, 1u, 2u};
622 writableCredential->setExpectedProofOfProvisioningSize(123456);
623 result = writableCredential->startPersonalization(3, entryCounts);
624 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
625 << endl;
626
627 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
628 ASSERT_TRUE(readerCertificate1);
629
630 optional<vector<uint8_t>> readerCertificate2 =
631 test_utils::generateReaderCertificate("123456987987987987987987");
632 ASSERT_TRUE(readerCertificate2);
633
634 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
635 {1, readerCertificate2.value(), true, 1},
636 {2, {}, false, 0}};
637
638 optional<vector<SecureAccessControlProfile>> secureProfiles =
639 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
640 ASSERT_TRUE(secureProfiles);
641
642 const vector<test_utils::TestEntryData> testEntries1 = {
643 // test empty name space
644 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
645 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
646 };
647
648 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
649 for (const auto& entry : testEntries1) {
650 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
651 encryptedBlobs, true));
652 }
653 const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
654 vector<int32_t>{0, 1}};
655
656 EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
657 encryptedBlobs, true));
658
659 // We expect this to fail because the namespace is out of order, all "Name Space"
660 // should have been called together
661 const vector<test_utils::TestEntryData> testEntries3 = {
662 {"Name Space", "First name", string("Alan"), vector<int32_t>{0, 1}},
663 {"Name Space", "Home address", string("Maida Vale, London, England"),
664 vector<int32_t>{0}},
665 };
666
667 for (const auto& entry : testEntries3) {
668 EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
669 encryptedBlobs, false));
670 }
671
672 vector<uint8_t> credentialData;
673 vector<uint8_t> proofOfProvisioningSignature;
674 result =
675 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
676
677 // should fail because test_utils::addEntry should have failed earlier.
678 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
679 << endl;
680 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
681 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
682 }
683
TEST_P(IdentityCredentialTests,verifyAccessControlProfileIdOutOfRange)684 TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
685 sp<IWritableIdentityCredential> writableCredential;
686 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
687 false /* testCredential */));
688
689 const vector<int32_t> entryCounts = {1};
690 writableCredential->setExpectedProofOfProvisioningSize(123456);
691 Status result = writableCredential->startPersonalization(1, entryCounts);
692 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
693 << endl;
694
695 SecureAccessControlProfile profile;
696
697 // This should fail because the id is >= 32
698 result = writableCredential->addAccessControlProfile(32, // id
699 {}, // readerCertificate
700 false, // userAuthenticationRequired
701 0, // timeoutMillis
702 42, // secureUserId
703 &profile);
704 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
705 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
706 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
707
708 // This should fail because the id is < 0
709 result = writableCredential->addAccessControlProfile(-1, // id
710 {}, // readerCertificate
711 false, // userAuthenticationRequired
712 0, // timeoutMillis
713 42, // secureUserId
714 &profile);
715 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
716 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
717 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
718 }
719
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