blob: 94d4c881b83bdbe07e0d3020d5707819813d1e42 [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>
Seth Moore1bf823c2022-01-25 23:04:37 +000021#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
22#include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
Selene Huang92b61d62020-03-04 02:24:16 -080023#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
David Zeuthen49f2d252020-10-16 11:27:24 -040034#include "Util.h"
Selene Huang92b61d62020-03-04 02:24:16 -080035
36namespace android::hardware::identity {
37
38using std::endl;
39using std::map;
40using std::optional;
41using std::string;
42using std::vector;
43
44using ::android::sp;
45using ::android::String16;
46using ::android::binder::Status;
Seth Moore1bf823c2022-01-25 23:04:37 +000047using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
48using ::android::hardware::security::keymint::MacedPublicKey;
Selene Huang92b61d62020-03-04 02:24:16 -080049
50class IdentityCredentialTests : public testing::TestWithParam<string> {
51 public:
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
61TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
62 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -070063
64 HardwareInformation hwInfo;
65 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
66
Selene Huang92b61d62020-03-04 02:24:16 -080067 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -040068 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
69 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -080070
71 vector<uint8_t> attestationChallenge;
72 vector<Certificate> attestationCertificate;
73 vector<uint8_t> attestationApplicationId = {};
74 result = writableCredential->getAttestationCertificate(
75 attestationApplicationId, attestationChallenge, &attestationCertificate);
76
David Zeuthenef739512020-06-03 13:24:52 -040077 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());
Selene Huang92b61d62020-03-04 02:24:16 -080081}
82
83TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
84 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -070085
86 HardwareInformation hwInfo;
87 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
88
Selene Huang92b61d62020-03-04 02:24:16 -080089 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -040090 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
91 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -080092
93 string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
94 vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
95 vector<Certificate> attestationCertificate;
David Zeuthen34abaae2020-10-26 20:26:36 -040096 vector<uint8_t> attestationApplicationId = {1};
Selene Huang92b61d62020-03-04 02:24:16 -080097
98 result = writableCredential->getAttestationCertificate(
99 attestationApplicationId, attestationChallenge, &attestationCertificate);
100
101 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
102 << endl;
103
David Zeuthen34abaae2020-10-26 20:26:36 -0400104 test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
105 attestationApplicationId, false);
Selene Huang92b61d62020-03-04 02:24:16 -0800106}
107
Seth Moore1bf823c2022-01-25 23:04:37 +0000108TEST_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
165TEST_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
Selene Huang92b61d62020-03-04 02:24:16 -0800205TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
206 Status result;
Selene Huangcab019a2020-03-11 04:37:48 -0700207
Selene Huang92b61d62020-03-04 02:24:16 -0800208 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400209 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
210 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800211
212 string challenge = "NotSoRandomChallenge1";
David Zeuthen34abaae2020-10-26 20:26:36 -0400213 test_utils::AttestationData attData(writableCredential, challenge,
214 {1} /* atteestationApplicationId */);
215 test_utils::validateAttestationCertificate(attData.attestationCertificate,
216 attData.attestationChallenge,
217 attData.attestationApplicationId, false);
Selene Huang92b61d62020-03-04 02:24:16 -0800218
219 string challenge2 = "NotSoRandomChallenge2";
David Zeuthen34abaae2020-10-26 20:26:36 -0400220 test_utils::AttestationData attData2(writableCredential, challenge2,
221 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800222 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
228TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
229 Status result;
230 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400231 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
232 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800233
234 // First call should go through
235 const vector<int32_t> entryCounts = {2, 4};
David Zeuthenef739512020-06-03 13:24:52 -0400236 writableCredential->setExpectedProofOfProvisioningSize(123456);
Selene Huang92b61d62020-03-04 02:24:16 -0800237 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
251TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
252 Status result;
253 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400254 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
255 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800256
257 // Verify minimal number of profile count and entry count
258 const vector<int32_t> entryCounts = {1, 1};
David Zeuthenef739512020-06-03 13:24:52 -0400259 writableCredential->setExpectedProofOfProvisioningSize(123456);
260 result = writableCredential->startPersonalization(1, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800261 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
262 << endl;
263}
264
265TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
266 Status result;
267 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400268 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
269 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800270
271 // Verify minimal number of profile count and entry count
272 const vector<int32_t> entryCounts = {1};
David Zeuthenef739512020-06-03 13:24:52 -0400273 writableCredential->setExpectedProofOfProvisioningSize(123456);
274 result = writableCredential->startPersonalization(1, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800275 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
276 << endl;
277}
278
279TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
280 Status result;
281 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400282 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
283 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800284
285 // Verify set a large number of profile count and entry count is ok
David Zeuthen630de2a2020-05-11 14:04:54 -0400286 const vector<int32_t> entryCounts = {255};
David Zeuthenef739512020-06-03 13:24:52 -0400287 writableCredential->setExpectedProofOfProvisioningSize(123456);
288 result = writableCredential->startPersonalization(25, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800289 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
290 << endl;
291}
292
293TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
294 Status result;
295 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400296 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
297 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800298
299 // Enter mismatched entry and profile numbers
300 const vector<int32_t> entryCounts = {5, 6};
David Zeuthenef739512020-06-03 13:24:52 -0400301 writableCredential->setExpectedProofOfProvisioningSize(123456);
302 result = writableCredential->startPersonalization(5, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800303 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
304 << endl;
305
Selene Huangcab019a2020-03-11 04:37:48 -0700306 optional<vector<uint8_t>> readerCertificate = test_utils::generateReaderCertificate("12345");
Selene Huang92b61d62020-03-04 02:24:16 -0800307 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 =
Selene Huangcab019a2020-03-11 04:37:48 -0700316 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800317 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
Selene Huangcab019a2020-03-11 04:37:48 -0700325 // startPersonalization, and begintest_utils::addEntry was not called.
Selene Huang92b61d62020-03-04 02:24:16 -0800326 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
332TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
333 Status result;
334 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400335 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
336 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800337
338 const vector<int32_t> entryCounts = {3, 6};
David Zeuthenef739512020-06-03 13:24:52 -0400339 writableCredential->setExpectedProofOfProvisioningSize(123456);
340 result = writableCredential->startPersonalization(3, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800341 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;
David Zeuthenef739512020-06-03 13:24:52 -0400357 int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
Selene Huang92b61d62020-03-04 02:24:16 -0800358 result = writableCredential->addAccessControlProfile(
359 testProfile.id, cert, testProfile.userAuthenticationRequired,
David Zeuthenef739512020-06-03 13:24:52 -0400360 testProfile.timeoutMillis, secureUserId, &profile);
Selene Huang92b61d62020-03-04 02:24:16 -0800361
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
388TEST_P(IdentityCredentialTests, verifyOneProfileAndEntryPass) {
389 Status result;
390
391 HardwareInformation hwInfo;
392 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
393
394 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400395 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
396 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800397
398 string challenge = "NotSoRandomChallenge1";
David Zeuthen34abaae2020-10-26 20:26:36 -0400399 test_utils::AttestationData attData(writableCredential, challenge,
400 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800401 EXPECT_TRUE(attData.result.isOk())
402 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
403
Selene Huangcab019a2020-03-11 04:37:48 -0700404 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800405 ASSERT_TRUE(readerCertificate1);
406
David Zeuthen28edb102020-04-28 18:54:55 -0400407 const vector<int32_t> entryCounts = {1u};
David Zeuthen34abaae2020-10-26 20:26:36 -0400408 size_t expectedPoPSize = 185 + readerCertificate1.value().size();
David Zeuthen28edb102020-04-28 18:54:55 -0400409 // 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
Selene Huang92b61d62020-03-04 02:24:16 -0800415 const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
416
417 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700418 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800419 ASSERT_TRUE(secureProfiles);
420
421 const vector<test_utils::TestEntryData> testEntries1 = {
David Zeuthen34abaae2020-10-26 20:26:36 -0400422 {"Name Space", "Last name", string("Turing"), vector<int32_t>{1}},
Selene Huang92b61d62020-03-04 02:24:16 -0800423 };
424
425 map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
426 for (const auto& entry : testEntries1) {
Selene Huangcab019a2020-03-11 04:37:48 -0700427 ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800428 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);
Max Biresa3c7f4c2021-04-09 08:56:40 -0700442 string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
Selene Huang92b61d62020-03-04 02:24:16 -0800443 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"
David Zeuthen34abaae2020-10-26 20:26:36 -0400460 " 'accessControlProfiles' : [1, ],\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800461 " },\n"
462 " ],\n"
463 " },\n"
David Zeuthen34abaae2020-10-26 20:26:36 -0400464 " false,\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800465 "]",
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
476TEST_P(IdentityCredentialTests, verifyManyProfilesAndEntriesPass) {
477 Status result;
478
479 HardwareInformation hwInfo;
480 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
481
482 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400483 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
484 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800485
486 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400487 test_utils::AttestationData attData(writableCredential, challenge,
488 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800489 EXPECT_TRUE(attData.result.isOk())
490 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
491
Selene Huangcab019a2020-03-11 04:37:48 -0700492 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800493 ASSERT_TRUE(readerCertificate1);
494
Selene Huangcab019a2020-03-11 04:37:48 -0700495 optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
Selene Huang92b61d62020-03-04 02:24:16 -0800496 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};
David Zeuthen28edb102020-04-28 18:54:55 -0400503 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);
Selene Huang92b61d62020-03-04 02:24:16 -0800508 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
509 << endl;
510
511 optional<vector<SecureAccessControlProfile>> secureProfiles =
Selene Huangcab019a2020-03-11 04:37:48 -0700512 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800513 ASSERT_TRUE(secureProfiles);
514
515 vector<uint8_t> portraitImage1;
Selene Huangcab019a2020-03-11 04:37:48 -0700516 test_utils::setImageData(portraitImage1);
Selene Huang92b61d62020-03-04 02:24:16 -0800517
518 vector<uint8_t> portraitImage2;
Selene Huangcab019a2020-03-11 04:37:48 -0700519 test_utils::setImageData(portraitImage2);
Selene Huang92b61d62020-03-04 02:24:16 -0800520
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) {
Selene Huangcab019a2020-03-11 04:37:48 -0700537 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800538 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);
Max Biresa3c7f4c2021-04-09 08:56:40 -0700552 string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(),
553 32, //
554 {"readerCertificate"});
Selene Huang92b61d62020-03-04 02:24:16 -0800555 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"
David Zeuthen34abaae2020-10-26 20:26:36 -0400625 " false,\n"
Selene Huang92b61d62020-03-04 02:24:16 -0800626 "]",
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
637TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
638 Status result;
639
640 HardwareInformation hwInfo;
641 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
642
643 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400644 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
645 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800646
647 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400648 test_utils::AttestationData attData(writableCredential, challenge,
649 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800650 ASSERT_TRUE(attData.result.isOk())
651 << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
652
Selene Huangcab019a2020-03-11 04:37:48 -0700653 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800654 ASSERT_TRUE(readerCertificate1);
655
656 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700657 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800658 ASSERT_TRUE(readerCertificate2);
659
David Zeuthen28edb102020-04-28 18:54:55 -0400660 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);
David Zeuthenef739512020-06-03 13:24:52 -0400666 result = writableCredential->startPersonalization(3, entryCounts);
David Zeuthen28edb102020-04-28 18:54:55 -0400667 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
668 << endl;
669
Selene Huang92b61d62020-03-04 02:24:16 -0800670 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 =
Selene Huangcab019a2020-03-11 04:37:48 -0700675 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800676 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) {
Selene Huangcab019a2020-03-11 04:37:48 -0700688 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800689 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
701TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
702 Status result;
703
704 HardwareInformation hwInfo;
705 ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
706
707 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400708 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
709 false /* testCredential */));
Selene Huang92b61d62020-03-04 02:24:16 -0800710
711 string challenge = "NotSoRandomChallenge";
David Zeuthen34abaae2020-10-26 20:26:36 -0400712 test_utils::AttestationData attData(writableCredential, challenge,
713 {} /* atteestationApplicationId */);
Selene Huang92b61d62020-03-04 02:24:16 -0800714 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};
David Zeuthenef739512020-06-03 13:24:52 -0400722 writableCredential->setExpectedProofOfProvisioningSize(123456);
723 result = writableCredential->startPersonalization(3, entryCounts);
Selene Huang92b61d62020-03-04 02:24:16 -0800724 ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
725 << endl;
726
Selene Huangcab019a2020-03-11 04:37:48 -0700727 optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
Selene Huang92b61d62020-03-04 02:24:16 -0800728 ASSERT_TRUE(readerCertificate1);
729
730 optional<vector<uint8_t>> readerCertificate2 =
Selene Huangcab019a2020-03-11 04:37:48 -0700731 test_utils::generateReaderCertificate("123456987987987987987987");
Selene Huang92b61d62020-03-04 02:24:16 -0800732 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 =
Selene Huangcab019a2020-03-11 04:37:48 -0700739 test_utils::addAccessControlProfiles(writableCredential, testProfiles);
Selene Huang92b61d62020-03-04 02:24:16 -0800740 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) {
Selene Huangcab019a2020-03-11 04:37:48 -0700750 EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800751 encryptedBlobs, true));
752 }
753 const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
754 vector<int32_t>{0, 1}};
755
Selene Huangcab019a2020-03-11 04:37:48 -0700756 EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800757 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) {
Selene Huangcab019a2020-03-11 04:37:48 -0700768 EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
Selene Huang92b61d62020-03-04 02:24:16 -0800769 encryptedBlobs, false));
770 }
771
772 vector<uint8_t> credentialData;
773 vector<uint8_t> proofOfProvisioningSignature;
774 result =
775 writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
776
Selene Huangcab019a2020-03-11 04:37:48 -0700777 // should fail because test_utils::addEntry should have failed earlier.
Selene Huang92b61d62020-03-04 02:24:16 -0800778 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
David Zeuthena0796e92020-04-27 15:24:55 -0400784TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
785 sp<IWritableIdentityCredential> writableCredential;
David Zeuthen34abaae2020-10-26 20:26:36 -0400786 ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
787 false /* testCredential */));
David Zeuthena0796e92020-04-27 15:24:55 -0400788
789 const vector<int32_t> entryCounts = {1};
David Zeuthenef739512020-06-03 13:24:52 -0400790 writableCredential->setExpectedProofOfProvisioningSize(123456);
David Zeuthena0796e92020-04-27 15:24:55 -0400791 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
Dan Shiba4d5322020-07-28 13:09:30 -0700820GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IdentityCredentialTests);
Selene Huang92b61d62020-03-04 02:24:16 -0800821INSTANTIATE_TEST_SUITE_P(
822 Identity, IdentityCredentialTests,
823 testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
824 android::PrintInstanceNameToString);
825
826} // namespace android::hardware::identity