/*
 * 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>

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 size_t buffer_size = end - *buffer;
        if (buffer_size < target->length) 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() {
    request_reenroll = false;
    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);
}

};

