|
|
|
|
@ -65,6 +65,8 @@ MODULE_LICENSE("GPL");
|
|
|
|
|
|
|
|
|
|
struct mp_hmac;
|
|
|
|
|
struct mp_cipher;
|
|
|
|
|
struct rtp_parsed;
|
|
|
|
|
struct mp_crypto_context;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -108,6 +110,9 @@ static int proc_main_list_show(struct seq_file *, void *);
|
|
|
|
|
static void table_push(struct mediaproxy_table *);
|
|
|
|
|
static struct mediaproxy_target *get_target(struct mediaproxy_table *, u_int16_t);
|
|
|
|
|
|
|
|
|
|
static int srtp_encrypt_aes_cm(struct mp_crypto_context *, struct mediaproxy_srtp *,
|
|
|
|
|
struct rtp_parsed *, u_int64_t);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -158,6 +163,10 @@ struct mediaproxy_table {
|
|
|
|
|
struct mp_cipher {
|
|
|
|
|
const char *name;
|
|
|
|
|
const char *tfm_name;
|
|
|
|
|
int (*decrypt)(struct mp_crypto_context *, struct mediaproxy_srtp *,
|
|
|
|
|
struct rtp_parsed *, u_int64_t);
|
|
|
|
|
int (*encrypt)(struct mp_crypto_context *, struct mediaproxy_srtp *,
|
|
|
|
|
struct rtp_parsed *, u_int64_t);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct mp_hmac {
|
|
|
|
|
@ -250,6 +259,8 @@ static const struct mp_cipher mp_ciphers[] = {
|
|
|
|
|
[MPC_AES_CM] = {
|
|
|
|
|
.name = "AES-CM",
|
|
|
|
|
.tfm_name = "aes",
|
|
|
|
|
.decrypt = srtp_encrypt_aes_cm,
|
|
|
|
|
.encrypt = srtp_encrypt_aes_cm,
|
|
|
|
|
},
|
|
|
|
|
[MPC_AES_F8] = {
|
|
|
|
|
.name = "AES-F8",
|
|
|
|
|
@ -894,7 +905,7 @@ static int validate_srtp(struct mediaproxy_srtp *s) {
|
|
|
|
|
|
|
|
|
|
/* XXX shared code */
|
|
|
|
|
static void aes_ctr_128(unsigned char *out, const unsigned char *in, int in_len,
|
|
|
|
|
struct crypto_cipher *tfm, const char *iv)
|
|
|
|
|
struct crypto_cipher *tfm, const unsigned char *iv)
|
|
|
|
|
{
|
|
|
|
|
unsigned char ivx[16];
|
|
|
|
|
unsigned char key_block[16];
|
|
|
|
|
@ -1613,14 +1624,16 @@ static u_int64_t packet_index(struct mp_crypto_context *c,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int srtp_auth_validate(struct mp_crypto_context *c,
|
|
|
|
|
struct mediaproxy_srtp *s, struct rtp_parsed *r)
|
|
|
|
|
struct mediaproxy_srtp *s, struct rtp_parsed *r,
|
|
|
|
|
u_int64_t pkt_idx)
|
|
|
|
|
{
|
|
|
|
|
unsigned char *auth_tag;
|
|
|
|
|
unsigned char hmac[20];
|
|
|
|
|
struct shash_desc *dsc;
|
|
|
|
|
u_int64_t pkt_idx;
|
|
|
|
|
u_int32_t roc;
|
|
|
|
|
|
|
|
|
|
if (s->hmac == MPH_NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
if (!c->hmac)
|
|
|
|
|
return 0;
|
|
|
|
|
if (!c->shash)
|
|
|
|
|
@ -1639,7 +1652,6 @@ static int srtp_auth_validate(struct mp_crypto_context *c,
|
|
|
|
|
if (!s->auth_tag_len)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
pkt_idx = packet_index(c, s, r->header);
|
|
|
|
|
roc = htonl((pkt_idx & 0xffffffff0000ULL) >> 16);
|
|
|
|
|
|
|
|
|
|
dsc = kmalloc(sizeof(*dsc) + crypto_shash_descsize(c->shash), GFP_ATOMIC);
|
|
|
|
|
@ -1681,6 +1693,56 @@ error:
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* XXX shared code */
|
|
|
|
|
static int srtp_encrypt_aes_cm(struct mp_crypto_context *c,
|
|
|
|
|
struct mediaproxy_srtp *s, struct rtp_parsed *r,
|
|
|
|
|
u_int64_t pkt_idx)
|
|
|
|
|
{
|
|
|
|
|
unsigned char iv[16];
|
|
|
|
|
u_int32_t *ivi;
|
|
|
|
|
u_int32_t idxh, idxl;
|
|
|
|
|
|
|
|
|
|
if (s->cipher == MPC_NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
if (!c->cipher)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
memcpy(iv, c->session_salt, 14);
|
|
|
|
|
iv[14] = iv[15] = '\0';
|
|
|
|
|
ivi = (void *) iv;
|
|
|
|
|
pkt_idx <<= 16;
|
|
|
|
|
idxh = htonl((pkt_idx & 0xffffffff00000000ULL) >> 32);
|
|
|
|
|
idxl = htonl(pkt_idx & 0xffffffffULL);
|
|
|
|
|
|
|
|
|
|
ivi[1] ^= r->header->ssrc;
|
|
|
|
|
ivi[2] ^= idxh;
|
|
|
|
|
ivi[3] ^= idxl;
|
|
|
|
|
|
|
|
|
|
aes_ctr_128(r->payload, r->payload, r->payload_len, c->tfm, iv);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline int srtp_encrypt(struct mp_crypto_context *c,
|
|
|
|
|
struct mediaproxy_srtp *s, struct rtp_parsed *r,
|
|
|
|
|
u_int64_t pkt_idx)
|
|
|
|
|
{
|
|
|
|
|
if (!c->cipher->encrypt)
|
|
|
|
|
return 0;
|
|
|
|
|
return c->cipher->encrypt(c, s, r, pkt_idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline int srtp_decrypt(struct mp_crypto_context *c,
|
|
|
|
|
struct mediaproxy_srtp *s, struct rtp_parsed *r,
|
|
|
|
|
u_int64_t pkt_idx)
|
|
|
|
|
{
|
|
|
|
|
if (!c->cipher->decrypt)
|
|
|
|
|
return 0;
|
|
|
|
|
return c->cipher->decrypt(c, s, r, pkt_idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned int mediaproxy46(struct sk_buff *skb, struct mediaproxy_table *t) {
|
|
|
|
|
struct udphdr *uh;
|
|
|
|
|
struct mediaproxy_target *g;
|
|
|
|
|
@ -1690,6 +1752,7 @@ static unsigned int mediaproxy46(struct sk_buff *skb, struct mediaproxy_table *t
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u_int32_t *u32;
|
|
|
|
|
struct rtp_parsed rtp;
|
|
|
|
|
u_int64_t pkt_idx = 0;
|
|
|
|
|
|
|
|
|
|
skb_reset_transport_header(skb);
|
|
|
|
|
uh = udp_hdr(skb);
|
|
|
|
|
@ -1729,8 +1792,20 @@ not_stun:
|
|
|
|
|
|
|
|
|
|
if (parse_rtp(&rtp, skb))
|
|
|
|
|
goto not_rtp;
|
|
|
|
|
if (srtp_auth_validate(&g->decrypt, &g->target.decrypt, &rtp))
|
|
|
|
|
pkt_idx = packet_index(&g->decrypt, &g->target.decrypt, rtp.header);
|
|
|
|
|
if (srtp_auth_validate(&g->decrypt, &g->target.decrypt, &rtp, pkt_idx))
|
|
|
|
|
goto skip3;
|
|
|
|
|
if (srtp_decrypt(&g->decrypt, &g->target.decrypt, &rtp, pkt_idx))
|
|
|
|
|
goto skip3;
|
|
|
|
|
|
|
|
|
|
skb_trim(skb, rtp.header_len + rtp.payload_len);
|
|
|
|
|
|
|
|
|
|
DBG("packet payload decrypted as %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x...\n",
|
|
|
|
|
rtp.payload[0], rtp.payload[1], rtp.payload[2], rtp.payload[3],
|
|
|
|
|
rtp.payload[4], rtp.payload[5], rtp.payload[6], rtp.payload[7],
|
|
|
|
|
rtp.payload[8], rtp.payload[9], rtp.payload[10], rtp.payload[11],
|
|
|
|
|
rtp.payload[12], rtp.payload[13], rtp.payload[14], rtp.payload[15],
|
|
|
|
|
rtp.payload[16], rtp.payload[17], rtp.payload[18], rtp.payload[19]);
|
|
|
|
|
|
|
|
|
|
not_rtp:
|
|
|
|
|
if (g->target.mirror_addr.family) {
|
|
|
|
|
|