blob: 8b0c0502265522f0da196e38e9102ac439edc50d [file] [log] [blame]
Selene Huang92b61d62020-03-04 02:24:16 -08001/*
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
34namespace android::hardware::identity {
35
36using std::endl;
37using std::map;
38using std::optional;
39using std::string;
40using std::vector;
41
42using ::android::sp;
43using ::android::String16;
44using ::android::binder::Status;
45
46class IdentityCredentialTests : public testing::TestWithParam<string> {
47 public:
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
57TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
58 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -070059
60 HardwareInformation hwInfo;
61 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
62
Selene Huang92b61d62020-03-04 02:24:16 -080063 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -070064 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -080065
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_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
73 << endl;
74
Selene Huangcab019a2020-03-11 04:37:48 -070075 EXPECT_TRUE(test_utils::validateAttestationCertificate(
76 attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
Selene Huang92b61d62020-03-04 02:24:16 -080077}
78
79TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
80 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -070081
82 HardwareInformation hwInfo;
83 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
84
Selene Huang92b61d62020-03-04 02:24:16 -080085 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -070086 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -080087
88 string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
89 vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
90 vector<Certificate> attestationCertificate;
91 vector<uint8_t> attestationApplicationId = {};
92
93 result = writableCredential->getAttestationCertificate(
94 attestationApplicationId, attestationChallenge, &attestationCertificate);
95
96 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
97 << endl;
98
Selene Huangcab019a2020-03-11 04:37:48 -070099 EXPECT_TRUE(test_utils::validateAttestationCertificate(
100 attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
Selene Huang92b61d62020-03-04 02:24:16 -0800101}
102
103TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
104 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -0700105
106 HardwareInformation hwInfo;
107 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
108
Selene Huang92b61d62020-03-04 02:24:16 -0800109 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700110 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800111
112 string challenge = "NotSoRandomChallenge1";
113 test_utils::AttestationData attData(writableCredential, challenge, {});
Selene Huangcab019a2020-03-11 04:37:48 -0700114 ASSERT_TRUE(test_utils::validateAttestationCertificate(
115 attData.attestationCertificate, attData.attestationChallenge,
116 attData.attestationApplicationId, hwInfo));
Selene Huang92b61d62020-03-04 02:24:16 -0800117
118 string challenge2 = "NotSoRandomChallenge2";
119 test_utils::AttestationData attData2(writableCredential, challenge2, {});
120 EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
121 << attData2.result.exceptionMessage() << endl;
122 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
123 EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, attData2.result.serviceSpecificErrorCode());
124}
125
126TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
127 Status result;
128 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700129 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800130
131 // First call should go through
132 const vector<int32_t> entryCounts = {2, 4};
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
147TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
148 Status result;
149 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700150 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800151
152 // Verify minimal number of profile count and entry count
153 const vector<int32_t> entryCounts = {1, 1};
154 writableCredential->startPersonalization(1, entryCounts);
155 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
156 << endl;
157}
158
159TEST_P(IdentityCredentialTests, verifyStartPersonalizationZero) {
160 Status result;
161 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700162 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800163
164 const vector<int32_t> entryCounts = {0};
165 writableCredential->startPersonalization(0, entryCounts);
166 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
167 << endl;
168}
169
170TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
171 Status result;
172 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700173 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800174
175 // Verify minimal number of profile count and entry count
176 const vector<int32_t> entryCounts = {1};
177 writableCredential->startPersonalization(1, entryCounts);
178 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
179 << endl;
180}
181
182TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
183 Status result;
184 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700185 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800186
187 // Verify set a large number of profile count and entry count is ok
188 const vector<int32_t> entryCounts = {3000};
189 writableCredential->startPersonalization(3500, entryCounts);
190 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
191 << endl;
192}
193
194TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
195 Status result;
196 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700197 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800198
199 // Enter mismatched entry and profile numbers
200 const vector<int32_t> entryCounts = {5, 6};
201 writableCredential->startPersonalization(5, entryCounts);
202 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
203 << endl;
204
Selene Huangcab019a2020-03-11 04:37:48 -0700205 optional<vector<uint8_t>> readerCertificate = test_utils::generateReaderCertificate("12345");
Selene Huang92b61d62020-03-04 02:24:16 -0800206 ASSERT_TRUE(readerCertificate);
207
208 const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
209 {1, readerCertificate.value(), false, 0},
210 {2, readerCertificate.value(), true, 1},
211 // Profile 4 (no authentication)
212 {4, {}, false, 0}};
213
214 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700215 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800216 ASSERT_TRUE(secureProfiles);
217
218 vector<uint8_t> credentialData;
219 vector<uint8_t> proofOfProvisioningSignature;
220 result =
221 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
222
223 // finishAddingEntries should fail because the number of addAccessControlProfile mismatched with
Selene Huangcab019a2020-03-11 04:37:48 -0700224 // startPersonalization, and begintest_utils::addEntry was not called.
Selene Huang92b61d62020-03-04 02:24:16 -0800225 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
226 << endl;
227 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
228 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
229}
230
231TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
232 Status result;
233 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700234 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800235
236 const vector<int32_t> entryCounts = {3, 6};
237 writableCredential->startPersonalization(3, entryCounts);
238 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
239 << endl;
240
241 const vector<test_utils::TestProfile> testProfiles = {// first profile should go though
242 {1, {}, true, 2},
243 // same id, different
244 // authentication requirement
245 {1, {}, true, 1},
246 // same id, different certificate
247 {1, {}, false, 0}};
248
249 bool expectOk = true;
250 for (const auto& testProfile : testProfiles) {
251 SecureAccessControlProfile profile;
252 Certificate cert;
253 cert.encodedCertificate = testProfile.readerCertificate;
254 result = writableCredential->addAccessControlProfile(
255 testProfile.id, cert, testProfile.userAuthenticationRequired,
256 testProfile.timeoutMillis, 0, &profile);
257
258 if (expectOk) {
259 expectOk = false;
260 // for profile should be allowed though as there are no duplications
261 // yet.
262 ASSERT_TRUE(result.isOk())
263 << result.exceptionCode() << "; " << result.exceptionMessage()
264 << "test profile id = " << testProfile.id << endl;
265
266 ASSERT_EQ(testProfile.id, profile.id);
267 ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
268 ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
269 ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
270 ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
271 } else {
272 // should not allow duplicate id profiles.
273 ASSERT_FALSE(result.isOk())
274 << result.exceptionCode() << "; " << result.exceptionMessage()
275 << ". Test profile id = " << testProfile.id
276 << ", timeout=" << testProfile.timeoutMillis << endl;
277 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
278 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA,
279 result.serviceSpecificErrorCode());
280 }
281 }
282}
283
284TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
285 Status result;
286
287 HardwareInformation hwInfo;
288 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
289
290 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700291 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800292
293 string challenge = "NotSoRandomChallenge1";
294 test_utils::AttestationData attData(writableCredential, challenge, {});
295 EXPECT_TRUE(attData.result.isOk())
296 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
297
Selene Huangcab019a2020-03-11 04:37:48 -0700298 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800299 ASSERT_TRUE(readerCertificate1);
300
David Zeuthen28edb102020-04-28 18:54:55 -0400301 const vector<int32_t> entryCounts = {1u};
302 size_t expectedPoPSize = 186 + readerCertificate1.value().size();
303 // OK to fail, not available in v1 HAL
304 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
305 result = writableCredential->startPersonalization(1, entryCounts);
306 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
307 << endl;
308
Selene Huang92b61d62020-03-04 02:24:16 -0800309 const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
310
311 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700312 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800313 ASSERT_TRUE(secureProfiles);
314
315 const vector<test_utils::TestEntryData> testEntries1 = {
316 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
317 };
318
319 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
320 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700321 ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800322 encryptedBlobs, true));
323 }
324
325 vector<uint8_t> credentialData;
326 vector<uint8_t> proofOfProvisioningSignature;
327 result =
328 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
329
330 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
331 << endl;
332
333 optional<vector<uint8_t>> proofOfProvisioning =
334 support::coseSignGetPayload(proofOfProvisioningSignature);
335 ASSERT_TRUE(proofOfProvisioning);
336 string cborPretty =
337 support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
338 EXPECT_EQ(
339 "[\n"
340 " 'ProofOfProvisioning',\n"
341 " 'org.iso.18013-5.2019.mdl',\n"
342 " [\n"
343 " {\n"
344 " 'id' : 1,\n"
345 " 'readerCertificate' : <not printed>,\n"
346 " 'userAuthenticationRequired' : true,\n"
347 " 'timeoutMillis' : 1,\n"
348 " },\n"
349 " ],\n"
350 " {\n"
351 " 'Name Space' : [\n"
352 " {\n"
353 " 'name' : 'Last name',\n"
354 " 'value' : 'Turing',\n"
355 " 'accessControlProfiles' : [0, 1, ],\n"
356 " },\n"
357 " ],\n"
358 " },\n"
359 " true,\n"
360 "]",
361 cborPretty);
362
363 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
364 attData.attestationCertificate[0].encodedCertificate);
365 ASSERT_TRUE(credentialPubKey);
366 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
367 {}, // Additional data
368 credentialPubKey.value()));
369}
370
371TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
372 Status result;
373
374 HardwareInformation hwInfo;
375 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
376
377 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700378 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800379
380 string challenge = "NotSoRandomChallenge";
381 test_utils::AttestationData attData(writableCredential, challenge, {});
382 EXPECT_TRUE(attData.result.isOk())
383 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
384
Selene Huangcab019a2020-03-11 04:37:48 -0700385 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800386 ASSERT_TRUE(readerCertificate1);
387
Selene Huangcab019a2020-03-11 04:37:48 -0700388 optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
Selene Huang92b61d62020-03-04 02:24:16 -0800389 ASSERT_TRUE(readerCertificate2);
390
391 const vector<test_utils::TestProfile> testProfiles = {
392 {1, readerCertificate1.value(), true, 1},
393 {2, readerCertificate2.value(), true, 2},
394 };
395 const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
David Zeuthen28edb102020-04-28 18:54:55 -0400396 size_t expectedPoPSize =
397 525021 + readerCertificate1.value().size() + readerCertificate2.value().size();
398 // OK to fail, not available in v1 HAL
399 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
400 result = writableCredential->startPersonalization(testProfiles.size(), entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800401 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
402 << endl;
403
404 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700405 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800406 ASSERT_TRUE(secureProfiles);
407
408 vector<uint8_t> portraitImage1;
Selene Huangcab019a2020-03-11 04:37:48 -0700409 test_utils::setImageData(portraitImage1);
Selene Huang92b61d62020-03-04 02:24:16 -0800410
411 vector<uint8_t> portraitImage2;
Selene Huangcab019a2020-03-11 04:37:48 -0700412 test_utils::setImageData(portraitImage2);
Selene Huang92b61d62020-03-04 02:24:16 -0800413
414 const vector<test_utils::TestEntryData> testEntries1 = {
415 {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
416 {"Name Space2", "Home address", string("Maida Vale, London, England"),
417 vector<int32_t>{1}},
418 {"Name Space2", "Work address", string("Maida Vale2, London, England"),
419 vector<int32_t>{2}},
420 {"Name Space2", "Trailer address", string("Maida, London, England"),
421 vector<int32_t>{1}},
422 {"Image", "Portrait image", portraitImage1, vector<int32_t>{1}},
423 {"Image2", "Work image", portraitImage2, vector<int32_t>{1, 2}},
424 {"Name Space3", "xyzw", string("random stuff"), vector<int32_t>{1, 2}},
425 {"Name Space3", "Something", string("Some string"), vector<int32_t>{2}},
426 };
427
428 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
429 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700430 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800431 encryptedBlobs, true));
432 }
433
434 vector<uint8_t> credentialData;
435 vector<uint8_t> proofOfProvisioningSignature;
436 result =
437 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
438
439 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
440 << endl;
441
442 optional<vector<uint8_t>> proofOfProvisioning =
443 support::coseSignGetPayload(proofOfProvisioningSignature);
444 ASSERT_TRUE(proofOfProvisioning);
445 string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(),
446 32, //
447 {"readerCertificate"});
448 EXPECT_EQ(
449 "[\n"
450 " 'ProofOfProvisioning',\n"
451 " 'org.iso.18013-5.2019.mdl',\n"
452 " [\n"
453 " {\n"
454 " 'id' : 1,\n"
455 " 'readerCertificate' : <not printed>,\n"
456 " 'userAuthenticationRequired' : true,\n"
457 " 'timeoutMillis' : 1,\n"
458 " },\n"
459 " {\n"
460 " 'id' : 2,\n"
461 " 'readerCertificate' : <not printed>,\n"
462 " 'userAuthenticationRequired' : true,\n"
463 " 'timeoutMillis' : 2,\n"
464 " },\n"
465 " ],\n"
466 " {\n"
467 " 'Name Space 1' : [\n"
468 " {\n"
469 " 'name' : 'Last name',\n"
470 " 'value' : 'Turing',\n"
471 " 'accessControlProfiles' : [1, 2, ],\n"
472 " },\n"
473 " ],\n"
474 " 'Name Space2' : [\n"
475 " {\n"
476 " 'name' : 'Home address',\n"
477 " 'value' : 'Maida Vale, London, England',\n"
478 " 'accessControlProfiles' : [1, ],\n"
479 " },\n"
480 " {\n"
481 " 'name' : 'Work address',\n"
482 " 'value' : 'Maida Vale2, London, England',\n"
483 " 'accessControlProfiles' : [2, ],\n"
484 " },\n"
485 " {\n"
486 " 'name' : 'Trailer address',\n"
487 " 'value' : 'Maida, London, England',\n"
488 " 'accessControlProfiles' : [1, ],\n"
489 " },\n"
490 " ],\n"
491 " 'Image' : [\n"
492 " {\n"
493 " 'name' : 'Portrait image',\n"
494 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
495 " 'accessControlProfiles' : [1, ],\n"
496 " },\n"
497 " ],\n"
498 " 'Image2' : [\n"
499 " {\n"
500 " 'name' : 'Work image',\n"
501 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
502 " 'accessControlProfiles' : [1, 2, ],\n"
503 " },\n"
504 " ],\n"
505 " 'Name Space3' : [\n"
506 " {\n"
507 " 'name' : 'xyzw',\n"
508 " 'value' : 'random stuff',\n"
509 " 'accessControlProfiles' : [1, 2, ],\n"
510 " },\n"
511 " {\n"
512 " 'name' : 'Something',\n"
513 " 'value' : 'Some string',\n"
514 " 'accessControlProfiles' : [2, ],\n"
515 " },\n"
516 " ],\n"
517 " },\n"
518 " true,\n"
519 "]",
520 cborPretty);
521
522 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
523 attData.attestationCertificate[0].encodedCertificate);
524 ASSERT_TRUE(credentialPubKey);
525 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
526 {}, // Additional data
527 credentialPubKey.value()));
528}
529
530TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
531 Status result;
532
533 HardwareInformation hwInfo;
534 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
535
536 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700537 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800538
539 string challenge = "NotSoRandomChallenge";
540 test_utils::AttestationData attData(writableCredential, challenge, {});
541 ASSERT_TRUE(attData.result.isOk())
542 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
543
Selene Huangcab019a2020-03-11 04:37:48 -0700544 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800545 ASSERT_TRUE(readerCertificate1);
546
547 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700548 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800549 ASSERT_TRUE(readerCertificate2);
550
David Zeuthen28edb102020-04-28 18:54:55 -0400551 const vector<int32_t> entryCounts = {2u, 2u};
552 size_t expectedPoPSize =
553 377 + readerCertificate1.value().size() + readerCertificate2.value().size();
554 ;
555 // OK to fail, not available in v1 HAL
556 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
557 writableCredential->startPersonalization(3, entryCounts);
558 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
559 << endl;
560
Selene Huang92b61d62020-03-04 02:24:16 -0800561 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
562 {1, readerCertificate2.value(), true, 1},
563 {2, {}, false, 0}};
564
565 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700566 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800567 ASSERT_TRUE(secureProfiles);
568
569 const vector<test_utils::TestEntryData> testEntries1 = {
570 // test empty name space
571 {"", "t name", string("Turing"), vector<int32_t>{2}},
572 {"", "Birth", string("19120623"), vector<int32_t>{2}},
573 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
574 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
575 };
576
577 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
578 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700579 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800580 encryptedBlobs, true));
581 }
582
583 vector<uint8_t> credentialData;
584 vector<uint8_t> proofOfProvisioningSignature;
585 result =
586 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
587
588 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
589 << endl;
590}
591
592TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
593 Status result;
594
595 HardwareInformation hwInfo;
596 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
597
598 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700599 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
Selene Huang92b61d62020-03-04 02:24:16 -0800600
601 string challenge = "NotSoRandomChallenge";
602 test_utils::AttestationData attData(writableCredential, challenge, {});
603 ASSERT_TRUE(attData.result.isOk())
604 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
605
606 // Enter mismatched entry and profile numbers.
607 // Technically the 2nd name space of "Name Space" occurs intermittently, 2
608 // before "Image" and 2 after image, which is not correct. All of same name
609 // space should occur together. Let's see if this fails.
610 const vector<int32_t> entryCounts = {2u, 1u, 2u};
611 writableCredential->startPersonalization(3, entryCounts);
612 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
613 << endl;
614
Selene Huangcab019a2020-03-11 04:37:48 -0700615 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800616 ASSERT_TRUE(readerCertificate1);
617
618 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700619 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800620 ASSERT_TRUE(readerCertificate2);
621
622 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
623 {1, readerCertificate2.value(), true, 1},
624 {2, {}, false, 0}};
625
626 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700627 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800628 ASSERT_TRUE(secureProfiles);
629
630 const vector<test_utils::TestEntryData> testEntries1 = {
631 // test empty name space
632 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
633 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
634 };
635
636 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
637 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700638 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800639 encryptedBlobs, true));
640 }
641 const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
642 vector<int32_t>{0, 1}};
643
Selene Huangcab019a2020-03-11 04:37:48 -0700644 EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800645 encryptedBlobs, true));
646
647 // We expect this to fail because the namespace is out of order, all "Name Space"
648 // should have been called together
649 const vector<test_utils::TestEntryData> testEntries3 = {
650 {"Name Space", "First name", string("Alan"), vector<int32_t>{0, 1}},
651 {"Name Space", "Home address", string("Maida Vale, London, England"),
652 vector<int32_t>{0}},
653 };
654
655 for (const auto& entry : testEntries3) {
Selene Huangcab019a2020-03-11 04:37:48 -0700656 EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800657 encryptedBlobs, false));
658 }
659
660 vector<uint8_t> credentialData;
661 vector<uint8_t> proofOfProvisioningSignature;
662 result =
663 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
664
Selene Huangcab019a2020-03-11 04:37:48 -0700665 // should fail because test_utils::addEntry should have failed earlier.
Selene Huang92b61d62020-03-04 02:24:16 -0800666 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
667 << endl;
668 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
669 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
670}
671
David Zeuthena0796e92020-04-27 15:24:55 -0400672TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
673 sp<IWritableIdentityCredential> writableCredential;
Selene Huangcab019a2020-03-11 04:37:48 -0700674 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
David Zeuthena0796e92020-04-27 15:24:55 -0400675
676 const vector<int32_t> entryCounts = {1};
677 Status result = writableCredential->startPersonalization(1, entryCounts);
678 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
679 << endl;
680
681 SecureAccessControlProfile profile;
682
683 // This should fail because the id is >= 32
684 result = writableCredential->addAccessControlProfile(32, // id
685 {}, // readerCertificate
686 false, // userAuthenticationRequired
687 0, // timeoutMillis
688 42, // secureUserId
689 &profile);
690 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
691 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
692 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
693
694 // This should fail because the id is < 0
695 result = writableCredential->addAccessControlProfile(-1, // id
696 {}, // readerCertificate
697 false, // userAuthenticationRequired
698 0, // timeoutMillis
699 42, // secureUserId
700 &profile);
701 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
702 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
703 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
704}
705
Selene Huang92b61d62020-03-04 02:24:16 -0800706INSTANTIATE_TEST_SUITE_P(
707 Identity, IdentityCredentialTests,
708 testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
709 android::PrintInstanceNameToString);
710
711} // namespace android::hardware::identity