/*
**
** 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>
#include <utility>

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 {
        // NOLINTNEXTLINE(google-explicit-constructor)
        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,
                                  keymaster_digest_t digest, 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;

    if (digest != KM_DIGEST_NONE && !contains(supported_digests->second, digest)) {
        LOG(WARNING) << "Digest " << digest << " requested but not supported by KM1 hal";
        return true;
    }

    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,
                               keymaster_digest_t digest, 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, digest, 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;

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

    return !has_purpose;
}

bool Keymaster1LegacySupport::RequiresSoftwareDigesting(const keymaster_digest_t digest,
                                                        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;

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

    /*
     * If the key does not have a purpose it is unusable, i.e., for private key operations.
     * The public key operations which don't need purpose authorization may as well be done
     * in software. This also addresses a bug by which begin operation on keys without purpose and
     * unauthorized digest which is also not supported by the wrapped KM1 device fail with
     * KM_UNSUPPORTED_DIGEST although they should not fail during the begin operation.
     * If it has a purpose and we reach this point we did not find unsupported digests, and
     * therefore do not required software digesting.
     */
    return !has_purpose;
}

template <>
keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::GenerateKey(
    const AuthorizationSet& key_description,  //
    UniquePtr<Key> attest_key,                //
    const KeymasterBlob& issuer_subject,      //
    KeymasterKeyBlob* key_blob,               //
    AuthorizationSet* hw_enforced,            //
    AuthorizationSet* sw_enforced,            //
    CertificateChain* cert_chain) const {
    if (legacy_support_.RequiresSoftwareDigesting(key_description)) {
        return software_digest_factory_.GenerateKey(key_description, std::move(attest_key),
                                                    issuer_subject, key_blob, hw_enforced,
                                                    sw_enforced, cert_chain);
    } 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, std::move(attest_key),
                                                issuer_subject, key_blob, hw_enforced, sw_enforced,
                                                cert_chain);
    }
}

template <>
keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadKey(
    KeymasterKeyBlob&& key_material, const AuthorizationSet& additional_params,
    AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, UniquePtr<Key>* key) const {
    keymaster_digest_t digest;
    if (!additional_params.GetTagValue(TAG_DIGEST, &digest)) {
        digest = KM_DIGEST_NONE;
    }
    bool requires_software_digesting =
        legacy_support_.RequiresSoftwareDigesting(digest, AuthProxy(hw_enforced, sw_enforced));
    auto rc = software_digest_factory_.LoadKey(std::move(key_material), additional_params,
                                               std::move(hw_enforced), std::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 {
    keymaster_digest_t digest;
    if (!additional_params.GetTagValue(TAG_DIGEST, &digest)) {
        digest = KM_DIGEST_NONE;
    }
    bool requires_software_digesting =
        legacy_support_.RequiresSoftwareDigesting(digest, AuthProxy(hw_enforced, sw_enforced));
    auto rc = software_digest_factory_.LoadKey(std::move(key_material), additional_params,
                                               std::move(hw_enforced), std::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
