blob: 680ba5b7f9bf4ed66a69975434bc20f089254fe7 [file] [log] [blame]
David Zeuthenef739512020-06-03 13:24:52 -04001/*
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 "ReaderAuthTests"
18
19#include <aidl/Gtest.h>
20#include <aidl/Vintf.h>
21#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
22#include <aidl/android/hardware/keymaster/VerificationToken.h>
23#include <android-base/logging.h>
24#include <android/hardware/identity/IIdentityCredentialStore.h>
25#include <android/hardware/identity/support/IdentityCredentialSupport.h>
26#include <binder/IServiceManager.h>
27#include <binder/ProcessState.h>
28#include <cppbor.h>
29#include <cppbor_parse.h>
30#include <gtest/gtest.h>
31#include <future>
32#include <map>
33#include <utility>
34
35#include "VtsIdentityTestUtils.h"
36
37namespace android::hardware::identity {
38
39using std::endl;
40using std::make_pair;
41using std::map;
42using std::optional;
43using std::pair;
44using std::string;
45using std::tie;
46using std::vector;
47
48using ::android::sp;
49using ::android::String16;
50using ::android::binder::Status;
51
52using ::android::hardware::keymaster::HardwareAuthToken;
53using ::android::hardware::keymaster::VerificationToken;
54
55class ReaderAuthTests : public testing::TestWithParam<string> {
56 public:
57 virtual void SetUp() override {
58 credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
59 String16(GetParam().c_str()));
60 ASSERT_NE(credentialStore_, nullptr);
61 }
62
63 void provisionData();
64 void retrieveData(const vector<uint8_t>& readerPrivateKey,
65 const vector<vector<uint8_t>>& readerCertChain, bool expectSuccess,
66 bool leaveOutAccessibleToAllFromRequestMessage);
67
68 // Set by provisionData
69 vector<uint8_t> readerPublicKey_;
70 vector<uint8_t> readerPrivateKey_;
71 vector<uint8_t> intermediateAPublicKey_;
72 vector<uint8_t> intermediateAPrivateKey_;
73 vector<uint8_t> intermediateBPublicKey_;
74 vector<uint8_t> intermediateBPrivateKey_;
75 vector<uint8_t> intermediateCPublicKey_;
76 vector<uint8_t> intermediateCPrivateKey_;
77
78 vector<uint8_t> cert_A_SelfSigned_;
79
80 vector<uint8_t> cert_B_SelfSigned_;
81
82 vector<uint8_t> cert_B_SignedBy_C_;
83
84 vector<uint8_t> cert_C_SelfSigned_;
85
86 vector<uint8_t> cert_reader_SelfSigned_;
87 vector<uint8_t> cert_reader_SignedBy_A_;
88 vector<uint8_t> cert_reader_SignedBy_B_;
89
90 SecureAccessControlProfile sacp0_;
91 SecureAccessControlProfile sacp1_;
92 SecureAccessControlProfile sacp2_;
93 SecureAccessControlProfile sacp3_;
94
95 vector<uint8_t> encContentAccessibleByA_;
96 vector<uint8_t> encContentAccessibleByAorB_;
97 vector<uint8_t> encContentAccessibleByB_;
98 vector<uint8_t> encContentAccessibleByC_;
99 vector<uint8_t> encContentAccessibleByAll_;
100 vector<uint8_t> encContentAccessibleByNone_;
101
102 vector<uint8_t> credentialData_;
103
104 // Set by retrieveData()
105 bool canGetAccessibleByA_;
106 bool canGetAccessibleByAorB_;
107 bool canGetAccessibleByB_;
108 bool canGetAccessibleByC_;
109 bool canGetAccessibleByAll_;
110 bool canGetAccessibleByNone_;
111
112 sp<IIdentityCredentialStore> credentialStore_;
113};
114
115pair<vector<uint8_t>, vector<uint8_t>> generateReaderKey() {
116 optional<vector<uint8_t>> keyPKCS8 = support::createEcKeyPair();
117 optional<vector<uint8_t>> publicKey = support::ecKeyPairGetPublicKey(keyPKCS8.value());
118 optional<vector<uint8_t>> privateKey = support::ecKeyPairGetPrivateKey(keyPKCS8.value());
119 return make_pair(publicKey.value(), privateKey.value());
120}
121
122vector<uint8_t> generateReaderCert(const vector<uint8_t>& publicKey,
123 const vector<uint8_t>& signingKey) {
124 time_t validityNotBefore = 0;
125 time_t validityNotAfter = 0xffffffff;
126 optional<vector<uint8_t>> cert =
127 support::ecPublicKeyGenerateCertificate(publicKey, signingKey, "24601", "Issuer",
128 "Subject", validityNotBefore, validityNotAfter);
129 return cert.value();
130}
131
132void ReaderAuthTests::provisionData() {
133 // Keys and certificates for intermediates.
134 tie(intermediateAPublicKey_, intermediateAPrivateKey_) = generateReaderKey();
135 tie(intermediateBPublicKey_, intermediateBPrivateKey_) = generateReaderKey();
136 tie(intermediateCPublicKey_, intermediateCPrivateKey_) = generateReaderKey();
137
138 cert_A_SelfSigned_ = generateReaderCert(intermediateAPublicKey_, intermediateAPrivateKey_);
139
140 cert_B_SelfSigned_ = generateReaderCert(intermediateBPublicKey_, intermediateBPrivateKey_);
141
142 cert_B_SignedBy_C_ = generateReaderCert(intermediateBPublicKey_, intermediateCPrivateKey_);
143
144 cert_C_SelfSigned_ = generateReaderCert(intermediateCPublicKey_, intermediateCPrivateKey_);
145
146 // Key and self-signed certificate reader
147 tie(readerPublicKey_, readerPrivateKey_) = generateReaderKey();
148 cert_reader_SelfSigned_ = generateReaderCert(readerPublicKey_, readerPrivateKey_);
149
150 // Certificate for reader signed by intermediates
151 cert_reader_SignedBy_A_ = generateReaderCert(readerPublicKey_, intermediateAPrivateKey_);
152 cert_reader_SignedBy_B_ = generateReaderCert(readerPublicKey_, intermediateBPrivateKey_);
153
154 string docType = "org.iso.18013-5.2019.mdl";
155 bool testCredential = true;
156 sp<IWritableIdentityCredential> wc;
157 ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
158
159 vector<uint8_t> attestationApplicationId = {};
160 vector<uint8_t> attestationChallenge = {1};
161 vector<Certificate> certChain;
162 ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
163 &certChain)
164 .isOk());
165
166 size_t proofOfProvisioningSize =
167 465 + cert_A_SelfSigned_.size() + cert_B_SelfSigned_.size() + cert_C_SelfSigned_.size();
168 ASSERT_TRUE(wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize).isOk());
169
170 // Not in v1 HAL, may fail
171 wc->startPersonalization(4 /* numAccessControlProfiles */,
172 {6} /* numDataElementsPerNamespace */);
173
174 // AIDL expects certificates wrapped in the Certificate type...
175 Certificate cert_A;
176 Certificate cert_B;
177 Certificate cert_C;
178 cert_A.encodedCertificate = cert_A_SelfSigned_;
179 cert_B.encodedCertificate = cert_B_SelfSigned_;
180 cert_C.encodedCertificate = cert_C_SelfSigned_;
181
182 // Access control profile 0: accessible by A
183 ASSERT_TRUE(wc->addAccessControlProfile(0, cert_A, false, 0, 0, &sacp0_).isOk());
184
185 // Access control profile 1: accessible by B
186 ASSERT_TRUE(wc->addAccessControlProfile(1, cert_B, false, 0, 0, &sacp1_).isOk());
187
188 // Access control profile 2: accessible by C
189 ASSERT_TRUE(wc->addAccessControlProfile(2, cert_C, false, 0, 0, &sacp2_).isOk());
190
191 // Access control profile 3: open access
192 ASSERT_TRUE(wc->addAccessControlProfile(3, {}, false, 0, 0, &sacp3_).isOk());
193
194 // Data Element: "Accessible by A"
195 ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "Accessible by A", 1).isOk());
196 ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByA_).isOk());
197
198 // Data Element: "Accessible by A or B"
199 ASSERT_TRUE(wc->beginAddEntry({0, 1}, "ns", "Accessible by A or B", 1).isOk());
200 ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAorB_).isOk());
201
202 // Data Element: "Accessible by B"
203 ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Accessible by B", 1).isOk());
204 ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByB_).isOk());
205
206 // Data Element: "Accessible by C"
207 ASSERT_TRUE(wc->beginAddEntry({2}, "ns", "Accessible by C", 1).isOk());
208 ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByC_).isOk());
209
210 // Data Element: "Accessible by All"
211 ASSERT_TRUE(wc->beginAddEntry({3}, "ns", "Accessible by All", 1).isOk());
212 ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAll_).isOk());
213
214 // Data Element: "Accessible by None"
215 ASSERT_TRUE(wc->beginAddEntry({}, "ns", "Accessible by None", 1).isOk());
216 ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByNone_).isOk());
217
218 vector<uint8_t> proofOfProvisioningSignature;
219 ASSERT_TRUE(wc->finishAddingEntries(&credentialData_, &proofOfProvisioningSignature).isOk());
220}
221
222RequestDataItem buildRequestDataItem(const string& name, size_t size,
223 vector<int32_t> accessControlProfileIds) {
224 RequestDataItem item;
225 item.name = name;
226 item.size = size;
227 item.accessControlProfileIds = accessControlProfileIds;
228 return item;
229}
230
231void ReaderAuthTests::retrieveData(const vector<uint8_t>& readerPrivateKey,
232 const vector<vector<uint8_t>>& readerCertChain,
233 bool expectSuccess,
234 bool leaveOutAccessibleToAllFromRequestMessage) {
235 canGetAccessibleByA_ = false;
236 canGetAccessibleByAorB_ = false;
237 canGetAccessibleByB_ = false;
238 canGetAccessibleByC_ = false;
239 canGetAccessibleByAll_ = false;
240 canGetAccessibleByNone_ = false;
241
242 sp<IIdentityCredential> c;
243 ASSERT_TRUE(credentialStore_
244 ->getCredential(
245 CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
246 credentialData_, &c)
247 .isOk());
248
249 optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
250 optional<vector<uint8_t>> readerEPublicKey =
251 support::ecKeyPairGetPublicKey(readerEKeyPair.value());
252 ASSERT_TRUE(c->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
253
254 vector<uint8_t> eKeyPair;
255 ASSERT_TRUE(c->createEphemeralKeyPair(&eKeyPair).isOk());
256 optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
257
258 // Calculate requestData field and sign it with the reader key.
259 auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey.value());
260 ASSERT_TRUE(getXYSuccess);
261 cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
262 vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
263 vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
264 cppbor::Array sessionTranscript = cppbor::Array()
265 .add(cppbor::Semantic(24, deviceEngagementBytes))
266 .add(cppbor::Semantic(24, eReaderPubBytes));
267 vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
268
269 vector<uint8_t> itemsRequestBytes;
270 if (leaveOutAccessibleToAllFromRequestMessage) {
271 itemsRequestBytes =
272 cppbor::Map("nameSpaces",
273 cppbor::Map().add("ns", cppbor::Map()
274 .add("Accessible by A", false)
275 .add("Accessible by A or B", false)
276 .add("Accessible by B", false)
277 .add("Accessible by C", false)
278 .add("Accessible by None", false)))
279 .encode();
280 } else {
281 itemsRequestBytes =
282 cppbor::Map("nameSpaces",
283 cppbor::Map().add("ns", cppbor::Map()
284 .add("Accessible by A", false)
285 .add("Accessible by A or B", false)
286 .add("Accessible by B", false)
287 .add("Accessible by C", false)
288 .add("Accessible by All", false)
289 .add("Accessible by None", false)))
290 .encode();
291 }
292 vector<uint8_t> dataToSign = cppbor::Array()
293 .add("ReaderAuthentication")
294 .add(sessionTranscript.clone())
295 .add(cppbor::Semantic(24, itemsRequestBytes))
296 .encode();
297
298 optional<vector<uint8_t>> readerSignature =
299 support::coseSignEcDsa(readerPrivateKey, // private key for reader
300 {}, // content
301 dataToSign, // detached content
302 support::certificateChainJoin(readerCertChain));
303 ASSERT_TRUE(readerSignature);
304
305 // Generate the key that will be used to sign AuthenticatedData.
306 vector<uint8_t> signingKeyBlob;
307 Certificate signingKeyCertificate;
308 ASSERT_TRUE(c->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
309
310 RequestNamespace rns;
311 rns.namespaceName = "ns";
312 rns.items.push_back(buildRequestDataItem("Accessible by A", 1, {0}));
313 rns.items.push_back(buildRequestDataItem("Accessible by A or B", 1, {0, 1}));
314 rns.items.push_back(buildRequestDataItem("Accessible by B", 1, {1}));
315 rns.items.push_back(buildRequestDataItem("Accessible by C", 1, {2}));
316 rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {3}));
317 rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
318 // OK to fail, not available in v1 HAL
319 c->setRequestedNamespaces({rns}).isOk();
320
321 // It doesn't matter since no user auth is needed in this particular test,
322 // but for good measure, clear out the tokens we pass to the HAL.
323 HardwareAuthToken authToken;
324 VerificationToken verificationToken;
325 authToken.challenge = 0;
326 authToken.userId = 0;
327 authToken.authenticatorId = 0;
328 authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
329 authToken.timestamp.milliSeconds = 0;
330 authToken.mac.clear();
331 verificationToken.challenge = 0;
332 verificationToken.timestamp.milliSeconds = 0;
333 verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
334 verificationToken.mac.clear();
335 // OK to fail, not available in v1 HAL
336 c->setVerificationToken(verificationToken);
337
338 Status status = c->startRetrieval(
339 {sacp0_, sacp1_, sacp2_, sacp3_}, authToken, itemsRequestBytes, signingKeyBlob,
340 sessionTranscriptBytes, readerSignature.value(), {6 /* numDataElementsPerNamespace */});
341 if (expectSuccess) {
342 ASSERT_TRUE(status.isOk());
343 } else {
344 ASSERT_FALSE(status.isOk());
345 return;
346 }
347
348 vector<uint8_t> decrypted;
349
350 status = c->startRetrieveEntryValue("ns", "Accessible by A", 1, {0});
351 if (status.isOk()) {
352 canGetAccessibleByA_ = true;
353 ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByA_, &decrypted).isOk());
354 }
355
356 status = c->startRetrieveEntryValue("ns", "Accessible by A or B", 1, {0, 1});
357 if (status.isOk()) {
358 canGetAccessibleByAorB_ = true;
359 ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByAorB_, &decrypted).isOk());
360 }
361
362 status = c->startRetrieveEntryValue("ns", "Accessible by B", 1, {1});
363 if (status.isOk()) {
364 canGetAccessibleByB_ = true;
365 ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByB_, &decrypted).isOk());
366 }
367
368 status = c->startRetrieveEntryValue("ns", "Accessible by C", 1, {2});
369 if (status.isOk()) {
370 canGetAccessibleByC_ = true;
371 ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByC_, &decrypted).isOk());
372 }
373
374 status = c->startRetrieveEntryValue("ns", "Accessible by All", 1, {3});
375 if (status.isOk()) {
376 canGetAccessibleByAll_ = true;
377 ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByAll_, &decrypted).isOk());
378 }
379
380 status = c->startRetrieveEntryValue("ns", "Accessible by None", 1, {});
381 if (status.isOk()) {
382 canGetAccessibleByNone_ = true;
383 ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByNone_, &decrypted).isOk());
384 }
385
386 vector<uint8_t> mac;
387 vector<uint8_t> deviceNameSpaces;
388 ASSERT_TRUE(c->finishRetrieval(&mac, &deviceNameSpaces).isOk());
389}
390
391TEST_P(ReaderAuthTests, presentingChain_Reader) {
392 provisionData();
393 retrieveData(readerPrivateKey_, {cert_reader_SelfSigned_}, true /* expectSuccess */,
394 false /* leaveOutAccessibleToAllFromRequestMessage */);
395 EXPECT_FALSE(canGetAccessibleByA_);
396 EXPECT_FALSE(canGetAccessibleByAorB_);
397 EXPECT_FALSE(canGetAccessibleByB_);
398 EXPECT_FALSE(canGetAccessibleByC_);
399 EXPECT_TRUE(canGetAccessibleByAll_);
400 EXPECT_FALSE(canGetAccessibleByNone_);
401}
402
403TEST_P(ReaderAuthTests, presentingChain_Reader_A) {
404 provisionData();
405 retrieveData(readerPrivateKey_, {cert_reader_SignedBy_A_, cert_A_SelfSigned_},
406 true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
407 EXPECT_TRUE(canGetAccessibleByA_);
408 EXPECT_TRUE(canGetAccessibleByAorB_);
409 EXPECT_FALSE(canGetAccessibleByB_);
410 EXPECT_FALSE(canGetAccessibleByC_);
411 EXPECT_TRUE(canGetAccessibleByAll_);
412 EXPECT_FALSE(canGetAccessibleByNone_);
413}
414
415TEST_P(ReaderAuthTests, presentingChain_Reader_B) {
416 provisionData();
417 retrieveData(readerPrivateKey_, {cert_reader_SignedBy_B_, cert_B_SelfSigned_},
418 true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
419 EXPECT_FALSE(canGetAccessibleByA_);
420 EXPECT_TRUE(canGetAccessibleByAorB_);
421 EXPECT_TRUE(canGetAccessibleByB_);
422 EXPECT_FALSE(canGetAccessibleByC_);
423 EXPECT_TRUE(canGetAccessibleByAll_);
424 EXPECT_FALSE(canGetAccessibleByNone_);
425}
426
427// This test proves that for the purpose of determining inclusion of an ACP certificate
428// in a presented reader chain, certificate equality is done by comparing public keys,
429// not bitwise comparison of the certificates.
430//
431// Specifically for this test, the ACP is configured with cert_B_SelfSigned_ and the
432// reader is presenting cert_B_SignedBy_C_. Both certificates have the same public
433// key - intermediateBPublicKey_ - but they are signed by different keys.
434//
435TEST_P(ReaderAuthTests, presentingChain_Reader_B_C) {
436 provisionData();
437 retrieveData(readerPrivateKey_,
438 {cert_reader_SignedBy_B_, cert_B_SignedBy_C_, cert_C_SelfSigned_},
439 true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
440 EXPECT_FALSE(canGetAccessibleByA_);
441 EXPECT_TRUE(canGetAccessibleByAorB_);
442 EXPECT_TRUE(canGetAccessibleByB_);
443 EXPECT_TRUE(canGetAccessibleByC_);
444 EXPECT_TRUE(canGetAccessibleByAll_);
445 EXPECT_FALSE(canGetAccessibleByNone_);
446}
447
448// This test presents a reader chain where the chain is invalid because
449// the 2nd certificate in the chain isn't signed by the 3rd one.
450//
451TEST_P(ReaderAuthTests, presentingInvalidChain) {
452 provisionData();
453 retrieveData(readerPrivateKey_,
454 {cert_reader_SignedBy_B_, cert_B_SelfSigned_, cert_C_SelfSigned_},
455 false /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
456}
457
458// This tests presents a valid reader chain but where requestMessage isn't
459// signed by the private key corresponding to the public key in the top-level
460// certificate.
461//
462TEST_P(ReaderAuthTests, presentingMessageSignedNotByTopLevel) {
463 provisionData();
464 retrieveData(intermediateBPrivateKey_,
465 {cert_reader_SignedBy_B_, cert_B_SignedBy_C_, cert_C_SelfSigned_},
466 false /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
467}
468
469// This test leaves out "Accessible by All" data element from the signed request
470// message (the CBOR from the reader) while still including this data element at
471// the API level. The call on the API level for said element will fail with
472// STATUS_NOT_IN_REQUEST_MESSAGE but this doesn't prevent the other elements
473// from being returned (if authorized, of course).
474//
475// This test verifies that.
476//
477TEST_P(ReaderAuthTests, limitedMessage) {
478 provisionData();
479 retrieveData(readerPrivateKey_, {cert_reader_SelfSigned_}, true /* expectSuccess */,
480 true /* leaveOutAccessibleToAllFromRequestMessage */);
481 EXPECT_FALSE(canGetAccessibleByA_);
482 EXPECT_FALSE(canGetAccessibleByAorB_);
483 EXPECT_FALSE(canGetAccessibleByB_);
484 EXPECT_FALSE(canGetAccessibleByC_);
485 EXPECT_FALSE(canGetAccessibleByAll_);
486 EXPECT_FALSE(canGetAccessibleByNone_);
487}
488
489TEST_P(ReaderAuthTests, ephemeralKeyNotInSessionTranscript) {
490 provisionData();
491
492 sp<IIdentityCredential> c;
493 ASSERT_TRUE(credentialStore_
494 ->getCredential(
495 CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
496 credentialData_, &c)
497 .isOk());
498
499 optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
500 optional<vector<uint8_t>> readerEPublicKey =
501 support::ecKeyPairGetPublicKey(readerEKeyPair.value());
502 ASSERT_TRUE(c->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
503
504 vector<uint8_t> eKeyPair;
505 ASSERT_TRUE(c->createEphemeralKeyPair(&eKeyPair).isOk());
506 optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
507
508 // Calculate requestData field and sign it with the reader key.
509 auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey.value());
510 ASSERT_TRUE(getXYSuccess);
511 // Instead of include the X and Y coordinates (|ephX| and |ephY|), add NUL bytes instead.
512 vector<uint8_t> nulls(32);
513 cppbor::Map deviceEngagement = cppbor::Map().add("ephX", nulls).add("ephY", nulls);
514 vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
515 vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
516 cppbor::Array sessionTranscript = cppbor::Array()
517 .add(cppbor::Semantic(24, deviceEngagementBytes))
518 .add(cppbor::Semantic(24, eReaderPubBytes));
519 vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
520
521 vector<uint8_t> itemsRequestBytes;
522 itemsRequestBytes =
523 cppbor::Map("nameSpaces",
524 cppbor::Map().add("ns", cppbor::Map()
525 .add("Accessible by A", false)
526 .add("Accessible by A or B", false)
527 .add("Accessible by B", false)
528 .add("Accessible by C", false)
529 .add("Accessible by None", false)))
530 .encode();
531 vector<uint8_t> dataToSign = cppbor::Array()
532 .add("ReaderAuthentication")
533 .add(sessionTranscript.clone())
534 .add(cppbor::Semantic(24, itemsRequestBytes))
535 .encode();
536
537 vector<vector<uint8_t>> readerCertChain = {cert_reader_SelfSigned_};
538 optional<vector<uint8_t>> readerSignature =
539 support::coseSignEcDsa(readerPrivateKey_, // private key for reader
540 {}, // content
541 dataToSign, // detached content
542 support::certificateChainJoin(readerCertChain));
543 ASSERT_TRUE(readerSignature);
544
545 // Generate the key that will be used to sign AuthenticatedData.
546 vector<uint8_t> signingKeyBlob;
547 Certificate signingKeyCertificate;
548 ASSERT_TRUE(c->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
549
550 RequestNamespace rns;
551 rns.namespaceName = "ns";
552 rns.items.push_back(buildRequestDataItem("Accessible by A", 1, {0}));
553 rns.items.push_back(buildRequestDataItem("Accessible by A or B", 1, {0, 1}));
554 rns.items.push_back(buildRequestDataItem("Accessible by B", 1, {1}));
555 rns.items.push_back(buildRequestDataItem("Accessible by C", 1, {2}));
556 rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {3}));
557 rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
558 // OK to fail, not available in v1 HAL
559 c->setRequestedNamespaces({rns}).isOk();
560
561 // It doesn't matter since no user auth is needed in this particular test,
562 // but for good measure, clear out the tokens we pass to the HAL.
563 HardwareAuthToken authToken;
564 VerificationToken verificationToken;
565 authToken.challenge = 0;
566 authToken.userId = 0;
567 authToken.authenticatorId = 0;
568 authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
569 authToken.timestamp.milliSeconds = 0;
570 authToken.mac.clear();
571 verificationToken.challenge = 0;
572 verificationToken.timestamp.milliSeconds = 0;
573 verificationToken.securityLevel =
574 ::android::hardware::keymaster::SecurityLevel::TRUSTED_ENVIRONMENT;
575 verificationToken.mac.clear();
576 // OK to fail, not available in v1 HAL
577 c->setVerificationToken(verificationToken);
578
579 // Finally check that STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND is returned.
580 // This proves that the TA checked for X and Y coordinatets and didn't find
581 // them.
582 Status status = c->startRetrieval(
583 {sacp0_, sacp1_, sacp2_, sacp3_}, authToken, itemsRequestBytes, signingKeyBlob,
584 sessionTranscriptBytes, readerSignature.value(), {6 /* numDataElementsPerNamespace */});
585 ASSERT_FALSE(status.isOk());
586 ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
587 ASSERT_EQ(IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
588 status.serviceSpecificErrorCode());
589}
590
591INSTANTIATE_TEST_SUITE_P(
592 Identity, ReaderAuthTests,
593 testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
594 android::PrintInstanceNameToString);
595
596} // namespace android::hardware::identity