+ if (silc_likely(cipher)) {
+ block_len = silc_cipher_get_block_len(cipher);
+
+ if (stream->iv_included) {
+ /* SID, IV and sequence number is included in the ciphertext */
+ sid = (SilcUInt8)inbuf->data[0];
+
+ if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR) {
+ /* Set the CTR mode IV from packet to counter block */
+ memcpy(iv, silc_cipher_get_iv(cipher), block_len);
+ silc_packet_receive_ctr_increment(stream, iv, inbuf->data + 1);
+ ivlen = 8 + 1;
+ } else {
+ /* Get IV from packet */
+ memcpy(iv, inbuf->data + 1, block_len);
+ ivlen = block_len + 1;
+ }
+ psnlen = 4;
+
+ /* Check SID, and get correct decryption key */
+ if (sid != stream->sid) {
+ /* If SID is recent get the previous key and use it */
+ if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
+ stream->receive_key[1] && !stream->receive_hmac[1]) {
+ cipher = stream->receive_key[1];
+ hmac = stream->receive_hmac[1];
+ } else {
+ /* The SID is unknown, drop rest of the data in buffer */
+ SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
+ sid, stream->sid));
+ silc_mutex_unlock(stream->lock);
+ SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
+ silc_mutex_lock(stream->lock);
+ silc_buffer_reset(inbuf);
+ return;
+ }
+ }
+ } else {
+ memcpy(iv, silc_cipher_get_iv(cipher), block_len);
+
+ /* If using CTR mode, increment the counter */
+ if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
+ silc_packet_receive_ctr_increment(stream, iv, NULL);
+ }
+
+ silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp,
+ block_len, iv);
+