X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilccore%2Fsilcchannel.c;h=5c83bbb422801ac4b472c19a18409a4ac8bde860;hp=491743c5a5c70f418a42b0edaa807fc86d361613;hb=382d15d447b7a95390decfa783836ae4fe255b3d;hpb=ae53ff9e5869bce8ec2fc5e276da711dcf9cd2bf diff --git a/lib/silccore/silcchannel.c b/lib/silccore/silcchannel.c index 491743c5..5c83bbb4 100644 --- a/lib/silccore/silcchannel.c +++ b/lib/silccore/silcchannel.c @@ -1,29 +1,42 @@ /* - silcchannel.c + silcchannel.c - Author: Pekka Riikonen + Author: Pekka Riikonen - Copyright (C) 1997 - 2001 Pekka Riikonen + Copyright (C) 1997 - 2002 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - + the Free Software Foundation; version 2 of the License. + This program 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 General Public License for more details. */ -/* Channel Payload, Channel Message Payload and Channel Key Payload - implementations. */ +/* Channel Payload and Channel Key Payload implementations. */ /* $Id$ */ #include "silcincludes.h" #include "silcchannel.h" -#include "silcchannel_i.h" + +/****************************************************************************** + + Channel Payload + +******************************************************************************/ + +/* Channel Message Payload structure. Contents of this structure is parsed + from SILC packets. */ +struct SilcChannelPayloadStruct { + unsigned char *channel_name; + unsigned char *channel_id; + SilcUInt32 mode; + SilcUInt16 name_len; + SilcUInt16 id_len; +}; /* Parses channel payload returning new channel payload structure. */ @@ -74,7 +87,8 @@ SilcDList silc_channel_payload_parse_list(const unsigned char *payload, SilcBufferStruct buffer; SilcDList list; SilcChannelPayload newp; - int len, ret; + SilcUInt32 len; + int ret; SILC_LOG_DEBUG(("Parsing channel payload list")); @@ -210,259 +224,6 @@ SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload) return payload->mode; } -/****************************************************************************** - - Channel Message Payload - -******************************************************************************/ - -/* Decrypts the channel message payload. First push the IV out of the - packet. The IV is used in the decryption process. Then decrypt the - message. After decyprtion, take the MAC from the decrypted packet, - compute MAC and compare the MACs. If they match, the decryption was - successful and we have the channel message ready to be displayed. */ - -bool silc_channel_message_payload_decrypt(unsigned char *data, - size_t data_len, - SilcCipher cipher, - SilcHmac hmac, - bool check_mac) -{ - SilcUInt32 iv_len, mac_len; - unsigned char *mac, mac2[32]; - - mac_len = silc_hmac_len(hmac); - iv_len = silc_cipher_get_block_len(cipher); - - if (data_len < mac_len) - return FALSE; - - if (check_mac) { - /* Take the MAC */ - mac = data + (data_len - mac_len); - - /* Check the MAC of the message */ - SILC_LOG_DEBUG(("Checking channel message MAC")); - silc_hmac_init(hmac); - silc_hmac_update(hmac, data, data_len - mac_len); - silc_hmac_final(hmac, mac2, &mac_len); - if (memcmp(mac, mac2, mac_len)) { - SILC_LOG_DEBUG(("Channel message MAC does not match")); - return FALSE; - } - SILC_LOG_DEBUG(("MAC is Ok")); - } - - /* Decrypt the channel message */ - silc_cipher_decrypt(cipher, data, data, - data_len - iv_len - mac_len, - data + (data_len - iv_len - mac_len)); - return TRUE; -} - -/* Parses channel message payload returning new channel payload structure. - This also decrypts it and checks the MAC. */ - -SilcChannelMessagePayload -silc_channel_message_payload_parse(unsigned char *payload, - SilcUInt32 payload_len, - SilcCipher cipher, - SilcHmac hmac) -{ - SilcBufferStruct buffer; - SilcChannelMessagePayload newp; - int ret; - SilcUInt32 iv_len, mac_len; - - SILC_LOG_DEBUG(("Parsing channel message payload")); - - silc_buffer_set(&buffer, payload, payload_len); - - /* Decrypt the payload */ - ret = silc_channel_message_payload_decrypt(buffer.data, buffer.len, - cipher, hmac, TRUE); - if (ret == FALSE) - return NULL; - - iv_len = silc_cipher_get_block_len(cipher); - mac_len = silc_hmac_len(hmac); - - newp = silc_calloc(1, sizeof(*newp)); - if (!newp) - return NULL; - - /* Parse the Channel Message Payload. */ - ret = silc_buffer_unformat(&buffer, - SILC_STR_UI_SHORT(&newp->flags), - SILC_STR_UI16_NSTRING_ALLOC(&newp->data, - &newp->data_len), - SILC_STR_UI16_NSTRING_ALLOC(&newp->pad, - &newp->pad_len), - SILC_STR_UI_XNSTRING(&newp->iv, iv_len), - SILC_STR_UI_XNSTRING(&newp->mac, mac_len), - SILC_STR_END); - if (ret == -1) - goto err; - - if ((newp->data_len > buffer.len - 6 - mac_len - iv_len) || - (newp->pad_len + newp->data_len > buffer.len - 6 - mac_len - iv_len)) { - SILC_LOG_ERROR(("Incorrect channel message payload in packet, " - "packet dropped")); - goto err; - } - - newp->iv_len = iv_len; - - return newp; - - err: - silc_channel_message_payload_free(newp); - return NULL; -} - -/* This function is used to encrypt the Channel Messsage Payload which is - the `data' and `data_len'. This is used internally by the Channel Message - Payload encoding routines but application may call this too if needed. - The `data_len' is the data lenght which is used to create MAC out of. - The `true_len' is the true length of `data' message payload and is used - assemble rest of the packet after MAC creation. The `true_len' length - packet will then be encrypted. */ - -bool silc_channel_message_payload_encrypt(unsigned char *data, - SilcUInt32 data_len, - unsigned char *iv, - SilcUInt32 iv_len, - SilcCipher cipher, - SilcHmac hmac) -{ - unsigned char mac[32]; - SilcUInt32 mac_len; - SilcBufferStruct buf; - - /* Encrypt payload of the packet. This is encrypted with the channel key. */ - silc_cipher_encrypt(cipher, data, data, data_len - iv_len, iv); - - /* Compute the MAC of the encrypted channel message data */ - silc_hmac_init(hmac); - silc_hmac_update(hmac, data, data_len); - silc_hmac_final(hmac, mac, &mac_len); - - /* Put rest of the data to the payload */ - silc_buffer_set(&buf, data, data_len + mac_len); - silc_buffer_pull(&buf, data_len); - silc_buffer_put(&buf, mac, mac_len); - - return TRUE; -} - -/* Encodes channel message payload into a buffer and returns it. This is used - to add channel message payload into a packet. As the channel payload is - encrypted separately from other parts of the packet padding must - be applied to the payload. */ - -SilcBuffer silc_channel_message_payload_encode(SilcMessageFlags flags, - SilcUInt16 data_len, - const unsigned char *data, - SilcUInt16 iv_len, - unsigned char *iv, - SilcCipher cipher, - SilcHmac hmac, - SilcRng rng) -{ - int i; - SilcBuffer buffer; - SilcUInt32 len, pad_len, mac_len; - unsigned char pad[16]; - - SILC_LOG_DEBUG(("Encoding channel message payload")); - - /* Calculate length of padding. IV is not included into the calculation - since it is not encrypted. */ - mac_len = silc_hmac_len(hmac); - data_len = SILC_CHANNEL_MESSAGE_DATALEN(data_len, mac_len + iv_len); - len = 6 + data_len; - pad_len = SILC_CHANNEL_MESSAGE_PAD(len); - - /* Allocate channel payload buffer */ - len += pad_len + iv_len + mac_len; - buffer = silc_buffer_alloc(len); - if (!buffer) - return NULL; - - /* Generate padding */ - if (rng) { - for (i = 0; i < pad_len; i++) pad[i] = silc_rng_get_byte_fast(rng); - } else { - for (i = 0; i < pad_len; i++) pad[i] = silc_rng_global_get_byte_fast(); - } - - /* Encode the Channel Message Payload */ - silc_buffer_pull_tail(buffer, 6 + data_len + pad_len + iv_len); - silc_buffer_format(buffer, - SILC_STR_UI_SHORT(flags), - SILC_STR_UI_SHORT(data_len), - SILC_STR_UI_XNSTRING(data, data_len), - SILC_STR_UI_SHORT(pad_len), - SILC_STR_UI_XNSTRING(pad, pad_len), - SILC_STR_UI_XNSTRING(iv, iv_len), - SILC_STR_END); - - memset(pad, 0, sizeof(pad)); - - if (!silc_channel_message_payload_encrypt(buffer->data, buffer->len, - iv, iv_len, cipher, hmac)) { - silc_buffer_free(buffer); - return NULL; - } - - silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer) - buffer->len); - - return buffer; -} - -/* Free's Channel Message Payload */ - -void silc_channel_message_payload_free(SilcChannelMessagePayload payload) -{ - if (payload->data) { - memset(payload->data, 0, payload->data_len); - silc_free(payload->data); - } - silc_free(payload); -} - -/* Return flags */ - -SilcMessageFlags -silc_channel_message_get_flags(SilcChannelMessagePayload payload) -{ - return payload->flags; -} - -/* Return data */ - -unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload, - SilcUInt32 *data_len) -{ - if (data_len) - *data_len = payload->data_len; - - return payload->data; -} - -/* Return MAC. The caller knows the length of the MAC */ - -unsigned char *silc_channel_message_get_mac(SilcChannelMessagePayload payload) -{ - return payload->mac; -} - -/* Return IV. The caller knows the length of the IV */ - -unsigned char *silc_channel_message_get_iv(SilcChannelMessagePayload payload) -{ - return payload->iv; -} /****************************************************************************** @@ -470,6 +231,17 @@ unsigned char *silc_channel_message_get_iv(SilcChannelMessagePayload payload) ******************************************************************************/ +/* Channel Key Payload structrue. Channel keys are parsed from SILC + packets into this structure. */ +struct SilcChannelKeyPayloadStruct { + unsigned char *id; + unsigned char *cipher; + unsigned char *key; + SilcUInt16 id_len; + SilcUInt16 cipher_len; + SilcUInt16 key_len; +}; + /* Parses channel key payload returning new channel key payload structure */ SilcChannelKeyPayload