/*
 * Copyright (C) 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 <keystore/authorization_set.h>

#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits>
#include <ostream>
#include <istream>

#include <new>

namespace keystore {

inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
    if (a.tag != b.tag) return a.tag < b.tag;
    int retval;
    switch (typeFromTag(a.tag)) {
    case TagType::INVALID:
    case TagType::BOOL:
        return false;
    case TagType::ENUM:
    case TagType::ENUM_REP:
    case TagType::UINT:
    case TagType::UINT_REP:
        return a.f.integer < b.f.integer;
    case TagType::ULONG:
    case TagType::ULONG_REP:
        return a.f.longInteger < b.f.longInteger;
    case TagType::DATE:
        return a.f.dateTime < b.f.dateTime;
    case TagType::BIGNUM:
    case TagType::BYTES:
        // Handle the empty cases.
        if (a.blob.size() == 0)
            return b.blob.size() != 0;
        if (b.blob.size() == 0) return false;

        retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
        // if one is the prefix of the other the longer wins
        if (retval == 0) return a.blob.size() < b.blob.size();
        // Otherwise a is less if a is less.
        else return retval < 0;
    }
    return false;
}

inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
    if (a.tag != b.tag) return false;

    switch (typeFromTag(a.tag)) {
    case TagType::INVALID:
    case TagType::BOOL:
        return true;
    case TagType::ENUM:
    case TagType::ENUM_REP:
    case TagType::UINT:
    case TagType::UINT_REP:
        return a.f.integer == b.f.integer;
    case TagType::ULONG:
    case TagType::ULONG_REP:
        return a.f.longInteger == b.f.longInteger;
    case TagType::DATE:
        return a.f.dateTime == b.f.dateTime;
    case TagType::BIGNUM:
    case TagType::BYTES:
        if (a.blob.size() != b.blob.size()) return false;
        return a.blob.size() == 0 ||
                memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
    }
    return false;
}

void AuthorizationSet::Sort() {
    std::sort(data_.begin(), data_.end(), keyParamLess);
}

void AuthorizationSet::Deduplicate() {
    if (data_.empty()) return;

    Sort();
    std::vector<KeyParameter> result;

    auto curr = data_.begin();
    auto prev = curr++;
    for (; curr != data_.end(); ++prev, ++curr) {
        if (prev->tag == Tag::INVALID) continue;

        if (!keyParamEqual(*prev, *curr)) {
            result.emplace_back(std::move(*prev));
        }
    }
    result.emplace_back(std::move(*prev));

    std::swap(data_, result);
}

void AuthorizationSet::Union(const AuthorizationSet& other) {
    data_.insert(data_.end(), other.data_.begin(), other.data_.end());
    Deduplicate();
}

void AuthorizationSet::Subtract(const AuthorizationSet& other) {
    Deduplicate();

    auto i = other.begin();
    while (i != other.end()) {
        int pos = -1;
        do {
            pos = find(i->tag, pos);
            if (pos != -1 && keyParamEqual(*i, data_[pos])) {
                data_.erase(data_.begin() + pos);
                break;
            }
        } while (pos != -1);
        ++i;
    }
}

int AuthorizationSet::find(Tag tag, int begin) const {
    auto iter = data_.begin() + (1 + begin);

    while (iter != data_.end() && iter->tag != tag) ++iter;

    if (iter != data_.end()) return iter - data_.begin();
    return -1;
}

bool AuthorizationSet::erase(int index) {
    auto pos = data_.begin() + index;
    if (pos != data_.end()) {
        data_.erase(pos);
        return true;
    }
    return false;
}

KeyParameter& AuthorizationSet::operator[](int at) {
    return data_[at];
}

const KeyParameter& AuthorizationSet::operator[](int at) const {
    return data_[at];
}

void AuthorizationSet::Clear() {
    data_.clear();
}

size_t AuthorizationSet::GetTagCount(Tag tag) const {
    size_t count = 0;
    for (int pos = -1; (pos = find(tag, pos)) != -1;)
        ++count;
    return count;
}

NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
    int pos = find(tag);
    if (pos == -1) return {};
    return data_[pos];
}

/**
 * Persistent format is:
 * | 32 bit indirect_size         |
 * --------------------------------
 * | indirect_size bytes of data  | this is where the blob data is stored
 * --------------------------------
 * | 32 bit element_count         | number of entries
 * | 32 bit elements_size         | total bytes used by entries (entries have variable length)
 * --------------------------------
 * | elementes_size bytes of data | where the elements are stored
 */

/**
 * Persistent format of blobs and bignums:
 * | 32 bit tag             |
 * | 32 bit blob_length     |
 * | 32 bit indirect_offset |
 */

struct OutStreams {
    std::ostream& indirect;
    std::ostream& elements;
};

OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
    uint32_t buffer;

    // write blob_length
    auto blob_length = blob.size();
    if (blob_length > std::numeric_limits<uint32_t>::max()) {
        out.elements.setstate(std::ios_base::badbit);
        return out;
    }
    buffer = blob_length;
    out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));

    // write indirect_offset
    auto offset = out.indirect.tellp();
    if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
            uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) { // overflow check
        out.elements.setstate(std::ios_base::badbit);
        return out;
    }
    buffer = offset;
    out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));

    // write blob to indirect stream
    if(blob_length)
        out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);

    return out;
}

