/*

  silcmessage.h

  Author: Pekka Riikonen <priikone@silcnet.org>

  Copyright (C) 1997 - 2014 Pekka Riikonen

  The contents of this file are subject to one of the Licenses specified 
  in the COPYING file;  You may not use this file except in compliance 
  with the License.

  The software distributed under the License is distributed on an "AS IS"
  basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
  KIND, either expressed or implied.  See the COPYING file for more
  information.

*/

/****h* silccore/SILC Message Interface
 *
 * DESCRIPTION
 *
 * This interface includes the implementation of the Message Payload that
 * is used to send private messages and channel messages.  The interface
 * is also able to automatically provide digital signature in the messages
 * if it is requested.  Message digital signatures may also be verified with
 * this interface.
 *
 ***/

#ifndef SILCMESSAGE_H
#define SILCMESSAGE_H

/****s* silccore/SilcMessageAPI/SilcMessagePayload
 *
 * NAME
 *
 *    typedef struct SilcMessagePayloadObject
 *      *SilcMessagePayload, SilcMessagePayloadStruct;
 *
 *
 * DESCRIPTION
 *
 *    This context is the actual Message Payload and is allocated
 *    by silc_message_payload_parse and given as argument usually
 *    to all silc_message_* functions.  It is freed by the
 *    silc_message_payload_free function.
 *
 ***/
typedef struct SilcMessagePayloadObject
  *SilcMessagePayload, SilcMessagePayloadStruct;

/****d* silccore/SilcMessageAPI/SilcMessageFlags
 *
 * NAME
 *
 *    typedef SilcUInt16 SilcMessageFlags;
 *
 * DESCRIPTION
 *
 *    The message flags type definition and the message flags.  The
 *    message flags are used to indicate some status of the message.
 *
 * SOURCE
 */
typedef SilcUInt16 SilcMessageFlags;

/* The message flags */
#define SILC_MESSAGE_FLAG_NONE        0x0000      /* No flags */
#define SILC_MESSAGE_FLAG_AUTOREPLY   0x0001	  /* Automatically replied */
#define SILC_MESSAGE_FLAG_NOREPLY     0x0002	  /* Send no reply to this */
#define SILC_MESSAGE_FLAG_ACTION      0x0004	  /* Action message */
#define SILC_MESSAGE_FLAG_NOTICE      0x0008	  /* Notice message */
#define SILC_MESSAGE_FLAG_REQUEST     0x0010	  /* A request */
#define SILC_MESSAGE_FLAG_SIGNED      0x0020	  /* Message is signed */
#define SILC_MESSAGE_FLAG_REPLY       0x0040	  /* A reply */
#define SILC_MESSAGE_FLAG_DATA        0x0080	  /* MIME object */
#define SILC_MESSAGE_FLAG_UTF8        0x0100	  /* UTF-8 string */
#define SILC_MESSAGE_FLAG_ACK         0x0200	  /* ACK messages */
#define SILC_MESSAGE_FLAG_STOP        0x0400      /* Stop indication */
#define SILC_MESSAGE_FLAG_PACKET      0x0800      /* Contains SILC packet */
#define SILC_MESSAGE_FLAG_RESERVED    0x1000      /* to 0x1000 */
#define SILC_MESSAGE_FLAG_PRIVATE     0x2000	  /* to 0x8000 */
/***/

