Identity Credential: Switch default implementation to use libeic.

Introduce platform-neutral C library ("libeic") which can be used to
implement an Identity Credential Trusted Application/Applet in Secure
Hardware.

The libeic library is intentionally low-level, has no dependencies
(not even libc), uses very little run-time memory (less than 500 bytes
during a provisioning or presentation session), and doesn't
dynamically allocate any memory. Crypto routines are provided by the
library user through a simple crypto interface defined in EicOps.

Also provide an Android-side HAL implementation designed to
communicate with libeic running in Secure Hardware outside
Android. Abstract out communications between HAL and TA in a couple of
SecureHardwareProxy* classes which mimic libeic 1:1.

The default implementation of the HAL is a combination of the
aforementioned HAL using libeic in-process backed by BoringSSL for the
crypto bits.

Test: atest VtsHalIdentityTargetTest
Test: atest android.security.identity.cts
Bug: 170146643
Change-Id: I3bf43fa7fd9362f94023052591801f2094a04607
diff --git a/identity/aidl/default/EicOpsImpl.cc b/identity/aidl/default/EicOpsImpl.cc
new file mode 100644
index 0000000..3f2ec8b
--- /dev/null
+++ b/identity/aidl/default/EicOpsImpl.cc
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EicOpsImpl"
+
+#include <optional>
+#include <tuple>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <string.h>
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <openssl/sha.h>
+
+#include <openssl/aes.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/hkdf.h>
+#include <openssl/hmac.h>
+#include <openssl/objects.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs12.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+
+#include "EicOps.h"
+
+using ::std::optional;
+using ::std::string;
+using ::std::tuple;
+using ::std::vector;
+
+void* eicMemSet(void* s, int c, size_t n) {
+    return memset(s, c, n);
+}
+
+void* eicMemCpy(void* dest, const void* src, size_t n) {
+    return memcpy(dest, src, n);
+}
+
+size_t eicStrLen(const char* s) {
+    return strlen(s);
+}
+
+int eicCryptoMemCmp(const void* s1, const void* s2, size_t n) {
+    return CRYPTO_memcmp(s1, s2, n);
+}
+
+void eicOpsHmacSha256Init(EicHmacSha256Ctx* ctx, const uint8_t* key, size_t keySize) {
+    HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
+    HMAC_CTX_init(realCtx);
+    if (HMAC_Init_ex(realCtx, key, keySize, EVP_sha256(), nullptr /* impl */) != 1) {
+        LOG(ERROR) << "Error initializing HMAC_CTX";
+    }
+}
+
+void eicOpsHmacSha256Update(EicHmacSha256Ctx* ctx, const uint8_t* data, size_t len) {
+    HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
+    if (HMAC_Update(realCtx, data, len) != 1) {
+        LOG(ERROR) << "Error updating HMAC_CTX";
+    }
+}
+
+void eicOpsHmacSha256Final(EicHmacSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]) {
+    HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
+    unsigned int size = 0;
+    if (HMAC_Final(realCtx, digest, &size) != 1) {
+        LOG(ERROR) << "Error finalizing HMAC_CTX";
+    }
+    if (size != EIC_SHA256_DIGEST_SIZE) {
+        LOG(ERROR) << "Expected 32 bytes from HMAC_Final, got " << size;
+    }
+}
+
+void eicOpsSha256Init(EicSha256Ctx* ctx) {
+    SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
+    SHA256_Init(realCtx);
+}
+
+void eicOpsSha256Update(EicSha256Ctx* ctx, const uint8_t* data, size_t len) {
+    SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
+    SHA256_Update(realCtx, data, len);
+}
+
+void eicOpsSha256Final(EicSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]) {
+    SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
+    SHA256_Final(digest, realCtx);
+}
+
+bool eicOpsRandom(uint8_t* buf, size_t numBytes) {
+    optional<vector<uint8_t>> bytes = ::android::hardware::identity::support::getRandom(numBytes);
+    if (!bytes.has_value()) {
+        return false;
+    }
+    memcpy(buf, bytes.value().data(), numBytes);
+    return true;
+}
+
+bool eicOpsEncryptAes128Gcm(
+        const uint8_t* key,    // Must be 16 bytes
+        const uint8_t* nonce,  // Must be 12 bytes
+        const uint8_t* data,   // May be NULL if size is 0
+        size_t dataSize,
+        const uint8_t* additionalAuthenticationData,  // May be NULL if size is 0
+        size_t additionalAuthenticationDataSize, uint8_t* encryptedData) {
+    vector<uint8_t> cppKey;
+    cppKey.resize(16);
+    memcpy(cppKey.data(), key, 16);
+
+    vector<uint8_t> cppData;
+    cppData.resize(dataSize);
+    if (dataSize > 0) {
+        memcpy(cppData.data(), data, dataSize);
+    }
+
+    vector<uint8_t> cppAAD;
+    cppAAD.resize(additionalAuthenticationDataSize);
+    if (additionalAuthenticationDataSize > 0) {
+        memcpy(cppAAD.data(), additionalAuthenticationData, additionalAuthenticationDataSize);
+    }
+
+    vector<uint8_t> cppNonce;
+    cppNonce.resize(12);
+    memcpy(cppNonce.data(), nonce, 12);
+
+    optional<vector<uint8_t>> cppEncryptedData =
+            android::hardware::identity::support::encryptAes128Gcm(cppKey, cppNonce, cppData,
+                                                                   cppAAD);
+    if (!cppEncryptedData.has_value()) {
+        return false;
+    }
+
+    memcpy(encryptedData, cppEncryptedData.value().data(), cppEncryptedData.value().size());
+    return true;
+}
+
+// Decrypts |encryptedData| using |key| and |additionalAuthenticatedData|,
+// returns resulting plaintext in |data| must be of size |encryptedDataSize| - 28.
+//
+// The format of |encryptedData| must be as specified in the
+// encryptAes128Gcm() function.
+bool eicOpsDecryptAes128Gcm(const uint8_t* key,  // Must be 16 bytes
+                            const uint8_t* encryptedData, size_t encryptedDataSize,
+                            const uint8_t* additionalAuthenticationData,
+                            size_t additionalAuthenticationDataSize, uint8_t* data) {
+    vector<uint8_t> keyVec;
+    keyVec.resize(16);
+    memcpy(keyVec.data(), key, 16);
+
+    vector<uint8_t> encryptedDataVec;
+    encryptedDataVec.resize(encryptedDataSize);
+    if (encryptedDataSize > 0) {
+        memcpy(encryptedDataVec.data(), encryptedData, encryptedDataSize);
+    }
+
+    vector<uint8_t> aadVec;
+    aadVec.resize(additionalAuthenticationDataSize);
+    if (additionalAuthenticationDataSize > 0) {
+        memcpy(aadVec.data(), additionalAuthenticationData, additionalAuthenticationDataSize);
+    }
+
+    optional<vector<uint8_t>> decryptedDataVec =
+            android::hardware::identity::support::decryptAes128Gcm(keyVec, encryptedDataVec,
+                                                                   aadVec);
+    if (!decryptedDataVec.has_value()) {
+        eicDebug("Error decrypting data");
+        return false;
+    }
+    if (decryptedDataVec.value().size() != encryptedDataSize - 28) {
+        eicDebug("Decrypted data is size %zd, expected %zd", decryptedDataVec.value().size(),
+                 encryptedDataSize - 28);
+        return false;
+    }
+
+    if (decryptedDataVec.value().size() > 0) {
+        memcpy(data, decryptedDataVec.value().data(), decryptedDataVec.value().size());
+    }
+    return true;
+}
+
+bool eicOpsCreateEcKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],
+                       uint8_t publicKey[EIC_P256_PUB_KEY_SIZE]) {
+    optional<vector<uint8_t>> keyPair = android::hardware::identity::support::createEcKeyPair();
+    if (!keyPair) {
+        eicDebug("Error creating EC keypair");
+        return false;
+    }
+    optional<vector<uint8_t>> privKey =
+            android::hardware::identity::support::ecKeyPairGetPrivateKey(keyPair.value());
+    if (!privKey) {
+        eicDebug("Error extracting private key");
+        return false;
+    }
+    if (privKey.value().size() != EIC_P256_PRIV_KEY_SIZE) {
+        eicDebug("Private key is not %zd bytes long as expected", (size_t)EIC_P256_PRIV_KEY_SIZE);
+        return false;
+    }
+
+    optional<vector<uint8_t>> pubKey =
+            android::hardware::identity::support::ecKeyPairGetPublicKey(keyPair.value());
+    if (!pubKey) {
+        eicDebug("Error extracting public key");
+        return false;
+    }
+    // ecKeyPairGetPublicKey() returns 0x04 | x | y, we don't want the leading 0x04.
+    if (pubKey.value().size() != EIC_P256_PUB_KEY_SIZE + 1) {
+        eicDebug("Private key is %zd bytes long, expected %zd", pubKey.value().size(),
+                 (size_t)EIC_P256_PRIV_KEY_SIZE + 1);
+        return false;
+    }
+
+    memcpy(privateKey, privKey.value().data(), EIC_P256_PRIV_KEY_SIZE);
+    memcpy(publicKey, pubKey.value().data() + 1, EIC_P256_PUB_KEY_SIZE);
+
+    return true;
+}
+
+bool 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) {
+    vector<uint8_t> challengeVec(challengeSize);
+    memcpy(challengeVec.data(), challenge, challengeSize);
+
+    vector<uint8_t> applicationIdVec(applicationIdSize);
+    memcpy(applicationIdVec.data(), applicationId, applicationIdSize);
+
+    optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> ret =
+            android::hardware::identity::support::createEcKeyPairAndAttestation(
+                    challengeVec, applicationIdVec, testCredential);
+    if (!ret) {
+        eicDebug("Error generating CredentialKey and attestation");
+        return false;
+    }
+
+    // Extract certificate chain.
+    vector<uint8_t> flatChain =
+            android::hardware::identity::support::certificateChainJoin(ret.value().second);
+    if (*certSize < flatChain.size()) {
+        eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
+                 flatChain.size());
+        return false;
+    }
+    memcpy(cert, flatChain.data(), flatChain.size());
+    *certSize = flatChain.size();
+
+    // Extract private key.
+    optional<vector<uint8_t>> privKey =
+            android::hardware::identity::support::ecKeyPairGetPrivateKey(ret.value().first);
+    if (!privKey) {
+        eicDebug("Error extracting private key");
+        return false;
+    }
+    if (privKey.value().size() != EIC_P256_PRIV_KEY_SIZE) {
+        eicDebug("Private key is not %zd bytes long as expected", (size_t)EIC_P256_PRIV_KEY_SIZE);
+        return false;
+    }
+
+    memcpy(privateKey, privKey.value().data(), EIC_P256_PRIV_KEY_SIZE);
+
+    return true;
+}
+
+bool 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, uint8_t* cert,
+                     size_t* certSize) {  // inout
+    vector<uint8_t> signingKeyVec(EIC_P256_PRIV_KEY_SIZE);
+    memcpy(signingKeyVec.data(), signingKey, EIC_P256_PRIV_KEY_SIZE);
+
+    vector<uint8_t> pubKeyVec(EIC_P256_PUB_KEY_SIZE + 1);
+    pubKeyVec[0] = 0x04;
+    memcpy(pubKeyVec.data() + 1, publicKey, EIC_P256_PUB_KEY_SIZE);
+
+    std::string serialDecimal = android::base::StringPrintf("%d", serial);
+
+    optional<vector<uint8_t>> certVec =
+            android::hardware::identity::support::ecPublicKeyGenerateCertificate(
+                    pubKeyVec, signingKeyVec, serialDecimal, issuerName, subjectName,
+                    validityNotBefore, validityNotAfter);
+    if (!certVec) {
+        eicDebug("Error generating certificate");
+        return false;
+    }
+
+    if (*certSize < certVec.value().size()) {
+        eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
+                 certVec.value().size());
+        return false;
+    }
+    memcpy(cert, certVec.value().data(), certVec.value().size());
+    *certSize = certVec.value().size();
+
+    return true;
+}
+
+bool 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]) {
+    vector<uint8_t> privKeyVec(EIC_P256_PRIV_KEY_SIZE);
+    memcpy(privKeyVec.data(), privateKey, EIC_P256_PRIV_KEY_SIZE);
+
+    vector<uint8_t> digestVec(EIC_SHA256_DIGEST_SIZE);
+    memcpy(digestVec.data(), digestOfData, EIC_SHA256_DIGEST_SIZE);
+
+    optional<vector<uint8_t>> derSignature =
+            android::hardware::identity::support::signEcDsaDigest(privKeyVec, digestVec);
+    if (!derSignature) {
+        eicDebug("Error signing data");
+        return false;
+    }
+
+    ECDSA_SIG* sig;
+    const unsigned char* p = derSignature.value().data();
+    sig = d2i_ECDSA_SIG(nullptr, &p, derSignature.value().size());
+    if (sig == nullptr) {
+        eicDebug("Error decoding DER signature");
+        return false;
+    }
+
+    if (BN_bn2binpad(sig->r, signature, 32) != 32) {
+        eicDebug("Error encoding r");
+        return false;
+    }
+    if (BN_bn2binpad(sig->s, signature + 32, 32) != 32) {
+        eicDebug("Error encoding s");
+        return false;
+    }
+
+    return true;
+}
+
+static const uint8_t hbkTest[16] = {0};
+static const uint8_t hbkReal[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+const uint8_t* eicOpsGetHardwareBoundKey(bool testCredential) {
+    if (testCredential) {
+        return hbkTest;
+    }
+    return hbkReal;
+}
+
+bool eicOpsValidateAuthToken(uint64_t /* challenge */, uint64_t /* secureUserId */,
+                             uint64_t /* authenticatorId */, int /* hardwareAuthenticatorType */,
+                             uint64_t /* timeStamp */, const uint8_t* /* mac */,
+                             size_t /* macSize */, uint64_t /* verificationTokenChallenge */,
+                             uint64_t /* verificationTokenTimeStamp */,
+                             int /* verificationTokenSecurityLevel */,
+                             const uint8_t* /* verificationTokenMac */,
+                             size_t /* verificationTokenMacSize */) {
+    // Here's where we would validate the passed-in |authToken| to assure ourselves
+    // that it comes from the e.g. biometric hardware and wasn't made up by an attacker.
+    //
+    // However this involves calculating the MAC which requires access to the to
+    // a pre-shared key which we don't have...
+    //
+    return true;
+}
+
+bool eicOpsX509GetPublicKey(const uint8_t* x509Cert, size_t x509CertSize, uint8_t* publicKey,
+                            size_t* publicKeySize) {
+    vector<uint8_t> chain;
+    chain.resize(x509CertSize);
+    memcpy(chain.data(), x509Cert, x509CertSize);
+    optional<vector<uint8_t>> res =
+            android::hardware::identity::support::certificateChainGetTopMostKey(chain);
+    if (!res) {
+        return false;
+    }
+    if (res.value().size() > *publicKeySize) {
+        eicDebug("Public key size is %zd but buffer only has room for %zd bytes",
+                 res.value().size(), *publicKeySize);
+        return false;
+    }
+    *publicKeySize = res.value().size();
+    memcpy(publicKey, res.value().data(), *publicKeySize);
+    eicDebug("Extracted %zd bytes public key from %zd bytes X.509 cert", *publicKeySize,
+             x509CertSize);
+    return true;
+}
+
+bool eicOpsX509CertSignedByPublicKey(const uint8_t* x509Cert, size_t x509CertSize,
+                                     const uint8_t* publicKey, size_t publicKeySize) {
+    vector<uint8_t> certVec(x509Cert, x509Cert + x509CertSize);
+    vector<uint8_t> publicKeyVec(publicKey, publicKey + publicKeySize);
+    return android::hardware::identity::support::certificateSignedByPublicKey(certVec,
+                                                                              publicKeyVec);
+}
+
+bool eicOpsEcDsaVerifyWithPublicKey(const uint8_t* digest, size_t digestSize,
+                                    const uint8_t* signature, size_t signatureSize,
+                                    const uint8_t* publicKey, size_t publicKeySize) {
+    vector<uint8_t> digestVec(digest, digest + digestSize);
+    vector<uint8_t> signatureVec(signature, signature + signatureSize);
+    vector<uint8_t> publicKeyVec(publicKey, publicKey + publicKeySize);
+
+    vector<uint8_t> derSignature;
+    if (!android::hardware::identity::support::ecdsaSignatureCoseToDer(signatureVec,
+                                                                       derSignature)) {
+        LOG(ERROR) << "Error convering signature to DER format";
+        return false;
+    }
+
+    if (!android::hardware::identity::support::checkEcDsaSignature(digestVec, derSignature,
+                                                                   publicKeyVec)) {
+        LOG(ERROR) << "Signature check failed";
+        return false;
+    }
+    return true;
+}
+
+bool 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]) {
+    vector<uint8_t> pubKeyVec(EIC_P256_PUB_KEY_SIZE + 1);
+    pubKeyVec[0] = 0x04;
+    memcpy(pubKeyVec.data() + 1, publicKey, EIC_P256_PUB_KEY_SIZE);
+
+    vector<uint8_t> privKeyVec(EIC_P256_PRIV_KEY_SIZE);
+    memcpy(privKeyVec.data(), privateKey, EIC_P256_PRIV_KEY_SIZE);
+
+    optional<vector<uint8_t>> shared =
+            android::hardware::identity::support::ecdh(pubKeyVec, privKeyVec);
+    if (!shared) {
+        LOG(ERROR) << "Error performing ECDH";
+        return false;
+    }
+    if (shared.value().size() != EIC_P256_COORDINATE_SIZE) {
+        LOG(ERROR) << "Unexpected size of shared secret " << shared.value().size() << " expected "
+                   << EIC_P256_COORDINATE_SIZE << " bytes";
+        return false;
+    }
+    memcpy(sharedSecret, shared.value().data(), EIC_P256_COORDINATE_SIZE);
+    return true;
+}
+
+bool 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) {
+    vector<uint8_t> sharedSecretVec(sharedSecretSize);
+    memcpy(sharedSecretVec.data(), sharedSecret, sharedSecretSize);
+    vector<uint8_t> saltVec(saltSize);
+    memcpy(saltVec.data(), salt, saltSize);
+    vector<uint8_t> infoVec(infoSize);
+    memcpy(infoVec.data(), info, infoSize);
+
+    optional<vector<uint8_t>> result = android::hardware::identity::support::hkdf(
+            sharedSecretVec, saltVec, infoVec, outputSize);
+    if (!result) {
+        LOG(ERROR) << "Error performing HKDF";
+        return false;
+    }
+    if (result.value().size() != outputSize) {
+        LOG(ERROR) << "Unexpected size of HKDF " << result.value().size() << " expected "
+                   << outputSize;
+        return false;
+    }
+    memcpy(output, result.value().data(), outputSize);
+    return true;
+}
+
+#ifdef EIC_DEBUG
+
+void eicPrint(const char* format, ...) {
+    va_list args;
+    va_start(args, format);
+    vfprintf(stderr, format, args);
+    va_end(args);
+}
+
+void eicHexdump(const char* message, const uint8_t* data, size_t dataSize) {
+    vector<uint8_t> dataVec(dataSize);
+    memcpy(dataVec.data(), data, dataSize);
+    android::hardware::identity::support::hexdump(message, dataVec);
+}
+
+void eicCborPrettyPrint(const uint8_t* cborData, size_t cborDataSize, size_t maxBStrSize) {
+    vector<uint8_t> cborDataVec(cborDataSize);
+    memcpy(cborDataVec.data(), cborData, cborDataSize);
+    string str =
+            android::hardware::identity::support::cborPrettyPrint(cborDataVec, maxBStrSize, {});
+    fprintf(stderr, "%s\n", str.c_str());
+}
+
+#endif  // EIC_DEBUG