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