/****f* silccore/SilcMessageAPI/silc_message_payload_decrypt
 *
 * SYNOPSIS
 *
 *    SilcBool silc_message_payload_decrypt(unsigned char *data,
 *                                          size_t data_len,
 *                                          SilcBool private_message,
 *                                          SilcBool static_key,
 *                                          SilcCipher cipher,
 *                                          SilcHmac hmac,
 *                                          unsigned char *sender_id,
 *                                          SilcUInt32 sender_id_len,
 *                                          unsigned char *receiver_id,
 *                                          SilcUInt32 receiver_id_len,
 *                                          SilcBool check_mac);
 *
 * DESCRIPTION
 *
 *    Decrypt Message Payload indicated by `data'.  If the payload is
 *    channel message then `private_message' is FALSE, and if it is
 *    private message it is TRUE.  If the private message key is static
 *    (pre-shared key) then protocol dictates that the IV is present
 *    and `static_key' must be set to TRUE.  If the key is not static
 *    (Key Agreement was done for the key) then it MUST be FALSE.  For
 *    channel messages the `static_key' is ignored.
 *
 *    The `sender_id' and `receiver_id' are the IDs from the packet header
 *    of the packet where this message payload was received.
 *
 *    This is usually used by the Message Payload interface itself but can
 *    be called by the appliation if separate decryption process is required.
 *    For example server might need to call this directly in some
 *    circumstances. The `cipher' is used to decrypt the payload.  If
 *    `check_mac' is FALSE then MAC is not verified.
 *
 ***/
SilcBool silc_message_payload_decrypt(unsigned char *data,
				      size_t data_len,
				      SilcBool private_message,
				      SilcBool static_key,
				      SilcCipher cipher,
				      SilcHmac hmac,
				      unsigned char *sender_id,
				      SilcUInt32 sender_id_len,
				      unsigned char *receiver_id,
				      SilcUInt32 receiver_id_len,
				      SilcBool check_mac);

/****f* silccore/SilcMessageAPI/silc_message_payload_parse
 *
 * SYNOPSIS
 *
 *    SilcMessagePayload
 *    silc_message_payload_parse(unsigned char *payload,
 *                               SilcUInt32 payload_len,
 *                               SilcBool private_message,
 *                               SilcBool static_key,
 *                               SilcCipher cipher,
 *                               SilcHmac hmac,
 *                               unsigned char *sender_id,
 *                               SilcUInt32 sender_id_len,
 *                               unsigned char *receiver_id,
 *                               SilcUInt32 receiver_id_len,
 *                               SilcStack stack,
 *                               SilcBool no_allocation,
 *                               SilcMessagePayload message);
 *
 * DESCRIPTION
 *
 *    Parses Message Payload returning new payload structure.  This also
 *    decrypts the payload and checks the MAC.  If the payload is
 *    channel message then `private_message' is FALSE, and if it is
 *    private message it is TRUE.  If the private message key is static
 *    (pre-shared key) then protocol dictates that the IV is present
 *    and `static_key' must be set to TRUE.  If the key is not static
 *    (Key Agreement was done for the key) then it MUST be FALSE.  For
 *    channel messages the `static_key' is ignored.
 *
 *    If the `hmac' is no provided then the MAC of the channel message is
 *    not verified.  If the message is private message and `cipher' is NULL
 *    then this assumes that the packet was decrypted with session keys
 *    (no private message key) and this merely decodes the payload.
 *
 *    The `sender_id' and `receiver_id' are the IDs from the packet header
 *    of the packet where this message payload was received.
 *
 *    If the `message' is non-NULL then that pre-allocated context is
 *    used in parsing.  Same context is returned.  Otherwise new context
 *    is allocated and returned.  If the `stack' is non-NULL then memory
 *    is allocated from that stack.  If `no_allocation' is TRUE then the
 *    `message' must be provided and data is merely parsed and referenced
 *    from `payload' and will become invalid when `payload' invalidates.
 *    If `no_allocation' is TRUE the routine does not do any allocations.
 *
 ***/
SilcMessagePayload
silc_message_payload_parse(unsigned char *payload,
			   SilcUInt32 payload_len,
			   SilcBool private_message,
			   SilcBool static_key,
			   SilcCipher cipher,
			   SilcHmac hmac,
			   unsigned char *sender_id,
			   SilcUInt32 sender_id_len,
			   unsigned char *receiver_id,
			   SilcUInt32 receiver_id_len,
			   SilcStack stack,
			   SilcBool no_allocation,
			   SilcMessagePayload message);

