/*
 * Copyright (C) 2015 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 "keystore"

#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>

#include <log/log.h>

#include "blob.h"

#include "keystore_utils.h"

#include <openssl/evp.h>
#include <openssl/rand.h>

#include <istream>
#include <ostream>
#include <streambuf>
#include <string>

#include <android-base/logging.h>

namespace {

constexpr size_t kGcmIvSizeBytes = 96 / 8;

template <typename T, void (*FreeFunc)(T*)> struct OpenSslObjectDeleter {
    void operator()(T* p) { FreeFunc(p); }
};

#define DEFINE_OPENSSL_OBJECT_POINTER(name)                                                        \
    typedef OpenSslObjectDeleter<name, name##_free> name##_Delete;                                 \
    typedef std::unique_ptr<name, name##_Delete> name##_Ptr;

DEFINE_OPENSSL_OBJECT_POINTER(EVP_CIPHER_CTX);

#if defined(__clang__)
#define OPTNONE __attribute__((optnone))
#elif defined(__GNUC__)
#define OPTNONE __attribute__((optimize("O0")))
#else
#error Need a definition for OPTNONE
#endif

class ArrayEraser {
  public:
    ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
    OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }

  private:
    volatile uint8_t* mArr;
    size_t mSize;
};

/**
 * Returns a EVP_CIPHER appropriate for the given key, based on the key's size.
 */
const EVP_CIPHER* getAesCipherForKey(const std::vector<uint8_t>& key) {
    const EVP_CIPHER* cipher = EVP_aes_256_gcm();
    if (key.size() == kAes128KeySizeBytes) {
        cipher = EVP_aes_128_gcm();
    }
    return cipher;
}

/*
 * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
 * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
 * 'tag'.
 */
ResponseCode AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len,
                             const std::vector<uint8_t>& key, const uint8_t* iv, uint8_t* tag) {

    // There can be 128-bit and 256-bit keys
    const EVP_CIPHER* cipher = getAesCipherForKey(key);

    EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());

    EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
    EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);

    std::unique_ptr<uint8_t[]> out_tmp(new uint8_t[len]);
    uint8_t* out_pos = out_tmp.get();
    int out_len;

    EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
    out_pos += out_len;
    EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
    out_pos += out_len;
    if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
        ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
              out_pos - out_tmp.get());
        return ResponseCode::SYSTEM_ERROR;
    }

    std::copy(out_tmp.get(), out_pos, out);
    EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);

    return ResponseCode::NO_ERROR;
}

/*
 * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
 * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
 * location as 'in').
 */
ResponseCode AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len,
                             const std::vector<uint8_t> key, const uint8_t* iv,
                             const uint8_t* tag) {

    // There can be 128-bit and 256-bit keys
    const EVP_CIPHER* cipher = getAesCipherForKey(key);

    EVP_CIPHER_CTX_Ptr ctx(EVP_CIPHER_CTX_new());

    EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key.data(), iv);
    EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
    EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));

    std::unique_ptr<uint8_t[]> out_tmp(new uint8_t[len]);
    ArrayEraser out_eraser(out_tmp.get(), len);
    uint8_t* out_pos = out_tmp.get();
    int out_len;

    EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
    out_pos += out_len;
    if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
        ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted");
        return ResponseCode::VALUE_CORRUPTED;
    }
    out_pos += out_len;
    if (out_pos - out_tmp.get() != static_cast<ssize_t>(len)) {
        ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
              out_pos - out_tmp.get());
        return ResponseCode::VALUE_CORRUPTED;
    }

    std::copy(out_tmp.get(), out_pos, out);

    return ResponseCode::NO_ERROR;
}

class ArrayStreamBuffer : public std::streambuf {
  public:
    template <typename T, size_t size> explicit ArrayStreamBuffer(const T (&data)[size]) {
        static_assert(sizeof(T) == 1, "Array element size too large");
        std::streambuf::char_type* d = const_cast<std::streambuf::char_type*>(
            reinterpret_cast<const std::streambuf::char_type*>(&data[0]));
        setg(d, d, d + size);
        setp(d, d + size);
    }

