/*
 * Copyright 2014 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 "operation.h"

#include <keymaster/authorization_set.h>
#include <keymaster/keymaster_context.h>

#include "key.h"

namespace keymaster {

bool OperationFactory::supported(keymaster_padding_t padding) const {
    size_t padding_count;
    const keymaster_padding_t* supported_paddings = SupportedPaddingModes(&padding_count);
    for (size_t i = 0; i < padding_count; ++i)
        if (padding == supported_paddings[i])
            return true;
    return false;
}

bool OperationFactory::supported(keymaster_block_mode_t block_mode) const {
    size_t block_mode_count;
    const keymaster_block_mode_t* supported_block_modes = SupportedBlockModes(&block_mode_count);
    for (size_t i = 0; i < block_mode_count; ++i)
        if (block_mode == supported_block_modes[i])
            return true;
    return false;
}

bool OperationFactory::supported(keymaster_digest_t digest) const {
    size_t digest_count;
    const keymaster_digest_t* supported_digests = SupportedDigests(&digest_count);
    for (size_t i = 0; i < digest_count; ++i)
        if (digest == supported_digests[i])
            return true;
    return false;
}

inline bool is_public_key_algorithm(keymaster_algorithm_t algorithm) {
    switch (algorithm) {
    case KM_ALGORITHM_HMAC:
    case KM_ALGORITHM_AES:
        return false;
    case KM_ALGORITHM_RSA:
    case KM_ALGORITHM_EC:
        return true;
    }

    // Unreachable.
    assert(false);
    return false;
}

bool OperationFactory::is_public_key_operation() const {
    KeyType key_type = registry_key();

    if (!is_public_key_algorithm(key_type.algorithm))
        return false;

    switch (key_type.purpose) {
    case KM_PURPOSE_VERIFY:
    case KM_PURPOSE_ENCRYPT:
        return true;
    case KM_PURPOSE_SIGN:
    case KM_PURPOSE_DECRYPT:
    case KM_PURPOSE_DERIVE_KEY:
        return false;
    };

    // Unreachable.
    assert(false);
    return false;
}

bool OperationFactory::GetAndValidatePadding(const AuthorizationSet& begin_params, const Key& key,
                                             keymaster_padding_t* padding,
                                             keymaster_error_t* error) const {
    *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
    if (!begin_params.GetTagValue(TAG_PADDING, padding)) {
        LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING));
        return false;
    } else if (!supported(*padding)) {
        LOG_E("Padding mode %d not supported", *padding);
        return false;
    } else if (
        // If it's a public key operation, all padding modes are authorized.
        !is_public_key_operation() &&
        // Otherwise the key needs to authorize the specific mode.
        !key.authorizations().Contains(TAG_PADDING, *padding) &&
        !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) {
        LOG_E("Padding mode %d was specified, but not authorized by key", *padding);
        *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
        return false;
    }

    *error = KM_ERROR_OK;
    return true;
}

bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
                                            keymaster_digest_t* digest,
                                            keymaster_error_t* error) const {
    *error = KM_ERROR_UNSUPPORTED_DIGEST;
    if (!begin_params.GetTagValue(TAG_DIGEST, digest)) {
        LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
        return false;
    } else if (!supported(*digest)) {
        LOG_E("Digest %d not supported", *digest);
        return false;
    } else if (
        // If it's a public key operation, all digests are authorized.
        !is_public_key_operation() &&
        // Otherwise the key needs to authorize the specific digest.
        !key.authorizations().Contains(TAG_DIGEST, *digest) &&
        !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) {
        LOG_E("Digest %d was specified, but not authorized by key", *digest);
        *error = KM_ERROR_INCOMPATIBLE_DIGEST;
        return false;
    }
    *error = KM_ERROR_OK;
    return true;
}

keymaster_error_t Operation::CreateOperationHandle(const KeymasterContext& context,
                                                   keymaster_operation_handle_t* op_handle) {
    return context.GenerateRandom(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle));
}

keymaster_error_t Operation::UpdateForFinish(const AuthorizationSet& input_params,
                                             const Buffer& input) {
    if (!input_params.empty() || input.available_read()) {
        size_t input_consumed;
        Buffer output;
        AuthorizationSet output_params;
        keymaster_error_t error =
            Update(input_params, input, &output_params, &output, &input_consumed);
        if (error != KM_ERROR_OK)
            return error;
        assert(input_consumed == input.available_read());
        assert(output_params.empty());
        assert(output.available_read() == 0);
    }

    return KM_ERROR_OK;
}

}  // namespace keymaster
