X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=blobdiff_plain;f=lib%2Fsilcclient%2Fclient_channel.c;h=4120695d76af08286853fa5fc5bdf31f0f767220;hp=7143c0e721aa734819971dac404aec36d3b514c9;hb=7f51164d1ac93077d832de44a8dc71783fab8b33;hpb=3c9b950049601eef814222c501114d6f2865b926 diff --git a/lib/silcclient/client_channel.c b/lib/silcclient/client_channel.c index 7143c0e7..4120695d 100644 --- a/lib/silcclient/client_channel.c +++ b/lib/silcclient/client_channel.c @@ -74,12 +74,12 @@ SilcBool silc_client_send_channel_message(SilcClient client, if (channel->internal.private_keys) { if (key) { /* Use key application specified */ - cipher = key->cipher; + cipher = key->send_key; hmac = key->hmac; } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY && channel->internal.curr_key) { /* Use current private key */ - cipher = channel->internal.curr_key->cipher; + cipher = channel->internal.curr_key->send_key; hmac = channel->internal.curr_key->hmac; } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY && !channel->internal.curr_key && @@ -88,7 +88,7 @@ SilcBool silc_client_send_channel_message(SilcClient client, and private keys are set. */ silc_dlist_start(channel->internal.private_keys); key = silc_dlist_get(channel->internal.private_keys); - cipher = key->cipher; + cipher = key->send_key; hmac = key->hmac; /* Use this key as current private key */ @@ -291,7 +291,7 @@ SILC_FSM_STATE(silc_client_channel_message) /* Parse the message payload. This also decrypts the payload */ payload = silc_message_payload_parse(silc_buffer_data(buffer), silc_buffer_len(buffer), - FALSE, FALSE, key->cipher, + FALSE, FALSE, key->receive_key, key->hmac, packet->src_id, packet->src_id_len, packet->dst_id, @@ -463,6 +463,9 @@ SilcBool silc_client_save_channel_key(SilcClient client, return FALSE; } + channel->cipher = silc_cipher_get_name(channel->internal.send_key); + channel->hmac = silc_hmac_get_name(channel->internal.hmac); + /* Set HMAC key */ silc_hash_make(silc_hmac_get_hash(channel->internal.hmac), key, tmp_len, hash); @@ -545,20 +548,30 @@ SilcBool silc_client_add_channel_private_key(SilcClient client, entry->name = name ? strdup(name) : NULL; /* Allocate the cipher and set the key */ - if (!silc_cipher_alloc(cipher, &entry->cipher)) { + if (!silc_cipher_alloc(cipher, &entry->send_key)) { silc_free(entry); silc_free(entry->name); silc_ske_free_key_material(keymat); return FALSE; } - silc_cipher_set_key(entry->cipher, keymat->send_enc_key, + if (!silc_cipher_alloc(cipher, &entry->receive_key)) { + silc_free(entry); + silc_free(entry->name); + silc_cipher_free(entry->send_key); + silc_ske_free_key_material(keymat); + return FALSE; + } + silc_cipher_set_key(entry->send_key, keymat->send_enc_key, keymat->enc_key_len, TRUE); + silc_cipher_set_key(entry->receive_key, keymat->send_enc_key, + keymat->enc_key_len, FALSE); /* Generate HMAC key from the channel key data and set it */ if (!silc_hmac_alloc(hmac, NULL, &entry->hmac)) { silc_free(entry); silc_free(entry->name); - silc_cipher_free(entry->cipher); + silc_cipher_free(entry->send_key); + silc_cipher_free(entry->receive_key); silc_ske_free_key_material(keymat); return FALSE; } @@ -571,8 +584,11 @@ SilcBool silc_client_add_channel_private_key(SilcClient client, /* Add to the private keys list */ silc_dlist_add(channel->internal.private_keys, entry); - if (!channel->internal.curr_key) + if (!channel->internal.curr_key) { channel->internal.curr_key = entry; + channel->cipher = silc_cipher_get_name(entry->send_key); + channel->hmac = silc_cipher_get_name(entry->send_key); + } /* Free the key material */ silc_ske_free_key_material(keymat); @@ -603,12 +619,21 @@ SilcBool silc_client_del_channel_private_keys(SilcClient client, while ((entry = silc_dlist_get(channel->internal.private_keys))) { silc_dlist_del(channel->internal.private_keys, entry); silc_free(entry->name); - silc_cipher_free(entry->cipher); + silc_cipher_free(entry->send_key); + silc_cipher_free(entry->receive_key); silc_hmac_free(entry->hmac); silc_free(entry); } channel->internal.curr_key = NULL; + if (channel->internal.send_key) + channel->cipher = silc_cipher_get_name(channel->internal.send_key); + else + channel->cipher = NULL; + if (channel->internal.hmac) + channel->hmac = silc_hmac_get_name(channel->internal.hmac); + else + channel->hmac = NULL; silc_dlist_uninit(channel->internal.private_keys); channel->internal.private_keys = NULL; @@ -640,12 +665,16 @@ SilcBool silc_client_del_channel_private_key(SilcClient client, if (entry != key) continue; - if (channel->internal.curr_key == entry) + if (channel->internal.curr_key == entry) { channel->internal.curr_key = NULL; + channel->cipher = silc_cipher_get_name(channel->internal.send_key); + channel->hmac = silc_hmac_get_name(channel->internal.hmac); + } silc_dlist_del(channel->internal.private_keys, entry); silc_free(entry->name); - silc_cipher_free(entry->cipher); + silc_cipher_free(entry->send_key); + silc_cipher_free(entry->receive_key); silc_hmac_free(entry->hmac); silc_free(entry); @@ -702,6 +731,8 @@ void silc_client_current_channel_private_key(SilcClient client, if (!channel) return; channel->internal.curr_key = key; + channel->cipher = silc_cipher_get_name(key->send_key); + channel->hmac = silc_hmac_get_name(key->hmac); } /***************************** Utility routines *****************************/ @@ -862,12 +893,29 @@ void silc_client_empty_channel(SilcClient client, SilcBool silc_client_channel_save_public_keys(SilcChannelEntry channel, unsigned char *chpk_list, - SilcUInt32 chpk_list_len) + SilcUInt32 chpk_list_len, + SilcBool remove_all) { SilcArgumentDecodedList a, b; SilcDList chpks; SilcBool found; + if (remove_all) { + /* Remove all channel public keys */ + if (!channel->channel_pubkeys) + return FALSE; + + silc_dlist_start(channel->channel_pubkeys); + while ((b = silc_dlist_get(channel->channel_pubkeys))) + silc_dlist_del(channel->channel_pubkeys, b); + + silc_dlist_uninit(channel->channel_pubkeys); + channel->channel_pubkeys = NULL; + + return TRUE; + } + + /* Parse channel public key list and add or remove public keys */ chpks = silc_argument_list_parse_decoded(chpk_list, chpk_list_len, SILC_ARGUMENT_PUBLIC_KEY); if (!chpks)