blob: 287ffb82e10a4a85b49daceb355c4014196b95eb [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>
26
27#include <openssl/sha.h>
28
29#include <openssl/aes.h>
30#include <openssl/bn.h>
31#include <openssl/crypto.h>
32#include <openssl/ec.h>
33#include <openssl/err.h>
34#include <openssl/evp.h>
35#include <openssl/hkdf.h>
36#include <openssl/hmac.h>
37#include <openssl/objects.h>
38#include <openssl/pem.h>
39#include <openssl/pkcs12.h>
40#include <openssl/rand.h>
41#include <openssl/x509.h>
42#include <openssl/x509_vfy.h>
43
44#include <libeic.h>
45
46using ::std::optional;
47using ::std::string;
48using ::std::tuple;
49using ::std::vector;
50
51namespace android::hardware::identity {
52
53// ----------------------------------------------------------------------
54
55FakeSecureHardwareProvisioningProxy::FakeSecureHardwareProvisioningProxy() {}
56
57FakeSecureHardwareProvisioningProxy::~FakeSecureHardwareProvisioningProxy() {}
58
59bool FakeSecureHardwareProvisioningProxy::shutdown() {
60 LOG(INFO) << "FakeSecureHardwarePresentationProxy shutdown";
61 return true;
62}
63
64bool FakeSecureHardwareProvisioningProxy::initialize(bool testCredential) {
65 LOG(INFO) << "FakeSecureHardwareProvisioningProxy created, sizeof(EicProvisioning): "
66 << sizeof(EicProvisioning);
67 return eicProvisioningInit(&ctx_, testCredential);
68}
69
David Zeuthen49f2d252020-10-16 11:27:24 -040070bool FakeSecureHardwareProvisioningProxy::initializeForUpdate(
71 bool testCredential, string docType, vector<uint8_t> encryptedCredentialKeys) {
72 return eicProvisioningInitForUpdate(&ctx_, testCredential, docType.c_str(),
73 encryptedCredentialKeys.data(),
74 encryptedCredentialKeys.size());
75}
76
David Zeuthen630de2a2020-05-11 14:04:54 -040077// Returns public key certificate.
78optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::createCredentialKey(
79 const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
80 uint8_t publicKeyCert[4096];
81 size_t publicKeyCertSize = sizeof publicKeyCert;
82 if (!eicProvisioningCreateCredentialKey(&ctx_, challenge.data(), challenge.size(),
83 applicationId.data(), applicationId.size(),
84 publicKeyCert, &publicKeyCertSize)) {
85 return {};
86 }
87 vector<uint8_t> pubKeyCert(publicKeyCertSize);
88 memcpy(pubKeyCert.data(), publicKeyCert, publicKeyCertSize);
89 return pubKeyCert;
90}
91
92bool FakeSecureHardwareProvisioningProxy::startPersonalization(
93 int accessControlProfileCount, vector<int> entryCounts, const string& docType,
94 size_t expectedProofOfProvisioningSize) {
95 if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount, entryCounts.data(),
96 entryCounts.size(), docType.c_str(),
97 expectedProofOfProvisioningSize)) {
98 return false;
99 }
100 return true;
101}
102
103// Returns MAC (28 bytes).
104optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addAccessControlProfile(
105 int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
106 uint64_t timeoutMillis, uint64_t secureUserId) {
107 vector<uint8_t> mac(28);
108 if (!eicProvisioningAddAccessControlProfile(
109 &ctx_, id, readerCertificate.data(), readerCertificate.size(),
110 userAuthenticationRequired, timeoutMillis, secureUserId, mac.data())) {
111 return {};
112 }
113 return mac;
114}
115
116bool FakeSecureHardwareProvisioningProxy::beginAddEntry(const vector<int>& accessControlProfileIds,
117 const string& nameSpace, const string& name,
118 uint64_t entrySize) {
119 uint8_t scratchSpace[512];
120 return eicProvisioningBeginAddEntry(&ctx_, accessControlProfileIds.data(),
121 accessControlProfileIds.size(), nameSpace.c_str(),
122 name.c_str(), entrySize, scratchSpace, sizeof scratchSpace);
123}
124
125// Returns encryptedContent.
126optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addEntryValue(
127 const vector<int>& accessControlProfileIds, const string& nameSpace, const string& name,
128 const vector<uint8_t>& content) {
129 vector<uint8_t> eicEncryptedContent;
130 uint8_t scratchSpace[512];
131 eicEncryptedContent.resize(content.size() + 28);
132 if (!eicProvisioningAddEntryValue(
133 &ctx_, accessControlProfileIds.data(), accessControlProfileIds.size(),
134 nameSpace.c_str(), name.c_str(), content.data(), content.size(),
135 eicEncryptedContent.data(), scratchSpace, sizeof scratchSpace)) {
136 return {};
137 }
138 return eicEncryptedContent;
139}
140
141// Returns signatureOfToBeSigned (EIC_ECDSA_P256_SIGNATURE_SIZE bytes).
142optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishAddingEntries() {
143 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
144 if (!eicProvisioningFinishAddingEntries(&ctx_, signatureOfToBeSigned.data())) {
145 return {};
146 }
147 return signatureOfToBeSigned;
148}
149
David Zeuthen49f2d252020-10-16 11:27:24 -0400150// Returns encryptedCredentialKeys.
David Zeuthen630de2a2020-05-11 14:04:54 -0400151optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishGetCredentialData(
152 const string& docType) {
David Zeuthen49f2d252020-10-16 11:27:24 -0400153 vector<uint8_t> encryptedCredentialKeys(116);
154 size_t size = encryptedCredentialKeys.size();
David Zeuthen630de2a2020-05-11 14:04:54 -0400155 if (!eicProvisioningFinishGetCredentialData(&ctx_, docType.c_str(),
David Zeuthen49f2d252020-10-16 11:27:24 -0400156 encryptedCredentialKeys.data(), &size)) {
David Zeuthen630de2a2020-05-11 14:04:54 -0400157 return {};
158 }
David Zeuthen49f2d252020-10-16 11:27:24 -0400159 encryptedCredentialKeys.resize(size);
David Zeuthen630de2a2020-05-11 14:04:54 -0400160 return encryptedCredentialKeys;
161}
162
163// ----------------------------------------------------------------------
164
165FakeSecureHardwarePresentationProxy::FakeSecureHardwarePresentationProxy() {}
166
167FakeSecureHardwarePresentationProxy::~FakeSecureHardwarePresentationProxy() {}
168
169bool FakeSecureHardwarePresentationProxy::initialize(bool testCredential, string docType,
170 vector<uint8_t> encryptedCredentialKeys) {
171 LOG(INFO) << "FakeSecureHardwarePresentationProxy created, sizeof(EicPresentation): "
172 << sizeof(EicPresentation);
173 return eicPresentationInit(&ctx_, testCredential, docType.c_str(),
David Zeuthen49f2d252020-10-16 11:27:24 -0400174 encryptedCredentialKeys.data(), encryptedCredentialKeys.size());
David Zeuthen630de2a2020-05-11 14:04:54 -0400175}
176
177// Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
178optional<pair<vector<uint8_t>, vector<uint8_t>>>
179FakeSecureHardwarePresentationProxy::generateSigningKeyPair(string docType, time_t now) {
180 uint8_t publicKeyCert[512];
181 size_t publicKeyCertSize = sizeof(publicKeyCert);
182 vector<uint8_t> signingKeyBlob(60);
183
184 if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), now, publicKeyCert,
185 &publicKeyCertSize, signingKeyBlob.data())) {
186 return {};
187 }
188
189 vector<uint8_t> cert;
190 cert.resize(publicKeyCertSize);
191 memcpy(cert.data(), publicKeyCert, publicKeyCertSize);
192
193 return std::make_pair(cert, signingKeyBlob);
194}
195
196// Returns private key
197optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::createEphemeralKeyPair() {
198 vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
199 if (!eicPresentationCreateEphemeralKeyPair(&ctx_, priv.data())) {
200 return {};
201 }
202 return priv;
203}
204
205optional<uint64_t> FakeSecureHardwarePresentationProxy::createAuthChallenge() {
206 uint64_t challenge;
207 if (!eicPresentationCreateAuthChallenge(&ctx_, &challenge)) {
208 return {};
209 }
210 return challenge;
211}
212
213bool FakeSecureHardwarePresentationProxy::shutdown() {
214 LOG(INFO) << "FakeSecureHardwarePresentationProxy shutdown";
215 return true;
216}
217
218bool FakeSecureHardwarePresentationProxy::pushReaderCert(const vector<uint8_t>& certX509) {
219 return eicPresentationPushReaderCert(&ctx_, certX509.data(), certX509.size());
220}
221
222bool FakeSecureHardwarePresentationProxy::validateRequestMessage(
223 const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& requestMessage,
224 int coseSignAlg, const vector<uint8_t>& readerSignatureOfToBeSigned) {
225 return eicPresentationValidateRequestMessage(
226 &ctx_, sessionTranscript.data(), sessionTranscript.size(), requestMessage.data(),
227 requestMessage.size(), coseSignAlg, readerSignatureOfToBeSigned.data(),
228 readerSignatureOfToBeSigned.size());
229}
230
231bool FakeSecureHardwarePresentationProxy::setAuthToken(
232 uint64_t challenge, uint64_t secureUserId, uint64_t authenticatorId,
233 int hardwareAuthenticatorType, uint64_t timeStamp, const vector<uint8_t>& mac,
234 uint64_t verificationTokenChallenge, uint64_t verificationTokenTimestamp,
235 int verificationTokenSecurityLevel, const vector<uint8_t>& verificationTokenMac) {
236 return eicPresentationSetAuthToken(&ctx_, challenge, secureUserId, authenticatorId,
237 hardwareAuthenticatorType, timeStamp, mac.data(), mac.size(),
238 verificationTokenChallenge, verificationTokenTimestamp,
239 verificationTokenSecurityLevel, verificationTokenMac.data(),
240 verificationTokenMac.size());
241}
242
243optional<bool> FakeSecureHardwarePresentationProxy::validateAccessControlProfile(
244 int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired,
245 int timeoutMillis, uint64_t secureUserId, const vector<uint8_t>& mac) {
246 bool accessGranted = false;
247 if (!eicPresentationValidateAccessControlProfile(&ctx_, id, readerCertificate.data(),
248 readerCertificate.size(),
249 userAuthenticationRequired, timeoutMillis,
250 secureUserId, mac.data(), &accessGranted)) {
251 return {};
252 }
253 return accessGranted;
254}
255
256bool FakeSecureHardwarePresentationProxy::startRetrieveEntries() {
257 return eicPresentationStartRetrieveEntries(&ctx_);
258}
259
260bool FakeSecureHardwarePresentationProxy::calcMacKey(
261 const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& readerEphemeralPublicKey,
262 const vector<uint8_t>& signingKeyBlob, const string& docType,
263 unsigned int numNamespacesWithValues, size_t expectedProofOfProvisioningSize) {
264 if (signingKeyBlob.size() != 60) {
265 eicDebug("Unexpected size %zd of signingKeyBlob, expected 60", signingKeyBlob.size());
266 return false;
267 }
268 return eicPresentationCalcMacKey(&ctx_, sessionTranscript.data(), sessionTranscript.size(),
269 readerEphemeralPublicKey.data(), signingKeyBlob.data(),
270 docType.c_str(), numNamespacesWithValues,
271 expectedProofOfProvisioningSize);
272}
273
274AccessCheckResult FakeSecureHardwarePresentationProxy::startRetrieveEntryValue(
275 const string& nameSpace, const string& name, unsigned int newNamespaceNumEntries,
276 int32_t entrySize, const vector<int32_t>& accessControlProfileIds) {
277 uint8_t scratchSpace[512];
278 EicAccessCheckResult result = eicPresentationStartRetrieveEntryValue(
279 &ctx_, nameSpace.c_str(), name.c_str(), newNamespaceNumEntries, entrySize,
280 accessControlProfileIds.data(), accessControlProfileIds.size(), scratchSpace,
281 sizeof scratchSpace);
282 switch (result) {
283 case EIC_ACCESS_CHECK_RESULT_OK:
284 return AccessCheckResult::kOk;
285 case EIC_ACCESS_CHECK_RESULT_NO_ACCESS_CONTROL_PROFILES:
286 return AccessCheckResult::kNoAccessControlProfiles;
287 case EIC_ACCESS_CHECK_RESULT_FAILED:
288 return AccessCheckResult::kFailed;
289 case EIC_ACCESS_CHECK_RESULT_USER_AUTHENTICATION_FAILED:
290 return AccessCheckResult::kUserAuthenticationFailed;
291 case EIC_ACCESS_CHECK_RESULT_READER_AUTHENTICATION_FAILED:
292 return AccessCheckResult::kReaderAuthenticationFailed;
293 }
294 eicDebug("Unknown result with code %d, returning kFailed", (int)result);
295 return AccessCheckResult::kFailed;
296}
297
298optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::retrieveEntryValue(
299 const vector<uint8_t>& encryptedContent, const string& nameSpace, const string& name,
300 const vector<int32_t>& accessControlProfileIds) {
301 uint8_t scratchSpace[512];
302 vector<uint8_t> content;
303 content.resize(encryptedContent.size() - 28);
304 if (!eicPresentationRetrieveEntryValue(
305 &ctx_, encryptedContent.data(), encryptedContent.size(), content.data(),
306 nameSpace.c_str(), name.c_str(), accessControlProfileIds.data(),
307 accessControlProfileIds.size(), scratchSpace, sizeof scratchSpace)) {
308 return {};
309 }
310 return content;
311}
312
313optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::finishRetrieval() {
314 vector<uint8_t> mac(32);
315 size_t macSize = 32;
316 if (!eicPresentationFinishRetrieval(&ctx_, mac.data(), &macSize)) {
317 return {};
318 }
319 mac.resize(macSize);
320 return mac;
321}
322
323optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::deleteCredential(
David Zeuthen49f2d252020-10-16 11:27:24 -0400324 const string& docType, const vector<uint8_t>& challenge, bool includeChallenge,
325 size_t proofOfDeletionCborSize) {
David Zeuthen630de2a2020-05-11 14:04:54 -0400326 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
David Zeuthen49f2d252020-10-16 11:27:24 -0400327 if (!eicPresentationDeleteCredential(&ctx_, docType.c_str(), challenge.data(), challenge.size(),
328 includeChallenge, proofOfDeletionCborSize,
David Zeuthen630de2a2020-05-11 14:04:54 -0400329 signatureOfToBeSigned.data())) {
330 return {};
331 }
332 return signatureOfToBeSigned;
333}
334
David Zeuthen49f2d252020-10-16 11:27:24 -0400335optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::proveOwnership(
336 const string& docType, bool testCredential, const vector<uint8_t>& challenge,
337 size_t proofOfOwnershipCborSize) {
338 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
339 if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), testCredential, challenge.data(),
340 challenge.size(), proofOfOwnershipCborSize,
341 signatureOfToBeSigned.data())) {
342 return {};
343 }
344 return signatureOfToBeSigned;
345}
346
David Zeuthen630de2a2020-05-11 14:04:54 -0400347} // namespace android::hardware::identity