/*
This file is part of GNUnet.
Copyright (C) 2020--2021 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @author Tobias Frisch
* @file src/messenger/messenger_api_message.h
* @brief messenger api: client and service implementation of GNUnet MESSENGER service
*/
#ifndef GNUNET_MESSENGER_API_MESSAGE_H
#define GNUNET_MESSENGER_API_MESSAGE_H
#include "platform.h"
#include "gnunet_crypto_lib.h"
#include "gnunet_identity_service.h"
#include "gnunet_mq_lib.h"
#include "gnunet_signatures.h"
#include "gnunet_messenger_service.h"
#include "messenger_api_ego.h"
#define GNUNET_MESSENGER_MAX_MESSAGE_SIZE (GNUNET_MAX_MESSAGE_SIZE - GNUNET_MIN_MESSAGE_SIZE)
#define GNUNET_MESSENGER_PADDING_MIN (sizeof(uint16_t) + sizeof(char))
#define GNUNET_MESSENGER_PADDING_LEVEL0 (512)
#define GNUNET_MESSENGER_PADDING_LEVEL1 (4096)
#define GNUNET_MESSENGER_PADDING_LEVEL2 (32768)
/**
* Creates and allocates a new message with a specific kind.
*
* @param[in] kind Kind of message
* @return New message
*/
struct GNUNET_MESSENGER_Message*
create_message (enum GNUNET_MESSENGER_MessageKind kind);
/**
* Creates and allocates a copy of a given message.
*
* @param[in] message Message
* @return New message
*/
struct GNUNET_MESSENGER_Message*
copy_message (const struct GNUNET_MESSENGER_Message *message);
/**
* Destroys a message and frees its memory fully.
*
* @param[in/out] message Message
*/
void
destroy_message (struct GNUNET_MESSENGER_Message *message);
/**
* Returns if the message should be bound to a member session.
*
* @param[in] message Message
* @return #GNUNET_YES or #GNUNET_NO
*/
int
is_message_session_bound (const struct GNUNET_MESSENGER_Message *message);
/**
* Returns the minimal size in bytes to encode a message of a specific kind.
*
* @param[in] kind Kind of message
* @return Minimal size to encode
*/
uint16_t
get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind);
/**
* Returns the exact size in bytes to encode a given message.
*
* @param[in] message Message
* @param[in] encode_signature Flag to include signature
* @return Size to encode
*/
uint16_t
get_message_size (const struct GNUNET_MESSENGER_Message *message,
int include_signature);
/**
* Encodes a given message into a buffer of a maximal length in bytes.
*
* @param[in] message Message
* @param[in] length Maximal length to encode
* @param[out] buffer Buffer
* @param[in] encode_signature Flag to include signature
*/
void
encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
int include_signature);
/**
* Decodes a message from a given buffer of a maximal length in bytes.
*
* If the buffer is too small for a message of its decoded kind the function fails with
* resulting #GNUNET_NO after decoding only the messages header.
*
* On success the function returns #GNUNET_YES.
*
* @param[out] message Message
* @param[in] length Maximal length to decode
* @param[in] buffer Buffer
* @param[out] padding Padding
* @return #GNUNET_YES on success, otherwise #GNUNET_NO
*/
int
decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
int include_signature, uint16_t *padding);
/**
* Calculates a hash of a given buffer with a length in bytes
* from a message.
*
* @param[in] message Message
* @param[in] length Length of buffer
* @param[in] buffer Buffer
* @param[out] hash Hash
*/
void
hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
struct GNUNET_HashCode *hash);
/**
* Signs the hash of a message with a given ego and writes the signature
* into the buffer as well.
*
* @param[in/out] message Message
* @param[in] length Length of buffer
* @param[out] buffer Buffer
* @param[in] hash Hash of message
* @param[in] ego EGO
*/
void
sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego);
/**
* Verifies the signature of a given message and its hash with a specific
* public key. The function returns #GNUNET_OK if the signature was valid, otherwise
* #GNUNET_SYSERR.
*
* @param[in] message Message
* @param[in] hash Hash of message
* @param[in] key Public key of EGO
* @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
*/
int
verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
const struct GNUNET_IDENTITY_PublicKey *key);
/**
* Encrypts a message using a given public key and replaces its body
* and kind with the now private encrypted message. The function returns
* #GNUNET_YES if the operation succeeded, otherwise #GNUNET_NO.
*
* @param[in/out] message Message
* @param[in] key Public key of EGO
* @return #GNUNET_YES on success, otherwise #GNUNET_NO
*/
int
encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key);
/**
* Decrypts a private message using a given private key and replaces its body
* and kind with the inner encrypted message. The function returns #GNUNET_YES if the
* operation succeeded, otherwise #GNUNET_NO.
*
* @param[in/out] message Message
* @param[in] key Private key of EGO
* @return #GNUNET_YES on success, otherwise #GNUNET_NO
*/
int
decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key);
#define GNUNET_MESSENGER_PACK_MODE_ENVELOPE 0x1
#define GNUNET_MESSENGER_PACK_MODE_UNKNOWN 0x0
/**
* Encodes the message to pack it into a newly allocated envelope if mode
* is equal to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message
* will be hashed if hash is not NULL and it will be signed if the ego is
* not NULL.
*
* @param[out] message Message
* @param[out] hash Hash of message
* @param[in] ego EGO to sign
* @param[in] mode Mode of packing
* @return Envelope or NULL
*/
struct GNUNET_MQ_Envelope*
pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
const struct GNUNET_MESSENGER_Ego *ego, int mode);
/**
* Returns if a specific kind of message should be sent by a client. The function returns
* #GNUNET_YES or #GNUNET_NO for recommendations and #GNUNET_SYSERR for specific kinds
* of messages which should not be sent manually at all.
*
* @param[in] message Message
*/
int
filter_message_sending (const struct GNUNET_MESSENGER_Message *message);
#endif //GNUNET_MESSENGER_API_MESSAGE_H