blob: cc63c482f1367d319539bdbc6e8dd3846f58e29e [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
David Zeuthen49f2d252020-10-16 11:27:24 -040032#include "Util.h"
Selene Huang92b61d62020-03-04 02:24:16 -080033
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;
David Zeuthen34abaae2020-10-26 20:26:36 -040064 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
65 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -080066
67 vector<uint8_t> attestationChallenge;
68 vector<Certificate> attestationCertificate;
69 vector<uint8_t> attestationApplicationId = {};
70 result = writableCredential->getAttestationCertificate(
71 attestationApplicationId, attestationChallenge, &attestationCertificate);
72
David Zeuthenef739512020-06-03 13:24:52 -040073 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
74 << endl;
75 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
76 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
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;
David Zeuthen34abaae2020-10-26 20:26:36 -040086 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
87 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -080088
89 string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
90 vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
91 vector<Certificate> attestationCertificate;
David Zeuthen34abaae2020-10-26 20:26:36 -040092 vector<uint8_t> attestationApplicationId = {1};
Selene Huang92b61d62020-03-04 02:24:16 -080093
94 result = writableCredential->getAttestationCertificate(
95 attestationApplicationId, attestationChallenge, &attestationCertificate);
96
97 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
98 << endl;
99
David Zeuthen34abaae2020-10-26 20:26:36 -0400100 test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
101 attestationApplicationId, false);
Selene Huang92b61d62020-03-04 02:24:16 -0800102}
103
104TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
105 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -0700106
Selene Huang92b61d62020-03-04 02:24:16 -0800107 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400108 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
109 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800110
111 string challenge = "NotSoRandomChallenge1";
David Zeuthen34abaae2020-10-26 20:26:36 -0400112 test_utils::AttestationData attData(writableCredential, challenge,
113 {1} /* atteestationApplicationId */);
114 test_utils::validateAttestationCertificate(attData.attestationCertificate,
115 attData.attestationChallenge,
116 attData.attestationApplicationId, false);
Selene Huang92b61d62020-03-04 02:24:16 -0800117
118 string challenge2 = "NotSoRandomChallenge2";
David Zeuthen34abaae2020-10-26 20:26:36 -0400119 test_utils::AttestationData attData2(writableCredential, challenge2,
120 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800121 EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
122 << attData2.result.exceptionMessage() << endl;
123 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
124 EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, attData2.result.serviceSpecificErrorCode());
125}
126
127TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
128 Status result;
129 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400130 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
131 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800132
133 // First call should go through
134 const vector<int32_t> entryCounts = {2, 4};
David Zeuthenef739512020-06-03 13:24:52 -0400135 writableCredential->setExpectedProofOfProvisioningSize(123456);
Selene Huang92b61d62020-03-04 02:24:16 -0800136 result = writableCredential->startPersonalization(5, entryCounts);
137 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
138 << endl;
139
140 // Call personalization again to check if repeat call is allowed.
141 result = writableCredential->startPersonalization(7, entryCounts);
142
143 // Second call to startPersonalization should have failed.
144 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
145 << endl;
146 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
147 EXPECT_EQ(IIdentityCredentialStore::STATUS_FAILED, result.serviceSpecificErrorCode());
148}
149
150TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
151 Status result;
152 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400153 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
154 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800155
156 // Verify minimal number of profile count and entry count
157 const vector<int32_t> entryCounts = {1, 1};
David Zeuthenef739512020-06-03 13:24:52 -0400158 writableCredential->setExpectedProofOfProvisioningSize(123456);
159 result = writableCredential->startPersonalization(1, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800160 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
161 << endl;
162}
163
164TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
165 Status result;
166 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400167 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
168 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800169
170 // Verify minimal number of profile count and entry count
171 const vector<int32_t> entryCounts = {1};
David Zeuthenef739512020-06-03 13:24:52 -0400172 writableCredential->setExpectedProofOfProvisioningSize(123456);
173 result = writableCredential->startPersonalization(1, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800174 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
175 << endl;
176}
177
178TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
179 Status result;
180 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400181 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
182 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800183
184 // Verify set a large number of profile count and entry count is ok
David Zeuthen630de2a2020-05-11 14:04:54 -0400185 const vector<int32_t> entryCounts = {255};
David Zeuthenef739512020-06-03 13:24:52 -0400186 writableCredential->setExpectedProofOfProvisioningSize(123456);
187 result = writableCredential->startPersonalization(25, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800188 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
189 << endl;
190}
191
192TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
193 Status result;
194 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400195 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
196 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800197
198 // Enter mismatched entry and profile numbers
199 const vector<int32_t> entryCounts = {5, 6};
David Zeuthenef739512020-06-03 13:24:52 -0400200 writableCredential->setExpectedProofOfProvisioningSize(123456);
201 result = writableCredential->startPersonalization(5, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800202 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;
David Zeuthen34abaae2020-10-26 20:26:36 -0400234 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
235 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800236
237 const vector<int32_t> entryCounts = {3, 6};
David Zeuthenef739512020-06-03 13:24:52 -0400238 writableCredential->setExpectedProofOfProvisioningSize(123456);
239 result = writableCredential->startPersonalization(3, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800240 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
241 << endl;
242
243 const vector<test_utils::TestProfile> testProfiles = {// first profile should go though
244 {1, {}, true, 2},
245 // same id, different
246 // authentication requirement
247 {1, {}, true, 1},
248 // same id, different certificate
249 {1, {}, false, 0}};
250
251 bool expectOk = true;
252 for (const auto& testProfile : testProfiles) {
253 SecureAccessControlProfile profile;
254 Certificate cert;
255 cert.encodedCertificate = testProfile.readerCertificate;
David Zeuthenef739512020-06-03 13:24:52 -0400256 int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
Selene Huang92b61d62020-03-04 02:24:16 -0800257 result = writableCredential->addAccessControlProfile(
258 testProfile.id, cert, testProfile.userAuthenticationRequired,
David Zeuthenef739512020-06-03 13:24:52 -0400259 testProfile.timeoutMillis, secureUserId, &profile);
Selene Huang92b61d62020-03-04 02:24:16 -0800260
261 if (expectOk) {
262 expectOk = false;
263 // for profile should be allowed though as there are no duplications
264 // yet.
265 ASSERT_TRUE(result.isOk())
266 << result.exceptionCode() << "; " << result.exceptionMessage()
267 << "test profile id = " << testProfile.id << endl;
268
269 ASSERT_EQ(testProfile.id, profile.id);
270 ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
271 ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
272 ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
273 ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
274 } else {
275 // should not allow duplicate id profiles.
276 ASSERT_FALSE(result.isOk())
277 << result.exceptionCode() << "; " << result.exceptionMessage()
278 << ". Test profile id = " << testProfile.id
279 << ", timeout=" << testProfile.timeoutMillis << endl;
280 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
281 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA,
282 result.serviceSpecificErrorCode());
283 }
284 }
285}
286
287TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
288 Status result;
289
290 HardwareInformation hwInfo;
291 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
292
293 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400294 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
295 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800296
297 string challenge = "NotSoRandomChallenge1";
David Zeuthen34abaae2020-10-26 20:26:36 -0400298 test_utils::AttestationData attData(writableCredential, challenge,
299 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800300 EXPECT_TRUE(attData.result.isOk())
301 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
302
Selene Huangcab019a2020-03-11 04:37:48 -0700303 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800304 ASSERT_TRUE(readerCertificate1);
305
David Zeuthen28edb102020-04-28 18:54:55 -0400306 const vector<int32_t> entryCounts = {1u};
David Zeuthen34abaae2020-10-26 20:26:36 -0400307 size_t expectedPoPSize = 185 + readerCertificate1.value().size();
David Zeuthen28edb102020-04-28 18:54:55 -0400308 // OK to fail, not available in v1 HAL
309 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
310 result = writableCredential->startPersonalization(1, entryCounts);
311 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
312 << endl;
313
Selene Huang92b61d62020-03-04 02:24:16 -0800314 const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
315
316 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700317 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800318 ASSERT_TRUE(secureProfiles);
319
320 const vector<test_utils::TestEntryData> testEntries1 = {
David Zeuthen34abaae2020-10-26 20:26:36 -0400321 {"Name Space", "Last name", string("Turing"), vector<int32_t>{1}},
Selene Huang92b61d62020-03-04 02:24:16 -0800322 };
323
324 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
325 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700326 ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800327 encryptedBlobs, true));
328 }
329
330 vector<uint8_t> credentialData;
331 vector<uint8_t> proofOfProvisioningSignature;
332 result =
333 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
334
335 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
336 << endl;
337
338 optional<vector<uint8_t>> proofOfProvisioning =
339 support::coseSignGetPayload(proofOfProvisioningSignature);
340 ASSERT_TRUE(proofOfProvisioning);
341 string cborPretty =
342 support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
343 EXPECT_EQ(
344 "[\n"
345 " 'ProofOfProvisioning',\n"
346 " 'org.iso.18013-5.2019.mdl',\n"
347 " [\n"
348 " {\n"
349 " 'id' : 1,\n"
350 " 'readerCertificate' : <not printed>,\n"
351 " 'userAuthenticationRequired' : true,\n"
352 " 'timeoutMillis' : 1,\n"
353 " },\n"
354 " ],\n"
355 " {\n"
356 " 'Name Space' : [\n"
357 " {\n"
358 " 'name' : 'Last name',\n"
359 " 'value' : 'Turing',\n"
David Zeuthen34abaae2020-10-26 20:26:36 -0400360 " 'accessControlProfiles' : [1, ],\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800361 " },\n"
362 " ],\n"
363 " },\n"
David Zeuthen34abaae2020-10-26 20:26:36 -0400364 " false,\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800365 "]",
366 cborPretty);
367
368 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
369 attData.attestationCertificate[0].encodedCertificate);
370 ASSERT_TRUE(credentialPubKey);
371 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
372 {}, // Additional data
373 credentialPubKey.value()));
374}
375
376TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
377 Status result;
378
379 HardwareInformation hwInfo;
380 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
381
382 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400383 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
384 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800385
386 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400387 test_utils::AttestationData attData(writableCredential, challenge,
388 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800389 EXPECT_TRUE(attData.result.isOk())
390 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
391
Selene Huangcab019a2020-03-11 04:37:48 -0700392 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800393 ASSERT_TRUE(readerCertificate1);
394
Selene Huangcab019a2020-03-11 04:37:48 -0700395 optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
Selene Huang92b61d62020-03-04 02:24:16 -0800396 ASSERT_TRUE(readerCertificate2);
397
398 const vector<test_utils::TestProfile> testProfiles = {
399 {1, readerCertificate1.value(), true, 1},
400 {2, readerCertificate2.value(), true, 2},
401 };
402 const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
David Zeuthen28edb102020-04-28 18:54:55 -0400403 size_t expectedPoPSize =
404 525021 + readerCertificate1.value().size() + readerCertificate2.value().size();
405 // OK to fail, not available in v1 HAL
406 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
407 result = writableCredential->startPersonalization(testProfiles.size(), entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800408 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
409 << endl;
410
411 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700412 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800413 ASSERT_TRUE(secureProfiles);
414
415 vector<uint8_t> portraitImage1;
Selene Huangcab019a2020-03-11 04:37:48 -0700416 test_utils::setImageData(portraitImage1);
Selene Huang92b61d62020-03-04 02:24:16 -0800417
418 vector<uint8_t> portraitImage2;
Selene Huangcab019a2020-03-11 04:37:48 -0700419 test_utils::setImageData(portraitImage2);
Selene Huang92b61d62020-03-04 02:24:16 -0800420
421 const vector<test_utils::TestEntryData> testEntries1 = {
422 {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
423 {"Name Space2", "Home address", string("Maida Vale, London, England"),
424 vector<int32_t>{1}},
425 {"Name Space2", "Work address", string("Maida Vale2, London, England"),
426 vector<int32_t>{2}},
427 {"Name Space2", "Trailer address", string("Maida, London, England"),
428 vector<int32_t>{1}},
429 {"Image", "Portrait image", portraitImage1, vector<int32_t>{1}},
430 {"Image2", "Work image", portraitImage2, vector<int32_t>{1, 2}},
431 {"Name Space3", "xyzw", string("random stuff"), vector<int32_t>{1, 2}},
432 {"Name Space3", "Something", string("Some string"), vector<int32_t>{2}},
433 };
434
435 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
436 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700437 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800438 encryptedBlobs, true));
439 }
440
441 vector<uint8_t> credentialData;
442 vector<uint8_t> proofOfProvisioningSignature;
443 result =
444 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
445
446 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
447 << endl;
448
449 optional<vector<uint8_t>> proofOfProvisioning =
450 support::coseSignGetPayload(proofOfProvisioningSignature);
451 ASSERT_TRUE(proofOfProvisioning);
452 string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(),
453 32, //
454 {"readerCertificate"});
455 EXPECT_EQ(
456 "[\n"
457 " 'ProofOfProvisioning',\n"
458 " 'org.iso.18013-5.2019.mdl',\n"
459 " [\n"
460 " {\n"
461 " 'id' : 1,\n"
462 " 'readerCertificate' : <not printed>,\n"
463 " 'userAuthenticationRequired' : true,\n"
464 " 'timeoutMillis' : 1,\n"
465 " },\n"
466 " {\n"
467 " 'id' : 2,\n"
468 " 'readerCertificate' : <not printed>,\n"
469 " 'userAuthenticationRequired' : true,\n"
470 " 'timeoutMillis' : 2,\n"
471 " },\n"
472 " ],\n"
473 " {\n"
474 " 'Name Space 1' : [\n"
475 " {\n"
476 " 'name' : 'Last name',\n"
477 " 'value' : 'Turing',\n"
478 " 'accessControlProfiles' : [1, 2, ],\n"
479 " },\n"
480 " ],\n"
481 " 'Name Space2' : [\n"
482 " {\n"
483 " 'name' : 'Home address',\n"
484 " 'value' : 'Maida Vale, London, England',\n"
485 " 'accessControlProfiles' : [1, ],\n"
486 " },\n"
487 " {\n"
488 " 'name' : 'Work address',\n"
489 " 'value' : 'Maida Vale2, London, England',\n"
490 " 'accessControlProfiles' : [2, ],\n"
491 " },\n"
492 " {\n"
493 " 'name' : 'Trailer address',\n"
494 " 'value' : 'Maida, London, England',\n"
495 " 'accessControlProfiles' : [1, ],\n"
496 " },\n"
497 " ],\n"
498 " 'Image' : [\n"
499 " {\n"
500 " 'name' : 'Portrait image',\n"
501 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
502 " 'accessControlProfiles' : [1, ],\n"
503 " },\n"
504 " ],\n"
505 " 'Image2' : [\n"
506 " {\n"
507 " 'name' : 'Work image',\n"
508 " 'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
509 " 'accessControlProfiles' : [1, 2, ],\n"
510 " },\n"
511 " ],\n"
512 " 'Name Space3' : [\n"
513 " {\n"
514 " 'name' : 'xyzw',\n"
515 " 'value' : 'random stuff',\n"
516 " 'accessControlProfiles' : [1, 2, ],\n"
517 " },\n"
518 " {\n"
519 " 'name' : 'Something',\n"
520 " 'value' : 'Some string',\n"
521 " 'accessControlProfiles' : [2, ],\n"
522 " },\n"
523 " ],\n"
524 " },\n"
David Zeuthen34abaae2020-10-26 20:26:36 -0400525 " false,\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800526 "]",
527 cborPretty);
528
529 optional<vector<uint8_t>> credentialPubKey = support::certificateChainGetTopMostKey(
530 attData.attestationCertificate[0].encodedCertificate);
531 ASSERT_TRUE(credentialPubKey);
532 EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
533 {}, // Additional data
534 credentialPubKey.value()));
535}
536
537TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
538 Status result;
539
540 HardwareInformation hwInfo;
541 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
542
543 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400544 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
545 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800546
547 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400548 test_utils::AttestationData attData(writableCredential, challenge,
549 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800550 ASSERT_TRUE(attData.result.isOk())
551 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
552
Selene Huangcab019a2020-03-11 04:37:48 -0700553 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800554 ASSERT_TRUE(readerCertificate1);
555
556 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700557 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800558 ASSERT_TRUE(readerCertificate2);
559
David Zeuthen28edb102020-04-28 18:54:55 -0400560 const vector<int32_t> entryCounts = {2u, 2u};
561 size_t expectedPoPSize =
562 377 + readerCertificate1.value().size() + readerCertificate2.value().size();
563 ;
564 // OK to fail, not available in v1 HAL
565 writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
David Zeuthenef739512020-06-03 13:24:52 -0400566 result = writableCredential->startPersonalization(3, entryCounts);
David Zeuthen28edb102020-04-28 18:54:55 -0400567 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
568 << endl;
569
Selene Huang92b61d62020-03-04 02:24:16 -0800570 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
571 {1, readerCertificate2.value(), true, 1},
572 {2, {}, false, 0}};
573
574 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700575 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800576 ASSERT_TRUE(secureProfiles);
577
578 const vector<test_utils::TestEntryData> testEntries1 = {
579 // test empty name space
580 {"", "t name", string("Turing"), vector<int32_t>{2}},
581 {"", "Birth", string("19120623"), vector<int32_t>{2}},
582 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
583 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
584 };
585
586 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
587 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700588 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800589 encryptedBlobs, true));
590 }
591
592 vector<uint8_t> credentialData;
593 vector<uint8_t> proofOfProvisioningSignature;
594 result =
595 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
596
597 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
598 << endl;
599}
600
601TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
602 Status result;
603
604 HardwareInformation hwInfo;
605 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
606
607 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400608 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
609 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800610
611 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400612 test_utils::AttestationData attData(writableCredential, challenge,
613 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800614 ASSERT_TRUE(attData.result.isOk())
615 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
616
617 // Enter mismatched entry and profile numbers.
618 // Technically the 2nd name space of "Name Space" occurs intermittently, 2
619 // before "Image" and 2 after image, which is not correct. All of same name
620 // space should occur together. Let's see if this fails.
621 const vector<int32_t> entryCounts = {2u, 1u, 2u};
David Zeuthenef739512020-06-03 13:24:52 -0400622 writableCredential->setExpectedProofOfProvisioningSize(123456);
623 result = writableCredential->startPersonalization(3, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800624 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
625 << endl;
626
Selene Huangcab019a2020-03-11 04:37:48 -0700627 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800628 ASSERT_TRUE(readerCertificate1);
629
630 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700631 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800632 ASSERT_TRUE(readerCertificate2);
633
634 const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
635 {1, readerCertificate2.value(), true, 1},
636 {2, {}, false, 0}};
637
638 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700639 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800640 ASSERT_TRUE(secureProfiles);
641
642 const vector<test_utils::TestEntryData> testEntries1 = {
643 // test empty name space
644 {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
645 {"Name Space", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
646 };
647
648 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
649 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700650 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800651 encryptedBlobs, true));
652 }
653 const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
654 vector<int32_t>{0, 1}};
655
Selene Huangcab019a2020-03-11 04:37:48 -0700656 EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800657 encryptedBlobs, true));
658
659 // We expect this to fail because the namespace is out of order, all "Name Space"
660 // should have been called together
661 const vector<test_utils::TestEntryData> testEntries3 = {
662 {"Name Space", "First name", string("Alan"), vector<int32_t>{0, 1}},
663 {"Name Space", "Home address", string("Maida Vale, London, England"),
664 vector<int32_t>{0}},
665 };
666
667 for (const auto& entry : testEntries3) {
Selene Huangcab019a2020-03-11 04:37:48 -0700668 EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800669 encryptedBlobs, false));
670 }
671
672 vector<uint8_t> credentialData;
673 vector<uint8_t> proofOfProvisioningSignature;
674 result =
675 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
676
Selene Huangcab019a2020-03-11 04:37:48 -0700677 // should fail because test_utils::addEntry should have failed earlier.
Selene Huang92b61d62020-03-04 02:24:16 -0800678 EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
679 << endl;
680 EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
681 EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
682}
683
David Zeuthena0796e92020-04-27 15:24:55 -0400684TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
685 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400686 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
687 false /* testCredential */));
David Zeuthena0796e92020-04-27 15:24:55 -0400688
689 const vector<int32_t> entryCounts = {1};
David Zeuthenef739512020-06-03 13:24:52 -0400690 writableCredential->setExpectedProofOfProvisioningSize(123456);
David Zeuthena0796e92020-04-27 15:24:55 -0400691 Status result = writableCredential->startPersonalization(1, entryCounts);
692 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
693 << endl;
694
695 SecureAccessControlProfile profile;
696
697 // This should fail because the id is >= 32
698 result = writableCredential->addAccessControlProfile(32, // id
699 {}, // readerCertificate
700 false, // userAuthenticationRequired
701 0, // timeoutMillis
702 42, // secureUserId
703 &profile);
704 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
705 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
706 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
707
708 // This should fail because the id is < 0
709 result = writableCredential->addAccessControlProfile(-1, // id
710 {}, // readerCertificate
711 false, // userAuthenticationRequired
712 0, // timeoutMillis
713 42, // secureUserId
714 &profile);
715 ASSERT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage();
716 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
717 ASSERT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
718}
719
Dan Shiba4d5322020-07-28 13:09:30 -0700720GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IdentityCredentialTests);
Selene Huang92b61d62020-03-04 02:24:16 -0800721INSTANTIATE_TEST_SUITE_P(
722 Identity, IdentityCredentialTests,
723 testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
724 android::PrintInstanceNameToString);
725
726} // namespace android::hardware::identity