/*
 * Copyright 2017 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 "secure_storage_manager.h"
#include "keymaster_attributes.pb.h"

#include <errno.h>
#include <stdio.h>
#include <uapi/err.h>

#include <lib/storage/storage.h>

#include <keymaster/UniquePtr.h>
#include <keymaster/android_keymaster_utils.h>
#include "pb_decode.h"
#include "pb_encode.h"
#include "trusty_logger.h"

namespace keymaster {

// Name of the attestation key file is kAttestKeyCertPrefix.%algorithm. This key
// file stores key and certificate chain in a protobuf format.
const char* kAttestKeyCertPrefix = "AttestKeyCert";
// Name of the legacy attestation key file prefix.
const char* kLegacyAttestKeyPrefix = "AttestKey.";
// Name of the legacy certificate file prefix.
const char* kLegacyAttestCertPrefix = "AttestCert.";

// Name of the file to store keymaster attributes in a protobuf format.
const char* kAttributeFileName = "Attribute";
// Name of the legacy keymaster attribute files.
const char* kLegacyAttestUuidFileName = "AttestUuid";
const char* kLegacyProductIdFileName = "ProductId";

// Maximum file name size.
static const int kStorageIdLengthMax = 64;

// These values should match keymaster_attributes.proto descriptions.
static const int kKeySizeMax = 2048;
static const int kCertSizeMax = 2048;

const char* GetKeySlotStr(AttestationKeySlot key_slot) {
    switch (key_slot) {
    case AttestationKeySlot::kRsa:
        return "rsa";
    case AttestationKeySlot::kEcdsa:
        return "ec";
    case AttestationKeySlot::kEddsa:
        return "ed";
    case AttestationKeySlot::kEpid:
        return "epid";
    case AttestationKeySlot::kClaimable0:
        return "c0";
    case AttestationKeySlot::kSomRsa:
        return "s_rsa";
    case AttestationKeySlot::kSomEcdsa:
        return "s_ec";
    case AttestationKeySlot::kSomEddsa:
        return "s_ed";
    case AttestationKeySlot::kSomEpid:
        return "s_epid";
    default:
        return "";
    }
}

class FileCloser {
public:
    file_handle_t get_file_handle() { return file_handle; }
    int open_file(storage_session_t session,
                  const char* name,
                  uint32_t flags,
                  uint32_t opflags) {
        return storage_open_file(session, &file_handle, name, flags, opflags);
    }
    ~FileCloser() {
        if (file_handle) {
            storage_close_file(file_handle);
        }
    }

private:
    file_handle_t file_handle = 0;
};

SecureStorageManager* SecureStorageManager::get_instance(
        bool translate_format) {
    static SecureStorageManager instance;
    if (instance.session_handle_ != STORAGE_INVALID_SESSION) {
        int rc = storage_end_transaction(instance.session_handle_, false);
        if (rc < 0) {
            LOG_E("Error: existing session is stale.", 0);
            storage_close_session(instance.session_handle_);
            instance.session_handle_ = STORAGE_INVALID_SESSION;
        }
    }
    if (instance.session_handle_ == STORAGE_INVALID_SESSION) {
        storage_open_session(&instance.session_handle_, STORAGE_CLIENT_TP_PORT);
        if (instance.session_handle_ == STORAGE_INVALID_SESSION) {
            return nullptr;
        }
    }
#ifdef KEYMASTER_LEGACY_FORMAT
    if (translate_format && instance.legacy_format) {
        keymaster_error_t err = instance.TranslateLegacyFormat();
        if (err != KM_ERROR_OK) {
            LOG_E("Failed to translate legacy file format!", 0);
            instance.CloseSession();
            return nullptr;
        } else {
            instance.legacy_format = false;
        }
    }
#endif  // #ifdef KEYMASTER_LEGACY_FORMAT
    return &instance;
}

keymaster_error_t SecureStorageManager::WriteKeyToStorage(
        AttestationKeySlot key_slot,
        const uint8_t* key,
        uint32_t key_size) {
    if (key_size > kKeySizeMax) {
        return KM_ERROR_INVALID_ARGUMENT;
    }
    AttestationKey* attestation_key_p;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    attestation_key->has_key = true;
    memcpy(attestation_key->key.bytes, key, key_size);
    attestation_key->key.size = key_size;

    err = WriteAttestationKey(key_slot, attestation_key.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

KeymasterKeyBlob SecureStorageManager::ReadKeyFromStorage(
        AttestationKeySlot key_slot,
        keymaster_error_t* error) {
    AttestationKey* attestation_key_p;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        if (error) {
            *error = err;
        }
        return {};
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    if (!attestation_key->has_key) {
        if (error) {
            *error = KM_ERROR_INVALID_ARGUMENT;
        }
        return {};
    }
    KeymasterKeyBlob result(attestation_key->key.size);
    if (result.key_material == nullptr) {
        if (error) {
            *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
        }
        return {};
    }
    memcpy(result.writable_data(), attestation_key->key.bytes,
           result.key_material_size);
    return result;
}

keymaster_error_t SecureStorageManager::AttestationKeyExists(
        AttestationKeySlot key_slot,
        bool* exists) {
    AttestationKey* attestation_key_p;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    *exists = attestation_key->has_key;
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::WriteCertToStorage(
        AttestationKeySlot key_slot,
        const uint8_t* cert,
        uint32_t cert_size,
        uint32_t index) {
    if (cert_size > kCertSizeMax || index >= kMaxCertChainLength) {
        return KM_ERROR_INVALID_ARGUMENT;
    }
    AttestationKey* attestation_key_p;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    if (attestation_key->certs_count < index) {
        /* Skip a layer in cert chain. */
        return KM_ERROR_INVALID_ARGUMENT;
    } else if (attestation_key->certs_count == index) {
        attestation_key->certs_count++;
    }
    attestation_key->certs[index].content.size = cert_size;
    memcpy(attestation_key->certs[index].content.bytes, cert, cert_size);

    err = WriteAttestationKey(key_slot, attestation_key.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

keymaster_error_t SecureStorageManager::ReadCertChainFromStorage(
        AttestationKeySlot key_slot,
        keymaster_cert_chain_t* cert_chain) {
    AttestationKey* attestation_key_p;
    // Clear entry count in case of early return.
    cert_chain->entry_count = 0;
    cert_chain->entries = nullptr;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    uint32_t cert_chain_length = attestation_key->certs_count;
    cert_chain->entry_count = cert_chain_length;
    if (cert_chain_length == 0) {
        return KM_ERROR_OK;
    }

    cert_chain->entries = new keymaster_blob_t[cert_chain_length];
    if (cert_chain->entries == nullptr) {
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
    memset(cert_chain->entries, 0,
           sizeof(keymaster_blob_t) * cert_chain_length);

    for (size_t i = 0; i < cert_chain_length; i++) {
        uint32_t content_size = attestation_key->certs[i].content.size;
        cert_chain->entries[i].data_length = content_size;
        uint8_t* buffer = new uint8_t[content_size];
        if (buffer == nullptr) {
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
        }
        memcpy(buffer, attestation_key->certs[i].content.bytes, content_size);
        cert_chain->entries[i].data = buffer;
    }

    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::DeleteCertChainFromStorage(
        AttestationKeySlot key_slot) {
    AttestationKey* attestation_key_p;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    attestation_key->certs_count = 0;

    err = WriteAttestationKey(key_slot, attestation_key.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

keymaster_error_t SecureStorageManager::ReadAtapCertChainFromStorage(
        AttestationKeySlot key_slot,
        AtapCertChain* cert_chain) {
    AttestationKey* attestation_key_p;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    uint32_t cert_chain_length = attestation_key->certs_count;
    cert_chain->entry_count = cert_chain_length;
    if (cert_chain_length == 0) {
        return KM_ERROR_OK;
    }

    for (size_t i = 0; i < cert_chain_length; i++) {
        uint32_t content_size = attestation_key->certs[i].content.size;
        cert_chain->entries[i].data_length = content_size;
        uint8_t* buffer = new uint8_t[content_size];
        if (buffer == nullptr) {
            return KM_ERROR_MEMORY_ALLOCATION_FAILED;
        }
        memcpy(buffer, attestation_key->certs[i].content.bytes, content_size);
        cert_chain->entries[i].data = buffer;
    }

    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::ReadCertChainLength(
        AttestationKeySlot key_slot,
        uint32_t* cert_chain_length) {
    AttestationKey* attestation_key_p;
    keymaster_error_t err = ReadAttestationKey(key_slot, &attestation_key_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<AttestationKey> attestation_key(attestation_key_p);
    *cert_chain_length = attestation_key->certs_count;
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::WriteAtapKeyAndCertsToStorage(
        AttestationKeySlot key_slot,
        const uint8_t* key,
        const uint32_t key_size,
        const AtapCertChain* cert_chain) {
    if (key_size > kKeySizeMax || cert_chain->entry_count > kCertSizeMax) {
        return KM_ERROR_INVALID_ARGUMENT;
    }
    UniquePtr<AttestationKey> attestation_key(
            new AttestationKey(AttestationKey_init_zero));
    attestation_key->has_key = true;
    attestation_key->key.size = key_size;
    memcpy(attestation_key->key.bytes, key, key_size);
    for (size_t i = 0; i < cert_chain->entry_count; i++) {
        attestation_key->certs[i].content.size =
                cert_chain->entries[i].data_length;
        memcpy(attestation_key->certs[i].content.bytes,
               cert_chain->entries[i].data, cert_chain->entries[i].data_length);
    }
    attestation_key->certs_count = cert_chain->entry_count;
    keymaster_error_t err =
            WriteAttestationKey(key_slot, attestation_key.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

keymaster_error_t SecureStorageManager::DeleteKey(AttestationKeySlot key_slot,
                                                  bool commit) {
    char key_file[kStorageIdLengthMax];
    snprintf(key_file, kStorageIdLengthMax, "%s.%s", kAttestKeyCertPrefix,
             GetKeySlotStr(key_slot));
    int rc = storage_delete_file(session_handle_, key_file,
                                 commit ? STORAGE_OP_COMPLETE : 0);
    if (rc < 0 && rc != ERR_NOT_FOUND) {
        LOG_E("Error: [%d] deleting storage object '%s'", rc, key_file);
        if (commit) {
            // If DeleteKey is part of a larger operations, then do not close
            // the session.
            CloseSession();
        }
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::ReadKeymasterAttributes(
        KeymasterAttributes** km_attributes_p) {
    UniquePtr<KeymasterAttributes> km_attributes(
            new KeymasterAttributes(KeymasterAttributes_init_zero));
    if (!km_attributes.get()) {
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
    keymaster_error_t err =
            DecodeFromFile(KeymasterAttributes_fields, km_attributes.get(),
                           kAttributeFileName);
    if (err < 0) {
        LOG_E("Error: [%d] decoding from file '%s'", err, kAttributeFileName);
        return err;
    }
    *km_attributes_p = km_attributes.release();
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::WriteKeymasterAttributes(
        const KeymasterAttributes* km_attributes,
        bool commit) {
    return EncodeToFile(KeymasterAttributes_fields, km_attributes,
                        kAttributeFileName, commit);
}

keymaster_error_t SecureStorageManager::ReadAttestationUuid(
        uint8_t attestation_uuid[kAttestationUuidSize]) {
    KeymasterAttributes* km_attributes_p;
    keymaster_error_t err = ReadKeymasterAttributes(&km_attributes_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<KeymasterAttributes> km_attributes(km_attributes_p);
    if (!(km_attributes->has_uuid)) {
        return KM_ERROR_INVALID_ARGUMENT;
    }
    if (km_attributes->uuid.size != kAttestationUuidSize) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    memcpy(attestation_uuid, km_attributes->uuid.bytes, kAttestationUuidSize);
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::WriteAttestationUuid(
        const uint8_t attestation_uuid[kAttestationUuidSize]) {
    KeymasterAttributes* km_attributes_p;
    keymaster_error_t err = ReadKeymasterAttributes(&km_attributes_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<KeymasterAttributes> km_attributes(km_attributes_p);
    km_attributes->has_uuid = true;
    km_attributes->uuid.size = kAttestationUuidSize;
    memcpy(km_attributes->uuid.bytes, attestation_uuid, kAttestationUuidSize);
    err = WriteKeymasterAttributes(km_attributes.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

keymaster_error_t SecureStorageManager::DeleteAttestationUuid() {
    KeymasterAttributes* km_attributes_p;
    keymaster_error_t err = ReadKeymasterAttributes(&km_attributes_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<KeymasterAttributes> km_attributes(km_attributes_p);
    km_attributes->has_uuid = false;
    err = WriteKeymasterAttributes(km_attributes.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

keymaster_error_t SecureStorageManager::SetProductId(
        const uint8_t product_id[kProductIdSize]) {
    KeymasterAttributes* km_attributes_p;
    keymaster_error_t err = ReadKeymasterAttributes(&km_attributes_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<KeymasterAttributes> km_attributes(km_attributes_p);
#ifndef KEYMASTER_DEBUG
    if (km_attributes->has_product_id) {
        LOG_E("Error: Product ID already set!\n", 0);
        return KM_ERROR_INVALID_ARGUMENT;
    }
#endif /* KEYMASTER_DEBUG */
    km_attributes->has_product_id = true;
    km_attributes->product_id.size = kProductIdSize;
    memcpy(km_attributes->product_id.bytes, product_id, kProductIdSize);
    err = WriteKeymasterAttributes(km_attributes.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

keymaster_error_t SecureStorageManager::ReadProductId(
        uint8_t product_id[kProductIdSize]) {
    KeymasterAttributes* km_attributes_p;
    keymaster_error_t err = ReadKeymasterAttributes(&km_attributes_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<KeymasterAttributes> km_attributes(km_attributes_p);
    if (!km_attributes->has_product_id) {
        return KM_ERROR_INVALID_ARGUMENT;
    }
    if (km_attributes->product_id.size != kProductIdSize) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    memcpy(product_id, km_attributes->product_id.bytes, kProductIdSize);
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::DeleteProductId() {
    KeymasterAttributes* km_attributes_p;
    keymaster_error_t err = ReadKeymasterAttributes(&km_attributes_p);
    if (err != KM_ERROR_OK) {
        CloseSession();
        return err;
    }
    UniquePtr<KeymasterAttributes> km_attributes(km_attributes_p);
    km_attributes_p->has_product_id = false;
    err = WriteKeymasterAttributes(km_attributes.get(), true);
    if (err != KM_ERROR_OK) {
        CloseSession();
    }
    return err;
}

keymaster_error_t SecureStorageManager::DeleteAllAttestationData() {
    if (DeleteKey(AttestationKeySlot::kRsa, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kEcdsa, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kEddsa, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kEpid, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kClaimable0, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kSomRsa, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kSomEcdsa, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kSomEddsa, false) != KM_ERROR_OK ||
        DeleteKey(AttestationKeySlot::kSomEpid, false) != KM_ERROR_OK) {
        // Something wrong, abort the transaction.
        storage_end_transaction(session_handle_, false);
        CloseSession();
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }
    int rc = storage_end_transaction(session_handle_, true);
    if (rc < 0) {
        LOG_E("Error: failed to commit transaction while deleting keys.", 0);
        CloseSession();
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::ReadAttestationKey(
        AttestationKeySlot key_slot,
        AttestationKey** attestation_key_p) {
    char key_file[kStorageIdLengthMax];
    snprintf(key_file, kStorageIdLengthMax, "%s.%s", kAttestKeyCertPrefix,
             GetKeySlotStr(key_slot));

    UniquePtr<AttestationKey> attestation_key(
            new AttestationKey(AttestationKey_init_zero));
    if (!attestation_key.get()) {
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
    keymaster_error_t err = DecodeFromFile(AttestationKey_fields,
                                           attestation_key.get(), key_file);
    if (err < 0) {
        LOG_E("Error: [%d] decoding from file '%s'", err, key_file);
        return err;
    }
    *attestation_key_p = attestation_key.release();
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::WriteAttestationKey(
        AttestationKeySlot key_slot,
        const AttestationKey* attestation_key,
        bool commit) {
    char key_file[kStorageIdLengthMax];
    snprintf(key_file, kStorageIdLengthMax, "%s.%s", kAttestKeyCertPrefix,
             GetKeySlotStr(key_slot));

    return EncodeToFile(AttestationKey_fields, attestation_key, key_file,
                        commit);
}

void SecureStorageManager::CloseSession() {
    if (session_handle_ != STORAGE_INVALID_SESSION) {
        storage_close_session(session_handle_);
        session_handle_ = STORAGE_INVALID_SESSION;
    }
}

struct FileStatus {
    /* How many bytes handled in the file. */
    uint64_t bytes_handled;
    file_handle_t file_handle;
    FileStatus() : bytes_handled(0), file_handle(0) {}
};

bool write_to_file_callback(pb_ostream_t* stream,
                            const uint8_t* buf,
                            size_t count) {
    FileStatus* file_status = reinterpret_cast<FileStatus*>(stream->state);
    /* Do not commit the write. */
    int rc = storage_write(file_status->file_handle, file_status->bytes_handled,
                           buf, count, 0);
    if (rc < 0 || static_cast<size_t>(rc) < count) {
        LOG_E("Error: failed to write to file: %d\n", rc);
        return false;
    }
    file_status->bytes_handled += rc;
    return true;
}

bool read_from_file_callback(pb_istream_t* stream, uint8_t* buf, size_t count) {
    if (buf == NULL) {
        return false;
    }
    FileStatus* file_status = reinterpret_cast<FileStatus*>(stream->state);
    int rc = storage_read(file_status->file_handle, file_status->bytes_handled,
                          buf, count);
    if (rc < 0 || static_cast<size_t>(rc) < count) {
        LOG_E("Error: failed to read from file: %d\n", rc);
        return false;
    }
    file_status->bytes_handled += rc;
    return true;
}

keymaster_error_t SecureStorageManager::EncodeToFile(const pb_field_t fields[],
                                                     const void* dest_struct,
                                                     const char filename[],
                                                     bool commit) {
    FileCloser file;
    int rc = file.open_file(
            session_handle_, filename,
            STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, 0);
    if (rc < 0) {
        LOG_E("Error: failed to open file '%s': %d\n", filename, rc);
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }
    FileStatus new_file_status;
    new_file_status.file_handle = file.get_file_handle();
    pb_ostream_t stream = {&write_to_file_callback, &new_file_status, SIZE_MAX,
                           0, 0};
    if (!pb_encode(&stream, fields, dest_struct)) {
        LOG_E("Error: encoding fields to file '%s'", filename);
        /* Abort the transaction. */
        storage_end_transaction(session_handle_, false);
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
    if (commit) {
        /* Commit the write. */
        rc = storage_end_transaction(session_handle_, true);
        if (rc < 0) {
            LOG_E("Error: failed to commit write transaction for file '%s': %d"
                  "\n",
                  filename, rc);
            return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
        }
    }
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::DecodeFromFile(
        const pb_field_t fields[],
        void* dest_struct,
        const char filename[]) {
    uint64_t file_size;
    FileCloser file;
    int rc = file.open_file(session_handle_, filename, 0, 0);
    if (rc == ERR_NOT_FOUND) {
        // File not exists
        return KM_ERROR_OK;
    }
    if (rc < 0) {
        LOG_E("Error: failed to open file '%s': %d\n", filename, rc);
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }
    rc = storage_get_file_size(file.get_file_handle(), &file_size);
    if (rc < 0) {
        LOG_E("Error: failed to get size of attributes file '%s': %d\n", rc);
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }
    FileStatus new_file_status;
    new_file_status.file_handle = file.get_file_handle();
    pb_istream_t stream = {&read_from_file_callback, &new_file_status,
                           static_cast<size_t>(file_size), 0};
    if (!pb_decode(&stream, fields, dest_struct)) {
        LOG_E("Error: decoding fields from file '%s'", filename);
        return KM_ERROR_MEMORY_ALLOCATION_FAILED;
    }
    return KM_ERROR_OK;
}

#ifdef KEYMASTER_LEGACY_FORMAT

keymaster_error_t SecureStorageManager::TranslateLegacyFormat() {
    FileCloser file;
    int rc = file.open_file(session_handle_, kAttributeFileName, 0, 0);
    if (rc == NO_ERROR) {
        // New attribute file exists, nothing to do.
        return KM_ERROR_OK;
    }
    AttestationKeySlot key_slots[] = {
            AttestationKeySlot::kRsa,        AttestationKeySlot::kEcdsa,
            AttestationKeySlot::kEddsa,      AttestationKeySlot::kEpid,
            AttestationKeySlot::kClaimable0, AttestationKeySlot::kSomRsa,
            AttestationKeySlot::kSomEcdsa,   AttestationKeySlot::kSomEddsa,
            AttestationKeySlot::kSomEpid};
    char key_file[kStorageIdLengthMax];
    char cert_file[kStorageIdLengthMax];
    uint32_t key_size;
    uint32_t cert_size;
    keymaster_error_t err;
    for (size_t i = 0; i < sizeof(key_slots) / sizeof(int); i++) {
        AttestationKeySlot key_slot = key_slots[i];
        UniquePtr<AttestationKey> attestation_key(
                new AttestationKey(AttestationKey_init_zero));
        snprintf(key_file, kStorageIdLengthMax, "%s.%s", kLegacyAttestKeyPrefix,
                 GetKeySlotStr(key_slot));
        err = LegacySecureStorageRead(key_file, attestation_key->key.bytes,
                                      &key_size, kKeySizeMax);
        if (err != KM_ERROR_OK) {
            return err;
        }
        if (key_size == 0) {
            // Legacy key file for this key slot is not found.
            continue;
        }
        attestation_key->key.size = key_size;
        attestation_key->has_key = true;
        // Do not commit the delete.
        rc = storage_delete_file(session_handle_, key_file, 0);
        if (rc < 0) {
            return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
        }
        for (int index = 0; index < kMaxCertChainLength; index++) {
            snprintf(cert_file, kStorageIdLengthMax, "%s.%s.%d",
                     kLegacyAttestCertPrefix, GetKeySlotStr(key_slot), index);
            err = LegacySecureStorageRead(
                    cert_file, attestation_key->certs[index].content.bytes,
                    &cert_size, kCertSizeMax);
            if (err != KM_ERROR_OK) {
                return err;
            }
            if (cert_size == 0) {
                // One cert does not exist, no need to continue reading.
                break;
            }
            attestation_key->certs[index].content.size = cert_size;
            attestation_key->certs_count = index + 1;
            // Do not commit the delete.
            rc = storage_delete_file(session_handle_, cert_file, 0);
            if (rc < 0) {
                return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
            }
        }
        // Do not commit the write.
        keymaster_error_t err =
                WriteAttestationKey(key_slot, attestation_key.get(), false);
        if (err != KM_ERROR_OK) {
            LOG_E("Failed to write attestation key for slot: %d: %d\n",
                  key_slot, err);
            return err;
        }
    }

    UniquePtr<KeymasterAttributes> km_attributes(
            new KeymasterAttributes(KeymasterAttributes_init_zero));
    uint32_t product_id_size;
    err = LegacySecureStorageRead(kLegacyProductIdFileName,
                                  km_attributes->product_id.bytes,
                                  &product_id_size, kProductIdSize);
    if (err != KM_ERROR_OK) {
        return err;
    }
    if (product_id_size != 0) {
        km_attributes->has_product_id = true;
        km_attributes->product_id.size = product_id_size;
        rc = storage_delete_file(session_handle_, kLegacyProductIdFileName, 0);
        if (rc < 0) {
            return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
        }
    }
    uint32_t uuid_size;
    err = LegacySecureStorageRead(kLegacyAttestUuidFileName,
                                  km_attributes->uuid.bytes, &uuid_size,
                                  kAttestationUuidSize);
    if (err != KM_ERROR_OK) {
        return err;
    }
    if (uuid_size != 0) {
        km_attributes->has_uuid = true;
        km_attributes->uuid.size = uuid_size;
        rc = storage_delete_file(session_handle_, kLegacyAttestUuidFileName, 0);
        if (rc < 0) {
            return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
        }
    }
    err = WriteKeymasterAttributes(km_attributes.get(), false);
    if (err != KM_ERROR_OK) {
        return err;
    }

    // Commit the pending transactions.
    rc = storage_end_transaction(session_handle_, STORAGE_OP_COMPLETE);
    if (rc < 0) {
        LOG_E("Error: failed to commit write transaction to translate file"
              " format.\n",
              0);
        return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
    }
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::LegacySecureStorageRead(
        const char* filename,
        void* data,
        uint32_t* size,
        uint32_t max_size) {
    FileCloser file;
    uint64_t file_size;
    int rc = file.open_file(session_handle_, filename, 0, 0);
    if (rc == ERR_NOT_FOUND) {
        *size = 0;
        return KM_ERROR_OK;
    }
    rc = storage_get_file_size(file.get_file_handle(), &file_size);
    if (rc < 0) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    if (file_size > static_cast<uint64_t>(max_size)) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    *size = static_cast<uint32_t>(file_size);
    rc = storage_read(file.get_file_handle(), 0, data, file_size);
    if (rc < 0) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    if (static_cast<uint32_t>(rc) < *size) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    return KM_ERROR_OK;
}

keymaster_error_t SecureStorageManager::LegacySecureStorageWrite(
        const char* filename,
        const uint8_t* data,
        uint32_t data_size) {
    FileCloser file;
    int rc = file.open_file(
            session_handle_, filename,
            STORAGE_FILE_OPEN_CREATE | STORAGE_FILE_OPEN_TRUNCATE, 0);
    if (rc < 0) {
        return KM_ERROR_UNKNOWN_ERROR;
    }
    rc = storage_write(file.get_file_handle(), 0, data, data_size,
                       STORAGE_OP_COMPLETE);
    if (rc < 0) {
        LOG_E("Error: [%d] writing storage object '%s'", rc, filename);
        return KM_ERROR_UNKNOWN_ERROR;
    }
    if (static_cast<uint32_t>(rc) < data_size) {
        LOG_E("Error: invalid object size [%d] from '%s'", rc, filename);
        return KM_ERROR_UNKNOWN_ERROR;
    }

    return KM_ERROR_OK;
}

// Deprecated implementation for writing key to storage, for backward
// compatibility tests only.
keymaster_error_t SecureStorageManager::LegacyWriteKeyToStorage(
        AttestationKeySlot key_slot,
        const uint8_t* key,
        uint32_t key_size) {
    char key_file[kStorageIdLengthMax];
    snprintf(key_file, kStorageIdLengthMax, "%s.%s", kLegacyAttestKeyPrefix,
             GetKeySlotStr(key_slot));
    return LegacySecureStorageWrite(key_file, key, key_size);
}

// Deprecated implementation for writing cert to storage, for backward
// compatibility tests only.
keymaster_error_t SecureStorageManager::LegacyWriteCertToStorage(
        AttestationKeySlot key_slot,
        const uint8_t* cert,
        uint32_t cert_size,
        uint32_t index) {
    char cert_file[kStorageIdLengthMax];
    snprintf(cert_file, kStorageIdLengthMax, "%s.%s.%d",
             kLegacyAttestCertPrefix, GetKeySlotStr(key_slot), index);
    return LegacySecureStorageWrite(cert_file, cert, cert_size);
}

// Deprecated, for unit tests only.
keymaster_error_t SecureStorageManager::LegacyWriteAttestationUuid(
        const uint8_t attestation_uuid[kAttestationUuidSize]) {
    return LegacySecureStorageWrite(kLegacyAttestUuidFileName, attestation_uuid,
                                    kAttestationUuidSize);
}

// Deprecated, for unit tests only.
keymaster_error_t SecureStorageManager::LegacySetProductId(
        const uint8_t product_id[kProductIdSize]) {
    return LegacySecureStorageWrite(kLegacyProductIdFileName, product_id,
                                    kProductIdSize);
}
#endif  // #ifdef KEYMASTER_LEGACY_FORMAT

SecureStorageManager::SecureStorageManager() {
    session_handle_ = STORAGE_INVALID_SESSION;
}

SecureStorageManager::~SecureStorageManager() {
    CloseSession();
}

}  // namespace keymaster
