implements in-kernel SRTP decryption (AES-CM)

git.mgm/mediaproxy-ng/github/master
Richard Fuchs 13 years ago
parent afdabe640d
commit 17c9b7dc8b

@ -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) {

Loading…
Cancel
Save