/*
**
** 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 <keymaster/legacy_support/keymaster1_legacy_support.h>

#include <android-base/logging.h>

#include <assert.h>

#include <algorithm>
#include <vector>

namespace keymaster {

template <typename T> std::vector<T> make_vector(const T* array, size_t len) {
    return std::vector<T>(array, array + len);
}

// This helper class implements just enough of the C++ standard collection interface to be able to
// accept push_back calls, and it does nothing but count them.  It's useful when you want to count
// insertions but not actually store anything.  It's used in digest_set_is_full below to count the
// size of a set intersection.
struct PushbackCounter {
    struct value_type {
        template <typename T> value_type(const T&) {}
    };
    void push_back(const value_type&) { ++count; }
    size_t count = 0;
};

static std::vector<keymaster_digest_t> full_digest_list = {
    KM_DIGEST_MD5,       KM_DIGEST_SHA1,      KM_DIGEST_SHA_2_224,
    KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};

template <typename Iter> static bool digest_set_is_full(Iter begin, Iter end) {
    PushbackCounter counter;
    std::set_intersection(begin, end, full_digest_list.begin(), full_digest_list.end(),
                          std::back_inserter(counter));
    return counter.count == full_digest_list.size();
}

static keymaster_error_t add_digests(const keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
                                     keymaster_purpose_t purpose,
                                     Keymaster1LegacySupport::DigestMap* map, bool* supports_all) {
    auto key = std::make_pair(algorithm, purpose);

    keymaster_digest_t* digests;
    size_t digests_length;
    keymaster_error_t error =
        dev->get_supported_digests(dev, algorithm, purpose, &digests, &digests_length);
    if (error != KM_ERROR_OK) {
        LOG(ERROR) << "Error " << error << " getting supported digests from keymaster1 device";
        return error;
    }
    std::unique_ptr<keymaster_digest_t, Malloc_Delete> digests_deleter(digests);

    auto digest_vec = make_vector(digests, digests_length);
    *supports_all = digest_set_is_full(digest_vec.begin(), digest_vec.end());
    (*map)[key] = std::move(digest_vec);
    return error;
}

static keymaster_error_t map_digests(const keymaster1_device_t* dev,
                                     Keymaster1LegacySupport::DigestMap* map,
                                     bool* supports_all) {
    map->clear();
    *supports_all = true;

    keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC, KM_ALGORITHM_HMAC};
    keymaster_purpose_t sig_purposes[] = {KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY};
    for (auto algorithm : sig_algorithms)
        for (auto purpose : sig_purposes) {
            bool alg_purpose_supports_all;
            keymaster_error_t error =
                add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
            if (error != KM_ERROR_OK)
                return error;
            *supports_all &= alg_purpose_supports_all;
        }

    keymaster_algorithm_t crypt_algorithms[] = {KM_ALGORITHM_RSA};
    keymaster_purpose_t crypt_purposes[] = {KM_PURPOSE_ENCRYPT, KM_PURPOSE_DECRYPT};
    for (auto algorithm : crypt_algorithms)
        for (auto purpose : crypt_purposes) {
            bool alg_purpose_supports_all;
            keymaster_error_t error =
                add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
            if (error != KM_ERROR_OK)
                return error;
            *supports_all &= alg_purpose_supports_all;
        }

    return KM_ERROR_OK;
}

Keymaster1LegacySupport::Keymaster1LegacySupport(const keymaster1_device_t* dev) {
    map_digests(dev, &device_digests_, &supports_all_);
}

template <typename Collection, typename Value> bool contains(const Collection& c, const Value& v) {
    return std::find(c.begin(), c.end(), v) != c.end();
}

template <typename T>
static bool findUnsupportedDigest(keymaster_algorithm_t algorithm,
                                  keymaster_purpose_t purpose,
                                  const T& params,
                                  const Keymaster1LegacySupport::DigestMap& digest_map) {
    auto supported_digests = digest_map.find(std::make_pair(algorithm, purpose));
    if (supported_digests == digest_map.end())
        // Invalid algorith/purpose pair (e.g. EC encrypt).  Let the error be handled by HW module.
        return false;

    for (auto& entry : params)
        if (entry.tag == TAG_DIGEST)
            if (!contains(supported_digests->second, entry.enumerated)) {
                LOG(WARNING) << "Digest " << entry.enumerated << " requested but not supported by KM1 hal";
                return true;
            }
    return false;
}

template <typename T>
bool requiresSoftwareDigesting(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
                               const T& params,
                               const Keymaster1LegacySupport::DigestMap& digest_map) {
    switch (algorithm) {
    case KM_ALGORITHM_AES:
    case KM_ALGORITHM_TRIPLE_DES:
        LOG(WARNING) << "Not performing software digesting for symmetric cipher keys";
        return false;
    case KM_ALGORITHM_HMAC:
    case KM_ALGORITHM_RSA:
    case KM_ALGORITHM_EC:
        break;
    }

    if (!findUnsupportedDigest(algorithm, purpose, params, digest_map)) {
        LOG(DEBUG) << "Requested digest(s) supported for algorithm " << algorithm << " and purpose " << purpose;
        return false;
    }

    return true;
}
bool Keymaster1LegacySupport::RequiresSoftwareDigesting(
        const AuthorizationSet& key_description) const {

    keymaster_algorithm_t algorithm;
    if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
        // The hardware module will return an error during keygen.
        return false;
    }

    if (supports_all_) return false;

    for (auto& entry : key_description)
        if (entry.tag == TAG_PURPOSE) {
            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(entry.enumerated);
            if (requiresSoftwareDigesting(algorithm, purpose, key_description, device_digests_))
                return true;
        }

    return false;
}

bool Keymaster1LegacySupport::RequiresSoftwareDigesting(
        const AuthProxy& key_description) const {

    keymaster_algorithm_t algorithm;
    if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
        // The hardware module will return an error during keygen.
        return false;
    }

    if (supports_all_) return false;

    for (auto& entry : key_description)
        if (entry.tag == TAG_PURPOSE) {
            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(entry.enumerated);
            if (requiresSoftwareDigesting(algorithm, purpose, key_description, device_digests_))
                return true;
        }

    return false;
}

template<>
keymaster_error_t
Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::GenerateKey(
        const AuthorizationSet& key_description,
        KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
        AuthorizationSet* sw_enforced) const {
    if (legacy_support_.RequiresSoftwareDigesting(key_description)) {
        return software_digest_factory_.GenerateKey(key_description, key_blob, hw_enforced,
                                             sw_enforced);
    } else {
        AuthorizationSet mutable_key_description = key_description;
        keymaster_ec_curve_t curve;
        if (key_description.GetTagValue(TAG_EC_CURVE, &curve)) {
            // Keymaster1 doesn't know about EC curves. We need to translate to key size.
            uint32_t key_size_from_curve;
            keymaster_error_t error = EcCurveToKeySize(curve, &key_size_from_curve);
            if (error != KM_ERROR_OK) {
                return error;
            }

            uint32_t key_size_from_desc;
            if (key_description.GetTagValue(TAG_KEY_SIZE, &key_size_from_desc)) {
                if (key_size_from_desc != key_size_from_curve) {
                    return KM_ERROR_INVALID_ARGUMENT;
                }
            } else {
                mutable_key_description.push_back(TAG_KEY_SIZE, key_size_from_curve);
            }
        }

        return passthrough_factory_.GenerateKey(mutable_key_description, key_blob, hw_enforced,
                                                sw_enforced);
    }
}

template<>
keymaster_error_t
Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
        const AuthorizationSet& additional_params,
        AuthorizationSet&& hw_enforced,
        AuthorizationSet&& sw_enforced,
        UniquePtr<Key>* key) const {
    bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(
                                                           AuthProxy(hw_enforced, sw_enforced));
    auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params,
                                               move(hw_enforced), move(sw_enforced), key);
    if (rc != KM_ERROR_OK) return rc;
    if (!requires_software_digesting) {
        (*key)->key_factory() = & passthrough_factory_;
    }
    return KM_ERROR_OK;
}

template<>
keymaster_error_t
Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
        const AuthorizationSet& additional_params,
        AuthorizationSet&& hw_enforced,
        AuthorizationSet&& sw_enforced,
        UniquePtr<Key>* key) const {
    bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(
                                                           AuthProxy(hw_enforced, sw_enforced));
    auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params,
                                               move(hw_enforced), move(sw_enforced), key);
    if (rc != KM_ERROR_OK) return rc;
    if (!requires_software_digesting) {
        (*key)->key_factory() = & passthrough_factory_;
    }
    return KM_ERROR_OK;
}


} // namespace keymaster
