/*
 * 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 <gatekeeper/gatekeeper_messages.h>

#include <string.h>

using namespace std;

namespace gatekeeper {

/**
 * Methods for serializing/deserializing SizedBuffers
 */

struct __attribute__((__packed__)) serial_header_t {
    uint32_t error;
    uint32_t user_id;
};

static inline uint32_t serialized_buffer_size(const SizedBuffer &buf) {
    return sizeof(buf.length) + buf.length;
}

static inline void append_to_buffer(uint8_t **buffer, const SizedBuffer *to_append) {
    memcpy(*buffer, &to_append->length, sizeof(to_append->length));
    *buffer += sizeof(to_append->length);
    if (to_append->length != 0) {
        memcpy(*buffer, to_append->buffer.get(), to_append->length);
        *buffer += to_append->length;
    }
}

static inline gatekeeper_error_t read_from_buffer(const uint8_t **buffer, const uint8_t *end,
        SizedBuffer *target) {
    if (*buffer + sizeof(target->length) > end) return ERROR_INVALID;

    memcpy(&target->length, *buffer, sizeof(target->length));
    *buffer += sizeof(target->length);
    if (target->length != 0) {
        const uint8_t *buffer_end = *buffer + target->length;
        if (buffer_end > end || buffer_end <= *buffer) return ERROR_INVALID;

        target->buffer.reset(new uint8_t[target->length]);
        memcpy(target->buffer.get(), *buffer, target->length);
        *buffer += target->length;
    }
    return ERROR_NONE;
}


uint32_t GateKeeperMessage::GetSerializedSize() const {
    if (error == ERROR_NONE) {
        uint32_t size = sizeof(serial_header_t) + nonErrorSerializedSize();
        return size;
    } else {
        uint32_t size = sizeof(serial_header_t);
        if (error == ERROR_RETRY) {
            size += sizeof(retry_timeout);
        }
        return size;
    }
}

uint32_t GateKeeperMessage::Serialize(uint8_t *buffer, const uint8_t *end) const {
    uint32_t bytes_written = 0;
    if (buffer + GetSerializedSize() > end) {
        return 0;
    }

    serial_header_t *header = reinterpret_cast<serial_header_t *>(buffer);
    if (error != ERROR_NONE) {
        if (buffer + sizeof(serial_header_t) > end) return 0;
        header->error = error;
        header->user_id = user_id;
        bytes_written += sizeof(*header);
        if (error == ERROR_RETRY) {
            memcpy(buffer + sizeof(serial_header_t), &retry_timeout, sizeof(retry_timeout));
            bytes_written  += sizeof(retry_timeout);
        }
    } else {
        if (buffer + sizeof(serial_header_t) + nonErrorSerializedSize() > end)
            return 0;
        header->error = error;
        header->user_id = user_id;
        nonErrorSerialize(buffer + sizeof(*header));
        bytes_written += sizeof(*header) + nonErrorSerializedSize();
    }

    return bytes_written;
}

gatekeeper_error_t GateKeeperMessage::Deserialize(const uint8_t *payload, const uint8_t *end) {
    if (payload + sizeof(uint32_t) > end) return ERROR_INVALID;
    const serial_header_t *header = reinterpret_cast<const serial_header_t *>(payload);
    if (header->error == ERROR_NONE) {
        if (payload == end) return ERROR_INVALID;
        user_id = header->user_id;
        error = nonErrorDeserialize(payload + sizeof(*header), end);
    } else {
        error = static_cast<gatekeeper_error_t>(header->error);
        user_id = header->user_id;
        if (error == ERROR_RETRY) {
            if (payload + sizeof(serial_header_t) < end) {
                memcpy(&retry_timeout, payload + sizeof(serial_header_t), sizeof(retry_timeout));
            } else {
                retry_timeout = 0;
            }
        }
    }

    return error;
}

void GateKeeperMessage::SetRetryTimeout(uint32_t retry_timeout) {
    this->retry_timeout = retry_timeout;
    this->error = ERROR_RETRY;
}

