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
66 vector<uint8_t> attestationChallenge;
67 vector<Certificate> attestationCertificate;
68 vector<uint8_t> attestationApplicationId = {};
69 result = writableCredential->getAttestationCertificate(
70 attestationApplicationId, attestationChallenge, &attestationCertificate);
71
72 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
73 << endl;
74 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
75 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
76 }
77
TEST_P(IdentityCredentialTests,verifyAttestationSuccessWithChallenge)78 TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
79 Status result;
80
81 HardwareInformation hwInfo;
82 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
83
84 sp<IWritableIdentityCredential> writableCredential;
85 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
86
87 string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
88 vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
89 vector<Certificate> attestationCertificate;
90 vector<uint8_t> attestationApplicationId = {};
91
92 result = writableCredential->getAttestationCertificate(
93 attestationApplicationId, attestationChallenge, &attestationCertificate);
94
95 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
96 << endl;
97
98 EXPECT_TRUE(test_utils::validateAttestationCertificate(
99 attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
100 }
101
TEST_P(IdentityCredentialTests,verifyAttestationDoubleCallFails)102 TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
103 Status result;
104
105 HardwareInformation hwInfo;
106 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
107
108 sp<IWritableIdentityCredential> writableCredential;
109 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
110
111 string challenge = "NotSoRandomChallenge1";
112 test_utils::AttestationData attData(writableCredential, challenge, {});
113 ASSERT_TRUE(test_utils::validateAttestationCertificate(
114 attData.attestationCertificate, attData.attestationChallenge,
115 attData.attestationApplicationId, hwInfo));
116
117 string challenge2 = "NotSoRandomChallenge2";
118 test_utils::AttestationData attData2(writableCredential, challenge2, {});
119 EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
120 << attData2.result.exceptionMessage() << endl;
121 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
122 EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, attData2.result.serviceSpecificErrorCode());
123 }
124
TEST_P(IdentityCredentialTests,verifyStartPersonalization)125 TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
126 Status result;
127 sp<IWritableIdentityCredential> writableCredential;
128 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
129
130 // First call should go through
131 const vector<int32_t> entryCounts = {2, 4};
132 writableCredential->setExpectedProofOfProvisioningSize(123456);
133 result = writableCredential->startPersonalization(5, entryCounts);
134 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
135 << endl;
136
137 // Call personalization again to check if repeat call is allowed.
138 result = writableCredential->startPersonalization(7, entryCounts);
139
140 // Second call to startPersonalization should have failed.
141 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
142 << endl;
143 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
144 EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
145 }
146
TEST_P(IdentityCredentialTests,verifyStartPersonalizationMin)147 TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
148 Status result;
149 sp<IWritableIdentityCredential> writableCredential;
150 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
151
152 // Verify minimal number of profile count and entry count
153 const vector<int32_t> entryCounts = {1, 1};
154 writableCredential->setExpectedProofOfProvisioningSize(123456);
155 result = writableCredential->startPersonalization(1, entryCounts);
156 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
157 << endl;
158 }
159
TEST_P(IdentityCredentialTests,verifyStartPersonalizationOne)160 TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
161 Status result;
162 sp<IWritableIdentityCredential> writableCredential;
163 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
164
165 // Verify minimal number of profile count and entry count
166 const vector<int32_t> entryCounts = {1};
167 writableCredential->setExpectedProofOfProvisioningSize(123456);
168 result = writableCredential->startPersonalization(1, entryCounts);
169 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
170 << endl;
171 }
172
TEST_P(IdentityCredentialTests,verifyStartPersonalizationLarge)173 TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
174 Status result;
175 sp<IWritableIdentityCredential> writableCredential;
176 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
177
178 // Verify set a large number of profile count and entry count is ok
179 const vector<int32_t> entryCounts = {3000};
180 writableCredential->setExpectedProofOfProvisioningSize(123456);
181 result = writableCredential->startPersonalization(25, entryCounts);
182 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
183 << endl;
184 }
185
TEST_P(IdentityCredentialTests,verifyProfileNumberMismatchShouldFail)186 TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
187 Status result;
188 sp<IWritableIdentityCredential> writableCredential;
189 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
190
191 // Enter mismatched entry and profile numbers
192 const vector<int32_t> entryCounts = {5, 6};
193 writableCredential->setExpectedProofOfProvisioningSize(123456);
194 result = writableCredential->startPersonalization(5, entryCounts);
195 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
196 << endl;
197
198 optional<vector<uint8_t>> readerCertificate = test_utils::generateReaderCertificate("12345");
199 ASSERT_TRUE(readerCertificate);
200
201 const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
202 {1, readerCertificate.value(), false, 0},
203 {2, readerCertificate.value(), true, 1},
204 // Profile 4 (no authentication)
205 {4, {}, false, 0}};
206
207 optional<vector<SecureAccessControlProfile>> secureProfiles =
208 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
209 ASSERT_TRUE(secureProfiles);
210
211 vector<uint8_t> credentialData;
212 vector<uint8_t> proofOfProvisioningSignature;
213 result =
214 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
215
216 // finishAddingEntries should fail because the number of addAccessControlProfile mismatched with
217 // startPersonalization, and begintest_utils::addEntry was not called.
218 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
219 << endl;
220 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
221 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
222 }
223
TEST_P(IdentityCredentialTests,verifyDuplicateProfileId)224 TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
225 Status result;
226 sp<IWritableIdentityCredential> writableCredential;
227 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
228
229 const vector<int32_t> entryCounts = {3, 6};
230 writableCredential->setExpectedProofOfProvisioningSize(123456);
231 result = writableCredential->startPersonalization(3, entryCounts);
232 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
233 << endl;
234
235 const vector<test_utils::TestProfile> testProfiles = {// first profile should go though
236 {1, {}, true, 2},
237 // same id, different
238 // authentication requirement
239 {1, {}, true, 1},
240 // same id, different certificate
241 {1, {}, false, 0}};
242
243 bool expectOk = true;
244 for (const auto& testProfile : testProfiles) {
245 SecureAccessControlProfile profile;
246 Certificate cert;
247 cert.encodedCertificate = testProfile.readerCertificate;
248 int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
249 result = writableCredential->addAccessControlProfile(
250 testProfile.id, cert, testProfile.userAuthenticationRequired,
251 testProfile.timeoutMillis, secureUserId, &profile);
252
253 if (expectOk) {
254 expectOk = false;
255 // for profile should be allowed though as there are no duplications
256 // yet.
257 ASSERT_TRUE(result.isOk())
258 << result.exceptionCode() << "; " << result.exceptionMessage()
259 << "test profile id = " << testProfile.id << endl;
260
261 ASSERT_EQ(testProfile.id, profile.id);
262 ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
263 ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
264 ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
265 ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
266 } else {
267 // should not allow duplicate id profiles.
268 ASSERT_FALSE(result.isOk())
269 << result.exceptionCode() << "; " << result.exceptionMessage()
270 << ". Test profile id = " << testProfile.id
271 << ", timeout=" << testProfile.timeoutMillis << endl;
272 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
273 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA,
274 result.serviceSpecificErrorCode());
275 }
276 }
277 }
278
TEST_P(IdentityCredentialTests,verifyOneProfileAndEntryPass)279 TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
280 Status result;
281
282 HardwareInformation hwInfo;
283 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
284
285 sp<IWritableIdentityCredential> writableCredential;
286 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
287
288 string challenge = "NotSoRandomChallenge1";
289 test_utils::AttestationData attData(writableCredential, challenge, {});
290 EXPECT_TRUE(attData.result.isOk())
291 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
292
293 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
294 ASSERT_TRUE(readerCertificate1);
295
296 const vector<int32_t> entryCounts = {1u};
297 size_t expectedPoPSize = 186 + readerCertificate1.value().size();
298 // OK to fail, not available in v1 HAL
299 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
300 result = writableCredential->startPersonalization(1, entryCounts);
301 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
302 << endl;
303
304 const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
305
306 optional<vector<SecureAccessControlProfile>> secureProfiles =
307 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
308 ASSERT_TRUE(secureProfiles);
309
310 const vector<test_utils::TestEntryData> testEntries1 = {
311 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
312 };
313
314 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
315 for (const auto& entry : testEntries1) {
316 ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
317 encryptedBlobs, true));
318 }
319
320 vector<uint8_t> credentialData;
321 vector<uint8_t> proofOfProvisioningSignature;
322 result =
323 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
324
325 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
326 << endl;
327
328 optional<vector<uint8_t>> proofOfProvisioning =
329 support::coseSignGetPayload(proofOfProvisioningSignature);
330 ASSERT_TRUE(proofOfProvisioning);
331 string cborPretty =
332 support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
333 EXPECT_EQ(
334 "[\n"
335 " 'ProofOfProvisioning',\n"
336 " 'org.iso.18013-5.2019.mdl',\n"
337 " [\n"
338 " {\n"
339 " 'id' : 1,\n"
340 " 'readerCertificate' : <not printed>,\n"
341 " 'userAuthenticationRequired' : true,\n"
342 " 'timeoutMillis' : 1,\n"
343 " },\n"
344 " ],\n"
345 " {\n"
346 " 'Name Space' : [\n"
347 " {\n"
348 " 'name' : 'Last name',\n"
349 " 'value' : 'Turing',\n"
350 " 'accessControlProfiles' : [0, 1, ],\n"
351 " },\n"
352 " ],\n"
353 " },\n"
354 " true,\n"
355 "]",
356 cborPretty);
357
358 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
359 attData.attestationCertificate[0].encodedCertificate);
360 ASSERT_TRUE(credentialPubKey);
361 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
362 {}, // Additional data
363 credentialPubKey.value()));
364 }
365
TEST_P(IdentityCredentialTests,verifyManyProfilesAndEntriesPass)366 TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
367 Status result;
368
369 HardwareInformation hwInfo;
370 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
371
372 sp<IWritableIdentityCredential> writableCredential;
373 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
374
375 string challenge = "NotSoRandomChallenge";
376 test_utils::AttestationData attData(writableCredential, challenge, {});
377 EXPECT_TRUE(attData.result.isOk())
378 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
379
380 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
381 ASSERT_TRUE(readerCertificate1);
382
383 optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
384 ASSERT_TRUE(readerCertificate2);
385
386 const vector<test_utils::TestProfile> testProfiles = {
387 {1, readerCertificate1.value(), true, 1},
388 {2, readerCertificate2.value(), true, 2},
389 };
390 const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
391 size_t expectedPoPSize =
392 525021 + readerCertificate1.value().size() + readerCertificate2.value().size();
393 // OK to fail, not available in v1 HAL
394 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
395 result = writableCredential->startPersonalization(testProfiles.size(), entryCounts);
396 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
397 << endl;
398
399 optional<vector<SecureAccessControlProfile>> secureProfiles =
400 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
401 ASSERT_TRUE(secureProfiles);
402
403 vector<uint8_t> portraitImage1;
404 test_utils::setImageData(portraitImage1);
405
406 vector<uint8_t> portraitImage2;
407 test_utils::setImageData(portraitImage2);
408
409 const vector<test_utils::TestEntryData> testEntries1 = {
410 {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
411 {"Name Space2", "Home address", string("Maida Vale, London, England"),
412 vector<int32_t>{1}},
413 {"Name Space2", "Work address", string("Maida Vale2, London, England"),
414 vector<int32_t>{2}},
415 {"Name Space2", "Trailer address", string("Maida, London, England"),
416 vector<int32_t>{1}},
417 {"Image", "Portrait image", portraitImage1, vector<int32_t>{1}},
418 {"Image2", "Work image", portraitImage2, vector<int32_t>{1, 2}},
419 {"Name Space3", "xyzw", string("random stuff"), vector<int32_t>{1, 2}},
420 {"Name Space3", "Something", string("Some string"), vector<int32_t>{2}},
421 };
422
423 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
424 for (const auto& entry : testEntries1) {
425 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
426 encryptedBlobs, true));
427 }
428
429 vector<uint8_t> credentialData;
430 vector<uint8_t> proofOfProvisioningSignature;
431 result =
432 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
433
434 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
435 << endl;
436
437 optional<vector<uint8_t>> proofOfProvisioning =
438 support::coseSignGetPayload(proofOfProvisioningSignature);
439 ASSERT_TRUE(proofOfProvisioning);
440 string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(),
441 32, //
442 {"readerCertificate"});
443 EXPECT_EQ(
444 "[\n"
445 " 'ProofOfProvisioning',\n"
446 " 'org.iso.18013-5.2019.mdl',\n"
447 " [\n"
448 " {\n"
449 " 'id' : 1,\n"
450 " 'readerCertificate' : <not printed>,\n"
451 " 'userAuthenticationRequired' : true,\n"
452 " 'timeoutMillis' : 1,\n"
453 " },\n"
454 " {\n"
455 " 'id' : 2,\n"
456 " 'readerCertificate' : <not printed>,\n"
457 " 'userAuthenticationRequired' : true,\n"
458 " 'timeoutMillis' : 2,\n"
459 " },\n"
460 " ],\n"
461 " {\n"
462 " 'Name Space 1' : [\n"
463 " {\n"
464 " 'name' : 'Last name',\n"
465 " 'value' : 'Turing',\n"
466 " 'accessControlProfiles' : [1, 2, ],\n"
467 " },\n"
468 " ],\n"
469 " 'Name Space2' : [\n"
470 " {\n"
471 " 'name' : 'Home address',\n"
472 " 'value' : 'Maida Vale, London, England',\n"
473 " 'accessControlProfiles' : [1, ],\n"
474 " },\n"
475 " {\n"
476 " 'name' : 'Work address',\n"
477 " 'value' : 'Maida Vale2, London, England',\n"
478 " 'accessControlProfiles' : [2, ],\n"
479 " },\n"
480 " {\n"
481 " 'name' : 'Trailer address',\n"
482 " 'value' : 'Maida, London, England',\n"
483 " 'accessControlProfiles' : [1, ],\n"
484 " },\n"
485 " ],\n"
486 " 'Image' : [\n"
487 " {\n"
488 " 'name' : 'Portrait image',\n"
489 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
490 " 'accessControlProfiles' : [1, ],\n"
491 " },\n"
492 " ],\n"
493 " 'Image2' : [\n"
494 " {\n"
495 " 'name' : 'Work image',\n"
496 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
497 " 'accessControlProfiles' : [1, 2, ],\n"
498 " },\n"
499 " ],\n"
500 " 'Name Space3' : [\n"
501 " {\n"
502 " 'name' : 'xyzw',\n"
503 " 'value' : 'random stuff',\n"
504 " 'accessControlProfiles' : [1, 2, ],\n"
505 " },\n"
506 " {\n"
507 " 'name' : 'Something',\n"
508 " 'value' : 'Some string',\n"
509 " 'accessControlProfiles' : [2, ],\n"
510 " },\n"
511 " ],\n"
512 " },\n"
513 " true,\n"
514 "]",
515 cborPretty);
516
517 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
518 attData.attestationCertificate[0].encodedCertificate);
519 ASSERT_TRUE(credentialPubKey);
520 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
521 {}, // Additional data
522 credentialPubKey.value()));
523 }
524
TEST_P(IdentityCredentialTests,verifyEmptyNameSpaceMixedWithNonEmptyWorks)525 TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
526 Status result;
527
528 HardwareInformation hwInfo;
529 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
530
531 sp<IWritableIdentityCredential> writableCredential;
532 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
533
534 string challenge = "NotSoRandomChallenge";
535 test_utils::AttestationData attData(writableCredential, challenge, {});
536 ASSERT_TRUE(attData.result.isOk())
537 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
538
539 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
540 ASSERT_TRUE(readerCertificate1);
541
542 optional<vector<uint8_t>> readerCertificate2 =
543 test_utils::generateReaderCertificate("123456987987987987987987");
544 ASSERT_TRUE(readerCertificate2);
545
546 const vector<int32_t> entryCounts = {2u, 2u};
547 size_t expectedPoPSize =
548 377 + readerCertificate1.value().size() + readerCertificate2.value().size();
549 ;
550 // OK to fail, not available in v1 HAL
551 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
552 result = writableCredential->startPersonalization(3, entryCounts);
553 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
554 << endl;
555
556 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
557 {1, readerCertificate2.value(), true, 1},
558 {2, {}, false, 0}};
559
560 optional<vector<SecureAccessControlProfile>> secureProfiles =
561 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
562 ASSERT_TRUE(secureProfiles);
563
564 const vector<test_utils::TestEntryData> testEntries1 = {
565 // test empty name space
566 {"", "t name", string("Turing"), vector<int32_t>{2}},
567 {"", "Birth", string("19120623"), vector<int32_t>{2}},
568 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
569 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
570 };
571
572 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
573 for (const auto& entry : testEntries1) {
574 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
575 encryptedBlobs, true));
576 }
577
578 vector<uint8_t> credentialData;
579 vector<uint8_t> proofOfProvisioningSignature;
580 result =
581 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
582
583 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
584 << endl;
585 }
586
TEST_P(IdentityCredentialTests,verifyInterleavingEntryNameSpaceOrderingFails)587 TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
588 Status result;
589
590 HardwareInformation hwInfo;
591 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
592
593 sp<IWritableIdentityCredential> writableCredential;
594 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
595
596 string challenge = "NotSoRandomChallenge";
597 test_utils::AttestationData attData(writableCredential, challenge, {});
598 ASSERT_TRUE(attData.result.isOk())
599 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
600
601 // Enter mismatched entry and profile numbers.
602 // Technically the 2nd name space of "Name Space" occurs intermittently, 2
603 // before "Image" and 2 after image, which is not correct. All of same name
604 // space should occur together. Let's see if this fails.
605 const vector<int32_t> entryCounts = {2u, 1u, 2u};
606 writableCredential->setExpectedProofOfProvisioningSize(123456);
607 result = writableCredential->startPersonalization(3, entryCounts);
608 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
609 << endl;
610
611 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
612 ASSERT_TRUE(readerCertificate1);
613
614 optional<vector<uint8_t>> readerCertificate2 =
615 test_utils::generateReaderCertificate("123456987987987987987987");
616 ASSERT_TRUE(readerCertificate2);
617
618 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
619 {1, readerCertificate2.value(), true, 1},
620 {2, {}, false, 0}};
621
622 optional<vector<SecureAccessControlProfile>> secureProfiles =
623 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
624 ASSERT_TRUE(secureProfiles);
625
626 const vector<test_utils::TestEntryData> testEntries1 = {
627 // test empty name space
628 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
629 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
630 };
631
632 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
633 for (const auto& entry : testEntries1) {
634 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
635 encryptedBlobs, true));
636 }
637 const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
638 vector<int32_t>{0, 1}};
639
640 EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
641 encryptedBlobs, true));
642
643 // We expect this to fail because the namespace is out of order, all "Name Space"
644 // should have been called together
645 const vector<test_utils::TestEntryData> testEntries3 = {
646 {"Name Space", "First name", string("Alan"), vector<int32_t>{0, 1}},
647 {"Name Space", "Home address", string("Maida Vale, London, England"),
648 vector<int32_t>{0}},
649 };
650
651 for (const auto& entry : testEntries3) {
652 EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
653 encryptedBlobs, false));
654 }
655
656 vector<uint8_t> credentialData;
657 vector<uint8_t> proofOfProvisioningSignature;
658 result =
659 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
660
661 // should fail because test_utils::addEntry should have failed earlier.
662 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
663 << endl;
664 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
665 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
666 }
667
TEST_P(IdentityCredentialTests,verifyAccessControlProfileIdOutOfRange)668 TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
669 sp<IWritableIdentityCredential> writableCredential;
670 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
671
672 const vector<int32_t> entryCounts = {1};
673 writableCredential->setExpectedProofOfProvisioningSize(123456);
674 Status result = writableCredential->startPersonalization(1, entryCounts);
675 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
676 << endl;
677
678 SecureAccessControlProfile profile;
679
680 // This should fail because the id is >= 32
681 result = writableCredential->addAccessControlProfile(32, // id
682 {}, // readerCertificate
683 false, // userAuthenticationRequired
684 0, // timeoutMillis
685 42, // secureUserId
686 &profile);
687 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
688 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
689 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
690
691 // This should fail because the id is < 0
692 result = writableCredential->addAccessControlProfile(-1, // id
693 {}, // readerCertificate
694 false, // userAuthenticationRequired
695 0, // timeoutMillis
696 42, // secureUserId
697 &profile);
698 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
699 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
700 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
701 }
702
703 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IdentityCredentialTests);
704 INSTANTIATE_TEST_SUITE_P(
705 Identity, IdentityCredentialTests,
706 testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
707 android::PrintInstanceNameToString);
708
709 } // namespace android::hardware::identity
710