+ else
+ {
+ /* Packet in the past/present, bad */
+ diff = -diff;
+ if ((diff >= 64) || ((s->rtcp.window >> diff) & 1))
+ return EACCES; // replay attack!
+ s->rtp.window |= 1 << diff;
+ }
+
+ /* Crypts SRTCP */
+ if (s->flags & SRTCP_UNENCRYPTED)
+ return 0;
+
+ uint32_t ssrc;
+ memcpy (&ssrc, buf + 4, 4);
+
+ if (rtcp_crypt (s->rtcp.cipher, ssrc, index, s->rtp.salt,
+ buf + 8, len - 8))
+ return EINVAL;
+ return 0;
+}
+
+
+/**
+ * Turns a RTCP packet into a SRTCP packet: encrypt it, then computes
+ * the authentication tag and appends it.
+ *
+ * @param buf RTCP packet to be encrypted/digested
+ * @param lenp pointer to the RTCP packet length on entry,
+ * set to the SRTCP length on exit (undefined in case of error)
+ * @param bufsize size (bytes) of the packet buffer
+ *
+ * @return 0 on success, in case of error:
+ * EINVAL malformatted RTCP packet or internal error
+ * ENOSPC bufsize is too small (to add index and authentication tag)
+ */
+int
+srtcp_send (srtp_session_t *s, uint8_t *buf, size_t *lenp, size_t bufsize)
+{
+ size_t len = *lenp;
+ if (bufsize < (len + 4 + s->tag_len))
+ return ENOSPC;
+
+ uint32_t index = ++s->rtcp_index;
+ if (index >> 31)
+ s->rtcp_index = index = 0; /* 31-bit wrap */
+
+ if ((s->flags & SRTCP_UNENCRYPTED) == 0)
+ index |= 0x80000000; /* Set Encrypted bit */
+ memcpy (buf + len, &(uint32_t){ htonl (index) }, 4);
+
+ int val = srtcp_crypt (s, buf, len);
+ if (val)
+ return val;
+
+ len += 4; /* Digests SRTCP index too */
+
+ const uint8_t *tag = rtcp_digest (s->rtp.mac, buf, len);
+ memcpy (buf + len, tag, s->tag_len);
+ *lenp = len + s->tag_len;
+ return 0;
+}
+
+
+/**
+ * Turns a SRTCP packet into a RTCP packet: authenticates the packet,
+ * then decrypts it.
+ *
+ * @param buf RTCP packet to be digested/decrypted
+ * @param lenp pointer to the SRTCP packet length on entry,
+ * set to the RTCP length on exit (undefined in case of error)
+ *
+ * @return 0 on success, in case of error:
+ * EINVAL malformatted SRTCP packet
+ * EACCES authentication failed (spoofed packet or out-of-sync)
+ */
+int
+srtcp_recv (srtp_session_t *s, uint8_t *buf, size_t *lenp)
+{
+ size_t len = *lenp;
+
+ if (len < (4u + s->tag_len))
+ return EINVAL;
+ len -= s->tag_len;