/*

  silcmessage.h 

  Author: Pekka Riikonen <priikone@silcnet.org>

  Copyright (C) 1997 - 2002 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.
 *
 * This interface defines also the SILC_MESSAGE_FLAG_SIGNED Payload,
 * which defines how channel messages and private messages can be digitally
 * signed.  This interface provides the payload parsing, encoding, 
 * signature computing and signature verification routines.
 *
 ***/

#ifndef SILCMESSAGE_H
#define SILCMESSAGE_H

/****s* silccore/SilcMessageAPI/SilcMessagePayload
 *
 * NAME
 * 
 *    typedef struct SilcMessagePayloadStruct *SilcMessagePayload;
 *
 *
 * 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 SilcMessagePayloadStruct *SilcMessagePayload;

/****s* silccore/SilcMessageAPI/SilcMessageSignedPayload
 *
 * NAME
 * 
 *    typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;
 *
 *
 * DESCRIPTION
 *
 *    This context represents the SILC_MESSAGE_FLAG_SIGNED Payload which
 *    is used with channel messages and private messages to indicate that
 *    the message is digitally signed.  This payload may include the
 *    message sender's public key and it includes the digital signature.
 *    This payload MUST NOT be used in any other context except with
 *    channel and private message sending and reception.
 *
 ***/
typedef struct SilcMessageSignedPayloadStruct *SilcMessageSignedPayload;

/****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_RESERVED    0x0400	  /* to 0x1000 */
#define SILC_MESSAGE_FLAG_PRIVATE     0x2000	  /* to 0x8000 */
/***/

/****f* silccore/SilcMessageAPI/silc_message_payload_decrypt
 *
 * SYNOPSIS
 *
 *    bool silc_message_payload_decrypt(unsigned char *data,
 *                                      size_t data_len,
 *                                      bool private_message,
 *                                      bool static_key,
 *                                      SilcCipher cipher,
 *                                      SilcHmac hmac,
 *                                      bool 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.
 *
 *    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.
 *
 ***/
bool silc_message_payload_decrypt(unsigned char *data,
				  size_t data_len,
				  bool private_message,
				  bool static_key,
				  SilcCipher cipher,
				  SilcHmac hmac,
				  bool check_mac);

/****f* silccore/SilcMessageAPI/silc_message_payload_parse
 *
 * SYNOPSIS
 *
 *    SilcMessagePayload 
 *    silc_message_payload_parse(unsigned char *payload,
 *                               SilcUInt32 payload_len,
 *                               bool private_message,
 *                               bool static_key,
 *                               SilcCipher cipher,
 *                               SilcHmac hmac);
 *
 * 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.
 *
 ***/
SilcMessagePayload 
silc_message_payload_parse(unsigned char *payload,
			   SilcUInt32 payload_len,
			   bool private_message,
			   bool static_key,
			   SilcCipher cipher,
			   SilcHmac hmac);

/****f* silccore/SilcMessageAPI/silc_message_payload_encrypt
 *
 * SYNOPSIS
 *
 *    bool silc_message_payload_encrypt(unsigned char *data,
 *                                      SilcUInt32 data_len,
 *                                      SilcUInt32 true_len,
 *                                      unsigned char *iv,
 *                                      SilcUInt32 iv_len,
 *                                      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.
 *
 *    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.
 *
 ***/
bool silc_message_payload_encrypt(unsigned char *data,
				  SilcUInt32 data_len,
				  SilcUInt32 true_len,
				  unsigned char *iv,
				  SilcUInt32 iv_len,
				  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,
 *                                           bool generate_iv,
 *                                           bool private_message,
 *                                           SilcCipher cipher,
 *                                           SilcHmac hmac,
 *                                           SilcRng rng,
 *                                           SilcPublicKey public_key,
 *                                           SilcPrivateKey private_key,
 *                                           SilcHash hash);
 *
 * 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.
 *
 ***/
SilcBuffer silc_message_payload_encode(SilcMessageFlags flags,
				       const unsigned char *data,
				       SilcUInt32 data_len,
				       bool generate_iv,
				       bool private_message,
				       SilcCipher cipher,
				       SilcHmac hmac,
				       SilcRng rng,
				       SilcPublicKey public_key,
				       SilcPrivateKey private_key,
				       SilcHash hash);

/****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_get_iv
 *
 * SYNOPSIS
 *
 *    unsigned char *
 *    silc_message_get_iv(SilcMessagePayload payload);
 *
 * DESCRIPTION
 *
 *    Return the IV of the payload. The caller must already know the 
 *    length of the IV. The caller must not free the IV.
 *
 ***/