  protected:
    pos_type seekoff(off_type off, std::ios_base::seekdir dir,
                     std::ios_base::openmode which = std::ios_base::in |
                                                     std::ios_base::out) override {
        bool in = which & std::ios_base::in;
        bool out = which & std::ios_base::out;
        if ((!in && !out) || (in && out && dir == std::ios_base::cur)) return -1;
        std::streambuf::char_type* newPosPtr;
        switch (dir) {
        case std::ios_base::beg:
            newPosPtr = pbase();
            break;
        case std::ios_base::cur:
            // if dir == cur then in xor out due to
            // if ((!in && !out) || (in && out && dir == std::ios_base::cur)) return -1; above
            if (in)
                newPosPtr = gptr();
            else
                newPosPtr = pptr();
            break;
        case std::ios_base::end:
            // in and out bounds are the same and cannot change, so we can take either range
            // regardless of the value of "which"
            newPosPtr = epptr();
            break;
        }
        newPosPtr += off;
        if (newPosPtr < pbase() || newPosPtr > epptr()) return -1;
        if (in) {
            gbump(newPosPtr - gptr());
        }
        if (out) {
            pbump(newPosPtr - pptr());
        }
        return newPosPtr - pbase();
    }
};

}  // namespace

Blob::Blob(const uint8_t* value, size_t valueLength, const uint8_t* info, uint8_t infoLength,
           BlobType type) {
    mBlob = std::make_unique<blobv3>();
    memset(mBlob.get(), 0, sizeof(blobv3));
    if (valueLength > kValueSize) {
        valueLength = kValueSize;
        ALOGW("Provided blob length too large");
    }
    if (infoLength + valueLength > kValueSize) {
        infoLength = kValueSize - valueLength;
        ALOGW("Provided info length too large");
    }
    mBlob->length = valueLength;
    memcpy(mBlob->value, value, valueLength);

    mBlob->info = infoLength;
    memcpy(mBlob->value + valueLength, info, infoLength);

    mBlob->version = CURRENT_BLOB_VERSION;
    mBlob->type = uint8_t(type);

    if (type == TYPE_MASTER_KEY) {
        mBlob->flags = KEYSTORE_FLAG_ENCRYPTED;
    } else {
        mBlob->flags = KEYSTORE_FLAG_NONE;
    }
}

Blob::Blob(blobv3 b) {
    mBlob = std::make_unique<blobv3>(b);
}

Blob::Blob() {
    if (mBlob) *mBlob = {};
}

Blob::Blob(const Blob& rhs) {
    if (rhs.mBlob) {
        mBlob = std::make_unique<blobv3>(*rhs.mBlob);
    }
}

Blob::Blob(Blob&& rhs) : mBlob(std::move(rhs.mBlob)) {}

Blob& Blob::operator=(const Blob& rhs) {
    if (&rhs != this) {
        if (mBlob) *mBlob = {};
        if (rhs) {
            mBlob = std::make_unique<blobv3>(*rhs.mBlob);
        } else {
            mBlob = {};
        }
    }
    return *this;
}

Blob& Blob::operator=(Blob&& rhs) {
    if (mBlob) *mBlob = {};
    mBlob = std::move(rhs.mBlob);
    return *this;
}

template <typename BlobType> static bool rawBlobIsEncrypted(const BlobType& blob) {
    if (blob.version < 2) return true;

    return blob.flags & (KEYSTORE_FLAG_ENCRYPTED | KEYSTORE_FLAG_SUPER_ENCRYPTED);
}

bool Blob::isEncrypted() const {
    if (mBlob->version < 2) {
        return true;
    }

    return mBlob->flags & KEYSTORE_FLAG_ENCRYPTED;
}

bool Blob::isSuperEncrypted() const {
    return mBlob->flags & KEYSTORE_FLAG_SUPER_ENCRYPTED;
}

