Browse Source

implement AES-CM encryption and adding auth tag, which completes in-kernel AES-CM SRTP support

git.mgm/mediaproxy-ng/github/master
Richard Fuchs 13 years ago
parent
commit
02176fcb0f
1 changed files with 115 additions and 44 deletions
  1. +115
    -44
      kernel-module/xt_MEDIAPROXY.c

+ 115
- 44
kernel-module/xt_MEDIAPROXY.c View File

@ -33,6 +33,7 @@ MODULE_LICENSE("GPL");
#define MAX_ID 64 /* - 1 */
#define MAX_SKB_TAIL_ROOM (128 + 20)
#define MIPF "%i:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x:%u"
#define MIPP(x) (x).family, \
@ -1552,23 +1553,23 @@ static int parse_rtp(struct rtp_parsed *rtp, struct sk_buff *skb) {
memset(rtp, 0, sizeof(*rtp));
if (skb->len < sizeof(*rtp->header))
return -1;
goto error;
rtp->header = (void *) skb->data;
if ((rtp->header->v_p_x_cc & 0xc0) != 0x80) /* version 2 */
return -1;
goto error;
rtp->header_len = sizeof(*rtp->header);
/* csrc list */
rtp->header_len += (rtp->header->v_p_x_cc & 0xf) * 4;
if (skb->len < rtp->header_len)
return -1;
goto error;
rtp->payload = skb->data + rtp->header_len;
rtp->payload_len = skb->len - rtp->header_len;
if ((rtp->header->v_p_x_cc & 0x10)) {
/* extension */
if (rtp->payload_len < sizeof(*ext))
return -1;
goto error;
ext = (void *) rtp->payload;
ext_len = 4 + ntohs(ext->length) * 4;
if (rtp->payload_len < ext_len)
@ -1580,6 +1581,10 @@ static int parse_rtp(struct rtp_parsed *rtp, struct sk_buff *skb) {
DBG("rtp header parsed, payload length is %u\n", rtp->payload_len);
return 0;
error:
memset(rtp, 0, sizeof(*rtp));
return -1;
}
/* XXX shared code */
@ -1623,31 +1628,13 @@ static u_int64_t packet_index(struct mp_crypto_context *c,
return index;
}
static int srtp_auth_validate(struct mp_crypto_context *c,
static int srtp_hash(unsigned char *hmac,
struct mp_crypto_context *c,
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_int32_t roc;
if (s->hmac == MPH_NULL)
return 0;
if (!c->hmac)
return 0;
if (!c->shash)
return -1;
if (r->payload_len < s->auth_tag_len)
return -1;
r->payload_len -= s->auth_tag_len;
auth_tag = r->payload + r->payload_len;
if (r->payload_len < s->mki_len)
return -1;
r->payload_len -= s->mki_len;
struct shash_desc *dsc;
if (!s->auth_tag_len)
return 0;
@ -1677,20 +1664,108 @@ static int srtp_auth_validate(struct mp_crypto_context *c,
hmac[8], hmac[9], hmac[10], hmac[11],
hmac[12], hmac[13], hmac[14], hmac[15],
hmac[16], hmac[17], hmac[18], hmac[19]);
DBG("packet auth tag %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
return 0;
error:
kfree(dsc);
return -1;
}
/* XXX shared code */
static void rtp_append_mki(struct rtp_parsed *r, struct mediaproxy_srtp *c) {
u_int32_t mki_part;
unsigned char *p;
if (!c->mki_len)
return;
p = r->payload + r->payload_len;
memset(p, 0, c->mki_len);
if (c->mki_len > 4) {
mki_part = (c->mki & 0xffffffff00000000ULL) >> 32;
mki_part = htonl(mki_part);
if (c->mki_len < 8)
memcpy(p, ((char *) &mki_part) + (8 - c->mki_len), c->mki_len - 4);
else
memcpy(p + (c->mki_len - 8), &mki_part, 4);
}
mki_part = (c->mki & 0xffffffffULL);
mki_part = htonl(mki_part);
if (c->mki_len < 4)
memcpy(p, ((char *) &mki_part) + (4 - c->mki_len), c->mki_len);
else
memcpy(p + (c->mki_len - 4), &mki_part, 4);
r->payload_len += c->mki_len;
}
static int srtp_authenticate(struct mp_crypto_context *c,
struct mediaproxy_srtp *s, struct rtp_parsed *r,
u_int64_t pkt_idx)
{
unsigned char hmac[20];
if (!r->header)
return 0;
if (s->hmac == MPH_NULL)
return 0;
if (!c->hmac)
return 0;
if (!c->shash)
return -1;
if (srtp_hash(hmac, c, s, r, pkt_idx))
return -1;
rtp_append_mki(r, s);
memcpy(r->payload + r->payload_len, hmac, s->auth_tag_len);
r->payload_len += s->auth_tag_len;
return 0;
}
static int srtp_auth_validate(struct mp_crypto_context *c,
struct mediaproxy_srtp *s, struct rtp_parsed *r,
u_int64_t pkt_idx)
{
unsigned char *auth_tag;
unsigned char hmac[20];
if (s->hmac == MPH_NULL)
return 0;
if (!c->hmac)
return 0;
if (!c->shash)
return -1;
if (r->payload_len < s->auth_tag_len)
return -1;
r->payload_len -= s->auth_tag_len;
auth_tag = r->payload + r->payload_len;
if (r->payload_len < s->mki_len)
return -1;
r->payload_len -= s->mki_len;
if (!s->auth_tag_len)
return 0;
DBG("packet auth tag %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
auth_tag[0], auth_tag[1], auth_tag[2], auth_tag[3],
auth_tag[4], auth_tag[5], auth_tag[6], auth_tag[7],
auth_tag[8], auth_tag[9], auth_tag[10], auth_tag[11],
auth_tag[12], auth_tag[13], auth_tag[14], auth_tag[15],
auth_tag[16], auth_tag[17], auth_tag[18], auth_tag[19]);
auth_tag[8], auth_tag[9]);
if (srtp_hash(hmac, c, s, r, pkt_idx))
return -1;
if (memcmp(auth_tag, hmac, s->auth_tag_len))
return -1;
return 0;
error:
kfree(dsc);
return -1;
}
@ -1729,6 +1804,8 @@ static inline int srtp_encrypt(struct mp_crypto_context *c,
struct mediaproxy_srtp *s, struct rtp_parsed *r,
u_int64_t pkt_idx)
{
if (!r->header)
return 0;
if (!c->cipher->encrypt)
return 0;
return c->cipher->encrypt(c, s, r, pkt_idx);
@ -1819,6 +1896,10 @@ not_rtp:
}
}
srtp_encrypt(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx);
skb_put(skb, g->target.encrypt.mki_len + g->target.encrypt.auth_tag_len);
srtp_authenticate(&g->encrypt, &g->target.encrypt, &rtp, pkt_idx);
err = send_proxy_packet(skb, &g->target.src_addr, &g->target.dst_addr, g->target.tos);
spin_lock_irqsave(&g->stats_lock, flags);
@ -1857,17 +1938,12 @@ static unsigned int mediaproxy4(struct sk_buff *oskb, const struct xt_action_par
struct sk_buff *skb;
struct iphdr *ih;
struct mediaproxy_table *t;
int headroom;
t = get_table(pinfo->id);
if (!t)
goto skip;
headroom = MAX_HEADER - sizeof(*ih);
if (skb_headroom(oskb) >= headroom)
skb = skb_copy(oskb, GFP_ATOMIC);
else
skb = skb_copy_expand(oskb, headroom, 0, GFP_ATOMIC);
skb = skb_copy_expand(oskb, MAX_HEADER, MAX_SKB_TAIL_ROOM, GFP_ATOMIC);
if (!skb)
goto skip3;
@ -1899,17 +1975,12 @@ static unsigned int mediaproxy6(struct sk_buff *oskb, const struct xt_action_par
struct sk_buff *skb;
struct ipv6hdr *ih;
struct mediaproxy_table *t;
int headroom;
t = get_table(pinfo->id);
if (!t)
goto skip;
headroom = MAX_HEADER - sizeof(*ih);
if (skb_headroom(oskb) >= headroom)
skb = skb_copy(oskb, GFP_ATOMIC);
else
skb = skb_copy_expand(oskb, headroom, 0, GFP_ATOMIC);
skb = skb_copy_expand(oskb, MAX_HEADER, MAX_SKB_TAIL_ROOM, GFP_ATOMIC);
if (!skb)
goto skip3;


Loading…
Cancel
Save