1 /*
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 "EicOpsImpl"
18 
19 #include <optional>
20 #include <tuple>
21 #include <vector>
22 
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <string.h>
26 
27 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
28 
29 #include <openssl/sha.h>
30 
31 #include <openssl/aes.h>
32 #include <openssl/bn.h>
33 #include <openssl/crypto.h>
34 #include <openssl/ec.h>
35 #include <openssl/err.h>
36 #include <openssl/evp.h>
37 #include <openssl/hkdf.h>
38 #include <openssl/hmac.h>
39 #include <openssl/objects.h>
40 #include <openssl/pem.h>
41 #include <openssl/pkcs12.h>
42 #include <openssl/rand.h>
43 #include <openssl/x509.h>
44 #include <openssl/x509_vfy.h>
45 
46 #include "EicOps.h"
47 
48 using ::std::map;
49 using ::std::optional;
50 using ::std::string;
51 using ::std::tuple;
52 using ::std::vector;
53 
eicMemSet(void * s,int c,size_t n)54 void* eicMemSet(void* s, int c, size_t n) {
55     return memset(s, c, n);
56 }
57 
eicMemCpy(void * dest,const void * src,size_t n)58 void* eicMemCpy(void* dest, const void* src, size_t n) {
59     return memcpy(dest, src, n);
60 }
61 
eicStrLen(const char * s)62 size_t eicStrLen(const char* s) {
63     return strlen(s);
64 }
65 
eicCryptoMemCmp(const void * s1,const void * s2,size_t n)66 int eicCryptoMemCmp(const void* s1, const void* s2, size_t n) {
67     return CRYPTO_memcmp(s1, s2, n);
68 }
69 
eicOpsHmacSha256Init(EicHmacSha256Ctx * ctx,const uint8_t * key,size_t keySize)70 void eicOpsHmacSha256Init(EicHmacSha256Ctx* ctx, const uint8_t* key, size_t keySize) {
71     HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
72     HMAC_CTX_init(realCtx);
73     if (HMAC_Init_ex(realCtx, key, keySize, EVP_sha256(), nullptr /* impl */) != 1) {
74         LOG(ERROR) << "Error initializing HMAC_CTX";
75     }
76 }
77 
eicOpsHmacSha256Update(EicHmacSha256Ctx * ctx,const uint8_t * data,size_t len)78 void eicOpsHmacSha256Update(EicHmacSha256Ctx* ctx, const uint8_t* data, size_t len) {
79     HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
80     if (HMAC_Update(realCtx, data, len) != 1) {
81         LOG(ERROR) << "Error updating HMAC_CTX";
82     }
83 }
84 
eicOpsHmacSha256Final(EicHmacSha256Ctx * ctx,uint8_t digest[EIC_SHA256_DIGEST_SIZE])85 void eicOpsHmacSha256Final(EicHmacSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]) {
86     HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
87     unsigned int size = 0;
88     if (HMAC_Final(realCtx, digest, &size) != 1) {
89         LOG(ERROR) << "Error finalizing HMAC_CTX";
90     }
91     if (size != EIC_SHA256_DIGEST_SIZE) {
92         LOG(ERROR) << "Expected 32 bytes from HMAC_Final, got " << size;
93     }
94 }
95 
eicOpsSha256Init(EicSha256Ctx * ctx)96 void eicOpsSha256Init(EicSha256Ctx* ctx) {
97     SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
98     SHA256_Init(realCtx);
99 }
100 
eicOpsSha256Update(EicSha256Ctx * ctx,const uint8_t * data,size_t len)101 void eicOpsSha256Update(EicSha256Ctx* ctx, const uint8_t* data, size_t len) {
102     SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
103     SHA256_Update(realCtx, data, len);
104 }
105 
eicOpsSha256Final(EicSha256Ctx * ctx,uint8_t digest[EIC_SHA256_DIGEST_SIZE])106 void eicOpsSha256Final(EicSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]) {
107     SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
108     SHA256_Final(digest, realCtx);
109 }
110 
eicOpsRandom(uint8_t * buf,size_t numBytes)111 bool eicOpsRandom(uint8_t* buf, size_t numBytes) {
112     optional<vector<uint8_t>> bytes = ::android::hardware::identity::support::getRandom(numBytes);
113     if (!bytes.has_value()) {
114         return false;
115     }
116     memcpy(buf, bytes.value().data(), numBytes);
117     return true;
118 }
119 
eicOpsEncryptAes128Gcm(const uint8_t * key,const uint8_t * nonce,const uint8_t * data,size_t dataSize,const uint8_t * additionalAuthenticationData,size_t additionalAuthenticationDataSize,uint8_t * encryptedData)120 bool eicOpsEncryptAes128Gcm(
121         const uint8_t* key,    // Must be 16 bytes
122         const uint8_t* nonce,  // Must be 12 bytes
123         const uint8_t* data,   // May be NULL if size is 0
124         size_t dataSize,
125         const uint8_t* additionalAuthenticationData,  // May be NULL if size is 0
126         size_t additionalAuthenticationDataSize, uint8_t* encryptedData) {
127     vector<uint8_t> cppKey;
128     cppKey.resize(16);
129     memcpy(cppKey.data(), key, 16);
130 
131     vector<uint8_t> cppData;
132     cppData.resize(dataSize);
133     if (dataSize > 0) {
134         memcpy(cppData.data(), data, dataSize);
135     }
136 
137     vector<uint8_t> cppAAD;
138     cppAAD.resize(additionalAuthenticationDataSize);
139     if (additionalAuthenticationDataSize > 0) {
140         memcpy(cppAAD.data(), additionalAuthenticationData, additionalAuthenticationDataSize);
141     }
142 
143     vector<uint8_t> cppNonce;
144     cppNonce.resize(12);
145     memcpy(cppNonce.data(), nonce, 12);
146 
147     optional<vector<uint8_t>> cppEncryptedData =
148             android::hardware::identity::support::encryptAes128Gcm(cppKey, cppNonce, cppData,
149                                                                    cppAAD);
150     if (!cppEncryptedData.has_value()) {
151         return false;
152     }
153 
154     memcpy(encryptedData, cppEncryptedData.value().data(), cppEncryptedData.value().size());
155     return true;
156 }
157 
158 // Decrypts |encryptedData| using |key| and |additionalAuthenticatedData|,
159 // returns resulting plaintext in |data| must be of size |encryptedDataSize| - 28.
160 //
161 // The format of |encryptedData| must be as specified in the
162 // encryptAes128Gcm() function.
eicOpsDecryptAes128Gcm(const uint8_t * key,const uint8_t * encryptedData,size_t encryptedDataSize,const uint8_t * additionalAuthenticationData,size_t additionalAuthenticationDataSize,uint8_t * data)163 bool eicOpsDecryptAes128Gcm(const uint8_t* key,  // Must be 16 bytes
164                             const uint8_t* encryptedData, size_t encryptedDataSize,
165                             const uint8_t* additionalAuthenticationData,
166                             size_t additionalAuthenticationDataSize, uint8_t* data) {
167     vector<uint8_t> keyVec;
168     keyVec.resize(16);
169     memcpy(keyVec.data(), key, 16);
170 
171     vector<uint8_t> encryptedDataVec;
172     encryptedDataVec.resize(encryptedDataSize);
173     if (encryptedDataSize > 0) {
174         memcpy(encryptedDataVec.data(), encryptedData, encryptedDataSize);
175     }
176 
177     vector<uint8_t> aadVec;
178     aadVec.resize(additionalAuthenticationDataSize);
179     if (additionalAuthenticationDataSize > 0) {
180         memcpy(aadVec.data(), additionalAuthenticationData, additionalAuthenticationDataSize);
181     }
182 
183     optional<vector<uint8_t>> decryptedDataVec =
184             android::hardware::identity::support::decryptAes128Gcm(keyVec, encryptedDataVec,
185                                                                    aadVec);
186     if (!decryptedDataVec.has_value()) {
187         eicDebug("Error decrypting data");
188         return false;
189     }
190     if (decryptedDataVec.value().size() != encryptedDataSize - 28) {
191         eicDebug("Decrypted data is size %zd, expected %zd", decryptedDataVec.value().size(),
192                  encryptedDataSize - 28);
193         return false;
194     }
195 
196     if (decryptedDataVec.value().size() > 0) {
197         memcpy(data, decryptedDataVec.value().data(), decryptedDataVec.value().size());
198     }
199     return true;
200 }
201 
eicOpsCreateEcKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],uint8_t publicKey[EIC_P256_PUB_KEY_SIZE])202 bool eicOpsCreateEcKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],
203                        uint8_t publicKey[EIC_P256_PUB_KEY_SIZE]) {
204     optional<vector<uint8_t>> keyPair = android::hardware::identity::support::createEcKeyPair();
205     if (!keyPair) {
206         eicDebug("Error creating EC keypair");
207         return false;
208     }
209     optional<vector<uint8_t>> privKey =
210             android::hardware::identity::support::ecKeyPairGetPrivateKey(keyPair.value());
211     if (!privKey) {
212         eicDebug("Error extracting private key");
213         return false;
214     }
215     if (privKey.value().size() != EIC_P256_PRIV_KEY_SIZE) {
216         eicDebug("Private key is %zd bytes, expected %zd", privKey.value().size(),
217                  (size_t)EIC_P256_PRIV_KEY_SIZE);
218         return false;
219     }
220 
221     optional<vector<uint8_t>> pubKey =
222             android::hardware::identity::support::ecKeyPairGetPublicKey(keyPair.value());
223     if (!pubKey) {
224         eicDebug("Error extracting public key");
225         return false;
226     }
227     // ecKeyPairGetPublicKey() returns 0x04 | x | y, we don't want the leading 0x04.
228     if (pubKey.value().size() != EIC_P256_PUB_KEY_SIZE + 1) {
229         eicDebug("Public key is %zd bytes long, expected %zd", pubKey.value().size(),
230                  (size_t)EIC_P256_PRIV_KEY_SIZE + 1);
231         return false;
232     }
233 
234     memcpy(privateKey, privKey.value().data(), EIC_P256_PRIV_KEY_SIZE);
235     memcpy(publicKey, pubKey.value().data() + 1, EIC_P256_PUB_KEY_SIZE);
236 
237     return true;
238 }
239 
eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],const uint8_t * challenge,size_t challengeSize,const uint8_t * applicationId,size_t applicationIdSize,bool testCredential,uint8_t * cert,size_t * certSize)240 bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge,
241                                size_t challengeSize, const uint8_t* applicationId,
242                                size_t applicationIdSize, bool testCredential, uint8_t* cert,
243                                size_t* certSize) {
244     vector<uint8_t> challengeVec(challengeSize);
245     memcpy(challengeVec.data(), challenge, challengeSize);
246 
247     vector<uint8_t> applicationIdVec(applicationIdSize);
248     memcpy(applicationIdVec.data(), applicationId, applicationIdSize);
249 
250     optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> ret =
251             android::hardware::identity::support::createEcKeyPairAndAttestation(
252                     challengeVec, applicationIdVec, testCredential);
253     if (!ret) {
254         eicDebug("Error generating CredentialKey and attestation");
255         return false;
256     }
257 
258     // Extract certificate chain.
259     vector<uint8_t> flatChain =
260             android::hardware::identity::support::certificateChainJoin(ret.value().second);
261     if (*certSize < flatChain.size()) {
262         eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
263                  flatChain.size());
264         return false;
265     }
266     memcpy(cert, flatChain.data(), flatChain.size());
267     *certSize = flatChain.size();
268 
269     // Extract private key.
270     optional<vector<uint8_t>> privKey =
271             android::hardware::identity::support::ecKeyPairGetPrivateKey(ret.value().first);
272     if (!privKey) {
273         eicDebug("Error extracting private key");
274         return false;
275     }
276     if (privKey.value().size() != EIC_P256_PRIV_KEY_SIZE) {
277         eicDebug("Private key is %zd bytes, expected %zd", privKey.value().size(),
278                  (size_t)EIC_P256_PRIV_KEY_SIZE);
279         return false;
280     }
281 
282     memcpy(privateKey, privKey.value().data(), EIC_P256_PRIV_KEY_SIZE);
283 
284     return true;
285 }
286 
eicOpsSignEcKey(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE],const uint8_t signingKey[EIC_P256_PRIV_KEY_SIZE],unsigned int serial,const char * issuerName,const char * subjectName,time_t validityNotBefore,time_t validityNotAfter,const uint8_t * proofOfBinding,size_t proofOfBindingSize,uint8_t * cert,size_t * certSize)287 bool eicOpsSignEcKey(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE],
288                      const uint8_t signingKey[EIC_P256_PRIV_KEY_SIZE], unsigned int serial,
289                      const char* issuerName, const char* subjectName, time_t validityNotBefore,
290                      time_t validityNotAfter, const uint8_t* proofOfBinding,
291                      size_t proofOfBindingSize, uint8_t* cert, size_t* certSize) {  // inout
292     vector<uint8_t> signingKeyVec(EIC_P256_PRIV_KEY_SIZE);
293     memcpy(signingKeyVec.data(), signingKey, EIC_P256_PRIV_KEY_SIZE);
294 
295     vector<uint8_t> pubKeyVec(EIC_P256_PUB_KEY_SIZE + 1);
296     pubKeyVec[0] = 0x04;
297     memcpy(pubKeyVec.data() + 1, publicKey, EIC_P256_PUB_KEY_SIZE);
298 
299     string serialDecimal = android::base::StringPrintf("%d", serial);
300 
301     map<string, vector<uint8_t>> extensions;
302     if (proofOfBinding != nullptr) {
303         vector<uint8_t> proofOfBindingVec(proofOfBinding, proofOfBinding + proofOfBindingSize);
304         extensions["1.3.6.1.4.1.11129.2.1.26"] = proofOfBindingVec;
305     }
306 
307     optional<vector<uint8_t>> certVec =
308             android::hardware::identity::support::ecPublicKeyGenerateCertificate(
309                     pubKeyVec, signingKeyVec, serialDecimal, issuerName, subjectName,
310                     validityNotBefore, validityNotAfter, extensions);
311     if (!certVec) {
312         eicDebug("Error generating certificate");
313         return false;
314     }
315 
316     if (*certSize < certVec.value().size()) {
317         eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
318                  certVec.value().size());
319         return false;
320     }
321     memcpy(cert, certVec.value().data(), certVec.value().size());
322     *certSize = certVec.value().size();
323 
324     return true;
325 }
326 
eicOpsEcDsa(const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],const uint8_t digestOfData[EIC_SHA256_DIGEST_SIZE],uint8_t signature[EIC_ECDSA_P256_SIGNATURE_SIZE])327 bool eicOpsEcDsa(const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],
328                  const uint8_t digestOfData[EIC_SHA256_DIGEST_SIZE],
329                  uint8_t signature[EIC_ECDSA_P256_SIGNATURE_SIZE]) {
330     vector<uint8_t> privKeyVec(EIC_P256_PRIV_KEY_SIZE);
331     memcpy(privKeyVec.data(), privateKey, EIC_P256_PRIV_KEY_SIZE);
332 
333     vector<uint8_t> digestVec(EIC_SHA256_DIGEST_SIZE);
334     memcpy(digestVec.data(), digestOfData, EIC_SHA256_DIGEST_SIZE);
335 
336     optional<vector<uint8_t>> derSignature =
337             android::hardware::identity::support::signEcDsaDigest(privKeyVec, digestVec);
338     if (!derSignature) {
339         eicDebug("Error signing data");
340         return false;
341     }
342 
343     ECDSA_SIG* sig;
344     const unsigned char* p = derSignature.value().data();
345     sig = d2i_ECDSA_SIG(nullptr, &p, derSignature.value().size());
346     if (sig == nullptr) {
347         eicDebug("Error decoding DER signature");
348         return false;
349     }
350 
351     if (BN_bn2binpad(sig->r, signature, 32) != 32) {
352         eicDebug("Error encoding r");
353         return false;
354     }
355     if (BN_bn2binpad(sig->s, signature + 32, 32) != 32) {
356         eicDebug("Error encoding s");
357         return false;
358     }
359 
360     return true;
361 }
362 
363 static const uint8_t hbkTest[16] = {0};
364 static const uint8_t hbkReal[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
365 
eicOpsGetHardwareBoundKey(bool testCredential)366 const uint8_t* eicOpsGetHardwareBoundKey(bool testCredential) {
367     if (testCredential) {
368         return hbkTest;
369     }
370     return hbkReal;
371 }
372 
eicOpsValidateAuthToken(uint64_t,uint64_t,uint64_t,int,uint64_t,const uint8_t *,size_t,uint64_t,uint64_t,int,const uint8_t *,size_t)373 bool eicOpsValidateAuthToken(uint64_t /* challenge */, uint64_t /* secureUserId */,
374                              uint64_t /* authenticatorId */, int /* hardwareAuthenticatorType */,
375                              uint64_t /* timeStamp */, const uint8_t* /* mac */,
376                              size_t /* macSize */, uint64_t /* verificationTokenChallenge */,
377                              uint64_t /* verificationTokenTimeStamp */,
378                              int /* verificationTokenSecurityLevel */,
379                              const uint8_t* /* verificationTokenMac */,
380                              size_t /* verificationTokenMacSize */) {
381     // Here's where we would validate the passed-in |authToken| to assure ourselves
382     // that it comes from the e.g. biometric hardware and wasn't made up by an attacker.
383     //
384     // However this involves calculating the MAC which requires access to the to
385     // a pre-shared key which we don't have...
386     //
387     return true;
388 }
389 
eicOpsX509GetPublicKey(const uint8_t * x509Cert,size_t x509CertSize,uint8_t * publicKey,size_t * publicKeySize)390 bool eicOpsX509GetPublicKey(const uint8_t* x509Cert, size_t x509CertSize, uint8_t* publicKey,
391                             size_t* publicKeySize) {
392     vector<uint8_t> chain;
393     chain.resize(x509CertSize);
394     memcpy(chain.data(), x509Cert, x509CertSize);
395     optional<vector<uint8_t>> res =
396             android::hardware::identity::support::certificateChainGetTopMostKey(chain);
397     if (!res) {
398         return false;
399     }
400     if (res.value().size() > *publicKeySize) {
401         eicDebug("Public key size is %zd but buffer only has room for %zd bytes",
402                  res.value().size(), *publicKeySize);
403         return false;
404     }
405     *publicKeySize = res.value().size();
406     memcpy(publicKey, res.value().data(), *publicKeySize);
407     eicDebug("Extracted %zd bytes public key from %zd bytes X.509 cert", *publicKeySize,
408              x509CertSize);
409     return true;
410 }
411 
eicOpsX509CertSignedByPublicKey(const uint8_t * x509Cert,size_t x509CertSize,const uint8_t * publicKey,size_t publicKeySize)412 bool eicOpsX509CertSignedByPublicKey(const uint8_t* x509Cert, size_t x509CertSize,
413                                      const uint8_t* publicKey, size_t publicKeySize) {
414     vector<uint8_t> certVec(x509Cert, x509Cert + x509CertSize);
415     vector<uint8_t> publicKeyVec(publicKey, publicKey + publicKeySize);
416     return android::hardware::identity::support::certificateSignedByPublicKey(certVec,
417                                                                               publicKeyVec);
418 }
419 
eicOpsEcDsaVerifyWithPublicKey(const uint8_t * digest,size_t digestSize,const uint8_t * signature,size_t signatureSize,const uint8_t * publicKey,size_t publicKeySize)420 bool eicOpsEcDsaVerifyWithPublicKey(const uint8_t* digest, size_t digestSize,
421                                     const uint8_t* signature, size_t signatureSize,
422                                     const uint8_t* publicKey, size_t publicKeySize) {
423     vector<uint8_t> digestVec(digest, digest + digestSize);
424     vector<uint8_t> signatureVec(signature, signature + signatureSize);
425     vector<uint8_t> publicKeyVec(publicKey, publicKey + publicKeySize);
426 
427     vector<uint8_t> derSignature;
428     if (!android::hardware::identity::support::ecdsaSignatureCoseToDer(signatureVec,
429                                                                        derSignature)) {
430         LOG(ERROR) << "Error convering signature to DER format";
431         return false;
432     }
433 
434     if (!android::hardware::identity::support::checkEcDsaSignature(digestVec, derSignature,
435                                                                    publicKeyVec)) {
436         LOG(ERROR) << "Signature check failed";
437         return false;
438     }
439     return true;
440 }
441 
eicOpsEcdh(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE],const uint8_t privateKey[EIC_P256_PUB_KEY_SIZE],uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE])442 bool eicOpsEcdh(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE],
443                 const uint8_t privateKey[EIC_P256_PUB_KEY_SIZE],
444                 uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE]) {
445     vector<uint8_t> pubKeyVec(EIC_P256_PUB_KEY_SIZE + 1);
446     pubKeyVec[0] = 0x04;
447     memcpy(pubKeyVec.data() + 1, publicKey, EIC_P256_PUB_KEY_SIZE);
448 
449     vector<uint8_t> privKeyVec(EIC_P256_PRIV_KEY_SIZE);
450     memcpy(privKeyVec.data(), privateKey, EIC_P256_PRIV_KEY_SIZE);
451 
452     optional<vector<uint8_t>> shared =
453             android::hardware::identity::support::ecdh(pubKeyVec, privKeyVec);
454     if (!shared) {
455         LOG(ERROR) << "Error performing ECDH";
456         return false;
457     }
458     if (shared.value().size() != EIC_P256_COORDINATE_SIZE) {
459         LOG(ERROR) << "Unexpected size of shared secret " << shared.value().size() << " expected "
460                    << EIC_P256_COORDINATE_SIZE << " bytes";
461         return false;
462     }
463     memcpy(sharedSecret, shared.value().data(), EIC_P256_COORDINATE_SIZE);
464     return true;
465 }
466 
eicOpsHkdf(const uint8_t * sharedSecret,size_t sharedSecretSize,const uint8_t * salt,size_t saltSize,const uint8_t * info,size_t infoSize,uint8_t * output,size_t outputSize)467 bool eicOpsHkdf(const uint8_t* sharedSecret, size_t sharedSecretSize, const uint8_t* salt,
468                 size_t saltSize, const uint8_t* info, size_t infoSize, uint8_t* output,
469                 size_t outputSize) {
470     vector<uint8_t> sharedSecretVec(sharedSecretSize);
471     memcpy(sharedSecretVec.data(), sharedSecret, sharedSecretSize);
472     vector<uint8_t> saltVec(saltSize);
473     memcpy(saltVec.data(), salt, saltSize);
474     vector<uint8_t> infoVec(infoSize);
475     memcpy(infoVec.data(), info, infoSize);
476 
477     optional<vector<uint8_t>> result = android::hardware::identity::support::hkdf(
478             sharedSecretVec, saltVec, infoVec, outputSize);
479     if (!result) {
480         LOG(ERROR) << "Error performing HKDF";
481         return false;
482     }
483     if (result.value().size() != outputSize) {
484         LOG(ERROR) << "Unexpected size of HKDF " << result.value().size() << " expected "
485                    << outputSize;
486         return false;
487     }
488     memcpy(output, result.value().data(), outputSize);
489     return true;
490 }
491 
492 #ifdef EIC_DEBUG
493 
eicPrint(const char * format,...)494 void eicPrint(const char* format, ...) {
495     va_list args;
496     va_start(args, format);
497     vfprintf(stderr, format, args);
498     va_end(args);
499 }
500 
eicHexdump(const char * message,const uint8_t * data,size_t dataSize)501 void eicHexdump(const char* message, const uint8_t* data, size_t dataSize) {
502     vector<uint8_t> dataVec(dataSize);
503     memcpy(dataVec.data(), data, dataSize);
504     android::hardware::identity::support::hexdump(message, dataVec);
505 }
506 
eicCborPrettyPrint(const uint8_t * cborData,size_t cborDataSize,size_t maxBStrSize)507 void eicCborPrettyPrint(const uint8_t* cborData, size_t cborDataSize, size_t maxBStrSize) {
508     vector<uint8_t> cborDataVec(cborDataSize);
509     memcpy(cborDataVec.data(), cborData, cborDataSize);
510     string str =
511             android::hardware::identity::support::cborPrettyPrint(cborDataVec, maxBStrSize, {});
512     fprintf(stderr, "%s\n", str.c_str());
513 }
514 
515 #endif  // EIC_DEBUG
516