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