VerifyRequest::VerifyRequest(uint32_t user_id, uint64_t challenge,
        SizedBuffer *enrolled_password_handle, SizedBuffer *provided_password_payload) {
    this->user_id = user_id;
    this->challenge = challenge;
    this->password_handle.buffer.reset(enrolled_password_handle->buffer.release());
    this->password_handle.length = enrolled_password_handle->length;
    this->provided_password.buffer.reset(provided_password_payload->buffer.release());
    this->provided_password.length = provided_password_payload->length;
}

VerifyRequest::VerifyRequest() {
    memset_s(&password_handle, 0, sizeof(password_handle));
    memset_s(&provided_password, 0, sizeof(provided_password));
}

VerifyRequest::~VerifyRequest() {
    if (password_handle.buffer.get()) {
        password_handle.buffer.reset();
    }

    if (provided_password.buffer.get()) {
        memset_s(provided_password.buffer.get(), 0, provided_password.length);
        provided_password.buffer.reset();
    }
}

uint32_t VerifyRequest::nonErrorSerializedSize() const {
    return sizeof(challenge) + serialized_buffer_size(password_handle)
            + serialized_buffer_size(provided_password);
}

void VerifyRequest::nonErrorSerialize(uint8_t *buffer) const {
    memcpy(buffer, &challenge, sizeof(challenge));
    buffer += sizeof(challenge);
    append_to_buffer(&buffer, &password_handle);
    append_to_buffer(&buffer, &provided_password);
}

gatekeeper_error_t VerifyRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
    gatekeeper_error_t error = ERROR_NONE;

    if (password_handle.buffer.get()) {
        password_handle.buffer.reset();
    }

    if (provided_password.buffer.get()) {
        memset_s(provided_password.buffer.get(), 0, provided_password.length);
        provided_password.buffer.reset();
    }

    memcpy(&challenge, payload, sizeof(challenge));
    payload += sizeof(challenge);

    error = read_from_buffer(&payload, end, &password_handle);
    if (error != ERROR_NONE) return error;

    return read_from_buffer(&payload, end, &provided_password);

}

VerifyResponse::VerifyResponse(uint32_t user_id, SizedBuffer *auth_token) {
    this->user_id = user_id;
    this->auth_token.buffer.reset(auth_token->buffer.release());
    this->auth_token.length = auth_token->length;
    this->request_reenroll = false;
}

VerifyResponse::VerifyResponse() {
    memset_s(&auth_token, 0, sizeof(auth_token));
};

VerifyResponse::~VerifyResponse() {
    if (auth_token.length > 0) {
        auth_token.buffer.reset();
    }
}

void VerifyResponse::SetVerificationToken(SizedBuffer *auth_token) {
    this->auth_token.buffer.reset(auth_token->buffer.release());
    this->auth_token.length = auth_token->length;
}

uint32_t VerifyResponse::nonErrorSerializedSize() const {
    return serialized_buffer_size(auth_token) + sizeof(request_reenroll);
}

void VerifyResponse::nonErrorSerialize(uint8_t *buffer) const {
    append_to_buffer(&buffer, &auth_token);
    memcpy(buffer, &request_reenroll, sizeof(request_reenroll));
}

gatekeeper_error_t VerifyResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
    if (auth_token.buffer.get()) {
        auth_token.buffer.reset();
    }

    gatekeeper_error_t err = read_from_buffer(&payload, end, &auth_token);
    if (err != ERROR_NONE) {
        return err;
    }

    memcpy(&request_reenroll, payload, sizeof(request_reenroll));
    return ERROR_NONE;
}

EnrollRequest::EnrollRequest(uint32_t user_id, SizedBuffer *password_handle,
        SizedBuffer *provided_password,  SizedBuffer *enrolled_password) {
    this->user_id = user_id;
    this->provided_password.buffer.reset(provided_password->buffer.release());
    this->provided_password.length = provided_password->length;

    if (enrolled_password == NULL) {
        this->enrolled_password.buffer.reset();
        this->enrolled_password.length = 0;
    } else {
        this->enrolled_password.buffer.reset(enrolled_password->buffer.release());
        this->enrolled_password.length = enrolled_password->length;
    }

    if (password_handle == NULL) {
        this->password_handle.buffer.reset();
        this->password_handle.length = 0;
    } else {
        this->password_handle.buffer.reset(password_handle->buffer.release());
        this->password_handle.length = password_handle->length;
    }
}

