+ /* Decrypt the payload */
+ if (cipher) {
+ /* Decrypt first block. This is to get the true length of the data in
+ payload. It is possible there is additional data after the message
+ payload with private messages. */
+ block_len = silc_cipher_get_block_len(cipher);
+ if (block_len > buffer.len)
+ goto err;
+ silc_cipher_decrypt(cipher, buffer.data, data, block_len,
+ silc_cipher_get_iv(cipher));
+
+ /* Length of encrypted area */
+ SILC_GET16_MSB(newp->message_len, data + 2);
+ totlen = 4 + newp->message_len;
+ pad_len = SILC_PRIVATE_MESSAGE_PAD(4 + newp->message_len);
+ totlen += pad_len;
+
+ /* Sanity checks */
+ if (totlen > buffer.len || newp->message_len < 1 ||
+ newp->message_len > buffer.len - 4) {
+ SILC_LOG_DEBUG(("Incorrect private message payload in packet"));
+ goto err;
+ }
+
+ /* Compute MAC for integrity check from the cipher text */
+ if (hmac) {
+ SILC_LOG_DEBUG(("Checking private message MAC"));
+ silc_hmac_init(hmac);
+ silc_hmac_update(hmac, buffer.data, totlen);
+ silc_hmac_final(hmac, mac, &mac_len);
+ if (memcmp(mac, buffer.data + totlen, mac_len)) {
+ SILC_LOG_DEBUG(("Private message MAC does not match"));
+ goto err;
+ }
+ SILC_LOG_DEBUG(("MAC is Ok"));
+ }
+
+ /* Now decrypt rest of the data */
+ memcpy(buffer.data, data, block_len);
+ if (totlen - block_len > 0)
+ silc_cipher_decrypt(cipher, buffer.data + block_len,
+ buffer.data + block_len, totlen - block_len,
+ silc_cipher_get_iv(cipher));
+ memset(data, 0, sizeof(data));
+ }
+
+ /* Parse the Private Message Payload. */
+ len = silc_buffer_unformat(&buffer,