template <typename T>
OutStreams& serializeParamValue(OutStreams& out, const T& value) {
    out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
    return out;
}

OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
    // skip invalid entries.
    return out;
}
template <typename T>
OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
    out.elements.write(reinterpret_cast<const char*>(&param.tag), sizeof(int32_t));
    return serializeParamValue(out, accessTagValue(ttag, param));
}

template <typename... T>
struct choose_serializer;
template <typename... Tags>
struct choose_serializer<MetaList<Tags...>> {
    static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
        return choose_serializer<Tags...>::serialize(out, param);
    }
};
template <>
struct choose_serializer<> {
    static OutStreams& serialize(OutStreams& out, const KeyParameter&) {
        return out;
    }
};
template <TagType tag_type, Tag tag, typename... Tail>
struct choose_serializer<TypedTag<tag_type, tag>, Tail...> {
    static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
        if (param.tag == tag) {
            return keystore::serialize(TypedTag<tag_type, tag>(), out, param);
        } else {
            return choose_serializer<Tail...>::serialize(out, param);
        }
    }
};

OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
    return choose_serializer<all_tags_t>::serialize(out, param);
}

std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
    std::stringstream indirect;
    std::stringstream elements;
    OutStreams streams = { indirect, elements };
    for (const auto& param: params) {
        serialize(streams, param);
    }
    if (indirect.bad() || elements.bad()) {
        out.setstate(std::ios_base::badbit);
        return out;
    }
    auto pos = indirect.tellp();
    if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
        out.setstate(std::ios_base::badbit);
        return out;
    }
    uint32_t indirect_size = pos;
    pos = elements.tellp();
    if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
        out.setstate(std::ios_base::badbit);
        return out;
    }
    uint32_t elements_size = pos;
    uint32_t element_count = params.size();

    out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));

    pos = out.tellp();
    if (indirect_size)
        out << indirect.rdbuf();
    assert(out.tellp() - pos == indirect_size);

    out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
    out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));

    pos = out.tellp();
    if (elements_size)
        out << elements.rdbuf();
    assert(out.tellp() - pos == elements_size);

    return out;
}

struct InStreams {
    std::istream& indirect;
    std::istream& elements;
};

InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
    uint32_t blob_length = 0;
    uint32_t offset = 0;
    in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
    blob->resize(blob_length);
    in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
    in.indirect.seekg(offset);
    in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
    return in;
}

template <typename T>
InStreams& deserializeParamValue(InStreams& in, T* value) {
    in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
    return in;
}

InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
    // there should be no invalid KeyParamaters but if handle them as zero sized.
    return in;
}

template <typename T>
InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
    return deserializeParamValue(in, &accessTagValue(ttag, *param));
}

template <typename... T>
struct choose_deserializer;
template <typename... Tags>
struct choose_deserializer<MetaList<Tags...>> {
    static InStreams& deserialize(InStreams& in, KeyParameter* param) {
        return choose_deserializer<Tags...>::deserialize(in, param);
    }
};
template <>
struct choose_deserializer<> {
    static InStreams& deserialize(InStreams& in, KeyParameter*) {
        // encountered an unknown tag -> fail parsing
        in.elements.setstate(std::ios_base::badbit);
        return in;
    }
};
template <TagType tag_type, Tag tag, typename... Tail>
struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
    static InStreams& deserialize(InStreams& in, KeyParameter* param) {
        if (param->tag == tag) {
            return keystore::deserialize(TypedTag<tag_type, tag>(), in, param);
        } else {
            return choose_deserializer<Tail...>::deserialize(in, param);
        }
    }
};

InStreams& deserialize(InStreams& in, KeyParameter* param) {
    in.elements.read(reinterpret_cast<char*>(&param->tag), sizeof(Tag));
    return choose_deserializer<all_tags_t>::deserialize(in, param);
}

std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
    uint32_t indirect_size = 0;
    in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
    std::string indirect_buffer(indirect_size, '\0');
    if (indirect_buffer.size() != indirect_size) {
        in.setstate(std::ios_base::badbit);
        return in;
    }
    in.read(&indirect_buffer[0], indirect_buffer.size());

    uint32_t element_count = 0;
    in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
    uint32_t elements_size = 0;
    in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));

    std::string elements_buffer(elements_size, '\0');
    if(elements_buffer.size() != elements_size) {
        in.setstate(std::ios_base::badbit);
        return in;
    }
    in.read(&elements_buffer[0], elements_buffer.size());

    if (in.bad()) return in;

    // TODO write one-shot stream buffer to avoid copying here
    std::stringstream indirect(indirect_buffer);
    std::stringstream elements(elements_buffer);
    InStreams streams = { indirect, elements };

    params->resize(element_count);

    for (uint32_t i = 0; i < element_count; ++i) {
        deserialize(streams, &(*params)[i]);
    }
    return in;
}
void AuthorizationSet::Serialize(std::ostream* out) const {
    serialize(*out, data_);
}
void AuthorizationSet::Deserialize(std::istream* in) {
    deserialize(*in, &data_);
}

}  // namespace keystore
