From d8d2a409ab02237d69a130ddcb93ad58dfcaaa23 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Mon, 11 Dec 2006 15:41:10 +0000 Subject: [PATCH] Added silc_packet_set_keys. Removed silc_packet_[get|set_[ciphers|hmacs]. --- lib/silccore/silcpacket.c | 251 +++++++++++++++++++++----------------- lib/silccore/silcpacket.h | 90 +++++--------- 2 files changed, 169 insertions(+), 172 deletions(-) diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index bf23cfe6..022ee1c5 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -153,6 +153,19 @@ do { \ static void silc_packet_dispatch(SilcPacket packet); static void silc_packet_read_process(SilcPacketStream stream); +static inline SilcBool silc_packet_send_raw(SilcPacketStream stream, + SilcPacketType type, + SilcPacketFlags flags, + SilcIdType src_id_type, + unsigned char *src_id, + SilcUInt32 src_id_len, + SilcIdType dst_id_type, + unsigned char *dst_id, + SilcUInt32 dst_id_len, + const unsigned char *data, + SilcUInt32 data_len, + SilcCipher cipher, + SilcHmac hmac); /************************ Static utility functions **************************/ @@ -171,9 +184,11 @@ SILC_TASK_CALLBACK(silc_packet_stream_inject_packet) } /* Write data to the stream. Must be called with ps->lock locked. Unlocks - the lock inside this function. */ + the lock inside this function, unless no_unlock is TRUE. Unlocks always + in case it returns FALSE. */ -static inline SilcBool silc_packet_stream_write(SilcPacketStream ps) +static inline SilcBool silc_packet_stream_write(SilcPacketStream ps, + SilcBool no_unlock) { SilcStream stream; SilcBool connected; @@ -194,14 +209,14 @@ static inline SilcBool silc_packet_stream_write(SilcPacketStream ps) if (i == -2) { /* Error */ silc_buffer_reset(&ps->outbuf); - silc_mutex_unlock(ps->lock); SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE); return FALSE; } if (i == -1) { /* Cannot write now, write later. */ - silc_mutex_unlock(ps->lock); + if (!no_unlock) + silc_mutex_unlock(ps->lock); return TRUE; } @@ -210,7 +225,8 @@ static inline SilcBool silc_packet_stream_write(SilcPacketStream ps) } silc_buffer_reset(&ps->outbuf); - silc_mutex_unlock(ps->lock); + if (!no_unlock) + silc_mutex_unlock(ps->lock); return TRUE; } @@ -238,7 +254,8 @@ static inline SilcBool silc_packet_stream_write(SilcPacketStream ps) if (i == -1) { /* Cannot write now, write later. */ - silc_mutex_unlock(ps->lock); + if (!no_unlock) + silc_mutex_unlock(ps->lock); return TRUE; } @@ -247,7 +264,8 @@ static inline SilcBool silc_packet_stream_write(SilcPacketStream ps) } silc_buffer_reset(&ps->outbuf); - silc_mutex_unlock(ps->lock); + if (!no_unlock) + silc_mutex_unlock(ps->lock); return TRUE; } @@ -407,7 +425,7 @@ static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status, } /* Write pending data to stream */ - silc_packet_stream_write(ps); + silc_packet_stream_write(ps, FALSE); break; case SILC_STREAM_CAN_READ: @@ -1004,104 +1022,97 @@ SilcStream silc_packet_stream_get_stream(SilcPacketStream stream) return stream->stream; } -/* Set ciphers for packet stream */ +/* Set keys. */ -void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send, - SilcCipher receive) +SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key, + SilcCipher receive_key, SilcHmac send_hmac, + SilcHmac receive_hmac, SilcBool rekey) { - SILC_LOG_DEBUG(("Setting new ciphers to packet stream")); + SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream)); + + /* If doing rekey, send REKEY_DONE packet */ + if (rekey) { + /* This will take stream lock. */ + if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0, + stream->src_id_type, stream->src_id, + stream->src_id_len, stream->dst_id_type, + stream->dst_id, stream->dst_id_len, + NULL, 0, stream->send_key[0], + stream->send_hmac[0])) + return FALSE; - silc_mutex_lock(stream->lock); + /* Write the packet to the stream */ + if (!silc_packet_stream_write(stream, TRUE)) + return FALSE; + } else { + silc_mutex_lock(stream->lock); + } - /* In case IV Included is set, save the old key */ + /* In case IV Included is set, save the old keys */ if (stream->iv_included) { - if (stream->send_key[1]) { + if (stream->send_key[1] && send_key) { silc_cipher_free(stream->send_key[1]); stream->send_key[1] = stream->send_key[0]; } - if (stream->receive_key[1]) { + if (stream->receive_key[1] && receive_key) { silc_cipher_free(stream->receive_key[1]); stream->receive_key[1] = stream->receive_key[0]; } - } else { - if (stream->send_key[0]) - silc_cipher_free(stream->send_key[0]); - if (stream->send_key[1]) - silc_cipher_free(stream->receive_key[0]); - } - - stream->send_key[0] = send; - stream->receive_key[0] = receive; - - silc_mutex_unlock(stream->lock); -} - -/* Return current ciphers from packet stream */ - -SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send, - SilcCipher *receive) -{ - if (!stream->send_key[0] && !stream->receive_key[0]) - return FALSE; - - silc_mutex_lock(stream->lock); - - if (send) - *send = stream->send_key[0]; - if (receive) - *receive = stream->receive_key[0]; - - silc_mutex_unlock(stream->lock); - - return TRUE; -} - -/* Set HMACs for packet stream */ - -void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send, - SilcHmac receive) -{ - SILC_LOG_DEBUG(("Setting new HMACs to packet stream")); - - silc_mutex_lock(stream->lock); - - /* In case IV Included is set, save the old HMAC */ - if (stream->iv_included) { - if (stream->send_hmac[1]) { + if (stream->send_hmac[1] && send_hmac) { silc_hmac_free(stream->send_hmac[1]); stream->send_hmac[1] = stream->send_hmac[0]; } - if (stream->receive_hmac[1]) { + if (stream->receive_hmac[1] && receive_hmac) { silc_hmac_free(stream->receive_hmac[1]); stream->receive_hmac[1] = stream->receive_hmac[0]; } } else { - if (stream->send_hmac[0]) + if (stream->send_key[0] && send_key) + silc_cipher_free(stream->send_key[0]); + if (stream->send_key[1] && receive_key) + silc_cipher_free(stream->receive_key[0]); + if (stream->send_hmac[0] && send_hmac) silc_hmac_free(stream->send_hmac[0]); - if (stream->receive_hmac[0]) + if (stream->receive_hmac[0] && receive_hmac) silc_hmac_free(stream->receive_hmac[0]); } - stream->send_hmac[0] = send; - stream->receive_hmac[0] = receive; + /* Set keys */ + if (send_key) + stream->send_key[0] = send_key; + if (receive_key) + stream->receive_key[0] = receive_key; + if (send_hmac) + stream->send_hmac[0] = send_hmac; + if (receive_hmac) + stream->receive_hmac[0] = receive_hmac; silc_mutex_unlock(stream->lock); + return TRUE; } -/* Return current HMACs from packet stream */ +/* Return current ciphers from packet stream */ -SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send, - SilcHmac *receive) +SilcBool silc_packet_get_keys(SilcPacketStream stream, + SilcCipher *send_key, + SilcCipher *receive_key, + SilcHmac *send_hmac, + SilcHmac *receive_hmac) { - if (!stream->send_hmac[0] && !stream->receive_hmac[0]) + if (!stream->send_key[0] && !stream->receive_key[0] && + !stream->send_hmac[0] && !stream->receive_hmac[0]) return FALSE; silc_mutex_lock(stream->lock); - if (send) - *send = stream->send_hmac[0]; - if (receive) - *receive = stream->receive_hmac[0]; + if (send_key) + *send_key = stream->send_key[0]; + if (receive_key) + *receive_key = stream->receive_key[0]; + if (send_hmac) + *send_hmac = stream->send_hmac[0]; + if (receive_hmac) + *receive_hmac = stream->receive_hmac[0]; silc_mutex_unlock(stream->lock); @@ -1202,10 +1213,10 @@ void silc_packet_free(SilcPacket packet) /* Prepare outgoing data buffer for packet sending. Returns the pointer to that buffer into the `packet'. */ -static SilcBool silc_packet_send_prepare(SilcPacketStream stream, - SilcUInt32 totlen, - SilcHmac hmac, - SilcBuffer packet) +static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream, + SilcUInt32 totlen, + SilcHmac hmac, + SilcBuffer packet) { unsigned char *oldptr; unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0; @@ -1229,21 +1240,23 @@ static SilcBool silc_packet_send_prepare(SilcPacketStream stream, return TRUE; } -/* Internal routine to send packet */ - -static SilcBool silc_packet_send_raw(SilcPacketStream stream, - SilcPacketType type, - SilcPacketFlags flags, - SilcIdType src_id_type, - unsigned char *src_id, - SilcUInt32 src_id_len, - SilcIdType dst_id_type, - unsigned char *dst_id, - SilcUInt32 dst_id_len, - const unsigned char *data, - SilcUInt32 data_len, - SilcCipher cipher, - SilcHmac hmac) +/* Internal routine to assemble outgoing packet. Assembles and encryptes + the packet. The silc_packet_stream_write needs to be called to send it + after this returns TRUE. */ + +static inline SilcBool silc_packet_send_raw(SilcPacketStream stream, + SilcPacketType type, + SilcPacketFlags flags, + SilcIdType src_id_type, + unsigned char *src_id, + SilcUInt32 src_id_len, + SilcIdType dst_id_type, + unsigned char *dst_id, + SilcUInt32 dst_id_len, + const unsigned char *data, + SilcUInt32 data_len, + SilcCipher cipher, + SilcHmac hmac) { unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4]; int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0); @@ -1366,8 +1379,7 @@ static SilcBool silc_packet_send_raw(SilcPacketStream stream, stream->send_psn++; } - /* Write the packet to the stream */ - return silc_packet_stream_write(stream); + return TRUE; } /* Sends a packet */ @@ -1376,16 +1388,21 @@ SilcBool silc_packet_send(SilcPacketStream stream, SilcPacketType type, SilcPacketFlags flags, const unsigned char *data, SilcUInt32 data_len) { - return silc_packet_send_raw(stream, type, flags, - stream->src_id_type, - stream->src_id, - stream->src_id_len, - stream->dst_id_type, - stream->dst_id, - stream->dst_id_len, - data, data_len, - stream->send_key[0], - stream->send_hmac[0]); + SilcBool ret; + + ret = silc_packet_send_raw(stream, type, flags, + stream->src_id_type, + stream->src_id, + stream->src_id_len, + stream->dst_id_type, + stream->dst_id, + stream->dst_id_len, + data, data_len, + stream->send_key[0], + stream->send_hmac[0]); + + /* Write the packet to the stream */ + return ret ? silc_packet_stream_write(stream, FALSE) : FALSE; } /* Sends a packet, extended routine */ @@ -1399,6 +1416,7 @@ SilcBool silc_packet_send_ext(SilcPacketStream stream, { unsigned char src_id_data[32], dst_id_data[32]; SilcUInt32 src_id_len, dst_id_len; + SilcBool ret; if (src_id) if (!silc_id_id2str(src_id, src_id_type, src_id_data, @@ -1409,16 +1427,19 @@ SilcBool silc_packet_send_ext(SilcPacketStream stream, sizeof(dst_id_data), &dst_id_len)) return FALSE; - return silc_packet_send_raw(stream, type, flags, - src_id ? src_id_type : stream->src_id_type, - src_id ? src_id_data : stream->src_id, - src_id ? src_id_len : stream->src_id_len, - dst_id ? dst_id_type : stream->dst_id_type, - dst_id ? dst_id_data : stream->dst_id, - dst_id ? dst_id_len : stream->dst_id_len, - data, data_len, - cipher ? cipher : stream->send_key[0], - hmac ? hmac : stream->send_hmac[0]); + ret = silc_packet_send_raw(stream, type, flags, + src_id ? src_id_type : stream->src_id_type, + src_id ? src_id_data : stream->src_id, + src_id ? src_id_len : stream->src_id_len, + dst_id ? dst_id_type : stream->dst_id_type, + dst_id ? dst_id_data : stream->dst_id, + dst_id ? dst_id_len : stream->dst_id_len, + data, data_len, + cipher ? cipher : stream->send_key[0], + hmac ? hmac : stream->send_hmac[0]); + + /* Write the packet to the stream */ + return ret ? silc_packet_stream_write(stream, FALSE) : FALSE; } /* Sends packet after formatting the arguments to buffer */ diff --git a/lib/silccore/silcpacket.h b/lib/silccore/silcpacket.h index 6cceb877..1a880927 100644 --- a/lib/silccore/silcpacket.h +++ b/lib/silccore/silcpacket.h @@ -720,74 +720,51 @@ void silc_packet_set_context(SilcPacketStream stream, void *stream_context); ***/ void *silc_packet_get_context(SilcPacketStream stream); -/****f* silccore/SilcPacketAPI/silc_packet_set_ciphers +/****f* silccore/SilcPacketAPI/silc_packet_set_keys * * SYNOPSIS * - * void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send, - * SilcCipher receive); + * void silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key, + * SilcCipher receive_key, SilcHmac send_hmac, + * SilcHmac receive_hmac, SilcBool rekey); * * DESCRIPTION * - * Set ciphers to be used to encrypt sent packets, and decrypt received - * packets. This can be called multiple times to change the ciphers. - * In this case if old cipher is set it will be freed. If ciphers are - * not set packets will not be encrypted or decrypted. + * Set ciphers and HMACs to be used to encrypt sent packets, and decrypt + * received packets. This can be called multiple times to change the + * ciphers and HMACs. * - ***/ -void silc_packet_set_ciphers(SilcPacketStream stream, SilcCipher send, - SilcCipher receive); - -/****f* silccore/SilcPacketAPI/silc_packet_get_ciphers - * - * SYNOPSIS - * - * SilcBool silc_packet_get_ciphers(SilcPacketStream stream, - * SilcCipher *send, - * SilcCipher *receive); - * - * DESCRIPTION - * - * Returns the pointers of current ciphers from the `stream'. Returns - * FALSE if ciphers are not set. - * - ***/ -SilcBool silc_packet_get_ciphers(SilcPacketStream stream, SilcCipher *send, - SilcCipher *receive); - -/****f* silccore/SilcPacketAPI/silc_packet_set_hmacs - * - * SYNOPSIS - * - * void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send, - * SilcHmac receive); - * - * DESCRIPTION + * If the `rekey' is TRUE this function will send SILC_PACKET_REKEY_DONE + * to the `stream' and will set the new keys. If it is FALSE the keys + * are changed but the packet is not changed. * - * Set HMACs to be used to create MACs for sent packets and to check - * MAC for received packets. This can be called multiple times to change - * the HMACs. In this case if old HMAC is set it will be freed. If - * HMACs are not set MACs are not generated or verified for packets. + * When changing keys the old cipher and HMACs will be freed. If the keys + * are not set at all, packets will not be encrypted or decrypted. * ***/ -void silc_packet_set_hmacs(SilcPacketStream stream, SilcHmac send, - SilcHmac receive); +SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key, + SilcCipher receive_key, SilcHmac send_hmac, + SilcHmac receive_hmac, SilcBool rekey); -/****f* silccore/SilcPacketAPI/silc_packet_get_hmacs +/****f* silccore/SilcPacketAPI/silc_packet_get_keys * * SYNOPSIS * - * SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send, - * SilcHmac *receive); + * SilcBool silc_packet_get_keys(SilcPacketStream stream, + * SilcCipher *send_key, + * SilcCipher *receive_key, + * SilcHmac *send_hmac, + * SilcHmac *receive_hmac); * * DESCRIPTION * - * Returns the pointers of current HMACs from the `stream'. Returns - * FALSE if HMACs are not set. + * Returns the pointers of current ciphers and HMACs from the `stream'. + * Returns FALSE if keys are not set. * ***/ -SilcBool silc_packet_get_hmacs(SilcPacketStream stream, SilcHmac *send, - SilcHmac *receive); +SilcBool silc_packet_get_keys(SilcPacketStream stream, + SilcCipher *send_key, SilcCipher *receive_key, + SilcHmac *send_hmac, SilcHmac *receive_hmac); /****f* silccore/SilcPacketAPI/silc_packet_set_ids * @@ -846,14 +823,13 @@ SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid); * DESCRIPTION * * Send `data' of length of `data_len' to the packet stream indicated by - * `stream'. If ciphers and HMACs were set using silc_packet_set_ciphers - * and silc_packet_set_hmacs the packet will be encrypted and MAC will be - * computed for it. If silc_packet_set_ids was used to set source and - * destination ID for the packet stream those IDs are used in the - * packet. If IDs have not been set and they need to be provided then - * silc_packet_send_ext function should be used. Otherwise, the packet - * will not have IDs set at all. Returns FALSE if packet could not be - * sent. + * `stream'. If ciphers and HMACs were set using silc_packet_set_keys + * the packet will be encrypted and MAC will be computed for it. If + * silc_packet_set_ids was used to set source and destination ID for the + * packet stream those IDs are used in the packet. If IDs have not been + * set and they need to be provided then silc_packet_send_ext function + * should be used. Otherwise, the packet will not have IDs set at all. + * Returns FALSE if packet could not be sent. * ***/ SilcBool silc_packet_send(SilcPacketStream stream, -- 2.24.0