/*
 * 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:
        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::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
