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