bool Blob::isCriticalToDeviceEncryption() const {
    return mBlob->flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
}

inline uint8_t setFlag(uint8_t flags, bool set, KeyStoreFlag flag) {
    return set ? (flags | flag) : (flags & ~flag);
}

void Blob::setEncrypted(bool encrypted) {
    mBlob->flags = setFlag(mBlob->flags, encrypted, KEYSTORE_FLAG_ENCRYPTED);
}

void Blob::setSuperEncrypted(bool superEncrypted) {
    mBlob->flags = setFlag(mBlob->flags, superEncrypted, KEYSTORE_FLAG_SUPER_ENCRYPTED);
}

void Blob::setCriticalToDeviceEncryption(bool critical) {
    mBlob->flags = setFlag(mBlob->flags, critical, KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
}

void Blob::setFallback(bool fallback) {
    if (fallback) {
        mBlob->flags |= KEYSTORE_FLAG_FALLBACK;
    } else {
        mBlob->flags &= ~KEYSTORE_FLAG_FALLBACK;
    }
}

static ResponseCode writeBlob(const std::string& filename, Blob blob, blobv3* rawBlob,
                              const std::vector<uint8_t>& aes_key, State state) {
    ALOGV("writing blob %s", filename.c_str());

    const size_t dataLength = rawBlob->length;
    rawBlob->length = htonl(rawBlob->length);

    if (blob.isEncrypted() || blob.isSuperEncrypted()) {
        if (state != STATE_NO_ERROR) {
            ALOGD("couldn't insert encrypted blob while not unlocked");
            return ResponseCode::LOCKED;
        }

        memset(rawBlob->initialization_vector, 0, AES_BLOCK_SIZE);
        if (!RAND_bytes(rawBlob->initialization_vector, kGcmIvSizeBytes)) {
            ALOGW("Could not read random data for: %s", filename.c_str());
            return ResponseCode::SYSTEM_ERROR;
        }

        auto rc = AES_gcm_encrypt(rawBlob->value /* in */, rawBlob->value /* out */, dataLength,
                                  aes_key, rawBlob->initialization_vector, rawBlob->aead_tag);
        if (rc != ResponseCode::NO_ERROR) return rc;
    }

    size_t fileLength = offsetof(blobv3, value) + dataLength + rawBlob->info;

    int out =
        TEMP_FAILURE_RETRY(open(filename.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR));
    if (out < 0) {
        ALOGW("could not open file: %s: %s", filename.c_str(), strerror(errno));
        return ResponseCode::SYSTEM_ERROR;
    }

    const size_t writtenBytes = writeFully(out, reinterpret_cast<uint8_t*>(rawBlob), fileLength);
    if (close(out) != 0) {
        return ResponseCode::SYSTEM_ERROR;
    }
    if (writtenBytes != fileLength) {
        ALOGW("blob not fully written %zu != %zu", writtenBytes, fileLength);
        unlink(filename.c_str());
        return ResponseCode::SYSTEM_ERROR;
    }
    return ResponseCode::NO_ERROR;
}

ResponseCode LockedKeyBlobEntry::writeBlobs(Blob keyBlob, Blob characteristicsBlob,
                                            const std::vector<uint8_t>& aes_key,
                                            State state) const {
    if (entry_ == nullptr) {
        return ResponseCode::SYSTEM_ERROR;
    }
    ResponseCode rc;
    if (keyBlob) {
        blobv3* rawBlob = keyBlob.mBlob.get();
        rc = writeBlob(entry_->getKeyBlobPath(), std::move(keyBlob), rawBlob, aes_key, state);
        if (rc != ResponseCode::NO_ERROR) {
            return rc;
        }
    }

    if (characteristicsBlob) {
        blobv3* rawBlob = characteristicsBlob.mBlob.get();
        rc = writeBlob(entry_->getCharacteristicsBlobPath(), std::move(characteristicsBlob),
                       rawBlob, aes_key, state);
    }
    return rc;
}

ResponseCode Blob::readBlob(const std::string& filename, const std::vector<uint8_t>& aes_key,
                            State state) {
    ResponseCode rc;
    ALOGV("reading blob %s", filename.c_str());
    std::unique_ptr<blobv3> rawBlob = std::make_unique<blobv3>();

    const int in = TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY));
    if (in < 0) {
        return (errno == ENOENT) ? ResponseCode::KEY_NOT_FOUND : ResponseCode::SYSTEM_ERROR;
    }

    // fileLength may be less than sizeof(mBlob)
    const size_t fileLength = readFully(in, (uint8_t*)rawBlob.get(), sizeof(blobv3));
    if (close(in) != 0) {
        return ResponseCode::SYSTEM_ERROR;
    }

    if (fileLength == 0) {
        LOG(ERROR) << __func__ << " VALUE_CORRUPTED file length == 0";
        return ResponseCode::VALUE_CORRUPTED;
    }

    if (rawBlobIsEncrypted(*rawBlob)) {
        if (state == STATE_LOCKED) {
            mBlob = std::move(rawBlob);
            return ResponseCode::LOCKED;
        }
        if (state == STATE_UNINITIALIZED) return ResponseCode::UNINITIALIZED;
    }

    if (fileLength < offsetof(blobv3, value)) {
        LOG(ERROR) << __func__ << " VALUE_CORRUPTED blob file too short: " << fileLength;
        return ResponseCode::VALUE_CORRUPTED;
    }

    if (rawBlob->version == 3) {
        const ssize_t encryptedLength = ntohl(rawBlob->length);

        if (rawBlobIsEncrypted(*rawBlob)) {
            rc = AES_gcm_decrypt(rawBlob->value /* in */, rawBlob->value /* out */, encryptedLength,
                                 aes_key, rawBlob->initialization_vector, rawBlob->aead_tag);
            if (rc != ResponseCode::NO_ERROR) {
                // If the blob was superencrypted and decryption failed, it is
                // almost certain that decryption is failing due to a user's
                // changed master key.
                if ((rawBlob->flags & KEYSTORE_FLAG_SUPER_ENCRYPTED) &&
                    (rc == ResponseCode::VALUE_CORRUPTED)) {
                    return ResponseCode::KEY_PERMANENTLY_INVALIDATED;
                }
                LOG(ERROR) << __func__ << " AES_gcm_decrypt returned: " << uint32_t(rc);

                return rc;
            }
        }
    } else if (rawBlob->version < 3) {
        blobv2& v2blob = reinterpret_cast<blobv2&>(*rawBlob);
        const size_t headerLength = offsetof(blobv2, encrypted);
        const ssize_t encryptedLength = fileLength - headerLength - v2blob.info;
        if (encryptedLength < 0) {
            LOG(ERROR) << __func__ << " VALUE_CORRUPTED v2blob file too short";
            return ResponseCode::VALUE_CORRUPTED;
        }

        if (rawBlobIsEncrypted(*rawBlob)) {
            if (encryptedLength % AES_BLOCK_SIZE != 0) {
                LOG(ERROR) << __func__
                           << " VALUE_CORRUPTED encrypted length is not a multiple"
                              " of the AES block size";
                return ResponseCode::VALUE_CORRUPTED;
            }

            AES_KEY key;
            AES_set_decrypt_key(aes_key.data(), kAesKeySize * 8, &key);
            AES_cbc_encrypt(v2blob.encrypted, v2blob.encrypted, encryptedLength, &key,
                            v2blob.vector, AES_DECRYPT);
            key = {};  // clear key

            uint8_t computedDigest[MD5_DIGEST_LENGTH];
            ssize_t digestedLength = encryptedLength - MD5_DIGEST_LENGTH;
            MD5(v2blob.digested, digestedLength, computedDigest);
            if (memcmp(v2blob.digest, computedDigest, MD5_DIGEST_LENGTH) != 0) {
                LOG(ERROR) << __func__ << " v2blob MD5 digest mismatch";
                return ResponseCode::VALUE_CORRUPTED;
            }
        }
    }

    const ssize_t maxValueLength = fileLength - offsetof(blobv3, value) - rawBlob->info;
    rawBlob->length = ntohl(rawBlob->length);
    if (rawBlob->length < 0 || rawBlob->length > maxValueLength ||
        rawBlob->length + rawBlob->info + AES_BLOCK_SIZE >
            static_cast<ssize_t>(sizeof(rawBlob->value))) {
        LOG(ERROR) << __func__ << " raw blob length is out of bounds";
        return ResponseCode::VALUE_CORRUPTED;
    }

    if (rawBlob->info != 0 && rawBlob->version < 3) {
        // move info from after padding to after data
        memmove(rawBlob->value + rawBlob->length, rawBlob->value + maxValueLength, rawBlob->info);
    }

    mBlob = std::move(rawBlob);
    return ResponseCode::NO_ERROR;
}