EnrollRequest::EnrollRequest() {
    memset_s(&provided_password, 0, sizeof(provided_password));
    memset_s(&enrolled_password, 0, sizeof(enrolled_password));
    memset_s(&password_handle, 0, sizeof(password_handle));
}

EnrollRequest::~EnrollRequest() {
    if (provided_password.buffer.get()) {
        memset_s(provided_password.buffer.get(), 0, provided_password.length);
        provided_password.buffer.reset();
    }

    if (enrolled_password.buffer.get()) {
        memset_s(enrolled_password.buffer.get(), 0, enrolled_password.length);
        enrolled_password.buffer.reset();
    }

    if (password_handle.buffer.get()) {
        memset_s(password_handle.buffer.get(), 0, password_handle.length);
        password_handle.buffer.reset();
    }
}

uint32_t EnrollRequest::nonErrorSerializedSize() const {
   return serialized_buffer_size(provided_password) + serialized_buffer_size(enrolled_password)
       + serialized_buffer_size(password_handle);
}

void EnrollRequest::nonErrorSerialize(uint8_t *buffer) const {
    append_to_buffer(&buffer, &provided_password);
    append_to_buffer(&buffer, &enrolled_password);
    append_to_buffer(&buffer, &password_handle);
}

gatekeeper_error_t EnrollRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
    gatekeeper_error_t ret;
    if (provided_password.buffer.get()) {
        memset_s(provided_password.buffer.get(), 0, provided_password.length);
        provided_password.buffer.reset();
    }

    if (enrolled_password.buffer.get()) {
        memset_s(enrolled_password.buffer.get(), 0, enrolled_password.length);
        enrolled_password.buffer.reset();
    }

    if (password_handle.buffer.get()) {
        memset_s(password_handle.buffer.get(), 0, password_handle.length);
        password_handle.buffer.reset();
    }

     ret = read_from_buffer(&payload, end, &provided_password);
     if (ret != ERROR_NONE) {
         return ret;
     }

     ret = read_from_buffer(&payload, end, &enrolled_password);
     if (ret != ERROR_NONE) {
         return ret;
     }

     return read_from_buffer(&payload, end, &password_handle);
}

EnrollResponse::EnrollResponse(uint32_t user_id, SizedBuffer *enrolled_password_handle) {
    this->user_id = user_id;
    this->enrolled_password_handle.buffer.reset(enrolled_password_handle->buffer.release());
    this->enrolled_password_handle.length = enrolled_password_handle->length;
}

EnrollResponse::EnrollResponse() {
    memset_s(&enrolled_password_handle, 0, sizeof(enrolled_password_handle));
}

EnrollResponse::~EnrollResponse() {
    if (enrolled_password_handle.buffer.get()) {
        enrolled_password_handle.buffer.reset();
    }
}

void EnrollResponse::SetEnrolledPasswordHandle(SizedBuffer *enrolled_password_handle) {
    this->enrolled_password_handle.buffer.reset(enrolled_password_handle->buffer.release());
    this->enrolled_password_handle.length = enrolled_password_handle->length;
}

uint32_t EnrollResponse::nonErrorSerializedSize() const {
    return serialized_buffer_size(enrolled_password_handle);
}

void EnrollResponse::nonErrorSerialize(uint8_t *buffer) const {
    append_to_buffer(&buffer, &enrolled_password_handle);
}

gatekeeper_error_t EnrollResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
    if (enrolled_password_handle.buffer.get()) {
        enrolled_password_handle.buffer.reset();
    }

    return read_from_buffer(&payload, end, &enrolled_password_handle);
}

};

