/*
 * Copyright 2021, 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 "MicrodroidKeymasterContext.h"

#include <android-base/logging.h>
#include <keymaster/key.h>
#include <keymaster/key_blob_utils/auth_encrypted_key_blob.h>
#include <keymaster/key_blob_utils/software_keyblobs.h>

using namespace ::keymaster;

// This value is used for the ROOT_OF_TRUST tag which is only used in
// attestation records which aren't supported in this implementation so a
// constant doesn't cause any hard. MicroDroid SoftWare root-of-trust.
static uint8_t SWROT[] = {'M', 'D', 'S', 'W'};
static const KeymasterBlob microdroidSoftwareRootOfTrust(SWROT);

keymaster_error_t MicrodroidKeymasterContext::CreateKeyBlob(const AuthorizationSet& key_description,
                                                            keymaster_key_origin_t origin,
                                                            const KeymasterKeyBlob& key_material,
                                                            KeymasterKeyBlob* blob,
                                                            AuthorizationSet* hw_enforced,
                                                            AuthorizationSet* sw_enforced) const {
    keymaster_error_t error;

    if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) {
        return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
    }

    error = SetKeyBlobAuthorizations(key_description, origin, os_version_, os_patchlevel_,
                                     hw_enforced, sw_enforced);
    if (error != KM_ERROR_OK) return error;

    AuthorizationSet hidden;
    error = BuildHiddenAuthorizations(key_description, &hidden, microdroidSoftwareRootOfTrust);
    if (error != KM_ERROR_OK) return error;

    CHECK(hw_enforced->empty());

    // Note that the authorizations included in the blob are not encrypted. This
    // doesn't pose a problem for the current applications but may be a
    // candidate for hardening.
    auto encrypted_key = EncryptKey(key_material, AES_GCM_WITH_SW_ENFORCED, *hw_enforced,
                                    *sw_enforced, hidden, root_key_, random_, &error);
    if (error != KM_ERROR_OK) return error;

    *blob = SerializeAuthEncryptedBlob(encrypted_key, *hw_enforced, *sw_enforced, &error);
    return error;
}

keymaster_error_t MicrodroidKeymasterContext::ParseKeyBlob(
        const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
        UniquePtr<Key>* key) const {
    keymaster_error_t error;

    AuthorizationSet hidden;
    error = BuildHiddenAuthorizations(additional_params, &hidden, microdroidSoftwareRootOfTrust);
    if (error != KM_ERROR_OK) return error;

    auto deserialized_key = DeserializeAuthEncryptedBlob(blob, &error);
    if (error != KM_ERROR_OK) return error;

    keymaster_algorithm_t algorithm;
    if (!deserialized_key.sw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) {
        return KM_ERROR_INVALID_ARGUMENT;
    }

    auto key_material = DecryptKey(deserialized_key, hidden, root_key_, &error);
    if (error != KM_ERROR_OK) return error;

    auto factory = GetKeyFactory(algorithm);
    return factory->LoadKey(move(key_material), additional_params,
                            move(deserialized_key.hw_enforced), move(deserialized_key.sw_enforced),
                            key);
}

static bool UpgradeIntegerTag(keymaster_tag_t tag, uint32_t value, AuthorizationSet* set) {
    int index = set->find(tag);
    if (index == -1) {
        keymaster_key_param_t param;
        param.tag = tag;
        param.integer = value;
        set->push_back(param);
        return true;
    }

    if (set->params[index].integer > value) return false;

    if (set->params[index].integer != value) {
        set->params[index].integer = value;
    }
    return true;
}

keymaster_error_t MicrodroidKeymasterContext::UpgradeKeyBlob(const KeymasterKeyBlob& key_to_upgrade,
                                                             const AuthorizationSet& upgrade_params,
                                                             KeymasterKeyBlob* upgraded_key) const {
    UniquePtr<Key> key;
    keymaster_error_t error = ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
    if (error != KM_ERROR_OK) return error;

    if (os_version_ == 0) {
        // We need to allow "upgrading" OS version to zero, to support upgrading from proper
        // numbered releases to unnumbered development and preview releases.

        int key_os_version_pos = key->sw_enforced().find(TAG_OS_VERSION);
        if (key_os_version_pos != -1) {
            uint32_t key_os_version = key->sw_enforced()[key_os_version_pos].integer;
            if (key_os_version != 0) {
                key->sw_enforced()[key_os_version_pos].integer = os_version_;
            }
        }
    }

    if (!UpgradeIntegerTag(TAG_OS_VERSION, os_version_, &key->sw_enforced()) ||
        !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, os_patchlevel_, &key->sw_enforced()))
        // One of the version fields would have been a downgrade. Not allowed.
        return KM_ERROR_INVALID_ARGUMENT;

    AuthorizationSet hidden;
    error = BuildHiddenAuthorizations(upgrade_params, &hidden, microdroidSoftwareRootOfTrust);
    if (error != KM_ERROR_OK) return error;

    auto encrypted_key =
            EncryptKey(key->key_material(), AES_GCM_WITH_SW_ENFORCED, key->hw_enforced(),
                       key->sw_enforced(), hidden, root_key_, random_, &error);
    if (error != KM_ERROR_OK) return error;

    *upgraded_key = SerializeAuthEncryptedBlob(encrypted_key, key->hw_enforced(),
                                               key->sw_enforced(), &error);
    return error;
}
