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