std::tuple<ResponseCode, Blob, Blob>
LockedKeyBlobEntry::readBlobs(const std::vector<uint8_t>& aes_key, State state) const {
    std::tuple<ResponseCode, Blob, Blob> result;
    auto& [rc, keyBlob, characteristicsBlob] = result;
    if (entry_ == nullptr) return rc = ResponseCode::SYSTEM_ERROR, result;

    rc = keyBlob.readBlob(entry_->getKeyBlobPath(), aes_key, state);
    if (rc != ResponseCode::NO_ERROR && rc != ResponseCode::UNINITIALIZED) {
        return result;
    }

    if (entry_->hasCharacteristicsBlob()) {
        characteristicsBlob.readBlob(entry_->getCharacteristicsBlobPath(), aes_key, state);
    }
    return result;
}

ResponseCode LockedKeyBlobEntry::deleteBlobs() const {
    if (entry_ == nullptr) return ResponseCode::NO_ERROR;

    // always try to delete both
    ResponseCode rc1 = (unlink(entry_->getKeyBlobPath().c_str()) && errno != ENOENT)
                           ? ResponseCode::SYSTEM_ERROR
                           : ResponseCode::NO_ERROR;
    if (rc1 != ResponseCode::NO_ERROR) {
        ALOGW("Failed to delete key blob file \"%s\"", entry_->getKeyBlobPath().c_str());
    }
    ResponseCode rc2 = (unlink(entry_->getCharacteristicsBlobPath().c_str()) && errno != ENOENT)
                           ? ResponseCode::SYSTEM_ERROR
                           : ResponseCode::NO_ERROR;
    if (rc2 != ResponseCode::NO_ERROR) {
        ALOGW("Failed to delete key characteristics file \"%s\"",
              entry_->getCharacteristicsBlobPath().c_str());
    }
    // then report the first error that occured
    if (rc1 != ResponseCode::NO_ERROR) return rc1;
    return rc2;
}

