/*
 * Copyright (C) 2015 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 <memory>
#include <vector>

#include <hardware/hw_auth_token.h>
#include <keystore/authorization_set.h>

#ifndef KEYSTORE_AUTH_TOKEN_TABLE_H_
#define KEYSTORE_AUTH_TOKEN_TABLE_H_

namespace keystore {

using android::hardware::keymaster::V3_0::HardwareAuthToken;

namespace test {
class AuthTokenTableTest;
}  // namespace test

time_t clock_gettime_raw();

/**
 * AuthTokenTable manages a set of received authorization tokens and can provide the appropriate
 * token for authorizing a key operation.
 *
 * To keep the table from growing without bound, superseded entries are removed when possible, and
 * least recently used entries are automatically pruned when when the table exceeds a size limit,
 * which is expected to be relatively small, since the implementation uses a linear search.
 */
class AuthTokenTable {
  public:
    explicit AuthTokenTable(size_t max_entries = 32, time_t (*clock_function)() = clock_gettime_raw)
        : max_entries_(max_entries), last_off_body_(clock_function()),
          clock_function_(clock_function) {}

    enum Error {
        OK,
        AUTH_NOT_REQUIRED = -1,
        AUTH_TOKEN_EXPIRED = -2,    // Found a matching token, but it's too old.
        AUTH_TOKEN_WRONG_SID = -3,  // Found a token with the right challenge, but wrong SID.  This
                                    // most likely indicates that the authenticator was updated
                                    // (e.g. new fingerprint enrolled).
        OP_HANDLE_REQUIRED = -4,    // The key requires auth per use but op_handle was zero.
        AUTH_TOKEN_NOT_FOUND = -5,
    };

    /**
     * Add an authorization token to the table.  The table takes ownership of the argument.
     */
    void AddAuthenticationToken(const HardwareAuthToken* token);

    /**
     * Find an authorization token that authorizes the operation specified by \p operation_handle on
     * a key with the characteristics specified in \p key_info.
     *
     * This method is O(n * m), where n is the number of KM_TAG_USER_SECURE_ID entries in key_info
     * and m is the number of entries in the table.  It could be made better, but n and m should
     * always be small.
     *
     * The table retains ownership of the returned object.
     */
    Error FindAuthorization(const AuthorizationSet& key_info, KeyPurpose purpose,
                            uint64_t op_handle, const HardwareAuthToken** found);

    /**
     * Mark operation completed.  This allows tokens associated with the specified operation to be
     * superseded by new tokens.
     */
    void MarkCompleted(const uint64_t op_handle);

    /**
     * Update the last_off_body_ timestamp so that tokens which remain authorized only so long as
     * the device stays on body can be revoked.
     */
    void onDeviceOffBody();

    void Clear();

    size_t size() { return entries_.size(); }

  private:
    friend class AuthTokenTableTest;

    class Entry {
      public:
        Entry(const HardwareAuthToken* token, time_t current_time);
        Entry(Entry&& entry) { *this = std::move(entry); }

        void operator=(Entry&& rhs) {
            token_ = std::move(rhs.token_);
            time_received_ = rhs.time_received_;
            last_use_ = rhs.last_use_;
            operation_completed_ = rhs.operation_completed_;
        }

        bool operator<(const Entry& rhs) const { return last_use_ < rhs.last_use_; }

        void UpdateLastUse(time_t time);

        bool Supersedes(const Entry& entry) const;
        bool SatisfiesAuth(const std::vector<uint64_t>& sids, HardwareAuthenticatorType auth_type);

        bool is_newer_than(const Entry* entry) const {
            if (!entry) return true;
            uint64_t ts = timestamp_host_order();
            uint64_t other_ts = entry->timestamp_host_order();
            // Normally comparing timestamp_host_order alone is sufficient, but here is an
            // additional hack to compare time_received value for some devices where their auth
            // tokens contain fixed timestamp (due to the a stuck secure RTC on them)
            return (ts > other_ts) ||
                   ((ts == other_ts) && (time_received_ > entry->time_received_));
        }

        void mark_completed() { operation_completed_ = true; }

        const HardwareAuthToken* token() { return token_.get(); }
        time_t time_received() const { return time_received_; }
        bool completed() const { return operation_completed_; }
        uint64_t timestamp_host_order() const;
        HardwareAuthenticatorType authenticator_type() const;

      private:
        std::unique_ptr<const HardwareAuthToken> token_;
        time_t time_received_;
        time_t last_use_;
        bool operation_completed_;
    };

    Error FindAuthPerOpAuthorization(const std::vector<uint64_t>& sids,
                                     HardwareAuthenticatorType auth_type, uint64_t op_handle,
                                     const HardwareAuthToken** found);
    Error FindTimedAuthorization(const std::vector<uint64_t>& sids,
                                 HardwareAuthenticatorType auth_type,
                                 const AuthorizationSet& key_info, const HardwareAuthToken** found);
    void ExtractSids(const AuthorizationSet& key_info, std::vector<uint64_t>* sids);
    void RemoveEntriesSupersededBy(const Entry& entry);
    bool IsSupersededBySomeEntry(const Entry& entry);

    std::vector<Entry> entries_;
    size_t max_entries_;
    time_t last_off_body_;
    time_t (*clock_function_)();
};

}  // namespace keymaster

#endif  // KEYSTORE_AUTH_TOKEN_TABLE_H_
