Custom XOR encryption of media stream causes "Error sending RTP: replay check failed (index too old)\n"

JS
Jan Skórczyński
Fri, Jul 13, 2018 1:55 PM

Hello,

I'm trying to add another layer of encryption to media stream using simple
XOR encryption.
What I've already done is implementing transport adapter and connect it as
master of srtp transport.

I did it by adding to my project xor_transport_adapter.cpp fill which share
the code with transport_adapter_example.c. I only add few modification
listed below:

//Contansts for buffer size
#define MAX_RTP_BUFFER_LEN    PJMEDIA_MAX_MTU
#define MAX_RTCP_BUFFER_LEN    PJMEDIA_MAX_MTU

// I keep buffers for outgoing messages and hash in adapter instance
/* The transport adapter instance */
struct xor_tp_adapter
{

/* Outgoing message buffer */
char rtp_tx_buffer[MAX_RTP_BUFFER_LEN]; //My buffer to operate on rtp

packets
char rtcp_tx_buffer[MAX_RTP_BUFFER_LEN]; // My buffer to operate on
rtcp packets

const char* xor_hash;  //My hash
pj_size_t xor_hash_size; // hash size

/* ... */
};

//I also develop function to make xor
void xor_protect_rtcp(char buffer, pj_size_t pkt_size, const char hash,
pj_size_t hash_size) {
for(unsigned i = 0; i<pkt_size; ++i) {
buffer[i] ^=  hash[i%hash_size];
}
}

//It is used in 5 places in code:
static pj_status_t transport_send_rtp( pjmedia_transport *tp,
const void *pkt,
pj_size_t size)
{
struct xor_tp_adapter adapter = (struct xor_tp_adapter)tp;

if (size > sizeof(adapter->rtp_tx_buffer)) {
    return PJ_ETOOBIG;
}

pj_memcpy(adapter->rtp_tx_buffer, pkt, size);
xor_protect_rtcp(adapter->rtp_tx_buffer,
                 size,
                 adapter->xor_hash, adapter->xor_hash_size);

return pjmedia_transport_send_rtp(adapter->slave_tp,

adapter->rtp_tx_buffer, size);
}

static pj_status_t transport_send_rtcp(pjmedia_transport *tp,
const void *pkt,
pj_size_t size)
{
struct xor_tp_adapter adapter = (struct xor_tp_adapter)tp;

pj_memcpy(adapter->rtcp_tx_buffer, pkt, size);
xor_protect_rtcp(adapter->rtcp_tx_buffer, size,
                 adapter->xor_hash, adapter->xor_hash_size);

return pjmedia_transport_send_rtcp(adapter->slave_tp,

adapter->rtcp_tx_buffer, size);
}

static void transport_rtp_cb(void *user_data, void *pkt, pj_ssize_t size)
{
struct xor_tp_adapter adapter = (struct xor_tp_adapter)user_data;

pj_assert(adapter->stream_rtp_cb != NULL);

xor_protect_rtcp((char*)pkt, size, adapter->xor_hash,

adapter->xor_hash_size);

adapter->stream_rtp_cb(adapter->stream_user_data, pkt, size);

}

static void transport_rtcp_cb(void *user_data, void *pkt, pj_ssize_t size)
{
struct xor_tp_adapter adapter = (struct xor_tp_adapter)user_data;

pj_assert(adapter->stream_rtcp_cb != NULL);

xor_unprotect_rtcp((char*)pkt, size, adapter->xor_hash,

adapter->xor_hash_size);

adapter->stream_rtcp_cb(adapter->stream_user_data, pkt, size);

}

static pj_status_t transport_send_rtcp2(pjmedia_transport *tp,
const pj_sockaddr_t *addr,
unsigned addr_len,
const void *pkt,
pj_size_t size)
{
struct xor_tp_adapter adapter = (struct xor_tp_adapter)tp;

pj_memcpy(adapter->rtcp_tx_buffer, pkt, size);
xor_protect_rtcp(adapter->rtcp_tx_buffer,
                 size,
                 adapter->xor_hash, adapter->xor_hash_size);

return pjmedia_transport_send_rtcp2(adapter->slave_tp, addr, addr_len,
                adapter->rtcp_tx_buffer, size);

}

