diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
new file mode 100644
index 0000000..7d93a4b
--- /dev/null
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -0,0 +1,1815 @@
+/*
+ * Copyright 2019, 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 "IdentityCredentialSupport"
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#define _POSIX_C_SOURCE 199309L
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <time.h>
+#include <iomanip>
+
+#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 <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+namespace android {
+namespace hardware {
+namespace identity {
+namespace support {
+
+using ::std::pair;
+using ::std::unique_ptr;
+
+// ---------------------------------------------------------------------------
+// Miscellaneous utilities.
+// ---------------------------------------------------------------------------
+
+void hexdump(const string& name, const vector<uint8_t>& data) {
+    fprintf(stderr, "%s: dumping %zd bytes\n", name.c_str(), data.size());
+    size_t n, m, o;
+    for (n = 0; n < data.size(); n += 16) {
+        fprintf(stderr, "%04zx  ", n);
+        for (m = 0; m < 16 && n + m < data.size(); m++) {
+            fprintf(stderr, "%02x ", data[n + m]);
+        }
+        for (o = m; o < 16; o++) {
+            fprintf(stderr, "   ");
+        }
+        fprintf(stderr, " ");
+        for (m = 0; m < 16 && n + m < data.size(); m++) {
+            int c = data[n + m];
+            fprintf(stderr, "%c", isprint(c) ? c : '.');
+        }
+        fprintf(stderr, "\n");
+    }
+    fprintf(stderr, "\n");
+}
+
+string encodeHex(const uint8_t* data, size_t dataLen) {
+    static const char hexDigits[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                                       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+    string ret;
+    ret.resize(dataLen * 2);
+    for (size_t n = 0; n < dataLen; n++) {
+        uint8_t byte = data[n];
+        ret[n * 2 + 0] = hexDigits[byte >> 4];
+        ret[n * 2 + 1] = hexDigits[byte & 0x0f];
+    }
+
+    return ret;
+}
+
+string encodeHex(const string& str) {
+    return encodeHex(reinterpret_cast<const uint8_t*>(str.data()), str.size());
+}
+
+string encodeHex(const vector<uint8_t>& data) {
+    return encodeHex(data.data(), data.size());
+}
+
+// Returns -1 on error, otherwise an integer in the range 0 through 15, both inclusive.
+int parseHexDigit(char hexDigit) {
+    if (hexDigit >= '0' && hexDigit <= '9') {
+        return int(hexDigit) - '0';
+    } else if (hexDigit >= 'a' && hexDigit <= 'f') {
+        return int(hexDigit) - 'a' + 10;
+    } else if (hexDigit >= 'A' && hexDigit <= 'F') {
+        return int(hexDigit) - 'A' + 10;
+    }
+    return -1;
+}
+
+optional<vector<uint8_t>> decodeHex(const string& hexEncoded) {
+    vector<uint8_t> out;
+    size_t hexSize = hexEncoded.size();
+    if ((hexSize & 1) != 0) {
+        LOG(ERROR) << "Size of data cannot be odd";
+        return {};
+    }
+
+    out.resize(hexSize / 2);
+    for (size_t n = 0; n < hexSize / 2; n++) {
+        int upperNibble = parseHexDigit(hexEncoded[n * 2]);
+        int lowerNibble = parseHexDigit(hexEncoded[n * 2 + 1]);
+        if (upperNibble == -1 || lowerNibble == -1) {
+            LOG(ERROR) << "Invalid hex digit at position " << n;
+            return {};
+        }
+        out[n] = (upperNibble << 4) + lowerNibble;
+    }
+
+    return out;
+}
+
+// ---------------------------------------------------------------------------
+// CBOR utilities.
+// ---------------------------------------------------------------------------
+
+static bool cborAreAllElementsNonCompound(const cppbor::CompoundItem* compoundItem) {
+    if (compoundItem->type() == cppbor::ARRAY) {
+        const cppbor::Array* array = compoundItem->asArray();
+        for (size_t n = 0; n < array->size(); n++) {
+            const cppbor::Item* entry = (*array)[n].get();
+            switch (entry->type()) {
+                case cppbor::ARRAY:
+                case cppbor::MAP:
+                    return false;
+                default:
+                    break;
+            }
+        }
+    } else {
+        const cppbor::Map* map = compoundItem->asMap();
+        for (size_t n = 0; n < map->size(); n++) {
+            auto [keyEntry, valueEntry] = (*map)[n];
+            switch (keyEntry->type()) {
+                case cppbor::ARRAY:
+                case cppbor::MAP:
+                    return false;
+                default:
+                    break;
+            }
+            switch (valueEntry->type()) {
+                case cppbor::ARRAY:
+                case cppbor::MAP:
+                    return false;
+                default:
+                    break;
+            }
+        }
+    }
+    return true;
+}
+
+static bool cborPrettyPrintInternal(const cppbor::Item* item, string& out, size_t indent,
+                                    size_t maxBStrSize, const vector<string>& mapKeysToNotPrint) {
+    char buf[80];
+
+    string indentString(indent, ' ');
+
+    switch (item->type()) {
+        case cppbor::UINT:
+            snprintf(buf, sizeof(buf), "%" PRIu64, item->asUint()->unsignedValue());
+            out.append(buf);
+            break;
+
+        case cppbor::NINT:
+            snprintf(buf, sizeof(buf), "%" PRId64, item->asNint()->value());
+            out.append(buf);
+            break;
+
+        case cppbor::BSTR: {
+            const cppbor::Bstr* bstr = item->asBstr();
+            const vector<uint8_t>& value = bstr->value();
+            if (value.size() > maxBStrSize) {
+                unsigned char digest[SHA_DIGEST_LENGTH];
+                SHA_CTX ctx;
+                SHA1_Init(&ctx);
+                SHA1_Update(&ctx, value.data(), value.size());
+                SHA1_Final(digest, &ctx);
+                char buf2[SHA_DIGEST_LENGTH * 2 + 1];
+                for (size_t n = 0; n < SHA_DIGEST_LENGTH; n++) {
+                    snprintf(buf2 + n * 2, 3, "%02x", digest[n]);
+                }
+                snprintf(buf, sizeof(buf), "<bstr size=%zd sha1=%s>", value.size(), buf2);
+                out.append(buf);
+            } else {
+                out.append("{");
+                for (size_t n = 0; n < value.size(); n++) {
+                    if (n > 0) {
+                        out.append(", ");
+                    }
+                    snprintf(buf, sizeof(buf), "0x%02x", value[n]);
+                    out.append(buf);
+                }
+                out.append("}");
+            }
+        } break;
+
+        case cppbor::TSTR:
+            out.append("'");
+            {
+                // TODO: escape "'" characters
+                out.append(item->asTstr()->value().c_str());
+            }
+            out.append("'");
+            break;
+
+        case cppbor::ARRAY: {
+            const cppbor::Array* array = item->asArray();
+            if (array->size() == 0) {
+                out.append("[]");
+            } else if (cborAreAllElementsNonCompound(array)) {
+                out.append("[");
+                for (size_t n = 0; n < array->size(); n++) {
+                    if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
+                                                 mapKeysToNotPrint)) {
+                        return false;
+                    }
+                    out.append(", ");
+                }
+                out.append("]");
+            } else {
+                out.append("[\n" + indentString);
+                for (size_t n = 0; n < array->size(); n++) {
+                    out.append("  ");
+                    if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
+                                                 mapKeysToNotPrint)) {
+                        return false;
+                    }
+                    out.append(",\n" + indentString);
+                }
+                out.append("]");
+            }
+        } break;
+
+        case cppbor::MAP: {
+            const cppbor::Map* map = item->asMap();
+
+            if (map->size() == 0) {
+                out.append("{}");
+            } else {
+                out.append("{\n" + indentString);
+                for (size_t n = 0; n < map->size(); n++) {
+                    out.append("  ");
+
+                    auto [map_key, map_value] = (*map)[n];
+
+                    if (!cborPrettyPrintInternal(map_key.get(), out, indent + 2, maxBStrSize,
+                                                 mapKeysToNotPrint)) {
+                        return false;
+                    }
+                    out.append(" : ");
+                    if (map_key->type() == cppbor::TSTR &&
+                        std::find(mapKeysToNotPrint.begin(), mapKeysToNotPrint.end(),
+                                  map_key->asTstr()->value()) != mapKeysToNotPrint.end()) {
+                        out.append("<not printed>");
+                    } else {
+                        if (!cborPrettyPrintInternal(map_value.get(), out, indent + 2, maxBStrSize,
+                                                     mapKeysToNotPrint)) {
+                            return false;
+                        }
+                    }
+                    out.append(",\n" + indentString);
+                }
+                out.append("}");
+            }
+        } break;
+
+        case cppbor::SEMANTIC: {
+            const cppbor::Semantic* semantic = item->asSemantic();
+            snprintf(buf, sizeof(buf), "tag %" PRIu64 " ", semantic->value());
+            out.append(buf);
+            cborPrettyPrintInternal(semantic->child().get(), out, indent, maxBStrSize,
+                                    mapKeysToNotPrint);
+        } break;
+
+        case cppbor::SIMPLE:
+            const cppbor::Bool* asBool = item->asSimple()->asBool();
+            const cppbor::Null* asNull = item->asSimple()->asNull();
+            if (asBool != nullptr) {
+                out.append(asBool->value() ? "true" : "false");
+            } else if (asNull != nullptr) {
+                out.append("null");
+            } else {
+                LOG(ERROR) << "Only boolean/null is implemented for SIMPLE";
+                return false;
+            }
+            break;
+    }
+
+    return true;
+}
+
+string cborPrettyPrint(const vector<uint8_t>& encodedCbor, size_t maxBStrSize,
+                       const vector<string>& mapKeysToNotPrint) {
+    auto [item, _, message] = cppbor::parse(encodedCbor);
+    if (item == nullptr) {
+        LOG(ERROR) << "Data to pretty print is not valid CBOR: " << message;
+        return "";
+    }
+
+    string out;
+    cborPrettyPrintInternal(item.get(), out, 0, maxBStrSize, mapKeysToNotPrint);
+    return out;
+}
+
+// ---------------------------------------------------------------------------
+// Crypto functionality / abstraction.
+// ---------------------------------------------------------------------------
+
+struct EVP_CIPHER_CTX_Deleter {
+    void operator()(EVP_CIPHER_CTX* ctx) const {
+        if (ctx != nullptr) {
+            EVP_CIPHER_CTX_free(ctx);
+        }
+    }
+};
+
+using EvpCipherCtxPtr = unique_ptr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_Deleter>;
+
+// bool getRandom(size_t numBytes, vector<uint8_t>& output) {
+optional<vector<uint8_t>> getRandom(size_t numBytes) {
+    vector<uint8_t> output;
+    output.resize(numBytes);
+    if (RAND_bytes(output.data(), numBytes) != 1) {
+        LOG(ERROR) << "RAND_bytes: failed getting " << numBytes << " random";
+        return {};
+    }
+    return output;
+}
+
+optional<vector<uint8_t>> decryptAes128Gcm(const vector<uint8_t>& key,
+                                           const vector<uint8_t>& encryptedData,
+                                           const vector<uint8_t>& additionalAuthenticatedData) {
+    int cipherTextSize = int(encryptedData.size()) - kAesGcmIvSize - kAesGcmTagSize;
+    if (cipherTextSize < 0) {
+        LOG(ERROR) << "encryptedData too small";
+        return {};
+    }
+    unsigned char* nonce = (unsigned char*)encryptedData.data();
+    unsigned char* cipherText = nonce + kAesGcmIvSize;
+    unsigned char* tag = cipherText + cipherTextSize;
+
+    vector<uint8_t> plainText;
+    plainText.resize(cipherTextSize);
+
+    auto ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new());
+    if (ctx.get() == nullptr) {
+        LOG(ERROR) << "EVP_CIPHER_CTX_new: failed";
+        return {};
+    }
+
+    if (EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
+        LOG(ERROR) << "EVP_DecryptInit_ex: failed";
+        return {};
+    }
+
+    if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, kAesGcmIvSize, NULL) != 1) {
+        LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting nonce length";
+        return {};
+    }
+
+    if (EVP_DecryptInit_ex(ctx.get(), NULL, NULL, (unsigned char*)key.data(), nonce) != 1) {
+        LOG(ERROR) << "EVP_DecryptInit_ex: failed";
+        return {};
+    }
+
+    int numWritten;
+    if (additionalAuthenticatedData.size() > 0) {
+        if (EVP_DecryptUpdate(ctx.get(), NULL, &numWritten,
+                              (unsigned char*)additionalAuthenticatedData.data(),
+                              additionalAuthenticatedData.size()) != 1) {
+            LOG(ERROR) << "EVP_DecryptUpdate: failed for additionalAuthenticatedData";
+            return {};
+        }
+        if ((size_t)numWritten != additionalAuthenticatedData.size()) {
+            LOG(ERROR) << "EVP_DecryptUpdate: Unexpected outl=" << numWritten << " (expected "
+                       << additionalAuthenticatedData.size() << ") for additionalAuthenticatedData";
+            return {};
+        }
+    }
+
+    if (EVP_DecryptUpdate(ctx.get(), (unsigned char*)plainText.data(), &numWritten, cipherText,
+                          cipherTextSize) != 1) {
+        LOG(ERROR) << "EVP_DecryptUpdate: failed";
+        return {};
+    }
+    if (numWritten != cipherTextSize) {
+        LOG(ERROR) << "EVP_DecryptUpdate: Unexpected outl=" << numWritten << " (expected "
+                   << cipherTextSize << ")";
+        return {};
+    }
+
+    if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kAesGcmTagSize, tag)) {
+        LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting expected tag";
+        return {};
+    }
+
+    int ret = EVP_DecryptFinal_ex(ctx.get(), (unsigned char*)plainText.data() + numWritten,
+                                  &numWritten);
+    if (ret != 1) {
+        LOG(ERROR) << "EVP_DecryptFinal_ex: failed";
+        return {};
+    }
+    if (numWritten != 0) {
+        LOG(ERROR) << "EVP_DecryptFinal_ex: Unexpected non-zero outl=" << numWritten;
+        return {};
+    }
+
+    return plainText;
+}
+
+optional<vector<uint8_t>> encryptAes128Gcm(const vector<uint8_t>& key, const vector<uint8_t>& nonce,
+                                           const vector<uint8_t>& data,
+                                           const vector<uint8_t>& additionalAuthenticatedData) {
+    if (key.size() != kAes128GcmKeySize) {
+        LOG(ERROR) << "key is not kAes128GcmKeySize bytes";
+        return {};
+    }
+    if (nonce.size() != kAesGcmIvSize) {
+        LOG(ERROR) << "nonce is not kAesGcmIvSize bytes";
+        return {};
+    }
+
+    // The result is the nonce (kAesGcmIvSize bytes), the ciphertext, and
+    // finally the tag (kAesGcmTagSize bytes).
+    vector<uint8_t> encryptedData;
+    encryptedData.resize(data.size() + kAesGcmIvSize + kAesGcmTagSize);
+    unsigned char* noncePtr = (unsigned char*)encryptedData.data();
+    unsigned char* cipherText = noncePtr + kAesGcmIvSize;
+    unsigned char* tag = cipherText + data.size();
+    memcpy(noncePtr, nonce.data(), kAesGcmIvSize);
+
+    auto ctx = EvpCipherCtxPtr(EVP_CIPHER_CTX_new());
+    if (ctx.get() == nullptr) {
+        LOG(ERROR) << "EVP_CIPHER_CTX_new: failed";
+        return {};
+    }
+
+    if (EVP_EncryptInit_ex(ctx.get(), EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) {
+        LOG(ERROR) << "EVP_EncryptInit_ex: failed";
+        return {};
+    }
+
+    if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, kAesGcmIvSize, NULL) != 1) {
+        LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed setting nonce length";
+        return {};
+    }
+
+    if (EVP_EncryptInit_ex(ctx.get(), NULL, NULL, (unsigned char*)key.data(),
+                           (unsigned char*)nonce.data()) != 1) {
+        LOG(ERROR) << "EVP_EncryptInit_ex: failed";
+        return {};
+    }
+
+    int numWritten;
+    if (additionalAuthenticatedData.size() > 0) {
+        if (EVP_EncryptUpdate(ctx.get(), NULL, &numWritten,
+                              (unsigned char*)additionalAuthenticatedData.data(),
+                              additionalAuthenticatedData.size()) != 1) {
+            LOG(ERROR) << "EVP_EncryptUpdate: failed for additionalAuthenticatedData";
+            return {};
+        }
+        if ((size_t)numWritten != additionalAuthenticatedData.size()) {
+            LOG(ERROR) << "EVP_EncryptUpdate: Unexpected outl=" << numWritten << " (expected "
+                       << additionalAuthenticatedData.size() << ") for additionalAuthenticatedData";
+            return {};
+        }
+    }
+
+    if (data.size() > 0) {
+        if (EVP_EncryptUpdate(ctx.get(), cipherText, &numWritten, (unsigned char*)data.data(),
+                              data.size()) != 1) {
+            LOG(ERROR) << "EVP_EncryptUpdate: failed";
+            return {};
+        }
+        if ((size_t)numWritten != data.size()) {
+            LOG(ERROR) << "EVP_EncryptUpdate: Unexpected outl=" << numWritten << " (expected "
+                       << data.size() << ")";
+            return {};
+        }
+    }
+
+    if (EVP_EncryptFinal_ex(ctx.get(), cipherText + numWritten, &numWritten) != 1) {
+        LOG(ERROR) << "EVP_EncryptFinal_ex: failed";
+        return {};
+    }
+    if (numWritten != 0) {
+        LOG(ERROR) << "EVP_EncryptFinal_ex: Unexpected non-zero outl=" << numWritten;
+        return {};
+    }
+
+    if (EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kAesGcmTagSize, tag) != 1) {
+        LOG(ERROR) << "EVP_CIPHER_CTX_ctrl: failed getting tag";
+        return {};
+    }
+
+    return encryptedData;
+}
+
+struct EC_KEY_Deleter {
+    void operator()(EC_KEY* key) const {
+        if (key != nullptr) {
+            EC_KEY_free(key);
+        }
+    }
+};
+using EC_KEY_Ptr = unique_ptr<EC_KEY, EC_KEY_Deleter>;
+
+struct EVP_PKEY_Deleter {
+    void operator()(EVP_PKEY* key) const {
+        if (key != nullptr) {
+            EVP_PKEY_free(key);
+        }
+    }
+};
+using EVP_PKEY_Ptr = unique_ptr<EVP_PKEY, EVP_PKEY_Deleter>;
+
+struct EVP_PKEY_CTX_Deleter {
+    void operator()(EVP_PKEY_CTX* ctx) const {
+        if (ctx != nullptr) {
+            EVP_PKEY_CTX_free(ctx);
+        }
+    }
+};
+using EVP_PKEY_CTX_Ptr = unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Deleter>;
+
+struct EC_GROUP_Deleter {
+    void operator()(EC_GROUP* group) const {
+        if (group != nullptr) {
+            EC_GROUP_free(group);
+        }
+    }
+};
+using EC_GROUP_Ptr = unique_ptr<EC_GROUP, EC_GROUP_Deleter>;
+
+struct EC_POINT_Deleter {
+    void operator()(EC_POINT* point) const {
+        if (point != nullptr) {
+            EC_POINT_free(point);
+        }
+    }
+};
+
+using EC_POINT_Ptr = unique_ptr<EC_POINT, EC_POINT_Deleter>;
+
+struct ECDSA_SIG_Deleter {
+    void operator()(ECDSA_SIG* sig) const {
+        if (sig != nullptr) {
+            ECDSA_SIG_free(sig);
+        }
+    }
+};
+using ECDSA_SIG_Ptr = unique_ptr<ECDSA_SIG, ECDSA_SIG_Deleter>;
+
+struct X509_Deleter {
+    void operator()(X509* x509) const {
+        if (x509 != nullptr) {
+            X509_free(x509);
+        }
+    }
+};
+using X509_Ptr = unique_ptr<X509, X509_Deleter>;
+
+struct PKCS12_Deleter {
+    void operator()(PKCS12* pkcs12) const {
+        if (pkcs12 != nullptr) {
+            PKCS12_free(pkcs12);
+        }
+    }
+};
+using PKCS12_Ptr = unique_ptr<PKCS12, PKCS12_Deleter>;
+
+struct BIGNUM_Deleter {
+    void operator()(BIGNUM* bignum) const {
+        if (bignum != nullptr) {
+            BN_free(bignum);
+        }
+    }
+};
+using BIGNUM_Ptr = unique_ptr<BIGNUM, BIGNUM_Deleter>;
+
+struct ASN1_INTEGER_Deleter {
+    void operator()(ASN1_INTEGER* value) const {
+        if (value != nullptr) {
+            ASN1_INTEGER_free(value);
+        }
+    }
+};
+using ASN1_INTEGER_Ptr = unique_ptr<ASN1_INTEGER, ASN1_INTEGER_Deleter>;
+
+struct ASN1_TIME_Deleter {
+    void operator()(ASN1_TIME* value) const {
+        if (value != nullptr) {
+            ASN1_TIME_free(value);
+        }
+    }
+};
+using ASN1_TIME_Ptr = unique_ptr<ASN1_TIME, ASN1_TIME_Deleter>;
+
+struct X509_NAME_Deleter {
+    void operator()(X509_NAME* value) const {
+        if (value != nullptr) {
+            X509_NAME_free(value);
+        }
+    }
+};
+using X509_NAME_Ptr = unique_ptr<X509_NAME, X509_NAME_Deleter>;
+
+vector<uint8_t> certificateChainJoin(const vector<vector<uint8_t>>& certificateChain) {
+    vector<uint8_t> ret;
+    for (const vector<uint8_t>& certificate : certificateChain) {
+        ret.insert(ret.end(), certificate.begin(), certificate.end());
+    }
+    return ret;
+}
+
+optional<vector<vector<uint8_t>>> certificateChainSplit(const vector<uint8_t>& certificateChain) {
+    const unsigned char* pStart = (unsigned char*)certificateChain.data();
+    const unsigned char* p = pStart;
+    const unsigned char* pEnd = p + certificateChain.size();
+    vector<vector<uint8_t>> certificates;
+    while (p < pEnd) {
+        size_t begin = p - pStart;
+        auto x509 = X509_Ptr(d2i_X509(nullptr, &p, pEnd - p));
+        size_t next = p - pStart;
+        if (x509 == nullptr) {
+            LOG(ERROR) << "Error parsing X509 certificate";
+            return {};
+        }
+        vector<uint8_t> cert =
+                vector<uint8_t>(certificateChain.begin() + begin, certificateChain.begin() + next);
+        certificates.push_back(std::move(cert));
+    }
+    return certificates;
+}
+
+static bool parseX509Certificates(const vector<uint8_t>& certificateChain,
+                                  vector<X509_Ptr>& parsedCertificates) {
+    const unsigned char* p = (unsigned char*)certificateChain.data();
+    const unsigned char* pEnd = p + certificateChain.size();
+    parsedCertificates.resize(0);
+    while (p < pEnd) {
+        auto x509 = X509_Ptr(d2i_X509(nullptr, &p, pEnd - p));
+        if (x509 == nullptr) {
+            LOG(ERROR) << "Error parsing X509 certificate";
+            return false;
+        }
+        parsedCertificates.push_back(std::move(x509));
+    }
+    return true;
+}
+
+// TODO: Right now the only check we perform is to check that each certificate
+//       is signed by its successor. We should - but currently don't - also check
+//       things like valid dates etc.
+//
+//       It would be nice to use X509_verify_cert() instead of doing our own thing.
+//
+bool certificateChainValidate(const vector<uint8_t>& certificateChain) {
+    vector<X509_Ptr> certs;
+
+    if (!parseX509Certificates(certificateChain, certs)) {
+        LOG(ERROR) << "Error parsing X509 certificates";
+        return false;
+    }
+
+    if (certs.size() == 1) {
+        return true;
+    }
+
+    for (size_t n = 1; n < certs.size(); n++) {
+        const X509_Ptr& keyCert = certs[n - 1];
+        const X509_Ptr& signingCert = certs[n];
+        EVP_PKEY_Ptr signingPubkey(X509_get_pubkey(signingCert.get()));
+        if (X509_verify(keyCert.get(), signingPubkey.get()) != 1) {
+            LOG(ERROR) << "Error validating cert at index " << n - 1
+                       << " is signed by its successor";
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool checkEcDsaSignature(const vector<uint8_t>& digest, const vector<uint8_t>& signature,
+                         const vector<uint8_t>& publicKey) {
+    const unsigned char* p = (unsigned char*)signature.data();
+    auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, signature.size()));
+    if (sig.get() == nullptr) {
+        LOG(ERROR) << "Error decoding DER encoded signature";
+        return false;
+    }
+
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
+        1) {
+        LOG(ERROR) << "Error decoding publicKey";
+        return false;
+    }
+    auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (ecKey.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return false;
+    }
+    if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
+        LOG(ERROR) << "Error setting group";
+        return false;
+    }
+    if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
+        LOG(ERROR) << "Error setting point";
+        return false;
+    }
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
+        LOG(ERROR) << "Error setting key";
+        return false;
+    }
+
+    int rc = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), ecKey.get());
+    if (rc != 1) {
+        LOG(ERROR) << "Error verifying signature (rc=" << rc << ")";
+        return false;
+    }
+
+    return true;
+}
+
+vector<uint8_t> sha256(const vector<uint8_t>& data) {
+    vector<uint8_t> ret;
+    ret.resize(SHA256_DIGEST_LENGTH);
+    SHA256_CTX ctx;
+    SHA256_Init(&ctx);
+    SHA256_Update(&ctx, data.data(), data.size());
+    SHA256_Final((unsigned char*)ret.data(), &ctx);
+    return ret;
+}
+
+optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data) {
+    auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr));
+    if (bn.get() == nullptr) {
+        LOG(ERROR) << "Error creating BIGNUM";
+        return {};
+    }
+
+    auto ec_key = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    if (EC_KEY_set_private_key(ec_key.get(), bn.get()) != 1) {
+        LOG(ERROR) << "Error setting private key from BIGNUM";
+        return {};
+    }
+
+    auto digest = sha256(data);
+    ECDSA_SIG* sig = ECDSA_do_sign(digest.data(), digest.size(), ec_key.get());
+    if (sig == nullptr) {
+        LOG(ERROR) << "Error signing digest";
+        return {};
+    }
+    size_t len = i2d_ECDSA_SIG(sig, nullptr);
+    vector<uint8_t> signature;
+    signature.resize(len);
+    unsigned char* p = (unsigned char*)signature.data();
+    i2d_ECDSA_SIG(sig, &p);
+    ECDSA_SIG_free(sig);
+    return signature;
+}
+
+optional<vector<uint8_t>> hmacSha256(const vector<uint8_t>& key, const vector<uint8_t>& data) {
+    HMAC_CTX ctx;
+    HMAC_CTX_init(&ctx);
+    if (HMAC_Init_ex(&ctx, key.data(), key.size(), EVP_sha256(), nullptr /* impl */) != 1) {
+        LOG(ERROR) << "Error initializing HMAC_CTX";
+        return {};
+    }
+    if (HMAC_Update(&ctx, data.data(), data.size()) != 1) {
+        LOG(ERROR) << "Error updating HMAC_CTX";
+        return {};
+    }
+    vector<uint8_t> hmac;
+    hmac.resize(32);
+    unsigned int size = 0;
+    if (HMAC_Final(&ctx, hmac.data(), &size) != 1) {
+        LOG(ERROR) << "Error finalizing HMAC_CTX";
+        return {};
+    }
+    if (size != 32) {
+        LOG(ERROR) << "Expected 32 bytes from HMAC_Final, got " << size;
+        return {};
+    }
+    return hmac;
+}
+
+optional<vector<uint8_t>> createEcKeyPair() {
+    auto ec_key = EC_KEY_Ptr(EC_KEY_new());
+    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    if (ec_key.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+
+    if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+        LOG(ERROR) << "Error generating key";
+        return {};
+    }
+
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
+        LOG(ERROR) << "Error getting private key";
+        return {};
+    }
+
+    int size = i2d_PrivateKey(pkey.get(), nullptr);
+    if (size == 0) {
+        LOG(ERROR) << "Error generating public key encoding";
+        return {};
+    }
+    vector<uint8_t> keyPair;
+    keyPair.resize(size);
+    unsigned char* p = keyPair.data();
+    i2d_PrivateKey(pkey.get(), &p);
+    return keyPair;
+}
+
+optional<vector<uint8_t>> ecKeyPairGetPublicKey(const vector<uint8_t>& keyPair) {
+    const unsigned char* p = (const unsigned char*)keyPair.data();
+    auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
+    if (pkey.get() == nullptr) {
+        LOG(ERROR) << "Error parsing keyPair";
+        return {};
+    }
+
+    auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
+    if (ecKey.get() == nullptr) {
+        LOG(ERROR) << "Failed getting EC key";
+        return {};
+    }
+
+    auto ecGroup = EC_KEY_get0_group(ecKey.get());
+    auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
+    int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
+                                  nullptr);
+    if (size == 0) {
+        LOG(ERROR) << "Error generating public key encoding";
+        return {};
+    }
+
+    vector<uint8_t> publicKey;
+    publicKey.resize(size);
+    EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
+                       publicKey.size(), nullptr);
+    return publicKey;
+}
+
+optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair) {
+    const unsigned char* p = (const unsigned char*)keyPair.data();
+    auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
+    if (pkey.get() == nullptr) {
+        LOG(ERROR) << "Error parsing keyPair";
+        return {};
+    }
+
+    auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
+    if (ecKey.get() == nullptr) {
+        LOG(ERROR) << "Failed getting EC key";
+        return {};
+    }
+
+    const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey.get());
+    if (bignum == nullptr) {
+        LOG(ERROR) << "Error getting bignum from private key";
+        return {};
+    }
+    vector<uint8_t> privateKey;
+    privateKey.resize(BN_num_bytes(bignum));
+    BN_bn2bin(bignum, privateKey.data());
+    return privateKey;
+}
+
+optional<vector<uint8_t>> ecKeyPairGetPkcs12(const vector<uint8_t>& keyPair, const string& name,
+                                             const string& serialDecimal, const string& issuer,
+                                             const string& subject, time_t validityNotBefore,
+                                             time_t validityNotAfter) {
+    const unsigned char* p = (const unsigned char*)keyPair.data();
+    auto pkey = EVP_PKEY_Ptr(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, keyPair.size()));
+    if (pkey.get() == nullptr) {
+        LOG(ERROR) << "Error parsing keyPair";
+        return {};
+    }
+
+    auto x509 = X509_Ptr(X509_new());
+    if (!x509.get()) {
+        LOG(ERROR) << "Error creating X509 certificate";
+        return {};
+    }
+
+    if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
+        LOG(ERROR) << "Error setting version to 3";
+        return {};
+    }
+
+    if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
+        LOG(ERROR) << "Error setting public key";
+        return {};
+    }
+
+    BIGNUM* bignumSerial = nullptr;
+    if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
+        LOG(ERROR) << "Error parsing serial";
+        return {};
+    }
+    auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
+    auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
+    if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
+        LOG(ERROR) << "Error setting serial";
+        return {};
+    }
+
+    auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
+    if (x509Issuer.get() == nullptr ||
+        X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
+                                   (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
+                                   0 /* set */) != 1 ||
+        X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
+        LOG(ERROR) << "Error setting issuer";
+        return {};
+    }
+
+    auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
+    if (x509Subject.get() == nullptr ||
+        X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
+                                   (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
+                                   0 /* set */) != 1 ||
+        X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
+        LOG(ERROR) << "Error setting subject";
+        return {};
+    }
+
+    auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
+    if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
+        LOG(ERROR) << "Error setting notBefore";
+        return {};
+    }
+
+    auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
+    if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
+        LOG(ERROR) << "Error setting notAfter";
+        return {};
+    }
+
+    if (X509_sign(x509.get(), pkey.get(), EVP_sha256()) == 0) {
+        LOG(ERROR) << "Error signing X509 certificate";
+        return {};
+    }
+
+    // Ideally we wouldn't encrypt it (we're only using this function for
+    // sending a key-pair over binder to the Android app) but BoringSSL does not
+    // support this: from pkcs8_x509.c in BoringSSL: "In OpenSSL, -1 here means
+    // to use no encryption, which we do not currently support."
+    //
+    // Passing nullptr as |pass|, though, means "no password". So we'll do that.
+    // Compare with the receiving side - CredstoreIdentityCredential.java - where
+    // an empty char[] is passed as the password.
+    //
+    auto pkcs12 = PKCS12_Ptr(PKCS12_create(nullptr, name.c_str(), pkey.get(), x509.get(),
+                                           nullptr,  // ca
+                                           0,        // nid_key
+                                           0,        // nid_cert
+                                           0,        // iter,
+                                           0,        // mac_iter,
+                                           0));      // keytype
+    if (pkcs12.get() == nullptr) {
+        char buf[128];
+        long errCode = ERR_get_error();
+        ERR_error_string_n(errCode, buf, sizeof buf);
+        LOG(ERROR) << "Error creating PKCS12, code " << errCode << ": " << buf;
+        return {};
+    }
+
+    unsigned char* buffer = nullptr;
+    int length = i2d_PKCS12(pkcs12.get(), &buffer);
+    if (length < 0) {
+        LOG(ERROR) << "Error encoding PKCS12";
+        return {};
+    }
+    vector<uint8_t> pkcs12Bytes;
+    pkcs12Bytes.resize(length);
+    memcpy(pkcs12Bytes.data(), buffer, length);
+    OPENSSL_free(buffer);
+
+    return pkcs12Bytes;
+}
+
+optional<vector<uint8_t>> ecPublicKeyGenerateCertificate(
+        const vector<uint8_t>& publicKey, const vector<uint8_t>& signingKey,
+        const string& serialDecimal, const string& issuer, const string& subject,
+        time_t validityNotBefore, time_t validityNotAfter) {
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
+        1) {
+        LOG(ERROR) << "Error decoding publicKey";
+        return {};
+    }
+    auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (ecKey.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+    if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
+        LOG(ERROR) << "Error setting group";
+        return {};
+    }
+    if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
+        LOG(ERROR) << "Error setting point";
+        return {};
+    }
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
+        LOG(ERROR) << "Error setting key";
+        return {};
+    }
+
+    auto bn = BIGNUM_Ptr(BN_bin2bn(signingKey.data(), signingKey.size(), nullptr));
+    if (bn.get() == nullptr) {
+        LOG(ERROR) << "Error creating BIGNUM for private key";
+        return {};
+    }
+    auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
+        LOG(ERROR) << "Error setting private key from BIGNUM";
+        return {};
+    }
+    auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
+        LOG(ERROR) << "Error setting private key";
+        return {};
+    }
+
+    auto x509 = X509_Ptr(X509_new());
+    if (!x509.get()) {
+        LOG(ERROR) << "Error creating X509 certificate";
+        return {};
+    }
+
+    if (!X509_set_version(x509.get(), 2 /* version 3, but zero-based */)) {
+        LOG(ERROR) << "Error setting version to 3";
+        return {};
+    }
+
+    if (X509_set_pubkey(x509.get(), pkey.get()) != 1) {
+        LOG(ERROR) << "Error setting public key";
+        return {};
+    }
+
+    BIGNUM* bignumSerial = nullptr;
+    if (BN_dec2bn(&bignumSerial, serialDecimal.c_str()) == 0) {
+        LOG(ERROR) << "Error parsing serial";
+        return {};
+    }
+    auto bignumSerialPtr = BIGNUM_Ptr(bignumSerial);
+    auto asnSerial = ASN1_INTEGER_Ptr(BN_to_ASN1_INTEGER(bignumSerial, nullptr));
+    if (X509_set_serialNumber(x509.get(), asnSerial.get()) != 1) {
+        LOG(ERROR) << "Error setting serial";
+        return {};
+    }
+
+    auto x509Issuer = X509_NAME_Ptr(X509_NAME_new());
+    if (x509Issuer.get() == nullptr ||
+        X509_NAME_add_entry_by_txt(x509Issuer.get(), "CN", MBSTRING_ASC,
+                                   (const uint8_t*)issuer.c_str(), issuer.size(), -1 /* loc */,
+                                   0 /* set */) != 1 ||
+        X509_set_issuer_name(x509.get(), x509Issuer.get()) != 1) {
+        LOG(ERROR) << "Error setting issuer";
+        return {};
+    }
+
+    auto x509Subject = X509_NAME_Ptr(X509_NAME_new());
+    if (x509Subject.get() == nullptr ||
+        X509_NAME_add_entry_by_txt(x509Subject.get(), "CN", MBSTRING_ASC,
+                                   (const uint8_t*)subject.c_str(), subject.size(), -1 /* loc */,
+                                   0 /* set */) != 1 ||
+        X509_set_subject_name(x509.get(), x509Subject.get()) != 1) {
+        LOG(ERROR) << "Error setting subject";
+        return {};
+    }
+
+    auto asnNotBefore = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotBefore));
+    if (asnNotBefore.get() == nullptr || X509_set_notBefore(x509.get(), asnNotBefore.get()) != 1) {
+        LOG(ERROR) << "Error setting notBefore";
+        return {};
+    }
+
+    auto asnNotAfter = ASN1_TIME_Ptr(ASN1_TIME_set(nullptr, validityNotAfter));
+    if (asnNotAfter.get() == nullptr || X509_set_notAfter(x509.get(), asnNotAfter.get()) != 1) {
+        LOG(ERROR) << "Error setting notAfter";
+        return {};
+    }
+
+    if (X509_sign(x509.get(), privPkey.get(), EVP_sha256()) == 0) {
+        LOG(ERROR) << "Error signing X509 certificate";
+        return {};
+    }
+
+    unsigned char* buffer = nullptr;
+    int length = i2d_X509(x509.get(), &buffer);
+    if (length < 0) {
+        LOG(ERROR) << "Error DER encoding X509 certificate";
+        return {};
+    }
+
+    vector<uint8_t> certificate;
+    certificate.resize(length);
+    memcpy(certificate.data(), buffer, length);
+    OPENSSL_free(buffer);
+    return certificate;
+}
+
+optional<vector<uint8_t>> ecdh(const vector<uint8_t>& publicKey,
+                               const vector<uint8_t>& privateKey) {
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
+        1) {
+        LOG(ERROR) << "Error decoding publicKey";
+        return {};
+    }
+    auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (ecKey.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+    if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
+        LOG(ERROR) << "Error setting group";
+        return {};
+    }
+    if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
+        LOG(ERROR) << "Error setting point";
+        return {};
+    }
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
+        LOG(ERROR) << "Error setting key";
+        return {};
+    }
+
+    auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
+    if (bn.get() == nullptr) {
+        LOG(ERROR) << "Error creating BIGNUM for private key";
+        return {};
+    }
+    auto privEcKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    if (EC_KEY_set_private_key(privEcKey.get(), bn.get()) != 1) {
+        LOG(ERROR) << "Error setting private key from BIGNUM";
+        return {};
+    }
+    auto privPkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (EVP_PKEY_set1_EC_KEY(privPkey.get(), privEcKey.get()) != 1) {
+        LOG(ERROR) << "Error setting private key";
+        return {};
+    }
+
+    auto ctx = EVP_PKEY_CTX_Ptr(EVP_PKEY_CTX_new(privPkey.get(), NULL));
+    if (ctx.get() == nullptr) {
+        LOG(ERROR) << "Error creating context";
+        return {};
+    }
+
+    if (EVP_PKEY_derive_init(ctx.get()) != 1) {
+        LOG(ERROR) << "Error initializing context";
+        return {};
+    }
+
+    if (EVP_PKEY_derive_set_peer(ctx.get(), pkey.get()) != 1) {
+        LOG(ERROR) << "Error setting peer";
+        return {};
+    }
+
+    /* Determine buffer length for shared secret */
+    size_t secretLen = 0;
+    if (EVP_PKEY_derive(ctx.get(), NULL, &secretLen) != 1) {
+        LOG(ERROR) << "Error determing length of shared secret";
+        return {};
+    }
+    vector<uint8_t> sharedSecret;
+    sharedSecret.resize(secretLen);
+
+    if (EVP_PKEY_derive(ctx.get(), sharedSecret.data(), &secretLen) != 1) {
+        LOG(ERROR) << "Error deriving shared secret";
+        return {};
+    }
+    return sharedSecret;
+}
+
+optional<vector<uint8_t>> hkdf(const vector<uint8_t>& sharedSecret, const vector<uint8_t>& salt,
+                               const vector<uint8_t>& info, size_t size) {
+    vector<uint8_t> derivedKey;
+    derivedKey.resize(size);
+    if (HKDF(derivedKey.data(), derivedKey.size(), EVP_sha256(), sharedSecret.data(),
+             sharedSecret.size(), salt.data(), salt.size(), info.data(), info.size()) != 1) {
+        LOG(ERROR) << "Error deriving key";
+        return {};
+    }
+    return derivedKey;
+}
+
+void removeLeadingZeroes(vector<uint8_t>& vec) {
+    while (vec.size() >= 1 && vec[0] == 0x00) {
+        vec.erase(vec.begin());
+    }
+}
+
+tuple<bool, vector<uint8_t>, vector<uint8_t>> ecPublicKeyGetXandY(
+        const vector<uint8_t>& publicKey) {
+    if (publicKey.size() != 65 || publicKey[0] != 0x04) {
+        LOG(ERROR) << "publicKey is not in the expected format";
+        return std::make_tuple(false, vector<uint8_t>(), vector<uint8_t>());
+    }
+    vector<uint8_t> x, y;
+    x.resize(32);
+    y.resize(32);
+    memcpy(x.data(), publicKey.data() + 1, 32);
+    memcpy(y.data(), publicKey.data() + 33, 32);
+
+    removeLeadingZeroes(x);
+    removeLeadingZeroes(y);
+
+    return std::make_tuple(true, x, y);
+}
+
+optional<vector<uint8_t>> certificateChainGetTopMostKey(const vector<uint8_t>& certificateChain) {
+    vector<X509_Ptr> certs;
+    if (!parseX509Certificates(certificateChain, certs)) {
+        return {};
+    }
+    if (certs.size() < 1) {
+        LOG(ERROR) << "No certificates in chain";
+        return {};
+    }
+
+    int algoId = OBJ_obj2nid(certs[0]->cert_info->key->algor->algorithm);
+    if (algoId != NID_X9_62_id_ecPublicKey) {
+        LOG(ERROR) << "Expected NID_X9_62_id_ecPublicKey, got " << OBJ_nid2ln(algoId);
+        return {};
+    }
+
+    auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
+    if (pkey.get() == nullptr) {
+        LOG(ERROR) << "No public key";
+        return {};
+    }
+
+    auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
+    if (ecKey.get() == nullptr) {
+        LOG(ERROR) << "Failed getting EC key";
+        return {};
+    }
+
+    auto ecGroup = EC_KEY_get0_group(ecKey.get());
+    auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
+    int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
+                                  nullptr);
+    if (size == 0) {
+        LOG(ERROR) << "Error generating public key encoding";
+        return {};
+    }
+    vector<uint8_t> publicKey;
+    publicKey.resize(size);
+    EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
+                       publicKey.size(), nullptr);
+    return publicKey;
+}
+
+// ---------------------------------------------------------------------------
+// COSE Utility Functions
+// ---------------------------------------------------------------------------
+
+vector<uint8_t> coseBuildToBeSigned(const vector<uint8_t>& encodedProtectedHeaders,
+                                    const vector<uint8_t>& data,
+                                    const vector<uint8_t>& detachedContent) {
+    cppbor::Array sigStructure;
+    sigStructure.add("Signature1");
+    sigStructure.add(encodedProtectedHeaders);
+
+    // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
+    // so external_aad is the empty bstr
+    vector<uint8_t> emptyExternalAad;
+    sigStructure.add(emptyExternalAad);
+
+    // Next field is the payload, independently of how it's transported (RFC
+    // 8152 section 4.4). Since our API specifies only one of |data| and
+    // |detachedContent| can be non-empty, it's simply just the non-empty one.
+    if (data.size() > 0) {
+        sigStructure.add(data);
+    } else {
+        sigStructure.add(detachedContent);
+    }
+    return sigStructure.encode();
+}
+
+vector<uint8_t> coseEncodeHeaders(const cppbor::Map& protectedHeaders) {
+    if (protectedHeaders.size() == 0) {
+        cppbor::Bstr emptyBstr(vector<uint8_t>({}));
+        return emptyBstr.encode();
+    }
+    return protectedHeaders.encode();
+}
+
+// From https://tools.ietf.org/html/rfc8152
+const int COSE_LABEL_ALG = 1;
+const int COSE_LABEL_X5CHAIN = 33;  // temporary identifier
+
+// From "COSE Algorithms" registry
+const int COSE_ALG_ECDSA_256 = -7;
+const int COSE_ALG_HMAC_256_256 = 5;
+
+bool ecdsaSignatureCoseToDer(const vector<uint8_t>& ecdsaCoseSignature,
+                             vector<uint8_t>& ecdsaDerSignature) {
+    if (ecdsaCoseSignature.size() != 64) {
+        LOG(ERROR) << "COSE signature length is " << ecdsaCoseSignature.size() << ", expected 64";
+        return false;
+    }
+
+    auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), 32, nullptr));
+    if (rBn.get() == nullptr) {
+        LOG(ERROR) << "Error creating BIGNUM for r";
+        return false;
+    }
+
+    auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + 32, 32, nullptr));
+    if (sBn.get() == nullptr) {
+        LOG(ERROR) << "Error creating BIGNUM for s";
+        return false;
+    }
+
+    ECDSA_SIG sig;
+    sig.r = rBn.get();
+    sig.s = sBn.get();
+
+    size_t len = i2d_ECDSA_SIG(&sig, nullptr);
+    ecdsaDerSignature.resize(len);
+    unsigned char* p = (unsigned char*)ecdsaDerSignature.data();
+    i2d_ECDSA_SIG(&sig, &p);
+
+    return true;
+}
+
+bool ecdsaSignatureDerToCose(const vector<uint8_t>& ecdsaDerSignature,
+                             vector<uint8_t>& ecdsaCoseSignature) {
+    ECDSA_SIG* sig;
+    const unsigned char* p = ecdsaDerSignature.data();
+    sig = d2i_ECDSA_SIG(nullptr, &p, ecdsaDerSignature.size());
+    if (sig == nullptr) {
+        LOG(ERROR) << "Error decoding DER signature";
+        return false;
+    }
+
+    ecdsaCoseSignature.clear();
+    ecdsaCoseSignature.resize(64);
+    if (BN_bn2binpad(sig->r, ecdsaCoseSignature.data(), 32) != 32) {
+        LOG(ERROR) << "Error encoding r";
+        return false;
+    }
+    if (BN_bn2binpad(sig->s, ecdsaCoseSignature.data() + 32, 32) != 32) {
+        LOG(ERROR) << "Error encoding s";
+        return false;
+    }
+    return true;
+}
+
+optional<vector<uint8_t>> coseSignEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data,
+                                        const vector<uint8_t>& detachedContent,
+                                        const vector<uint8_t>& certificateChain) {
+    cppbor::Map unprotectedHeaders;
+    cppbor::Map protectedHeaders;
+
+    if (data.size() > 0 && detachedContent.size() > 0) {
+        LOG(ERROR) << "data and detachedContent cannot both be non-empty";
+        return {};
+    }
+
+    protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
+
+    if (certificateChain.size() != 0) {
+        optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
+        if (!certs) {
+            LOG(ERROR) << "Error splitting certificate chain";
+            return {};
+        }
+        if (certs.value().size() == 1) {
+            unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
+        } else {
+            cppbor::Array certArray;
+            for (const vector<uint8_t>& cert : certs.value()) {
+                certArray.add(cert);
+            }
+            unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
+        }
+    }
+
+    vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
+    vector<uint8_t> toBeSigned =
+            coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
+
+    optional<vector<uint8_t>> derSignature = signEcDsa(key, toBeSigned);
+    if (!derSignature) {
+        LOG(ERROR) << "Error signing toBeSigned data";
+        return {};
+    }
+    vector<uint8_t> coseSignature;
+    if (!ecdsaSignatureDerToCose(derSignature.value(), coseSignature)) {
+        LOG(ERROR) << "Error converting ECDSA signature from DER to COSE format";
+        return {};
+    }
+
+    cppbor::Array coseSign1;
+    coseSign1.add(encodedProtectedHeaders);
+    coseSign1.add(std::move(unprotectedHeaders));
+    if (data.size() == 0) {
+        cppbor::Null nullValue;
+        coseSign1.add(std::move(nullValue));
+    } else {
+        coseSign1.add(data);
+    }
+    coseSign1.add(coseSignature);
+    vector<uint8_t> signatureCoseSign1;
+    signatureCoseSign1 = coseSign1.encode();
+    return signatureCoseSign1;
+}
+
+bool coseCheckEcDsaSignature(const vector<uint8_t>& signatureCoseSign1,
+                             const vector<uint8_t>& detachedContent,
+                             const vector<uint8_t>& publicKey) {
+    auto [item, _, message] = cppbor::parse(signatureCoseSign1);
+    if (item == nullptr) {
+        LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
+        return false;
+    }
+    const cppbor::Array* array = item->asArray();
+    if (array == nullptr) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array";
+        return false;
+    }
+    if (array->size() != 4) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
+        return false;
+    }
+
+    const cppbor::Bstr* encodedProtectedHeadersBstr = (*array)[0]->asBstr();
+    ;
+    if (encodedProtectedHeadersBstr == nullptr) {
+        LOG(ERROR) << "Value for encodedProtectedHeaders is not a bstr";
+        return false;
+    }
+    const vector<uint8_t> encodedProtectedHeaders = encodedProtectedHeadersBstr->value();
+
+    const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
+    if (unprotectedHeaders == nullptr) {
+        LOG(ERROR) << "Value for unprotectedHeaders is not a map";
+        return false;
+    }
+
+    vector<uint8_t> data;
+    const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
+    if (payloadAsSimple != nullptr) {
+        if (payloadAsSimple->asNull() == nullptr) {
+            LOG(ERROR) << "Value for payload is not null or a bstr";
+            return false;
+        }
+    } else {
+        const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
+        if (payloadAsBstr == nullptr) {
+            LOG(ERROR) << "Value for payload is not null or a bstr";
+            return false;
+        }
+        data = payloadAsBstr->value();  // TODO: avoid copy
+    }
+
+    if (data.size() > 0 && detachedContent.size() > 0) {
+        LOG(ERROR) << "data and detachedContent cannot both be non-empty";
+        return false;
+    }
+
+    const cppbor::Bstr* signatureBstr = (*array)[3]->asBstr();
+    if (signatureBstr == nullptr) {
+        LOG(ERROR) << "Value for signature is a bstr";
+        return false;
+    }
+    const vector<uint8_t>& coseSignature = signatureBstr->value();
+
+    vector<uint8_t> derSignature;
+    if (!ecdsaSignatureCoseToDer(coseSignature, derSignature)) {
+        LOG(ERROR) << "Error converting ECDSA signature from COSE to DER format";
+        return false;
+    }
+
+    vector<uint8_t> toBeSigned =
+            coseBuildToBeSigned(encodedProtectedHeaders, data, detachedContent);
+    if (!checkEcDsaSignature(support::sha256(toBeSigned), derSignature, publicKey)) {
+        LOG(ERROR) << "Signature check failed";
+        return false;
+    }
+    return true;
+}
+
+optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1) {
+    auto [item, _, message] = cppbor::parse(signatureCoseSign1);
+    if (item == nullptr) {
+        LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
+        return {};
+    }
+    const cppbor::Array* array = item->asArray();
+    if (array == nullptr) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array";
+        return {};
+    }
+    if (array->size() != 4) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
+        return {};
+    }
+
+    vector<uint8_t> data;
+    const cppbor::Simple* payloadAsSimple = (*array)[2]->asSimple();
+    if (payloadAsSimple != nullptr) {
+        if (payloadAsSimple->asNull() == nullptr) {
+            LOG(ERROR) << "Value for payload is not null or a bstr";
+            return {};
+        }
+        // payload is null, so |data| should be empty (as it is)
+    } else {
+        const cppbor::Bstr* payloadAsBstr = (*array)[2]->asBstr();
+        if (payloadAsBstr == nullptr) {
+            LOG(ERROR) << "Value for payload is not null or a bstr";
+            return {};
+        }
+        // Copy payload into |data|
+        data = payloadAsBstr->value();
+    }
+
+    return data;
+}
+
+optional<vector<uint8_t>> coseSignGetX5Chain(const vector<uint8_t>& signatureCoseSign1) {
+    auto [item, _, message] = cppbor::parse(signatureCoseSign1);
+    if (item == nullptr) {
+        LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
+        return {};
+    }
+    const cppbor::Array* array = item->asArray();
+    if (array == nullptr) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array";
+        return {};
+    }
+    if (array->size() != 4) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
+        return {};
+    }
+
+    const cppbor::Map* unprotectedHeaders = (*array)[1]->asMap();
+    if (unprotectedHeaders == nullptr) {
+        LOG(ERROR) << "Value for unprotectedHeaders is not a map";
+        return {};
+    }
+
+    for (size_t n = 0; n < unprotectedHeaders->size(); n++) {
+        auto [keyItem, valueItem] = (*unprotectedHeaders)[n];
+        const cppbor::Int* number = keyItem->asInt();
+        if (number == nullptr) {
+            LOG(ERROR) << "Key item in top-level map is not a number";
+            return {};
+        }
+        int label = number->value();
+        if (label == COSE_LABEL_X5CHAIN) {
+            const cppbor::Bstr* bstr = valueItem->asBstr();
+            if (bstr != nullptr) {
+                return bstr->value();
+            }
+            const cppbor::Array* array = valueItem->asArray();
+            if (array != nullptr) {
+                vector<uint8_t> certs;
+                for (size_t m = 0; m < array->size(); m++) {
+                    const cppbor::Bstr* bstr = ((*array)[m])->asBstr();
+                    if (bstr == nullptr) {
+                        LOG(ERROR) << "Item in x5chain array is not a bstr";
+                        return {};
+                    }
+                    const vector<uint8_t>& certValue = bstr->value();
+                    certs.insert(certs.end(), certValue.begin(), certValue.end());
+                }
+                return certs;
+            }
+            LOG(ERROR) << "Value for x5chain label is not a bstr or array";
+            return {};
+        }
+    }
+    LOG(ERROR) << "Did not find x5chain label in unprotected headers";
+    return {};
+}
+
+vector<uint8_t> coseBuildToBeMACed(const vector<uint8_t>& encodedProtectedHeaders,
+                                   const vector<uint8_t>& data,
+                                   const vector<uint8_t>& detachedContent) {
+    cppbor::Array macStructure;
+    macStructure.add("MAC0");
+    macStructure.add(encodedProtectedHeaders);
+
+    // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
+    // so external_aad is the empty bstr
+    vector<uint8_t> emptyExternalAad;
+    macStructure.add(emptyExternalAad);
+
+    // Next field is the payload, independently of how it's transported (RFC
+    // 8152 section 4.4). Since our API specifies only one of |data| and
+    // |detachedContent| can be non-empty, it's simply just the non-empty one.
+    if (data.size() > 0) {
+        macStructure.add(data);
+    } else {
+        macStructure.add(detachedContent);
+    }
+
+    return macStructure.encode();
+}
+
+optional<vector<uint8_t>> coseMac0(const vector<uint8_t>& key, const vector<uint8_t>& data,
+                                   const vector<uint8_t>& detachedContent) {
+    cppbor::Map unprotectedHeaders;
+    cppbor::Map protectedHeaders;
+
+    if (data.size() > 0 && detachedContent.size() > 0) {
+        LOG(ERROR) << "data and detachedContent cannot both be non-empty";
+        return {};
+    }
+
+    protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
+
+    vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
+    vector<uint8_t> toBeMACed = coseBuildToBeMACed(encodedProtectedHeaders, data, detachedContent);
+
+    optional<vector<uint8_t>> mac = hmacSha256(key, toBeMACed);
+    if (!mac) {
+        LOG(ERROR) << "Error MACing toBeMACed data";
+        return {};
+    }
+
+    cppbor::Array array;
+    array.add(encodedProtectedHeaders);
+    array.add(std::move(unprotectedHeaders));
+    if (data.size() == 0) {
+        cppbor::Null nullValue;
+        array.add(std::move(nullValue));
+    } else {
+        array.add(data);
+    }
+    array.add(mac.value());
+    return array.encode();
+}
+
+// ---------------------------------------------------------------------------
+// Platform abstraction.
+// ---------------------------------------------------------------------------
+
+// This is not a very random HBK but that's OK because this is the SW
+// implementation where it can't be kept secret.
+vector<uint8_t> hardwareBoundKey = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+const vector<uint8_t>& getHardwareBoundKey() {
+    return hardwareBoundKey;
+}
+
+// ---------------------------------------------------------------------------
+// Utility functions specific to IdentityCredential.
+// ---------------------------------------------------------------------------
+
+Result okResult{ResultCode::OK, ""};
+
+const Result& resultOK() {
+    return okResult;
+}
+
+Result result(ResultCode code, const char* format, ...) {
+    va_list ap;
+    va_start(ap, format);
+    string str;
+    android::base::StringAppendV(&str, format, ap);
+    va_end(ap);
+    return Result{code, str};
+}
+
+vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize) {
+    vector<vector<uint8_t>> ret;
+
+    size_t contentSize = content.size();
+    if (contentSize <= maxChunkSize) {
+        ret.push_back(content);
+        return ret;
+    }
+
+    size_t numChunks = (contentSize + maxChunkSize - 1) / maxChunkSize;
+
+    size_t pos = 0;
+    for (size_t n = 0; n < numChunks; n++) {
+        size_t size = contentSize - pos;
+        if (size > maxChunkSize) {
+            size = maxChunkSize;
+        }
+        auto begin = content.begin() + pos;
+        auto end = content.begin() + pos + size;
+        ret.emplace_back(vector<uint8_t>(begin, end));
+        pos += maxChunkSize;
+    }
+
+    return ret;
+}
+
+vector<uint8_t> secureAccessControlProfileEncodeCbor(const SecureAccessControlProfile& profile) {
+    cppbor::Map map;
+    map.add("id", profile.id);
+
+    if (profile.readerCertificate.size() > 0) {
+        map.add("readerCertificate", cppbor::Bstr(profile.readerCertificate));
+    }
+
+    if (profile.userAuthenticationRequired) {
+        map.add("userAuthenticationRequired", profile.userAuthenticationRequired);
+        map.add("timeoutMillis", profile.timeoutMillis);
+        map.add("secureUserId", profile.secureUserId);
+    }
+
+    return map.encode();
+}
+
+optional<vector<uint8_t>> secureAccessControlProfileCalcMac(
+        const SecureAccessControlProfile& profile, const vector<uint8_t>& storageKey) {
+    vector<uint8_t> cborData = secureAccessControlProfileEncodeCbor(profile);
+
+    optional<vector<uint8_t>> nonce = getRandom(12);
+    if (!nonce) {
+        return {};
+    }
+    optional<vector<uint8_t>> macO = encryptAes128Gcm(storageKey, nonce.value(), {}, cborData);
+    if (!macO) {
+        return {};
+    }
+    return macO.value();
+}
+
+bool secureAccessControlProfileCheckMac(const SecureAccessControlProfile& profile,
+                                        const vector<uint8_t>& storageKey) {
+    vector<uint8_t> cborData = secureAccessControlProfileEncodeCbor(profile);
+
+    if (profile.mac.size() < kAesGcmIvSize) {
+        return false;
+    }
+    vector<uint8_t> nonce =
+            vector<uint8_t>(profile.mac.begin(), profile.mac.begin() + kAesGcmIvSize);
+    optional<vector<uint8_t>> mac = encryptAes128Gcm(storageKey, nonce, {}, cborData);
+    if (!mac) {
+        return false;
+    }
+    if (mac.value() != vector<uint8_t>(profile.mac)) {
+        return false;
+    }
+    return true;
+}
+
+vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+const vector<uint8_t>& getTestHardwareBoundKey() {
+    return testHardwareBoundKey;
+}
+
+vector<uint8_t> entryCreateAdditionalData(const string& nameSpace, const string& name,
+                                          const vector<uint16_t> accessControlProfileIds) {
+    cppbor::Map map;
+    map.add("Namespace", nameSpace);
+    map.add("Name", name);
+
+    cppbor::Array acpIds;
+    for (auto id : accessControlProfileIds) {
+        acpIds.add(id);
+    }
+    map.add("AccessControlProfileIds", std::move(acpIds));
+    return map.encode();
+}
+
+}  // namespace support
+}  // namespace identity
+}  // namespace hardware
+}  // namespace android
diff --git a/identity/support/src/cppbor.cpp b/identity/support/src/cppbor.cpp
new file mode 100644
index 0000000..d289985
--- /dev/null
+++ b/identity/support/src/cppbor.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include "cppbor.h"
+#include "cppbor_parse.h"
+
+#define LOG_TAG "CppBor"
+#include <android-base/logging.h>
+
+namespace cppbor {
+
+namespace {
+
+template <typename T, typename Iterator, typename = std::enable_if<std::is_unsigned<T>::value>>
+Iterator writeBigEndian(T value, Iterator pos) {
+    for (unsigned i = 0; i < sizeof(value); ++i) {
+        *pos++ = static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1)));
+        value = static_cast<T>(value << 8);
+    }
+    return pos;
+}
+
+template <typename T, typename = std::enable_if<std::is_unsigned<T>::value>>
+void writeBigEndian(T value, std::function<void(uint8_t)>& cb) {
+    for (unsigned i = 0; i < sizeof(value); ++i) {
+        cb(static_cast<uint8_t>(value >> (8 * (sizeof(value) - 1))));
+        value = static_cast<T>(value << 8);
+    }
+}
+
+}  // namespace
+
+size_t headerSize(uint64_t addlInfo) {
+    if (addlInfo < ONE_BYTE_LENGTH) return 1;
+    if (addlInfo <= std::numeric_limits<uint8_t>::max()) return 2;
+    if (addlInfo <= std::numeric_limits<uint16_t>::max()) return 3;
+    if (addlInfo <= std::numeric_limits<uint32_t>::max()) return 5;
+    return 9;
+}
+
+uint8_t* encodeHeader(MajorType type, uint64_t addlInfo, uint8_t* pos, const uint8_t* end) {
+    size_t sz = headerSize(addlInfo);
+    if (end - pos < static_cast<ssize_t>(sz)) return nullptr;
+    switch (sz) {
+        case 1:
+            *pos++ = type | static_cast<uint8_t>(addlInfo);
+            return pos;
+        case 2:
+            *pos++ = type | ONE_BYTE_LENGTH;
+            *pos++ = static_cast<uint8_t>(addlInfo);
+            return pos;
+        case 3:
+            *pos++ = type | TWO_BYTE_LENGTH;
+            return writeBigEndian(static_cast<uint16_t>(addlInfo), pos);
+        case 5:
+            *pos++ = type | FOUR_BYTE_LENGTH;
+            return writeBigEndian(static_cast<uint32_t>(addlInfo), pos);
+        case 9:
+            *pos++ = type | EIGHT_BYTE_LENGTH;
+            return writeBigEndian(addlInfo, pos);
+        default:
+            CHECK(false);  // Impossible to get here.
+            return nullptr;
+    }
+}
+
+void encodeHeader(MajorType type, uint64_t addlInfo, EncodeCallback encodeCallback) {
+    size_t sz = headerSize(addlInfo);
+    switch (sz) {
+        case 1:
+            encodeCallback(type | static_cast<uint8_t>(addlInfo));
+            break;
+        case 2:
+            encodeCallback(type | ONE_BYTE_LENGTH);
+            encodeCallback(static_cast<uint8_t>(addlInfo));
+            break;
+        case 3:
+            encodeCallback(type | TWO_BYTE_LENGTH);
+            writeBigEndian(static_cast<uint16_t>(addlInfo), encodeCallback);
+            break;
+        case 5:
+            encodeCallback(type | FOUR_BYTE_LENGTH);
+            writeBigEndian(static_cast<uint32_t>(addlInfo), encodeCallback);
+            break;
+        case 9:
+            encodeCallback(type | EIGHT_BYTE_LENGTH);
+            writeBigEndian(addlInfo, encodeCallback);
+            break;
+        default:
+            CHECK(false);  // Impossible to get here.
+    }
+}
+
+bool Item::operator==(const Item& other) const& {
+    if (type() != other.type()) return false;
+    switch (type()) {
+        case UINT:
+            return *asUint() == *(other.asUint());
+        case NINT:
+            return *asNint() == *(other.asNint());
+        case BSTR:
+            return *asBstr() == *(other.asBstr());
+        case TSTR:
+            return *asTstr() == *(other.asTstr());
+        case ARRAY:
+            return *asArray() == *(other.asArray());
+        case MAP:
+            return *asMap() == *(other.asMap());
+        case SIMPLE:
+            return *asSimple() == *(other.asSimple());
+        case SEMANTIC:
+            return *asSemantic() == *(other.asSemantic());
+        default:
+            CHECK(false);  // Impossible to get here.
+            return false;
+    }
+}
+
+Nint::Nint(int64_t v) : mValue(v) {
+    CHECK(v < 0) << "Only negative values allowed";
+}
+
+bool Simple::operator==(const Simple& other) const& {
+    if (simpleType() != other.simpleType()) return false;
+
+    switch (simpleType()) {
+        case BOOLEAN:
+            return *asBool() == *(other.asBool());
+        case NULL_T:
+            return true;
+        default:
+            CHECK(false);  // Impossible to get here.
+            return false;
+    }
+}
+
+uint8_t* Bstr::encode(uint8_t* pos, const uint8_t* end) const {
+    pos = encodeHeader(mValue.size(), pos, end);
+    if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
+    return std::copy(mValue.begin(), mValue.end(), pos);
+}
+
+void Bstr::encodeValue(EncodeCallback encodeCallback) const {
+    for (auto c : mValue) {
+        encodeCallback(c);
+    }
+}
+
+uint8_t* Tstr::encode(uint8_t* pos, const uint8_t* end) const {
+    pos = encodeHeader(mValue.size(), pos, end);
+    if (!pos || end - pos < static_cast<ptrdiff_t>(mValue.size())) return nullptr;
+    return std::copy(mValue.begin(), mValue.end(), pos);
+}
+
+void Tstr::encodeValue(EncodeCallback encodeCallback) const {
+    for (auto c : mValue) {
+        encodeCallback(static_cast<uint8_t>(c));
+    }
+}
+
+bool CompoundItem::operator==(const CompoundItem& other) const& {
+    return type() == other.type()             //
+           && addlInfo() == other.addlInfo()  //
+           // Can't use vector::operator== because the contents are pointers.  std::equal lets us
+           // provide a predicate that does the dereferencing.
+           && std::equal(mEntries.begin(), mEntries.end(), other.mEntries.begin(),
+                         [](auto& a, auto& b) -> bool { return *a == *b; });
+}
+
+uint8_t* CompoundItem::encode(uint8_t* pos, const uint8_t* end) const {
+    pos = encodeHeader(addlInfo(), pos, end);
+    if (!pos) return nullptr;
+    for (auto& entry : mEntries) {
+        pos = entry->encode(pos, end);
+        if (!pos) return nullptr;
+    }
+    return pos;
+}
+
+void CompoundItem::encode(EncodeCallback encodeCallback) const {
+    encodeHeader(addlInfo(), encodeCallback);
+    for (auto& entry : mEntries) {
+        entry->encode(encodeCallback);
+    }
+}
+
+void Map::assertInvariant() const {
+    CHECK(mEntries.size() % 2 == 0);
+}
+
+std::unique_ptr<Item> Map::clone() const {
+    assertInvariant();
+    auto res = std::make_unique<Map>();
+    for (size_t i = 0; i < mEntries.size(); i += 2) {
+        res->add(mEntries[i]->clone(), mEntries[i + 1]->clone());
+    }
+    return res;
+}
+
+std::unique_ptr<Item> Array::clone() const {
+    auto res = std::make_unique<Array>();
+    for (size_t i = 0; i < mEntries.size(); i++) {
+        res->add(mEntries[i]->clone());
+    }
+    return res;
+}
+
+void Semantic::assertInvariant() const {
+    CHECK(mEntries.size() == 1);
+}
+
+}  // namespace cppbor
diff --git a/identity/support/src/cppbor_parse.cpp b/identity/support/src/cppbor_parse.cpp
new file mode 100644
index 0000000..c9ebb8a
--- /dev/null
+++ b/identity/support/src/cppbor_parse.cpp
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+#include "cppbor_parse.h"
+
+#include <sstream>
+#include <stack>
+
+#define LOG_TAG "CppBor"
+#include <android-base/logging.h>
+
+namespace cppbor {
+
+namespace {
+
+std::string insufficientLengthString(size_t bytesNeeded, size_t bytesAvail,
+                                     const std::string& type) {
+    std::stringstream errStream;
+    errStream << "Need " << bytesNeeded << " byte(s) for " << type << ", have " << bytesAvail
+              << ".";
+    return errStream.str();
+}
+
+template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
+std::tuple<bool, uint64_t, const uint8_t*> parseLength(const uint8_t* pos, const uint8_t* end,
+                                                       ParseClient* parseClient) {
+    if (pos + sizeof(T) > end) {
+        parseClient->error(pos - 1, insufficientLengthString(sizeof(T), end - pos, "length field"));
+        return {false, 0, pos};
+    }
+
+    const uint8_t* intEnd = pos + sizeof(T);
+    T result = 0;
+    do {
+        result = static_cast<T>((result << 8) | *pos++);
+    } while (pos < intEnd);
+    return {true, result, pos};
+}
+
+std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
+                                                          ParseClient* parseClient);
+
+std::tuple<const uint8_t*, ParseClient*> handleUint(uint64_t value, const uint8_t* hdrBegin,
+                                                    const uint8_t* hdrEnd,
+                                                    ParseClient* parseClient) {
+    std::unique_ptr<Item> item = std::make_unique<Uint>(value);
+    return {hdrEnd,
+            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
+}
+
+std::tuple<const uint8_t*, ParseClient*> handleNint(uint64_t value, const uint8_t* hdrBegin,
+                                                    const uint8_t* hdrEnd,
+                                                    ParseClient* parseClient) {
+    if (value > std::numeric_limits<int64_t>::max()) {
+        parseClient->error(hdrBegin, "NINT values that don't fit in int64_t are not supported.");
+        return {hdrBegin, nullptr /* end parsing */};
+    }
+    std::unique_ptr<Item> item = std::make_unique<Nint>(-1 - static_cast<uint64_t>(value));
+    return {hdrEnd,
+            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
+}
+
+std::tuple<const uint8_t*, ParseClient*> handleBool(uint64_t value, const uint8_t* hdrBegin,
+                                                    const uint8_t* hdrEnd,
+                                                    ParseClient* parseClient) {
+    std::unique_ptr<Item> item = std::make_unique<Bool>(value == TRUE);
+    return {hdrEnd,
+            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
+}
+
+std::tuple<const uint8_t*, ParseClient*> handleNull(const uint8_t* hdrBegin, const uint8_t* hdrEnd,
+                                                    ParseClient* parseClient) {
+    std::unique_ptr<Item> item = std::make_unique<Null>();
+    return {hdrEnd,
+            parseClient->item(item, hdrBegin, hdrEnd /* valueBegin */, hdrEnd /* itemEnd */)};
+}
+
+template <typename T>
+std::tuple<const uint8_t*, ParseClient*> handleString(uint64_t length, const uint8_t* hdrBegin,
+                                                      const uint8_t* valueBegin, const uint8_t* end,
+                                                      const std::string& errLabel,
+                                                      ParseClient* parseClient) {
+    if (end - valueBegin < static_cast<ssize_t>(length)) {
+        parseClient->error(hdrBegin, insufficientLengthString(length, end - valueBegin, errLabel));
+        return {hdrBegin, nullptr /* end parsing */};
+    }
+
+    std::unique_ptr<Item> item = std::make_unique<T>(valueBegin, valueBegin + length);
+    return {valueBegin + length,
+            parseClient->item(item, hdrBegin, valueBegin, valueBegin + length)};
+}
+
+class IncompleteItem {
+  public:
+    virtual ~IncompleteItem() {}
+    virtual void add(std::unique_ptr<Item> item) = 0;
+};
+
+class IncompleteArray : public Array, public IncompleteItem {
+  public:
+    IncompleteArray(size_t size) : mSize(size) {}
+
+    // We return the "complete" size, rather than the actual size.
+    size_t size() const override { return mSize; }
+
+    void add(std::unique_ptr<Item> item) override {
+        mEntries.reserve(mSize);
+        mEntries.push_back(std::move(item));
+    }
+
+  private:
+    size_t mSize;
+};
+
+class IncompleteMap : public Map, public IncompleteItem {
+  public:
+    IncompleteMap(size_t size) : mSize(size) {}
+
+    // We return the "complete" size, rather than the actual size.
+    size_t size() const override { return mSize; }
+
+    void add(std::unique_ptr<Item> item) override {
+        mEntries.reserve(mSize * 2);
+        mEntries.push_back(std::move(item));
+    }
+
+  private:
+    size_t mSize;
+};
+
+class IncompleteSemantic : public Semantic, public IncompleteItem {
+  public:
+    IncompleteSemantic(uint64_t value) : Semantic(value) {}
+
+    // We return the "complete" size, rather than the actual size.
+    size_t size() const override { return 1; }
+
+    void add(std::unique_ptr<Item> item) override {
+        mEntries.reserve(1);
+        mEntries.push_back(std::move(item));
+    }
+};
+
+std::tuple<const uint8_t*, ParseClient*> handleEntries(size_t entryCount, const uint8_t* hdrBegin,
+                                                       const uint8_t* pos, const uint8_t* end,
+                                                       const std::string& typeName,
+                                                       ParseClient* parseClient) {
+    while (entryCount > 0) {
+        --entryCount;
+        if (pos == end) {
+            parseClient->error(hdrBegin, "Not enough entries for " + typeName + ".");
+            return {hdrBegin, nullptr /* end parsing */};
+        }
+        std::tie(pos, parseClient) = parseRecursively(pos, end, parseClient);
+        if (!parseClient) return {hdrBegin, nullptr};
+    }
+    return {pos, parseClient};
+}
+
+std::tuple<const uint8_t*, ParseClient*> handleCompound(
+        std::unique_ptr<Item> item, uint64_t entryCount, const uint8_t* hdrBegin,
+        const uint8_t* valueBegin, const uint8_t* end, const std::string& typeName,
+        ParseClient* parseClient) {
+    parseClient =
+            parseClient->item(item, hdrBegin, valueBegin, valueBegin /* don't know the end yet */);
+    if (!parseClient) return {hdrBegin, nullptr};
+
+    const uint8_t* pos;
+    std::tie(pos, parseClient) =
+            handleEntries(entryCount, hdrBegin, valueBegin, end, typeName, parseClient);
+    if (!parseClient) return {hdrBegin, nullptr};
+
+    return {pos, parseClient->itemEnd(item, hdrBegin, valueBegin, pos)};
+}
+
+std::tuple<const uint8_t*, ParseClient*> parseRecursively(const uint8_t* begin, const uint8_t* end,
+                                                          ParseClient* parseClient) {
+    const uint8_t* pos = begin;
+
+    MajorType type = static_cast<MajorType>(*pos & 0xE0);
+    uint8_t tagInt = *pos & 0x1F;
+    ++pos;
+
+    bool success = true;
+    uint64_t addlData;
+    if (tagInt < ONE_BYTE_LENGTH || tagInt > EIGHT_BYTE_LENGTH) {
+        addlData = tagInt;
+    } else {
+        switch (tagInt) {
+            case ONE_BYTE_LENGTH:
+                std::tie(success, addlData, pos) = parseLength<uint8_t>(pos, end, parseClient);
+                break;
+
+            case TWO_BYTE_LENGTH:
+                std::tie(success, addlData, pos) = parseLength<uint16_t>(pos, end, parseClient);
+                break;
+
+            case FOUR_BYTE_LENGTH:
+                std::tie(success, addlData, pos) = parseLength<uint32_t>(pos, end, parseClient);
+                break;
+
+            case EIGHT_BYTE_LENGTH:
+                std::tie(success, addlData, pos) = parseLength<uint64_t>(pos, end, parseClient);
+                break;
+
+            default:
+                CHECK(false);  //  It's impossible to get here
+                break;
+        }
+    }
+
+    if (!success) return {begin, nullptr};
+
+    switch (type) {
+        case UINT:
+            return handleUint(addlData, begin, pos, parseClient);
+
+        case NINT:
+            return handleNint(addlData, begin, pos, parseClient);
+
+        case BSTR:
+            return handleString<Bstr>(addlData, begin, pos, end, "byte string", parseClient);
+
+        case TSTR:
+            return handleString<Tstr>(addlData, begin, pos, end, "text string", parseClient);
+
+        case ARRAY:
+            return handleCompound(std::make_unique<IncompleteArray>(addlData), addlData, begin, pos,
+                                  end, "array", parseClient);
+
+        case MAP:
+            return handleCompound(std::make_unique<IncompleteMap>(addlData), addlData * 2, begin,
+                                  pos, end, "map", parseClient);
+
+        case SEMANTIC:
+            return handleCompound(std::make_unique<IncompleteSemantic>(addlData), 1, begin, pos,
+                                  end, "semantic", parseClient);
+
+        case SIMPLE:
+            switch (addlData) {
+                case TRUE:
+                case FALSE:
+                    return handleBool(addlData, begin, pos, parseClient);
+                case NULL_V:
+                    return handleNull(begin, pos, parseClient);
+            }
+    }
+    CHECK(false);  // Impossible to get here.
+    return {};
+}
+
+class FullParseClient : public ParseClient {
+  public:
+    virtual ParseClient* item(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
+                              const uint8_t* end) override {
+        if (mParentStack.empty() && !item->isCompound()) {
+            // This is the first and only item.
+            mTheItem = std::move(item);
+            mPosition = end;
+            return nullptr;  //  We're done.
+        }
+
+        if (item->isCompound()) {
+            // Starting a new compound data item, i.e. a new parent.  Save it on the parent stack.
+            // It's safe to save a raw pointer because the unique_ptr is guaranteed to stay in
+            // existence until the corresponding itemEnd() call.
+            assert(dynamic_cast<CompoundItem*>(item.get()));
+            mParentStack.push(static_cast<CompoundItem*>(item.get()));
+            return this;
+        } else {
+            appendToLastParent(std::move(item));
+            return this;
+        }
+    }
+
+    virtual ParseClient* itemEnd(std::unique_ptr<Item>& item, const uint8_t*, const uint8_t*,
+                                 const uint8_t* end) override {
+        CHECK(item->isCompound() && item.get() == mParentStack.top());
+        mParentStack.pop();
+
+        if (mParentStack.empty()) {
+            mTheItem = std::move(item);
+            mPosition = end;
+            return nullptr;  // We're done
+        } else {
+            appendToLastParent(std::move(item));
+            return this;
+        }
+    }
+
+    virtual void error(const uint8_t* position, const std::string& errorMessage) override {
+        mPosition = position;
+        mErrorMessage = errorMessage;
+    }
+
+    std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
+               std::string /* errMsg */>
+    parseResult() {
+        std::unique_ptr<Item> p = std::move(mTheItem);
+        return {std::move(p), mPosition, std::move(mErrorMessage)};
+    }
+
+  private:
+    void appendToLastParent(std::unique_ptr<Item> item) {
+        auto parent = mParentStack.top();
+        assert(dynamic_cast<IncompleteItem*>(parent));
+        if (parent->type() == ARRAY) {
+            static_cast<IncompleteArray*>(parent)->add(std::move(item));
+        } else if (parent->type() == MAP) {
+            static_cast<IncompleteMap*>(parent)->add(std::move(item));
+        } else if (parent->type() == SEMANTIC) {
+            static_cast<IncompleteSemantic*>(parent)->add(std::move(item));
+        } else {
+            CHECK(false);  // Impossible to get here.
+        }
+    }
+
+    std::unique_ptr<Item> mTheItem;
+    std::stack<CompoundItem*> mParentStack;
+    const uint8_t* mPosition = nullptr;
+    std::string mErrorMessage;
+};
+
+}  // anonymous namespace
+
+void parse(const uint8_t* begin, const uint8_t* end, ParseClient* parseClient) {
+    parseRecursively(begin, end, parseClient);
+}
+
+std::tuple<std::unique_ptr<Item> /* result */, const uint8_t* /* newPos */,
+           std::string /* errMsg */>
+parse(const uint8_t* begin, const uint8_t* end) {
+    FullParseClient parseClient;
+    parse(begin, end, &parseClient);
+    return parseClient.parseResult();
+}
+
+}  // namespace cppbor