keystore::SecurityLevel Blob::getSecurityLevel() const {
    return keystore::flagsToSecurityLevel(mBlob->flags);
}

void Blob::setSecurityLevel(keystore::SecurityLevel secLevel) {
    mBlob->flags &= ~(KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX);
    mBlob->flags |= keystore::securityLevelToFlags(secLevel);
}

std::tuple<bool, keystore::AuthorizationSet, keystore::AuthorizationSet>
Blob::getKeyCharacteristics() const {
    std::tuple<bool, keystore::AuthorizationSet, keystore::AuthorizationSet> result;
    auto& [success, hwEnforced, swEnforced] = result;
    success = false;
    ArrayStreamBuffer buf(mBlob->value);
    std::istream in(&buf);

    // only the characteristics cache has both sets
    if (getType() == TYPE_KEY_CHARACTERISTICS_CACHE) {
        hwEnforced.Deserialize(&in);
    } else if (getType() != TYPE_KEY_CHARACTERISTICS) {
        // if its not the cache and not the legacy characteristics file we have no business
        // here
        return result;
    }
    swEnforced.Deserialize(&in);
    success = !in.bad();

    return result;
}
bool Blob::putKeyCharacteristics(const keystore::AuthorizationSet& hwEnforced,
                                 const keystore::AuthorizationSet& swEnforced) {
    if (!mBlob) mBlob = std::make_unique<blobv3>();
    mBlob->version = CURRENT_BLOB_VERSION;
    ArrayStreamBuffer buf(mBlob->value);
    std::ostream out(&buf);
    hwEnforced.Serialize(&out);
    swEnforced.Serialize(&out);
    if (out.bad()) return false;
    setType(TYPE_KEY_CHARACTERISTICS_CACHE);
    mBlob->length = out.tellp();
    return true;
}

