1 /*
2 * Copyright 2021, 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 "RemoteSecureHardwareProxy"
18
19 #include "RemoteSecureHardwareProxy.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
46 using ::std::optional;
47 using ::std::string;
48 using ::std::tuple;
49 using ::std::vector;
50
51 namespace android::hardware::identity {
52
53 // ----------------------------------------------------------------------
54
RemoteSecureHardwareProvisioningProxy()55 RemoteSecureHardwareProvisioningProxy::RemoteSecureHardwareProvisioningProxy() {
56 }
57
58 RemoteSecureHardwareProvisioningProxy::
~RemoteSecureHardwareProvisioningProxy()59 ~RemoteSecureHardwareProvisioningProxy() {}
60
shutdown()61 bool RemoteSecureHardwareProvisioningProxy::shutdown() {
62 LOG(INFO) << "RemoteSecureHardwarePresentationProxy shutdown";
63 return true;
64 }
65
initialize(bool testCredential)66 bool RemoteSecureHardwareProvisioningProxy::initialize(bool testCredential) {
67 LOG(INFO) << "RemoteSecureHardwareProvisioningProxy created, "
68 "sizeof(EicProvisioning): "
69 << sizeof(EicProvisioning);
70 return eicProvisioningInit(&ctx_, testCredential);
71 }
72
initializeForUpdate(bool testCredential,string docType,vector<uint8_t> encryptedCredentialKeys)73 bool RemoteSecureHardwareProvisioningProxy::initializeForUpdate(
74 bool testCredential, string docType,
75 vector<uint8_t> encryptedCredentialKeys) {
76 return eicProvisioningInitForUpdate(
77 &ctx_, testCredential, docType.c_str(), docType.size(),
78 encryptedCredentialKeys.data(), encryptedCredentialKeys.size());
79 }
80
81 // Returns public key certificate.
82 optional<vector<uint8_t>>
createCredentialKey(const vector<uint8_t> & challenge,const vector<uint8_t> & applicationId)83 RemoteSecureHardwareProvisioningProxy::createCredentialKey(
84 const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
85 uint8_t publicKeyCert[4096];
86 size_t publicKeyCertSize = sizeof publicKeyCert;
87 if (!eicProvisioningCreateCredentialKey(
88 &ctx_, challenge.data(), challenge.size(), applicationId.data(),
89 applicationId.size(), publicKeyCert, &publicKeyCertSize)) {
90 return {};
91 }
92 vector<uint8_t> pubKeyCert(publicKeyCertSize);
93 memcpy(pubKeyCert.data(), publicKeyCert, publicKeyCertSize);
94 return pubKeyCert;
95 }
96
startPersonalization(int accessControlProfileCount,vector<int> entryCounts,const string & docType,size_t expectedProofOfProvisioningSize)97 bool RemoteSecureHardwareProvisioningProxy::startPersonalization(
98 int accessControlProfileCount, vector<int> entryCounts,
99 const string& docType, size_t expectedProofOfProvisioningSize) {
100 if (!eicProvisioningStartPersonalization(
101 &ctx_, accessControlProfileCount, entryCounts.data(),
102 entryCounts.size(), docType.c_str(), docType.size(),
103 expectedProofOfProvisioningSize)) {
104 return false;
105 }
106 return true;
107 }
108
109 // Returns MAC (28 bytes).
110 optional<vector<uint8_t>>
addAccessControlProfile(int id,const vector<uint8_t> & readerCertificate,bool userAuthenticationRequired,uint64_t timeoutMillis,uint64_t secureUserId)111 RemoteSecureHardwareProvisioningProxy::addAccessControlProfile(
112 int id, const vector<uint8_t>& readerCertificate,
113 bool userAuthenticationRequired, uint64_t timeoutMillis,
114 uint64_t secureUserId) {
115 vector<uint8_t> mac(28);
116 uint8_t scratchSpace[512];
117 if (!eicProvisioningAddAccessControlProfile(
118 &ctx_, id, readerCertificate.data(), readerCertificate.size(),
119 userAuthenticationRequired, timeoutMillis, secureUserId, mac.data(),
120 scratchSpace, sizeof(scratchSpace))) {
121 return {};
122 }
123 return mac;
124 }
125
beginAddEntry(const vector<int> & accessControlProfileIds,const string & nameSpace,const string & name,uint64_t entrySize)126 bool RemoteSecureHardwareProvisioningProxy::beginAddEntry(
127 const vector<int>& accessControlProfileIds, const string& nameSpace,
128 const string& name, uint64_t entrySize) {
129 uint8_t scratchSpace[512];
130 vector<uint8_t> uint8AccessControlProfileIds;
131 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
132 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
133 }
134
135 return eicProvisioningBeginAddEntry(
136 &ctx_, uint8AccessControlProfileIds.data(),
137 uint8AccessControlProfileIds.size(), nameSpace.c_str(), nameSpace.size(),
138 name.c_str(), name.size(), entrySize, scratchSpace, sizeof(scratchSpace));
139 }
140
141 // Returns encryptedContent.
addEntryValue(const vector<int> & accessControlProfileIds,const string & nameSpace,const string & name,const vector<uint8_t> & content)142 optional<vector<uint8_t>> RemoteSecureHardwareProvisioningProxy::addEntryValue(
143 const vector<int>& accessControlProfileIds, const string& nameSpace,
144 const string& name, const vector<uint8_t>& content) {
145 vector<uint8_t> eicEncryptedContent;
146 uint8_t scratchSpace[512];
147 vector<uint8_t> uint8AccessControlProfileIds;
148 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
149 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
150 }
151
152 eicEncryptedContent.resize(content.size() + 28);
153 if (!eicProvisioningAddEntryValue(&ctx_, uint8AccessControlProfileIds.data(),
154 uint8AccessControlProfileIds.size(),
155 nameSpace.c_str(), nameSpace.size(),
156 name.c_str(), name.size(), content.data(),
157 content.size(), eicEncryptedContent.data(),
158 scratchSpace, sizeof(scratchSpace))) {
159 return {};
160 }
161 return eicEncryptedContent;
162 }
163
164 // Returns signatureOfToBeSigned (EIC_ECDSA_P256_SIGNATURE_SIZE bytes).
165 optional<vector<uint8_t>>
finishAddingEntries()166 RemoteSecureHardwareProvisioningProxy::finishAddingEntries() {
167 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
168 if (!eicProvisioningFinishAddingEntries(&ctx_,
169 signatureOfToBeSigned.data())) {
170 return {};
171 }
172 return signatureOfToBeSigned;
173 }
174
175 // Returns encryptedCredentialKeys.
176 optional<vector<uint8_t>>
finishGetCredentialData(const string & docType)177 RemoteSecureHardwareProvisioningProxy::finishGetCredentialData(
178 const string& docType) {
179 vector<uint8_t> encryptedCredentialKeys(116);
180 size_t size = encryptedCredentialKeys.size();
181 if (!eicProvisioningFinishGetCredentialData(
182 &ctx_, docType.c_str(), docType.size(),
183 encryptedCredentialKeys.data(), &size)) {
184 return {};
185 }
186 encryptedCredentialKeys.resize(size);
187 return encryptedCredentialKeys;
188 }
189
190 // ----------------------------------------------------------------------
191
RemoteSecureHardwarePresentationProxy()192 RemoteSecureHardwarePresentationProxy::RemoteSecureHardwarePresentationProxy() {
193 }
194
195 RemoteSecureHardwarePresentationProxy::
~RemoteSecureHardwarePresentationProxy()196 ~RemoteSecureHardwarePresentationProxy() {}
197
initialize(bool testCredential,string docType,vector<uint8_t> encryptedCredentialKeys)198 bool RemoteSecureHardwarePresentationProxy::initialize(
199 bool testCredential, string docType,
200 vector<uint8_t> encryptedCredentialKeys) {
201 LOG(INFO) << "RemoteSecureHardwarePresentationProxy created, "
202 "sizeof(EicPresentation): "
203 << sizeof(EicPresentation);
204 return eicPresentationInit(&ctx_, testCredential, docType.c_str(),
205 docType.size(), encryptedCredentialKeys.data(),
206 encryptedCredentialKeys.size());
207 }
208
209 // Returns publicKeyCert (1st component) and signingKeyBlob (2nd component)
210 optional<pair<vector<uint8_t>, vector<uint8_t>>>
generateSigningKeyPair(string docType,time_t now)211 RemoteSecureHardwarePresentationProxy::generateSigningKeyPair(string docType,
212 time_t now) {
213 uint8_t publicKeyCert[512];
214 size_t publicKeyCertSize = sizeof(publicKeyCert);
215 vector<uint8_t> signingKeyBlob(60);
216
217 if (!eicPresentationGenerateSigningKeyPair(
218 &ctx_, docType.c_str(), docType.size(), now, publicKeyCert,
219 &publicKeyCertSize, signingKeyBlob.data())) {
220 return {};
221 }
222
223 vector<uint8_t> cert;
224 cert.resize(publicKeyCertSize);
225 memcpy(cert.data(), publicKeyCert, publicKeyCertSize);
226
227 return std::make_pair(cert, signingKeyBlob);
228 }
229
230 // Returns private key
231 optional<vector<uint8_t>>
createEphemeralKeyPair()232 RemoteSecureHardwarePresentationProxy::createEphemeralKeyPair() {
233 vector<uint8_t> priv(EIC_P256_PRIV_KEY_SIZE);
234 if (!eicPresentationCreateEphemeralKeyPair(&ctx_, priv.data())) {
235 return {};
236 }
237 return priv;
238 }
239
240 optional<uint64_t>
createAuthChallenge()241 RemoteSecureHardwarePresentationProxy::createAuthChallenge() {
242 uint64_t challenge;
243 if (!eicPresentationCreateAuthChallenge(&ctx_, &challenge)) {
244 return {};
245 }
246 return challenge;
247 }
248
shutdown()249 bool RemoteSecureHardwarePresentationProxy::shutdown() {
250 LOG(INFO) << "RemoteSecureHardwarePresentationProxy shutdown";
251 return true;
252 }
253
pushReaderCert(const vector<uint8_t> & certX509)254 bool RemoteSecureHardwarePresentationProxy::pushReaderCert(
255 const vector<uint8_t>& certX509) {
256 return eicPresentationPushReaderCert(&ctx_, certX509.data(), certX509.size());
257 }
258
validateRequestMessage(const vector<uint8_t> & sessionTranscript,const vector<uint8_t> & requestMessage,int coseSignAlg,const vector<uint8_t> & readerSignatureOfToBeSigned)259 bool RemoteSecureHardwarePresentationProxy::validateRequestMessage(
260 const vector<uint8_t>& sessionTranscript,
261 const vector<uint8_t>& requestMessage, int coseSignAlg,
262 const vector<uint8_t>& readerSignatureOfToBeSigned) {
263 return eicPresentationValidateRequestMessage(
264 &ctx_, sessionTranscript.data(), sessionTranscript.size(),
265 requestMessage.data(), requestMessage.size(), coseSignAlg,
266 readerSignatureOfToBeSigned.data(), readerSignatureOfToBeSigned.size());
267 }
268
setAuthToken(uint64_t challenge,uint64_t secureUserId,uint64_t authenticatorId,int hardwareAuthenticatorType,uint64_t timeStamp,const vector<uint8_t> & mac,uint64_t verificationTokenChallenge,uint64_t verificationTokenTimestamp,int verificationTokenSecurityLevel,const vector<uint8_t> & verificationTokenMac)269 bool RemoteSecureHardwarePresentationProxy::setAuthToken(
270 uint64_t challenge, uint64_t secureUserId, uint64_t authenticatorId,
271 int hardwareAuthenticatorType, uint64_t timeStamp,
272 const vector<uint8_t>& mac, uint64_t verificationTokenChallenge,
273 uint64_t verificationTokenTimestamp, int verificationTokenSecurityLevel,
274 const vector<uint8_t>& verificationTokenMac) {
275 return eicPresentationSetAuthToken(
276 &ctx_, challenge, secureUserId, authenticatorId,
277 hardwareAuthenticatorType, timeStamp, mac.data(), mac.size(),
278 verificationTokenChallenge, verificationTokenTimestamp,
279 verificationTokenSecurityLevel, verificationTokenMac.data(),
280 verificationTokenMac.size());
281 }
282
283 optional<bool>
validateAccessControlProfile(int id,const vector<uint8_t> & readerCertificate,bool userAuthenticationRequired,int timeoutMillis,uint64_t secureUserId,const vector<uint8_t> & mac)284 RemoteSecureHardwarePresentationProxy::validateAccessControlProfile(
285 int id, const vector<uint8_t>& readerCertificate,
286 bool userAuthenticationRequired, int timeoutMillis, uint64_t secureUserId,
287 const vector<uint8_t>& mac) {
288 bool accessGranted = false;
289 uint8_t scratchSpace[512];
290 if (!eicPresentationValidateAccessControlProfile(
291 &ctx_, id, readerCertificate.data(), readerCertificate.size(),
292 userAuthenticationRequired, timeoutMillis, secureUserId, mac.data(),
293 &accessGranted, scratchSpace, sizeof(scratchSpace))) {
294 return {};
295 }
296 return accessGranted;
297 }
298
startRetrieveEntries()299 bool RemoteSecureHardwarePresentationProxy::startRetrieveEntries() {
300 return eicPresentationStartRetrieveEntries(&ctx_);
301 }
302
calcMacKey(const vector<uint8_t> & sessionTranscript,const vector<uint8_t> & readerEphemeralPublicKey,const vector<uint8_t> & signingKeyBlob,const string & docType,unsigned int numNamespacesWithValues,size_t expectedProofOfProvisioningSize)303 bool RemoteSecureHardwarePresentationProxy::calcMacKey(
304 const vector<uint8_t>& sessionTranscript,
305 const vector<uint8_t>& readerEphemeralPublicKey,
306 const vector<uint8_t>& signingKeyBlob, const string& docType,
307 unsigned int numNamespacesWithValues,
308 size_t expectedProofOfProvisioningSize) {
309 if (signingKeyBlob.size() != 60) {
310 eicDebug("Unexpected size %zd of signingKeyBlob, expected 60",
311 signingKeyBlob.size());
312 return false;
313 }
314 return eicPresentationCalcMacKey(
315 &ctx_, sessionTranscript.data(), sessionTranscript.size(),
316 readerEphemeralPublicKey.data(), signingKeyBlob.data(), docType.c_str(),
317 docType.size(), numNamespacesWithValues, expectedProofOfProvisioningSize);
318 }
319
320 AccessCheckResult
startRetrieveEntryValue(const string & nameSpace,const string & name,unsigned int newNamespaceNumEntries,int32_t entrySize,const vector<int32_t> & accessControlProfileIds)321 RemoteSecureHardwarePresentationProxy::startRetrieveEntryValue(
322 const string& nameSpace, const string& name,
323 unsigned int newNamespaceNumEntries, int32_t entrySize,
324 const vector<int32_t>& accessControlProfileIds) {
325 uint8_t scratchSpace[512];
326 vector<uint8_t> uint8AccessControlProfileIds;
327 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
328 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
329 }
330
331 EicAccessCheckResult result = eicPresentationStartRetrieveEntryValue(
332 &ctx_, nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(),
333 newNamespaceNumEntries, entrySize, uint8AccessControlProfileIds.data(),
334 uint8AccessControlProfileIds.size(), scratchSpace, sizeof(scratchSpace));
335 switch (result) {
336 case EIC_ACCESS_CHECK_RESULT_OK:
337 return AccessCheckResult::kOk;
338 case EIC_ACCESS_CHECK_RESULT_NO_ACCESS_CONTROL_PROFILES:
339 return AccessCheckResult::kNoAccessControlProfiles;
340 case EIC_ACCESS_CHECK_RESULT_FAILED:
341 return AccessCheckResult::kFailed;
342 case EIC_ACCESS_CHECK_RESULT_USER_AUTHENTICATION_FAILED:
343 return AccessCheckResult::kUserAuthenticationFailed;
344 case EIC_ACCESS_CHECK_RESULT_READER_AUTHENTICATION_FAILED:
345 return AccessCheckResult::kReaderAuthenticationFailed;
346 }
347 eicDebug("Unknown result with code %d, returning kFailed", (int)result);
348 return AccessCheckResult::kFailed;
349 }
350
351 optional<vector<uint8_t>>
retrieveEntryValue(const vector<uint8_t> & encryptedContent,const string & nameSpace,const string & name,const vector<int32_t> & accessControlProfileIds)352 RemoteSecureHardwarePresentationProxy::retrieveEntryValue(
353 const vector<uint8_t>& encryptedContent, const string& nameSpace,
354 const string& name, const vector<int32_t>& accessControlProfileIds) {
355 uint8_t scratchSpace[512];
356 vector<uint8_t> uint8AccessControlProfileIds;
357 for (size_t i = 0; i < accessControlProfileIds.size(); i++) {
358 uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF);
359 }
360
361 vector<uint8_t> content;
362 content.resize(encryptedContent.size() - 28);
363 if (!eicPresentationRetrieveEntryValue(
364 &ctx_, encryptedContent.data(), encryptedContent.size(),
365 content.data(), nameSpace.c_str(), nameSpace.size(), name.c_str(),
366 name.size(), uint8AccessControlProfileIds.data(),
367 uint8AccessControlProfileIds.size(), scratchSpace,
368 sizeof(scratchSpace))) {
369 return {};
370 }
371 return content;
372 }
373
374 optional<vector<uint8_t>>
finishRetrieval()375 RemoteSecureHardwarePresentationProxy::finishRetrieval() {
376 vector<uint8_t> mac(32);
377 size_t macSize = 32;
378 if (!eicPresentationFinishRetrieval(&ctx_, mac.data(), &macSize)) {
379 return {};
380 }
381 mac.resize(macSize);
382 return mac;
383 }
384
385 optional<vector<uint8_t>>
deleteCredential(const string & docType,const vector<uint8_t> & challenge,bool includeChallenge,size_t proofOfDeletionCborSize)386 RemoteSecureHardwarePresentationProxy::deleteCredential(
387 const string& docType, const vector<uint8_t>& challenge,
388 bool includeChallenge, size_t proofOfDeletionCborSize) {
389 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
390 if (!eicPresentationDeleteCredential(
391 &ctx_, docType.c_str(), docType.size(), challenge.data(),
392 challenge.size(), includeChallenge, proofOfDeletionCborSize,
393 signatureOfToBeSigned.data())) {
394 return {};
395 }
396 return signatureOfToBeSigned;
397 }
398
proveOwnership(const string & docType,bool testCredential,const vector<uint8_t> & challenge,size_t proofOfOwnershipCborSize)399 optional<vector<uint8_t>> RemoteSecureHardwarePresentationProxy::proveOwnership(
400 const string& docType, bool testCredential,
401 const vector<uint8_t>& challenge, size_t proofOfOwnershipCborSize) {
402 vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE);
403 if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), docType.size(),
404 testCredential, challenge.data(),
405 challenge.size(), proofOfOwnershipCborSize,
406 signatureOfToBeSigned.data())) {
407 return {};
408 }
409 return signatureOfToBeSigned;
410 }
411
412 } // namespace android::hardware::identity
413