X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilccore%2Fsilcchannel.c;h=ae6ac4be73493973807189e916b875809ddc6176;hb=a818c5b5411bbc4436d1c5f011236985c96bb787;hp=79419968176b334d0a64a13c514d98dcff7f8ec4;hpb=e8c2b7b9cabcf221862e7d91a1a7a1e0d6f02dd8;p=silc.git diff --git a/lib/silccore/silcchannel.c b/lib/silccore/silcchannel.c index 79419968..ae6ac4be 100644 --- a/lib/silccore/silcchannel.c +++ b/lib/silccore/silcchannel.c @@ -33,17 +33,17 @@ /* Channel Message Payload structure. Contents of this structure is parsed from SILC packets. */ struct SilcChannelPayloadStruct { - uint16 name_len; + SilcUInt16 name_len; unsigned char *channel_name; - uint16 id_len; + SilcUInt16 id_len; unsigned char *channel_id; - uint32 mode; + SilcUInt32 mode; }; /* Parses channel payload returning new channel payload structure. */ SilcChannelPayload silc_channel_payload_parse(const unsigned char *payload, - uint32 payload_len) + SilcUInt32 payload_len) { SilcBufferStruct buffer; SilcChannelPayload new; @@ -81,7 +81,7 @@ SilcChannelPayload silc_channel_payload_parse(const unsigned char *payload, /* Parses list of channel payloads returning list of payloads. */ SilcDList silc_channel_payload_parse_list(const unsigned char *payload, - uint32 payload_len) + SilcUInt32 payload_len) { SilcBufferStruct buffer; SilcDList list; @@ -129,10 +129,10 @@ SilcDList silc_channel_payload_parse_list(const unsigned char *payload, /* Encode new channel payload and returns it as buffer. */ SilcBuffer silc_channel_payload_encode(const unsigned char *channel_name, - uint16 channel_name_len, + SilcUInt16 channel_name_len, const unsigned char *channel_id, - uint32 channel_id_len, - uint32 mode) + SilcUInt32 channel_id_len, + SilcUInt32 mode) { SilcBuffer buffer; @@ -172,8 +172,8 @@ void silc_channel_payload_list_free(SilcDList list) while ((entry = silc_dlist_get(list)) != SILC_LIST_END) { silc_free(entry->channel_name); silc_free(entry->channel_id); - silc_free(entry); silc_dlist_del(list, entry); + silc_free(entry); } silc_dlist_uninit(list); @@ -182,7 +182,7 @@ void silc_channel_payload_list_free(SilcDList list) /* Return the channel name */ unsigned char *silc_channel_get_name(SilcChannelPayload payload, - uint32 *channel_name_len) + SilcUInt32 *channel_name_len) { if (channel_name_len) *channel_name_len = payload->name_len; @@ -193,7 +193,7 @@ unsigned char *silc_channel_get_name(SilcChannelPayload payload, /* Return the channel ID */ unsigned char *silc_channel_get_id(SilcChannelPayload payload, - uint32 *channel_id_len) + SilcUInt32 *channel_id_len) { if (channel_id_len) *channel_id_len = payload->id_len; @@ -213,7 +213,7 @@ SilcChannelID *silc_channel_get_id_parse(SilcChannelPayload payload) channel or perhaps the mode of the client on the channel. The protocol dictates what the usage of the mode is in different circumstances. */ -uint32 silc_channel_get_mode(SilcChannelPayload payload) +SilcUInt32 silc_channel_get_mode(SilcChannelPayload payload) { return payload->mode; } @@ -230,48 +230,65 @@ uint32 silc_channel_get_mode(SilcChannelPayload payload) from SILC packets. */ struct SilcChannelMessagePayloadStruct { SilcMessageFlags flags; - uint16 data_len; + SilcUInt16 data_len; unsigned char *data; unsigned char *mac; unsigned char *iv; }; -/* Decrypts the 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. */ -int silc_channel_message_payload_decrypt(unsigned char *data, - size_t data_len, - SilcCipher cipher, - SilcHmac hmac) +bool silc_channel_message_payload_decrypt(unsigned char *data, + size_t data_len, + SilcCipher cipher, + SilcHmac hmac) { - uint32 iv_len, mac_len; + SilcUInt32 iv_len, mac_len; unsigned char *end, *mac, mac2[32]; + unsigned char *dst, iv[SILC_CIPHER_MAX_IV_SIZE]; - /* Decrypt the channel message. 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 successfull - and we have the channel message ready to be displayed. */ + /* Push the IV out of the packet, and copy the IV since we do not want + to modify the original data buffer. */ end = data + data_len; - - /* Push the IV out of the packet */ iv_len = silc_cipher_get_block_len(cipher); + memcpy(iv, end - iv_len, iv_len); + + /* Allocate destination decryption buffer since we do not want to modify + the original data buffer, since we might want to call this function + many times for same payload. */ + if (hmac) + dst = silc_calloc(data_len - iv_len, sizeof(*dst)); + else + dst = data; /* Decrypt the channel message */ - silc_cipher_decrypt(cipher, data, data, data_len - iv_len, (end - iv_len)); + silc_cipher_decrypt(cipher, data, dst, data_len - iv_len, iv); - /* Take the MAC */ if (hmac) { + /* Take the MAC */ + end = dst + (data_len - iv_len); mac_len = silc_hmac_len(hmac); - mac = (end - iv_len - mac_len); + mac = (end - mac_len); /* Check the MAC of the message */ SILC_LOG_DEBUG(("Checking channel message MACs")); - silc_hmac_make(hmac, data, (data_len - iv_len - mac_len), mac2, &mac_len); + silc_hmac_make(hmac, dst, (data_len - iv_len - mac_len), mac2, &mac_len); if (memcmp(mac, mac2, mac_len)) { SILC_LOG_DEBUG(("Channel message MACs does not match")); + silc_free(dst); return FALSE; } SILC_LOG_DEBUG(("MAC is Ok")); + + /* Now copy the decrypted data into the buffer since it is verified + it decrypted correctly. */ + memcpy(data, dst, data_len - iv_len); + memset(dst, 0, data_len - iv_len); + silc_free(dst); } return TRUE; @@ -282,14 +299,14 @@ int silc_channel_message_payload_decrypt(unsigned char *data, SilcChannelMessagePayload silc_channel_message_payload_parse(unsigned char *payload, - uint32 payload_len, + SilcUInt32 payload_len, SilcCipher cipher, SilcHmac hmac) { SilcBufferStruct buffer; SilcChannelMessagePayload new; int ret; - uint32 iv_len, mac_len; + SilcUInt32 iv_len, mac_len; SILC_LOG_DEBUG(("Parsing channel message payload")); @@ -318,7 +335,7 @@ silc_channel_message_payload_parse(unsigned char *payload, if (ret == -1) goto err; - if (new->data_len < 1 || new->data_len > buffer.len) { + if (new->data_len > buffer.len) { SILC_LOG_ERROR(("Incorrect channel message payload in packet, " "packet dropped")); goto err; @@ -336,17 +353,17 @@ silc_channel_message_payload_parse(unsigned char *payload, encrypted separately from other parts of the packet padding must be applied to the payload. */ -SilcBuffer silc_channel_message_payload_encode(uint16 flags, - uint16 data_len, +SilcBuffer silc_channel_message_payload_encode(SilcUInt16 flags, + SilcUInt16 data_len, const unsigned char *data, - uint16 iv_len, + SilcUInt16 iv_len, unsigned char *iv, SilcCipher cipher, SilcHmac hmac) { int i; SilcBuffer buffer; - uint32 len, pad_len, mac_len; + SilcUInt32 len, pad_len, mac_len; unsigned char pad[16]; unsigned char mac[32]; @@ -419,7 +436,7 @@ silc_channel_message_get_flags(SilcChannelMessagePayload payload) /* Return data */ unsigned char *silc_channel_message_get_data(SilcChannelMessagePayload payload, - uint32 *data_len) + SilcUInt32 *data_len) { if (data_len) *data_len = payload->data_len; @@ -450,11 +467,11 @@ 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 { - uint16 id_len; + SilcUInt16 id_len; unsigned char *id; - uint16 cipher_len; + SilcUInt16 cipher_len; unsigned char *cipher; - uint16 key_len; + SilcUInt16 key_len; unsigned char *key; }; @@ -462,7 +479,7 @@ struct SilcChannelKeyPayloadStruct { SilcChannelKeyPayload silc_channel_key_payload_parse(const unsigned char *payload, - uint32 payload_len) + SilcUInt32 payload_len) { SilcBufferStruct buffer; SilcChannelKeyPayload new; @@ -505,15 +522,15 @@ silc_channel_key_payload_parse(const unsigned char *payload, /* Encodes channel key payload into a buffer and returns it. This is used to add channel key payload into a packet. */ -SilcBuffer silc_channel_key_payload_encode(uint16 id_len, +SilcBuffer silc_channel_key_payload_encode(SilcUInt16 id_len, const unsigned char *id, - uint16 cipher_len, + SilcUInt16 cipher_len, const unsigned char *cipher, - uint16 key_len, + SilcUInt16 key_len, const unsigned char *key) { SilcBuffer buffer; - uint32 len; + SilcUInt32 len; SILC_LOG_DEBUG(("Encoding channel key payload")); @@ -555,7 +572,7 @@ void silc_channel_key_payload_free(SilcChannelKeyPayload payload) /* Return ID */ unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload, - uint32 *id_len) + SilcUInt32 *id_len) { if (id_len) *id_len = payload->id_len; @@ -566,7 +583,7 @@ unsigned char *silc_channel_key_get_id(SilcChannelKeyPayload payload, /* Return cipher name */ unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload, - uint32 *cipher_len) + SilcUInt32 *cipher_len) { if (cipher_len) *cipher_len = payload->cipher_len; @@ -577,7 +594,7 @@ unsigned char *silc_channel_key_get_cipher(SilcChannelKeyPayload payload, /* Return key */ unsigned char *silc_channel_key_get_key(SilcChannelKeyPayload payload, - uint32 *key_len) + SilcUInt32 *key_len) { if (key_len) *key_len = payload->key_len;