void LockedKeyBlobEntry::put(const KeyBlobEntry& entry) {
    std::unique_lock<std::mutex> lock(locked_blobs_mutex_);
    locked_blobs_.erase(entry);
    lock.unlock();
    locked_blobs_mutex_cond_var_.notify_all();
}

LockedKeyBlobEntry::~LockedKeyBlobEntry() {
    if (entry_ != nullptr) put(*entry_);
}

LockedKeyBlobEntry LockedKeyBlobEntry::get(KeyBlobEntry entry) {
    std::unique_lock<std::mutex> lock(locked_blobs_mutex_);
    locked_blobs_mutex_cond_var_.wait(
        lock, [&] { return locked_blobs_.find(entry) == locked_blobs_.end(); });
    auto [iterator, success] = locked_blobs_.insert(std::move(entry));
    if (!success) return {};
    return LockedKeyBlobEntry(*iterator);
}

std::set<KeyBlobEntry> LockedKeyBlobEntry::locked_blobs_;
std::mutex LockedKeyBlobEntry::locked_blobs_mutex_;
std::condition_variable LockedKeyBlobEntry::locked_blobs_mutex_cond_var_;

/* Here is the encoding of key names. This is necessary in order to allow arbitrary
 * characters in key names. Characters in [0-~] are not encoded. Others are encoded
 * into two bytes. The first byte is one of [+-.] which represents the first
 * two bits of the character. The second byte encodes the rest of the bits into
 * [0-o]. Therefore in the worst case the length of a key gets doubled. Note
 * that Base64 cannot be used here due to the need of prefix match on keys. */

std::string encodeKeyName(const std::string& keyName) {
    std::string encodedName;
    encodedName.reserve(keyName.size() * 2);
    auto in = keyName.begin();
    while (in != keyName.end()) {
        // Input character needs to be encoded.
        if (*in < '0' || *in > '~') {
            // Encode the two most-significant bits of the input char in the first
            // output character, by counting up from 43 ('+').
            encodedName.append(1, '+' + (uint8_t(*in) >> 6));
            // Encode the six least-significant bits of the input char in the second
            // output character, by counting up from 48 ('0').
            // This is safe because the maximum value is 112, which is the
            // character 'p'.
            encodedName.append(1, '0' + (*in & 0x3F));
        } else {
            // No need to encode input char - append as-is.
            encodedName.append(1, *in);
        }
        ++in;
    }
    return encodedName;
}

std::string decodeKeyName(const std::string& encodedName) {
    std::string decodedName;
    decodedName.reserve(encodedName.size());
    auto in = encodedName.begin();
    bool multichar = false;
    char c;
    while (in != encodedName.end()) {
        if (multichar) {
            // Second part of a multi-character encoding. Turn off the multichar
            // flag and set the six least-significant bits of c to the value originally
            // encoded by counting up from '0'.
            multichar = false;
            decodedName.append(1, c | (uint8_t(*in) - '0'));
        } else if (*in >= '+' && *in <= '.') {
            // First part of a multi-character encoding. Set the multichar flag
            // and set the two most-significant bits of c to be the two bits originally
            // encoded by counting up from '+'.
            multichar = true;
            c = (*in - '+') << 6;
        } else {
            // Regular character, append as-is.
            decodedName.append(1, *in);
        }
        ++in;
    }
    // mulitchars at the end get truncated
    return decodedName;
}