unsigned char *silc_message_get_iv(SilcMessagePayload payload);

/****f* silccore/SilcMessageAPI/silc_message_get_signature
 *
 * SYNOPSIS
 *
 *    SilcMessageSignedPayload
 *    silc_message_get_signature(SilcMessagePayload payload);
 *
 * DESCRIPTION
 *
 *    Returns the pointer to the signature of the message if the
 *    SILC_MESSAGE_FLAG_SIGNED was set.  If the flag is set and this
 *    function returns NULL then error had occurred and the signature
 *    could not be retrieved from the message.
 *
 *    The caller SHOULD verify the signature by calling the
 *    silc_message_signed_verify function.  Caller must not free the
 *    returned payload pointer.
 *
 ***/
SilcMessageSignedPayload
silc_message_get_signature(SilcMessagePayload payload);

/****f* silccore/SilcMessageAPI/silc_message_signed_payload_parse
 *
 * SYNOPSIS
 *
 *    SilcMessageSignedPayload
 *    silc_message_signed_payload_parse(const unsigned char *data,
 *                                      SilcUInt32 data_len);
 *
 * DESCRIPTION
 *
 *    Parses the SilcMessageSignedPayload Payload from the `data' of
 *    length of `data_len' bytes.  The `data' must be payload without
 *    the actual message payload.  Returns the parsed payload or NULL
 *    on error.  Caller must free the returned payload.  Application
 *    usually does not need to call this since the function
 *    silc_message_payload_parse calls this automatically for signed
 *    messages.
 *
 ***/
SilcMessageSignedPayload
silc_message_signed_payload_parse(const unsigned char *data,
				  SilcUInt32 data_len);

/****f* silccore/SilcMessageAPI/silc_message_signed_payload_encode
 *
 * SYNOPSIS
 *
 *    SilcBuffer
 *    silc_message_signed_payload_encode(const unsigned char *message_payload,
 *                                       SilcUInt32 message_payload_len,
 *                                       SilcPublicKey public_key,
 *                                       SilcPrivateKey private_key,
 *                                       SilcHash hash);
 *
 * DESCRIPTION
 *
 *    Encodes the SilcMessageSignedPayload Payload and computes the
 *    digital signature.  The `message_payload' is the message data that
 *    is used in the signature computation.  The encoding of the buffer
 *    is specified in the SILC protocol.  If `public_key' is provided
 *    then the public key included in the payload.  The `private_key'
 *    is used to produce the signature.  This function returns the encoded
 *    payload with the signature or NULL on error.  Caller must free the
 *    returned buffer.  The `hash' SHOULD be SHA-1 hash function.
 *    
 *    Application usually does not need to call this since the function
 *    silc_message_payload_encode calls this automatically if the caller
 *    wants to sign the message.
 *
 ***/
SilcBuffer
silc_message_signed_payload_encode(const unsigned char *message_payload,
				   SilcUInt32 message_payload_len,
				   SilcPublicKey public_key,
				   SilcPrivateKey private_key,
				   SilcHash hash);

/****f* silccore/SilcMessageAPI/silc_message_signed_payload_free
 *
 * SYNOPSIS
 *
 *    void silc_message_signed_payload_free(SilcMessageSignedPayload sig);
 *
 * DESCRIPTION
 *
 *    Frees the SilcMessageSignedPayload Payload.
 *
 ***/
void silc_message_signed_payload_free(SilcMessageSignedPayload sig);

/****f* silccore/SilcMessageAPI/silc_message_signed_verify
 *
 * SYNOPSIS
 *
 *    int silc_message_signed_verify(SilcMessageSignedPayload sig,
 *                                   SilcMessagePayload message,
 *                                   SilcPublicKey remote_public_key,
 *                                   SilcHash hash);
 *
 * DESCRIPTION
 *
 *    This routine can be used to verify the signature found in
 *    SilcMessageSignedPayload Payload.  This returns SILC_AUTH_OK if the
 *    signature verification was successful.
 *
 ***/
int silc_message_signed_verify(SilcMessageSignedPayload sig,
			       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(SilcMessageSignedPayload sig,
 *                                       unsigned char **pk_data,
 *                                       SilcUInt32 *pk_data_len);
 *
 * DESCRIPTION
 *
 *    Returns the decoded SilcPublicKey from the SilcMessageSignedPayload
 *    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(SilcMessageSignedPayload sig,
				   unsigned char **pk_data,
				   SilcUInt32 *pk_data_len);

#endif /* SILCMESSAGE_H */
