- payload = silc_channel_message_payload_parse(buffer, channel->channel_key,
- channel->hmac);
- if (!payload)
- goto out;
- } else if (channel->private_keys) {
- SilcChannelPrivateKey entry;
-
- silc_dlist_start(channel->private_keys);
- while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
- /* Parse the channel message payload. This also decrypts the payload */
- payload = silc_channel_message_payload_parse(buffer, entry->cipher,
- entry->hmac);
- if (payload)
- break;
+ payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE,
+ FALSE, channel->channel_key,
+ channel->hmac);
+
+ /* If decryption failed and we have just performed channel key rekey
+ we will use the old key in decryption. If that fails too then we
+ cannot do more and will drop the packet. */
+ if (!payload) {
+ SilcCipher key;
+ SilcHmac hmac;
+ int i;
+
+ if (!channel->old_channel_keys ||
+ !silc_dlist_count(channel->old_channel_keys))
+ goto out;
+
+ SILC_LOG_DEBUG(("Attempting to decrypt with old channel key(s)"));
+
+ silc_dlist_end(channel->old_channel_keys);
+ silc_dlist_end(channel->old_hmacs);
+ for (i = 0; i < silc_dlist_count(channel->old_channel_keys); i++) {
+ key = silc_dlist_get(channel->old_channel_keys);
+ hmac = silc_dlist_get(channel->old_hmacs);
+ if (!key || !hmac)
+ break;
+
+ payload = silc_message_payload_parse(buffer->data, buffer->len,
+ FALSE, FALSE, key, hmac);
+ if (payload)
+ break;
+ }
+ if (!payload)
+ goto out;