std::string KeyBlobEntry::getKeyBlobBaseName() const {
    std::stringstream s;
    if (masterkey_) {
        s << alias_;
    } else {
        s << uid_ << "_" << encodeKeyName(alias_);
    }
    return s.str();
}

std::string KeyBlobEntry::getKeyBlobPath() const {
    std::stringstream s;
    if (masterkey_) {
        s << user_dir_ << "/" << alias_;
    } else {
        s << user_dir_ << "/" << uid_ << "_" << encodeKeyName(alias_);
    }
    return s.str();
}

std::string KeyBlobEntry::getCharacteristicsBlobBaseName() const {
    std::stringstream s;
    if (!masterkey_) s << "." << uid_ << "_chr_" << encodeKeyName(alias_);
    return s.str();
}

std::string KeyBlobEntry::getCharacteristicsBlobPath() const {
    std::stringstream s;
    if (!masterkey_)
        s << user_dir_ << "/"
          << "." << uid_ << "_chr_" << encodeKeyName(alias_);
    return s.str();
}

bool KeyBlobEntry::hasKeyBlob() const {
    return !access(getKeyBlobPath().c_str(), R_OK | W_OK);
}
bool KeyBlobEntry::hasCharacteristicsBlob() const {
    return !access(getCharacteristicsBlobPath().c_str(), R_OK | W_OK);
}

static std::tuple<bool, uid_t, std::string> filename2UidAlias(const std::string& filepath) {
    std::tuple<bool, uid_t, std::string> result;

    auto& [success, uid, alias] = result;

    success = false;

    auto filenamebase = filepath.find_last_of('/');
    std::string filename =
        filenamebase == std::string::npos ? filepath : filepath.substr(filenamebase + 1);

    if (filename[0] == '.') return result;

    auto sep = filename.find('_');
    if (sep == std::string::npos) return result;

    std::stringstream s(filename.substr(0, sep));
    s >> uid;
    if (!s) return result;

    alias = decodeKeyName(filename.substr(sep + 1));
    success = true;
    return result;
}

std::tuple<ResponseCode, std::list<LockedKeyBlobEntry>>
LockedKeyBlobEntry::list(const std::string& user_dir,
                         std::function<bool(uid_t, const std::string&)> filter) {
    std::list<LockedKeyBlobEntry> matches;

    // This is a fence against any concurrent database accesses during database iteration.
    // Only the keystore thread can lock entries. So it cannot be starved
    // by workers grabbing new individual locks. We just wait here until all
    // workers have relinquished their locked files.
    std::unique_lock<std::mutex> lock(locked_blobs_mutex_);
    locked_blobs_mutex_cond_var_.wait(lock, [&] { return locked_blobs_.empty(); });

    DIR* dir = opendir(user_dir.c_str());
    if (!dir) {
        ALOGW("can't open directory for user: %s", strerror(errno));
        return std::tuple<ResponseCode, std::list<LockedKeyBlobEntry>&&>{ResponseCode::SYSTEM_ERROR,
                                                                         std::move(matches)};
    }

    struct dirent* file;
    while ((file = readdir(dir)) != nullptr) {
        // We only care about files.
        if (file->d_type != DT_REG) {
            continue;
        }

        // Skip anything that starts with a "."
        if (file->d_name[0] == '.') {
            continue;
        }

        auto [success, uid, alias] = filename2UidAlias(file->d_name);

        if (!success) {
            ALOGW("could not parse key filename \"%s\"", file->d_name);
            continue;
        }

        if (!filter(uid, alias)) continue;

        auto [iterator, dummy] = locked_blobs_.emplace(alias, user_dir, uid);
        matches.push_back(*iterator);
    }
    closedir(dir);
    return std::tuple<ResponseCode, std::list<LockedKeyBlobEntry>&&>{ResponseCode::NO_ERROR,
                                                                     std::move(matches)};
}
