blob: 91e634c0c3988455c250291b357ef36166a7e619 [file] [log] [blame]
David Zeuthen630de2a2020-05-11 14:04:54 -04001/*
2 * Copyright 2020, 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 "FakeSecureHardwareProxy"
18
19#include "FakeSecureHardwareProxy.h"
20
21#include <android/hardware/identity/support/IdentityCredentialSupport.h>
22
23#include <android-base/logging.h>
24#include <android-base/stringprintf.h>
25#include <string.h>
David Zeuthen1eb12b22021-09-11 13:59:43 -040026#include <map>
David Zeuthen630de2a2020-05-11 14:04:54 -040027
28#include <openssl/sha.h>
29
30#include <openssl/aes.h>
31#include <openssl/bn.h>
32#include <openssl/crypto.h>
33#include <openssl/ec.h>
34#include <openssl/err.h>
35#include <openssl/evp.h>
36#include <openssl/hkdf.h>
37#include <openssl/hmac.h>
38#include <openssl/objects.h>
39#include <openssl/pem.h>
40#include <openssl/pkcs12.h>
41#include <openssl/rand.h>
42#include <openssl/x509.h>
43#include <openssl/x509_vfy.h>
44
45#include <libeic.h>
46
47using ::std::optional;
48using ::std::string;
49using ::std::tuple;
50using ::std::vector;
51
52namespace android::hardware::identity {
53
54// ----------------------------------------------------------------------
55
David Zeuthen1eb12b22021-09-11 13:59:43 -040056// The singleton EicProvisioning object used everywhere.
57//
58EicProvisioning FakeSecureHardwareProvisioningProxy::ctx_;
David Zeuthen630de2a2020-05-11 14:04:54 -040059
David Zeuthen1eb12b22021-09-11 13:59:43 -040060FakeSecureHardwareProvisioningProxy::~FakeSecureHardwareProvisioningProxy() {
61 if (id_ != 0) {
62 shutdown();
63 }
David Zeuthen630de2a2020-05-11 14:04:54 -040064}
65
66bool FakeSecureHardwareProvisioningProxy::initialize(bool testCredential) {
David Zeuthen1eb12b22021-09-11 13:59:43 -040067 if (id_ != 0) {
68 LOG(WARNING) << "Proxy is already initialized";
69 return false;
70 }
71 bool initialized = eicProvisioningInit(&ctx_, testCredential);
72 if (!initialized) {
73 return false;
74 }
75 optional<uint32_t> id = getId();
76 if (!id) {
77 LOG(WARNING) << "Error getting id";
78 return false;
79 }
80 id_ = id.value();
81 return true;
David Zeuthen630de2a2020-05-11 14:04:54 -040082}
83
David Zeuthen49f2d252020-10-16 11:27:24 -040084bool FakeSecureHardwareProvisioningProxy::initializeForUpdate(
David Zeuthen1eb12b22021-09-11 13:59:43 -040085 bool testCredential, const string& docType,
86 const vector<uint8_t>& encryptedCredentialKeys) {
87 if (id_ != 0) {
88 LOG(WARNING) << "Proxy is already initialized";
89 return false;
90 }
91 bool initialized = eicProvisioningInitForUpdate(&ctx_, testCredential, docType.c_str(),
92 docType.size(), encryptedCredentialKeys.data(),
93 encryptedCredentialKeys.size());
94 if (!initialized) {
95 return false;
96 }
97 optional<uint32_t> id = getId();
98 if (!id) {
99 LOG(WARNING) << "Error getting id";
100 return false;
101 }
102 id_ = id.value();
103 return true;
104}
105
106optional<uint32_t> FakeSecureHardwareProvisioningProxy::getId() {
107 uint32_t id;
108 if (!eicProvisioningGetId(&ctx_, &id)) {
109 return std::nullopt;
110 }
111 return id;
112}
113
114bool FakeSecureHardwareProvisioningProxy::validateId(const string& callerName) {
115 if (id_ == 0) {
116 LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
117 << ": While validating expected id is 0";
118 return false;
119 }
120 optional<uint32_t> id = getId();
121 if (!id) {
122 LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
123 << ": Error getting id for validating";
124 return false;
125 }
126 if (id.value() != id_) {
127 LOG(WARNING) << "FakeSecureHardwareProvisioningProxy::" << callerName
128 << ": While validating expected id " << id_ << " but got " << id.value();
129 return false;
130 }
131 return true;
132}
133
134bool FakeSecureHardwareProvisioningProxy::shutdown() {
135 bool validated = validateId(__func__);
136 id_ = 0;
137 if (!validated) {
138 return false;
139 }
140 if (!eicProvisioningShutdown(&ctx_)) {
141 LOG(INFO) << "Error shutting down provisioning";
142 return false;
143 }
144 return true;
David Zeuthen49f2d252020-10-16 11:27:24 -0400145}
146
David Zeuthen630de2a2020-05-11 14:04:54 -0400147// Returns public key certificate.
148optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::createCredentialKey(
149 const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400150 if (!validateId(__func__)) {
151 return std::nullopt;
152 }
153
David Zeuthen630de2a2020-05-11 14:04:54 -0400154 uint8_t publicKeyCert[4096];
155 size_t publicKeyCertSize = sizeof publicKeyCert;
156 if (!eicProvisioningCreateCredentialKey(&ctx_, challenge.data(), challenge.size(),
157 applicationId.data(), applicationId.size(),
Seth Moorebe321132022-01-25 22:44:24 +0000158 publicKeyCert, &publicKeyCertSize)) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400159 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400160 }
161 vector<uint8_t> pubKeyCert(publicKeyCertSize);
162 memcpy(pubKeyCert.data(), publicKeyCert, publicKeyCertSize);
163 return pubKeyCert;
164}
165
166bool FakeSecureHardwareProvisioningProxy::startPersonalization(
David Zeuthen1eb12b22021-09-11 13:59:43 -0400167 int accessControlProfileCount, const vector<int>& entryCounts, const string& docType,
David Zeuthen630de2a2020-05-11 14:04:54 -0400168 size_t expectedProofOfProvisioningSize) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400169 if (!validateId(__func__)) {
170 return false;
171 }
Joseph Jangdabb3c52021-09-01 16:50:09 +0800172
173 if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount,
174 entryCounts.data(),
175 entryCounts.size(),
176 docType.c_str(), docType.size(),
David Zeuthen630de2a2020-05-11 14:04:54 -0400177 expectedProofOfProvisioningSize)) {
178 return false;
179 }
180 return true;
181}
182
183// Returns MAC (28 bytes).
184optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addAccessControlProfile(
185 int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
186 uint64_t timeoutMillis, uint64_t secureUserId) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400187 if (!validateId(__func__)) {
188 return std::nullopt;
189 }
190
David Zeuthen630de2a2020-05-11 14:04:54 -0400191 vector<uint8_t> mac(28);
Joseph Jangdabb3c52021-09-01 16:50:09 +0800192 uint8_t scratchSpace[512];
David Zeuthen630de2a2020-05-11 14:04:54 -0400193 if (!eicProvisioningAddAccessControlProfile(
194 &ctx_, id, readerCertificate.data(), readerCertificate.size(),
Joseph Jangdabb3c52021-09-01 16:50:09 +0800195 userAuthenticationRequired, timeoutMillis, secureUserId, mac.data(),
196 scratchSpace, sizeof(scratchSpace))) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400197 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400198 }
199 return mac;
200}
201
202bool FakeSecureHardwareProvisioningProxy::beginAddEntry(const vector<int>& accessControlProfileIds,
203 const string& nameSpace, const string& name,
204 uint64_t entrySize) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400205 if (!validateId(__func__)) {
206 return false;
207 }
208
David Zeuthen630de2a2020-05-11 14:04:54 -0400209 uint8_t scratchSpace[512];
Joseph Jangdabb3c52021-09-01 16:50:09 +0800210 vector<uint8_t> uint8AccessControlProfileIds;
211 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
212 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
213 }
214
215 return eicProvisioningBeginAddEntry(&ctx_, uint8AccessControlProfileIds.data(),
216 uint8AccessControlProfileIds.size(), nameSpace.c_str(),
217 nameSpace.size(), name.c_str(), name.size(), entrySize,
218 scratchSpace, sizeof(scratchSpace));
David Zeuthen630de2a2020-05-11 14:04:54 -0400219}
220
221// Returns encryptedContent.
222optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addEntryValue(
223 const vector<int>& accessControlProfileIds, const string& nameSpace, const string& name,
224 const vector<uint8_t>& content) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400225 if (!validateId(__func__)) {
226 return std::nullopt;
227 }
228
David Zeuthen630de2a2020-05-11 14:04:54 -0400229 vector<uint8_t> eicEncryptedContent;
230 uint8_t scratchSpace[512];
Joseph Jangdabb3c52021-09-01 16:50:09 +0800231 vector<uint8_t> uint8AccessControlProfileIds;
232 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
233 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
234 }
235
David Zeuthen630de2a2020-05-11 14:04:54 -0400236 eicEncryptedContent.resize(content.size() + 28);
237 if (!eicProvisioningAddEntryValue(
Joseph Jangdabb3c52021-09-01 16:50:09 +0800238 &ctx_, uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(),
239 nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(), content.data(),
240 content.size(), eicEncryptedContent.data(), scratchSpace, sizeof(scratchSpace))) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400241 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400242 }
243 return eicEncryptedContent;
244}
245
246// Returns signatureOfToBeSigned (EIC_ECDSA_P256_SIGNATURE_SIZE bytes).
247optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishAddingEntries() {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400248 if (!validateId(__func__)) {
249 return std::nullopt;
250 }
251
David Zeuthen630de2a2020-05-11 14:04:54 -0400252 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
253 if (!eicProvisioningFinishAddingEntries(&ctx_, signatureOfToBeSigned.data())) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400254 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400255 }
256 return signatureOfToBeSigned;
257}
258
David Zeuthen49f2d252020-10-16 11:27:24 -0400259// Returns encryptedCredentialKeys.
David Zeuthen630de2a2020-05-11 14:04:54 -0400260optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishGetCredentialData(
261 const string& docType) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400262 if (!validateId(__func__)) {
263 return std::nullopt;
264 }
265
David Zeuthen49f2d252020-10-16 11:27:24 -0400266 vector<uint8_t> encryptedCredentialKeys(116);
267 size_t size = encryptedCredentialKeys.size();
Joseph Jangdabb3c52021-09-01 16:50:09 +0800268 if (!eicProvisioningFinishGetCredentialData(&ctx_, docType.c_str(), docType.size(),
David Zeuthen49f2d252020-10-16 11:27:24 -0400269 encryptedCredentialKeys.data(), &size)) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400270 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400271 }
David Zeuthen49f2d252020-10-16 11:27:24 -0400272 encryptedCredentialKeys.resize(size);
David Zeuthen630de2a2020-05-11 14:04:54 -0400273 return encryptedCredentialKeys;
274}
275
276// ----------------------------------------------------------------------
277
David Zeuthen1eb12b22021-09-11 13:59:43 -0400278// The singleton EicSession object used everywhere.
279//
280EicSession FakeSecureHardwareSessionProxy::ctx_;
David Zeuthen630de2a2020-05-11 14:04:54 -0400281
David Zeuthen1eb12b22021-09-11 13:59:43 -0400282FakeSecureHardwareSessionProxy::~FakeSecureHardwareSessionProxy() {
283 if (id_ != 0) {
284 shutdown();
285 }
286}
David Zeuthen630de2a2020-05-11 14:04:54 -0400287
David Zeuthen1eb12b22021-09-11 13:59:43 -0400288bool FakeSecureHardwareSessionProxy::initialize() {
289 if (id_ != 0) {
290 LOG(WARNING) << "Proxy is already initialized";
291 return false;
292 }
293 bool initialized = eicSessionInit(&ctx_);
294 if (!initialized) {
295 return false;
296 }
297 optional<uint32_t> id = getId();
298 if (!id) {
299 LOG(WARNING) << "Error getting id";
300 return false;
301 }
302 id_ = id.value();
303 return true;
304}
305
306optional<uint32_t> FakeSecureHardwareSessionProxy::getId() {
307 uint32_t id;
308 if (!eicSessionGetId(&ctx_, &id)) {
309 return std::nullopt;
310 }
311 return id;
312}
313
314bool FakeSecureHardwareSessionProxy::shutdown() {
315 bool validated = validateId(__func__);
316 id_ = 0;
317 if (!validated) {
318 return false;
319 }
320 if (!eicSessionShutdown(&ctx_)) {
321 LOG(INFO) << "Error shutting down session";
322 return false;
323 }
324 return true;
325}
326
327bool FakeSecureHardwareSessionProxy::validateId(const string& callerName) {
328 if (id_ == 0) {
329 LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
330 << ": While validating expected id is 0";
331 return false;
332 }
333 optional<uint32_t> id = getId();
334 if (!id) {
335 LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
336 << ": Error getting id for validating";
337 return false;
338 }
339 if (id.value() != id_) {
340 LOG(WARNING) << "FakeSecureHardwareSessionProxy::" << callerName
341 << ": While validating expected id " << id_ << " but got " << id.value();
342 return false;
343 }
344 return true;
345}
346
347optional<uint64_t> FakeSecureHardwareSessionProxy::getAuthChallenge() {
348 if (!validateId(__func__)) {
349 return std::nullopt;
350 }
351
352 uint64_t authChallenge;
353 if (!eicSessionGetAuthChallenge(&ctx_, &authChallenge)) {
354 return std::nullopt;
355 }
356 return authChallenge;
357}
358
359optional<vector<uint8_t>> FakeSecureHardwareSessionProxy::getEphemeralKeyPair() {
360 if (!validateId(__func__)) {
361 return std::nullopt;
362 }
363
364 vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
365 if (!eicSessionGetEphemeralKeyPair(&ctx_, priv.data())) {
366 return std::nullopt;
367 }
368 return priv;
369}
370
371bool FakeSecureHardwareSessionProxy::setReaderEphemeralPublicKey(
372 const vector<uint8_t>& readerEphemeralPublicKey) {
373 if (!validateId(__func__)) {
374 return false;
375 }
376
377 return eicSessionSetReaderEphemeralPublicKey(&ctx_, readerEphemeralPublicKey.data());
378}
379
380bool FakeSecureHardwareSessionProxy::setSessionTranscript(
381 const vector<uint8_t>& sessionTranscript) {
382 if (!validateId(__func__)) {
383 return false;
384 }
385
386 return eicSessionSetSessionTranscript(&ctx_, sessionTranscript.data(),
387 sessionTranscript.size());
388}
389
390// ----------------------------------------------------------------------
391
392// The singleton EicPresentation object used everywhere.
393//
394EicPresentation FakeSecureHardwarePresentationProxy::ctx_;
395
396FakeSecureHardwarePresentationProxy::~FakeSecureHardwarePresentationProxy() {
397 if (id_ != 0) {
398 shutdown();
399 }
400}
401
402bool FakeSecureHardwarePresentationProxy::initialize(
403 uint32_t sessionId, bool testCredential, const string& docType,
404 const vector<uint8_t>& encryptedCredentialKeys) {
405 if (id_ != 0) {
406 LOG(WARNING) << "Proxy is already initialized";
407 return false;
408 }
409 bool initialized =
410 eicPresentationInit(&ctx_, sessionId, testCredential, docType.c_str(), docType.size(),
411 encryptedCredentialKeys.data(), encryptedCredentialKeys.size());
412 if (!initialized) {
413 return false;
414 }
415 optional<uint32_t> id = getId();
416 if (!id) {
417 LOG(WARNING) << "Error getting id";
418 return false;
419 }
420 id_ = id.value();
421 return true;
422}
423
424optional<uint32_t> FakeSecureHardwarePresentationProxy::getId() {
425 uint32_t id;
426 if (!eicPresentationGetId(&ctx_, &id)) {
427 return std::nullopt;
428 }
429 return id;
430}
431
432bool FakeSecureHardwarePresentationProxy::validateId(const string& callerName) {
433 if (id_ == 0) {
434 LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
435 << ": While validating expected id is 0";
436 return false;
437 }
438 optional<uint32_t> id = getId();
439 if (!id) {
440 LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
441 << ": Error getting id for validating";
442 return false;
443 }
444 if (id.value() != id_) {
445 LOG(WARNING) << "FakeSecureHardwarePresentationProxy::" << callerName
446 << ": While validating expected id " << id_ << " but got " << id.value();
447 return false;
448 }
449 return true;
450}
451
452bool FakeSecureHardwarePresentationProxy::shutdown() {
453 bool validated = validateId(__func__);
454 id_ = 0;
455 if (!validated) {
456 return false;
457 }
458 if (!eicPresentationShutdown(&ctx_)) {
459 LOG(INFO) << "Error shutting down presentation";
460 return false;
461 }
462 return true;
David Zeuthen630de2a2020-05-11 14:04:54 -0400463}
464
465// Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
466optional<pair<vector<uint8_t>, vector<uint8_t>>>
David Zeuthen1eb12b22021-09-11 13:59:43 -0400467FakeSecureHardwarePresentationProxy::generateSigningKeyPair(const string& docType, time_t now) {
468 if (!validateId(__func__)) {
469 return std::nullopt;
470 }
471
David Zeuthen630de2a2020-05-11 14:04:54 -0400472 uint8_t publicKeyCert[512];
473 size_t publicKeyCertSize = sizeof(publicKeyCert);
474 vector<uint8_t> signingKeyBlob(60);
475
Joseph Jangdabb3c52021-09-01 16:50:09 +0800476 if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), docType.size(), now,
477 publicKeyCert, &publicKeyCertSize,
478 signingKeyBlob.data())) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400479 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400480 }
481
482 vector<uint8_t> cert;
483 cert.resize(publicKeyCertSize);
484 memcpy(cert.data(), publicKeyCert, publicKeyCertSize);
485
486 return std::make_pair(cert, signingKeyBlob);
487}
488
489// Returns private key
490optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::createEphemeralKeyPair() {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400491 if (!validateId(__func__)) {
492 return std::nullopt;
493 }
494
David Zeuthen630de2a2020-05-11 14:04:54 -0400495 vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
496 if (!eicPresentationCreateEphemeralKeyPair(&ctx_, priv.data())) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400497 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400498 }
499 return priv;
500}
501
502optional<uint64_t> FakeSecureHardwarePresentationProxy::createAuthChallenge() {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400503 if (!validateId(__func__)) {
504 return std::nullopt;
505 }
506
David Zeuthen630de2a2020-05-11 14:04:54 -0400507 uint64_t challenge;
508 if (!eicPresentationCreateAuthChallenge(&ctx_, &challenge)) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400509 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400510 }
511 return challenge;
512}
513
David Zeuthen630de2a2020-05-11 14:04:54 -0400514bool FakeSecureHardwarePresentationProxy::pushReaderCert(const vector<uint8_t>& certX509) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400515 if (!validateId(__func__)) {
516 return false;
517 }
518
David Zeuthen630de2a2020-05-11 14:04:54 -0400519 return eicPresentationPushReaderCert(&ctx_, certX509.data(), certX509.size());
520}
521
522bool FakeSecureHardwarePresentationProxy::validateRequestMessage(
523 const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& requestMessage,
524 int coseSignAlg, const vector<uint8_t>& readerSignatureOfToBeSigned) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400525 if (!validateId(__func__)) {
526 return false;
527 }
528
David Zeuthen630de2a2020-05-11 14:04:54 -0400529 return eicPresentationValidateRequestMessage(
530 &ctx_, sessionTranscript.data(), sessionTranscript.size(), requestMessage.data(),
531 requestMessage.size(), coseSignAlg, readerSignatureOfToBeSigned.data(),
532 readerSignatureOfToBeSigned.size());
533}
534
535bool FakeSecureHardwarePresentationProxy::setAuthToken(
536 uint64_t challenge, uint64_t secureUserId, uint64_t authenticatorId,
537 int hardwareAuthenticatorType, uint64_t timeStamp, const vector<uint8_t>& mac,
538 uint64_t verificationTokenChallenge, uint64_t verificationTokenTimestamp,
539 int verificationTokenSecurityLevel, const vector<uint8_t>& verificationTokenMac) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400540 if (!validateId(__func__)) {
541 return false;
542 }
543
David Zeuthen630de2a2020-05-11 14:04:54 -0400544 return eicPresentationSetAuthToken(&ctx_, challenge, secureUserId, authenticatorId,
545 hardwareAuthenticatorType, timeStamp, mac.data(), mac.size(),
546 verificationTokenChallenge, verificationTokenTimestamp,
547 verificationTokenSecurityLevel, verificationTokenMac.data(),
548 verificationTokenMac.size());
549}
550
551optional<bool> FakeSecureHardwarePresentationProxy::validateAccessControlProfile(
552 int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
553 int timeoutMillis, uint64_t secureUserId, const vector<uint8_t>& mac) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400554 if (!validateId(__func__)) {
555 return std::nullopt;
556 }
557
David Zeuthen630de2a2020-05-11 14:04:54 -0400558 bool accessGranted = false;
Joseph Jangdabb3c52021-09-01 16:50:09 +0800559 uint8_t scratchSpace[512];
David Zeuthen630de2a2020-05-11 14:04:54 -0400560 if (!eicPresentationValidateAccessControlProfile(&ctx_, id, readerCertificate.data(),
561 readerCertificate.size(),
562 userAuthenticationRequired, timeoutMillis,
Joseph Jangdabb3c52021-09-01 16:50:09 +0800563 secureUserId, mac.data(), &accessGranted,
564 scratchSpace, sizeof(scratchSpace))) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400565 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400566 }
567 return accessGranted;
568}
569
570bool FakeSecureHardwarePresentationProxy::startRetrieveEntries() {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400571 if (!validateId(__func__)) {
572 return false;
573 }
574
David Zeuthen630de2a2020-05-11 14:04:54 -0400575 return eicPresentationStartRetrieveEntries(&ctx_);
576}
577
578bool FakeSecureHardwarePresentationProxy::calcMacKey(
579 const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& readerEphemeralPublicKey,
580 const vector<uint8_t>& signingKeyBlob, const string& docType,
581 unsigned int numNamespacesWithValues, size_t expectedProofOfProvisioningSize) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400582 if (!validateId(__func__)) {
583 return false;
584 }
585
David Zeuthen630de2a2020-05-11 14:04:54 -0400586 if (signingKeyBlob.size() != 60) {
587 eicDebug("Unexpected size %zd of signingKeyBlob, expected 60", signingKeyBlob.size());
588 return false;
589 }
590 return eicPresentationCalcMacKey(&ctx_, sessionTranscript.data(), sessionTranscript.size(),
591 readerEphemeralPublicKey.data(), signingKeyBlob.data(),
Joseph Jangdabb3c52021-09-01 16:50:09 +0800592 docType.c_str(), docType.size(), numNamespacesWithValues,
David Zeuthen630de2a2020-05-11 14:04:54 -0400593 expectedProofOfProvisioningSize);
594}
595
596AccessCheckResult FakeSecureHardwarePresentationProxy::startRetrieveEntryValue(
597 const string& nameSpace, const string& name, unsigned int newNamespaceNumEntries,
598 int32_t entrySize, const vector<int32_t>& accessControlProfileIds) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400599 if (!validateId(__func__)) {
600 return AccessCheckResult::kFailed;
601 }
602
David Zeuthen630de2a2020-05-11 14:04:54 -0400603 uint8_t scratchSpace[512];
Joseph Jangdabb3c52021-09-01 16:50:09 +0800604 vector<uint8_t> uint8AccessControlProfileIds;
605 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
606 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
607 }
608
David Zeuthen630de2a2020-05-11 14:04:54 -0400609 EicAccessCheckResult result = eicPresentationStartRetrieveEntryValue(
Joseph Jangdabb3c52021-09-01 16:50:09 +0800610 &ctx_, nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(),
611 newNamespaceNumEntries, entrySize, uint8AccessControlProfileIds.data(),
612 uint8AccessControlProfileIds.size(), scratchSpace,
613 sizeof(scratchSpace));
David Zeuthen630de2a2020-05-11 14:04:54 -0400614 switch (result) {
615 case EIC_ACCESS_CHECK_RESULT_OK:
616 return AccessCheckResult::kOk;
617 case EIC_ACCESS_CHECK_RESULT_NO_ACCESS_CONTROL_PROFILES:
618 return AccessCheckResult::kNoAccessControlProfiles;
619 case EIC_ACCESS_CHECK_RESULT_FAILED:
620 return AccessCheckResult::kFailed;
621 case EIC_ACCESS_CHECK_RESULT_USER_AUTHENTICATION_FAILED:
622 return AccessCheckResult::kUserAuthenticationFailed;
623 case EIC_ACCESS_CHECK_RESULT_READER_AUTHENTICATION_FAILED:
624 return AccessCheckResult::kReaderAuthenticationFailed;
625 }
626 eicDebug("Unknown result with code %d, returning kFailed", (int)result);
627 return AccessCheckResult::kFailed;
628}
629
630optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::retrieveEntryValue(
631 const vector<uint8_t>& encryptedContent, const string& nameSpace, const string& name,
632 const vector<int32_t>& accessControlProfileIds) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400633 if (!validateId(__func__)) {
634 return std::nullopt;
635 }
636
David Zeuthen630de2a2020-05-11 14:04:54 -0400637 uint8_t scratchSpace[512];
Joseph Jangdabb3c52021-09-01 16:50:09 +0800638 vector<uint8_t> uint8AccessControlProfileIds;
639 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
640 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
641 }
642
David Zeuthen630de2a2020-05-11 14:04:54 -0400643 vector<uint8_t> content;
644 content.resize(encryptedContent.size() - 28);
645 if (!eicPresentationRetrieveEntryValue(
646 &ctx_, encryptedContent.data(), encryptedContent.size(), content.data(),
Joseph Jangdabb3c52021-09-01 16:50:09 +0800647 nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(),
648 uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(),
649 scratchSpace, sizeof(scratchSpace))) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400650 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400651 }
652 return content;
653}
654
655optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::finishRetrieval() {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400656 if (!validateId(__func__)) {
657 return std::nullopt;
658 }
659
David Zeuthen630de2a2020-05-11 14:04:54 -0400660 vector<uint8_t> mac(32);
661 size_t macSize = 32;
662 if (!eicPresentationFinishRetrieval(&ctx_, mac.data(), &macSize)) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400663 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400664 }
665 mac.resize(macSize);
666 return mac;
667}
668
669optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::deleteCredential(
David Zeuthen49f2d252020-10-16 11:27:24 -0400670 const string& docType, const vector<uint8_t>& challenge, bool includeChallenge,
671 size_t proofOfDeletionCborSize) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400672 if (!validateId(__func__)) {
673 return std::nullopt;
674 }
675
David Zeuthen630de2a2020-05-11 14:04:54 -0400676 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
Joseph Jangdabb3c52021-09-01 16:50:09 +0800677 if (!eicPresentationDeleteCredential(&ctx_, docType.c_str(), docType.size(), challenge.data(),
678 challenge.size(), includeChallenge,
679 proofOfDeletionCborSize, signatureOfToBeSigned.data())) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400680 return std::nullopt;
David Zeuthen630de2a2020-05-11 14:04:54 -0400681 }
682 return signatureOfToBeSigned;
683}
684
David Zeuthen49f2d252020-10-16 11:27:24 -0400685optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::proveOwnership(
686 const string& docType, bool testCredential, const vector<uint8_t>& challenge,
687 size_t proofOfOwnershipCborSize) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400688 if (!validateId(__func__)) {
689 return std::nullopt;
690 }
691
David Zeuthen49f2d252020-10-16 11:27:24 -0400692 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
Joseph Jangdabb3c52021-09-01 16:50:09 +0800693 if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), docType.size(), testCredential,
694 challenge.data(), challenge.size(), proofOfOwnershipCborSize,
David Zeuthen49f2d252020-10-16 11:27:24 -0400695 signatureOfToBeSigned.data())) {
David Zeuthen1eb12b22021-09-11 13:59:43 -0400696 return std::nullopt;
David Zeuthen49f2d252020-10-16 11:27:24 -0400697 }
698 return signatureOfToBeSigned;
699}
700
David Zeuthen630de2a2020-05-11 14:04:54 -0400701} // namespace android::hardware::identity