/****f* silccore/SilcMessageAPI/silc_message_payload_encrypt
 *
 * SYNOPSIS
 *
 *    SilcBool silc_message_payload_encrypt(unsigned char *data,
 *                                          SilcUInt32 data_len,
 *                                          SilcUInt32 true_len,
 *                                          unsigned char *iv,
 *                                          SilcID *sender_id,
 *                                          SilcID *receiver_id,
 *                                          SilcCipher cipher,
 *                                          SilcHmac hmac);
 *
 * DESCRIPTION
 *
 *    This function is used to encrypt the Messsage Payload which is
 *    the `data' and `data_len'.  The `data_len' is the data length which
 *    is used to create MAC out of.  The `data' MUST have additional space
 *    after `true_len' bytes for the MAC which is appended to the data.
 *    The `sender_id' is the ID message sender and `receiver_id' is ID of
 *    message receiver.
 *
 *    This is usually used by the Message Payload interface itself but can
 *    be called by the appliation if separate encryption process is required.
 *    For example server might need to call this directly in some
 *    circumstances. The `cipher' is used to encrypt the payload and `hmac'
 *    to compute the MAC for the payload.
 *
 ***/
SilcBool silc_message_payload_encrypt(unsigned char *data,
				      SilcUInt32 data_len,
				      SilcUInt32 true_len,
				      unsigned char *iv,
				      SilcID *sender_id,
				      SilcID *receiver_id,
				      SilcCipher cipher,
				      SilcHmac hmac);

/****f* silccore/SilcMessageAPI/silc_message_payload_encode
 *
 * SYNOPSIS
 *
 *    SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
 *                                           const unsigned char *data,
 *                                           SilcUInt32 data_len,
 *                                           SilcBool generate_iv,
 *                                           SilcBool private_message,
 *                                           SilcCipher cipher,
 *                                           SilcHmac hmac,
 *                                           SilcRng rng,
 *                                           SilcPublicKey public_key,
 *                                           SilcPrivateKey private_key,
 *                                           SilcHash hash,
 *                                           SilcID *sender_id,
 *                                           SilcID *receiver_id,
 *                                           SilcBuffer buffer);
 *
 * DESCRIPTION
 *
 *    Encodes a Message Payload into a buffer and returns it.  This is
 *    used to encode channel messages and private messages into a packet.
 *    If `private_message' is FALSE then this encodes channel message, if
 *    it is TRUE this encodes private message.  If `private_message' is
 *    TRUE then `generate_iv' MUST be FALSE if the private message key
 *    `cipher' is not static key (pre-shared key).  If it is static key
 *    then protocol dictates that IV must be present in the Message Payload
 *    and `generate_iv' must be TRUE.  The caller must know whether the key
 *    is static or not for private messages.  If the key was generated with
 *    Key Agreement protocol then `generate_iv' is always FALSE.  For
 *    channel messages `generate_iv' is always set to TRUE value.
 *
 *    The `cipher' is the cipher used to encrypt the message and `hmac'
 *    is used to compute the MAC for the payload.  If encoding private
 *    message that will be encrypted with session keys (no private message
 *    key) then `cipher' and `hmac' is NULL and this merely encodes the
 *    payload buffer, and the caller must encrypt the packet later.
 *    If `rng' is NULL then global RNG is used, if non-NULL then the
 *    `rng' is used (for IV and padding generation).
 *
 *    The `public_key', `private_key' and `hash' are provided only if the
 *    flags includes SILC_MESSAGE_FLAG_SIGNED, in which case the message
 *    will be digitally signed.  If `public_key' is non-NULL then it will
 *    be included in the message.  The `private_message' and `hash' MUST
 *    be provided.  The `hash' SHOULD be SHA1.
 *
 *    The `sender_id' is the ID message sender and `receiver_id' is ID of
 *    message receiver.
 *
 *    If the `buffer' is non-NULL then the payload will be encoded into
 *    that buffer.  The same buffer is returned.  Otherwise new buffer is
 *    allocated and returned.  The `buffer' will be automatically enlarged
 *    if the payload does not fit to it.
 *
 ***/
SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
				       const unsigned char *data,
				       SilcUInt32 data_len,
				       SilcBool generate_iv,
				       SilcBool private_message,
				       SilcCipher cipher,
				       SilcHmac hmac,
				       SilcRng rng,
				       SilcPublicKey public_key,
				       SilcPrivateKey private_key,
				       SilcHash hash,
				       SilcID *sender_id,
				       SilcID *receiver_id,
				       SilcBuffer buffer);

/****f* silccore/SilcMessageAPI/silc_message_payload_free
 *
 * SYNOPSIS
 *
 *    void silc_message_payload_free(SilcMessagePayload payload);
 *
 * DESCRIPTION
 *
 *    Free's Message Payload and all data in it.
 *
 ***/
void silc_message_payload_free(SilcMessagePayload payload);

/****f* silccore/SilcMessageAPI/silc_message_get_flags
 *
 * SYNOPSIS
 *
 *    SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload);
 *
 * DESCRIPTION
 *
 *    Returns the message flags from the payload.
 *
 ***/
SilcMessageFlags silc_message_get_flags(SilcMessagePayload payload);

/****f* silccore/SilcMessageAPI/silc_message_get_data
 *
 * SYNOPSIS
 *
 *    unsigned char *
 *    silc_message_get_data(SilcMessagePayload payload,
 *                                  SilcUInt32 *data_len);
 *
 * DESCRIPTION
 *
 *    Return the data in the payload, that is, the actual message data.
 *    The caller must not free it.
 *
 ***/
unsigned char *silc_message_get_data(SilcMessagePayload payload,
				     SilcUInt32 *data_len);

/****f* silccore/SilcMessageAPI/silc_message_get_mac
 *
 * SYNOPSIS
 *
 *    unsigned char *
 *    silc_message_get_mac(SilcMessagePayload payload);
 *
 * DESCRIPTION
 *
 *    Return the MAC of the payload. The caller must already know the
 *    length of the MAC. The caller must not free the MAC.
 *
 ***/
unsigned char *silc_message_get_mac(SilcMessagePayload payload);

/****f* silccore/SilcMessageAPI/silc_message_signed_verify
 *
 * SYNOPSIS
 *
 *    SilcAuthResult
 *    silc_message_signed_verify(SilcMessagePayload message,
 *                               SilcPublicKey remote_public_key,
 *                               SilcHash hash);
 *
 * DESCRIPTION
 *
 *    This routine can be used to verify the digital signature from the
 *    message indicated by `message'.  The signature is present only if
 *    the SILC_MESSAGE_FLAG_SIGNED is set in the message flags.  This
 *    returns SILC_AUTH_OK if the signature verification was successful.
 *
 ***/
SilcAuthResult silc_message_signed_verify(SilcMessagePayload message,
					  SilcPublicKey remote_public_key,
					  SilcHash hash);

/****f* silccore/SilcMessageAPI/silc_message_signed_get_public_key
 *
 * SYNOPSIS
 *
 *    SilcPublicKey
 *    silc_message_signed_get_public_key(SilcMessagePayload payload,
 *                                       const unsigned char **pk_data,
 *                                       SilcUInt32 *pk_data_len);
 *
 * DESCRIPTION
 *
 *    Returns the decoded SilcPublicKey from the message payload or NULL
 *    if it does not include public key.  The caller must free the returned
 *    public key pointer.  This also returns the raw public key (before
 *    decoding) into `pk_data' and `pk_data_len' if they are provided.  The
 *    caller must not free these pointers.
 *
 ***/
SilcPublicKey
silc_message_signed_get_public_key(SilcMessagePayload payload,
				   const unsigned char **pk_data,
				   SilcUInt32 *pk_data_len);

#include "silcmessage_i.h"

#endif /* SILCMESSAGE_H */
