/*
 * Copyright 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 <arpa/inet.h>
#include <iostream>

#include <gtest/gtest.h>
#include <hardware/hw_auth_token.h>
#include <UniquePtr.h>

#include "../SoftGateKeeper.h"

using ::gatekeeper::SizedBuffer;
using ::testing::Test;
using ::gatekeeper::EnrollRequest;
using ::gatekeeper::EnrollResponse;
using ::gatekeeper::VerifyRequest;
using ::gatekeeper::VerifyResponse;
using ::gatekeeper::SoftGateKeeper;
using ::gatekeeper::secure_id_t;

static void do_enroll(SoftGateKeeper &gatekeeper, EnrollResponse *response) {
    SizedBuffer password;

    password.buffer.reset(new uint8_t[16]);
    password.length = 16;
    memset(password.buffer.get(), 0, 16);
    EnrollRequest request(0, NULL, &password, NULL);

    gatekeeper.Enroll(request, response);
}

TEST(GateKeeperTest, EnrollSuccess) {
    SoftGateKeeper gatekeeper;
    EnrollResponse response;
    do_enroll(gatekeeper, &response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
}

TEST(GateKeeperTest, EnrollBogusData) {
    SoftGateKeeper gatekeeper;
    SizedBuffer password;
    EnrollResponse response;

    EnrollRequest request(0, NULL, &password, NULL);

    gatekeeper.Enroll(request, &response);

    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
}

TEST(GateKeeperTest, VerifySuccess) {
    SoftGateKeeper gatekeeper;
    SizedBuffer provided_password;
    EnrollResponse enroll_response;

    provided_password.buffer.reset(new uint8_t[16]);
    provided_password.length = 16;
    memset(provided_password.buffer.get(), 0, 16);

    do_enroll(gatekeeper, &enroll_response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
    VerifyRequest request(0, 1, &enroll_response.enrolled_password_handle,
            &provided_password);
    VerifyResponse response;

    gatekeeper.Verify(request, &response);

    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);

    hw_auth_token_t *auth_token =
        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());

    ASSERT_EQ((uint32_t) HW_AUTH_PASSWORD, ntohl(auth_token->authenticator_type));
    ASSERT_EQ((uint64_t) 1, auth_token->challenge);
    ASSERT_NE(~((uint32_t) 0), auth_token->timestamp);
    ASSERT_NE((uint64_t) 0, auth_token->user_id);
    ASSERT_NE((uint64_t) 0, auth_token->authenticator_id);
}

TEST(GateKeeperTest, TrustedReEnroll) {
    SoftGateKeeper gatekeeper;
    SizedBuffer provided_password;
    EnrollResponse enroll_response;
    SizedBuffer password_handle;

    // do_enroll enrolls an all 0 password
    provided_password.buffer.reset(new uint8_t[16]);
    provided_password.length = 16;
    memset(provided_password.buffer.get(), 0, 16);
    do_enroll(gatekeeper, &enroll_response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);

    // keep a copy of the handle
    password_handle.buffer.reset(new uint8_t[enroll_response.enrolled_password_handle.length]);
    password_handle.length = enroll_response.enrolled_password_handle.length;
    memcpy(password_handle.buffer.get(), enroll_response.enrolled_password_handle.buffer.get(),
            password_handle.length);

    // verify first password
    VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle,
            &provided_password);
    VerifyResponse response;
    gatekeeper.Verify(request, &response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
    hw_auth_token_t *auth_token =
        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());

    secure_id_t secure_id = auth_token->user_id;

    // enroll new password
    provided_password.buffer.reset(new uint8_t[16]);
    provided_password.length = 16;
    memset(provided_password.buffer.get(), 0, 16);
    SizedBuffer password;
    password.buffer.reset(new uint8_t[16]);
    memset(password.buffer.get(), 1, 16);
    password.length = 16;
    EnrollRequest enroll_request(0, &password_handle, &password, &provided_password);
    gatekeeper.Enroll(enroll_request, &enroll_response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);

    // verify new password
    password.buffer.reset(new uint8_t[16]);
    memset(password.buffer.get(), 1, 16);
    password.length = 16;
    VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle,
            &password);
    gatekeeper.Verify(new_request, &response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
    ASSERT_EQ(secure_id,
        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id);
}


TEST(GateKeeperTest, UntrustedReEnroll) {
    SoftGateKeeper gatekeeper;
    SizedBuffer provided_password;
    EnrollResponse enroll_response;

    // do_enroll enrolls an all 0 password
    provided_password.buffer.reset(new uint8_t[16]);
    provided_password.length = 16;
    memset(provided_password.buffer.get(), 0, 16);
    do_enroll(gatekeeper, &enroll_response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);

    // verify first password
    VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle,
            &provided_password);
    VerifyResponse response;
    gatekeeper.Verify(request, &response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
    hw_auth_token_t *auth_token =
        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());

    secure_id_t secure_id = auth_token->user_id;

    // enroll new password
    SizedBuffer password;
    password.buffer.reset(new uint8_t[16]);
    memset(password.buffer.get(), 1, 16);
    password.length = 16;
    EnrollRequest enroll_request(0, NULL, &password, NULL);
    gatekeeper.Enroll(enroll_request, &enroll_response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);

    // verify new password
    password.buffer.reset(new uint8_t[16]);
    memset(password.buffer.get(), 1, 16);
    password.length = 16;
    VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle,
            &password);
    gatekeeper.Verify(new_request, &response);
    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
    ASSERT_NE(secure_id,
        reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id);
}


TEST(GateKeeperTest, VerifyBogusData) {
    SoftGateKeeper gatekeeper;
    SizedBuffer provided_password;
    SizedBuffer password_handle;
    VerifyResponse response;

    VerifyRequest request(0, 0, &provided_password, &password_handle);

    gatekeeper.Verify(request, &response);

    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
}
