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