Every seems to work nice for the first 2-4 seconds of call. After that time
I receive many errors like this:
Error sending RTP: replay check failed (index too old)\n

Could someone point out what I am doing wrong and how should I handle this?

Hello, I'm trying to add another layer of encryption to media stream using simple XOR encryption. What I've already done is implementing transport adapter and connect it as master of srtp transport. I did it by adding to my project xor_transport_adapter.cpp fill which share the code with transport_adapter_example.c. I only add few modification listed below: //Contansts for buffer size #define MAX_RTP_BUFFER_LEN PJMEDIA_MAX_MTU #define MAX_RTCP_BUFFER_LEN PJMEDIA_MAX_MTU // I keep buffers for outgoing messages and hash in adapter instance /* The transport adapter instance */ struct xor_tp_adapter { /* Outgoing message buffer */ char rtp_tx_buffer[MAX_RTP_BUFFER_LEN]; //My buffer to operate on rtp packets char rtcp_tx_buffer[MAX_RTP_BUFFER_LEN]; // My buffer to operate on rtcp packets const char* xor_hash; //My hash pj_size_t xor_hash_size; // hash size /* ... */ }; //I also develop function to make xor void xor_protect_rtcp(char *buffer, pj_size_t pkt_size, const char* hash, pj_size_t hash_size) { for(unsigned i = 0; i<pkt_size; ++i) { buffer[i] ^= hash[i%hash_size]; } } //It is used in 5 places in code: static pj_status_t transport_send_rtp( pjmedia_transport *tp, const void *pkt, pj_size_t size) { struct xor_tp_adapter *adapter = (struct xor_tp_adapter*)tp; if (size > sizeof(adapter->rtp_tx_buffer)) { return PJ_ETOOBIG; } pj_memcpy(adapter->rtp_tx_buffer, pkt, size); xor_protect_rtcp(adapter->rtp_tx_buffer, size, adapter->xor_hash, adapter->xor_hash_size); return pjmedia_transport_send_rtp(adapter->slave_tp, adapter->rtp_tx_buffer, size); } static pj_status_t transport_send_rtcp(pjmedia_transport *tp, const void *pkt, pj_size_t size) { struct xor_tp_adapter *adapter = (struct xor_tp_adapter*)tp; pj_memcpy(adapter->rtcp_tx_buffer, pkt, size); xor_protect_rtcp(adapter->rtcp_tx_buffer, size, adapter->xor_hash, adapter->xor_hash_size); return pjmedia_transport_send_rtcp(adapter->slave_tp, adapter->rtcp_tx_buffer, size); } static void transport_rtp_cb(void *user_data, void *pkt, pj_ssize_t size) { struct xor_tp_adapter *adapter = (struct xor_tp_adapter*)user_data; pj_assert(adapter->stream_rtp_cb != NULL); xor_protect_rtcp((char*)pkt, size, adapter->xor_hash, adapter->xor_hash_size); adapter->stream_rtp_cb(adapter->stream_user_data, pkt, size); } static void transport_rtcp_cb(void *user_data, void *pkt, pj_ssize_t size) { struct xor_tp_adapter *adapter = (struct xor_tp_adapter*)user_data; pj_assert(adapter->stream_rtcp_cb != NULL); xor_unprotect_rtcp((char*)pkt, size, adapter->xor_hash, adapter->xor_hash_size); adapter->stream_rtcp_cb(adapter->stream_user_data, pkt, size); } static pj_status_t transport_send_rtcp2(pjmedia_transport *tp, const pj_sockaddr_t *addr, unsigned addr_len, const void *pkt, pj_size_t size) { struct xor_tp_adapter *adapter = (struct xor_tp_adapter*)tp; pj_memcpy(adapter->rtcp_tx_buffer, pkt, size); xor_protect_rtcp(adapter->rtcp_tx_buffer, size, adapter->xor_hash, adapter->xor_hash_size); return pjmedia_transport_send_rtcp2(adapter->slave_tp, addr, addr_len, adapter->rtcp_tx_buffer, size); } Every seems to work nice for the first 2-4 seconds of call. After that time I receive many errors like this: Error sending RTP: replay check failed (index too old)\n Could someone point out what I am doing wrong and how should I handle this?