/*
 * 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 <keymaster/authorization_set.h>
#include <keymaster/key.h>
#include <keymaster/operation.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:
    case KM_ALGORITHM_TRIPLE_DES:
        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:
    case KM_PURPOSE_WRAP:
        return true;
    case KM_PURPOSE_SIGN:
    case KM_PURPOSE_DECRYPT:
    case KM_PURPOSE_DERIVE_KEY:
    case KM_PURPOSE_AGREE_KEY:
    case KM_PURPOSE_ATTEST_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 {
    return GetAndValidateDigest(begin_params, key, digest, error, false);
}

bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
                                            keymaster_digest_t* digest, keymaster_error_t* error,
                                            bool require_explicit_digest) const {
    *error = KM_ERROR_UNSUPPORTED_DIGEST;
    if (!begin_params.GetTagValue(TAG_DIGEST, digest)) {
        if (require_explicit_digest) {
            return false;
        }
        if (key.authorizations().Contains(TAG_DIGEST, KM_DIGEST_NONE)) {
            *digest = KM_DIGEST_NONE;
        } else {
            LOG_E("%d digests specified in begin params and NONE not authorized",
                  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::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
