From d1ce4eb9a861066fbbcdf4cbbecabd98f85fb9f6 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 24 Jun 2013 11:52:08 -0400 Subject: [PATCH] aes-f8 goes kernel --- daemon/crypto.c | 2 +- kernel-module/xt_MEDIAPROXY.c | 147 +++++++++++++++++++++++++++++----- 2 files changed, 130 insertions(+), 19 deletions(-) diff --git a/daemon/crypto.c b/daemon/crypto.c index a39e3f1eb..e3e5694ae 100644 --- a/daemon/crypto.c +++ b/daemon/crypto.c @@ -86,7 +86,7 @@ const struct crypto_suite crypto_suites[] = { .session_salt_len = 14, .srtp_lifetime = 1ULL << 48, .srtcp_lifetime = 1ULL << 31, - .kernel_cipher = 0, + .kernel_cipher = MPC_AES_F8, .kernel_hmac = MPH_HMAC_SHA1, .srtp_auth_tag = 10, .srtcp_auth_tag = 10, diff --git a/kernel-module/xt_MEDIAPROXY.c b/kernel-module/xt_MEDIAPROXY.c index 77a60b11a..0e480e7f6 100644 --- a/kernel-module/xt_MEDIAPROXY.c +++ b/kernel-module/xt_MEDIAPROXY.c @@ -111,8 +111,11 @@ 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 aes_f8_session_key_init(struct mp_crypto_context *, struct mediaproxy_srtp *); static int srtp_encrypt_aes_cm(struct mp_crypto_context *, struct mediaproxy_srtp *, struct rtp_parsed *, u_int64_t); +static int srtp_encrypt_aes_f8(struct mp_crypto_context *, struct mediaproxy_srtp *, + struct rtp_parsed *, u_int64_t); @@ -125,7 +128,7 @@ struct mp_crypto_context { unsigned char session_salt[14]; unsigned char session_auth_key[20]; u_int32_t roc; - struct crypto_cipher *tfm; + struct crypto_cipher *tfm[2]; struct crypto_shash *shash; const struct mp_cipher *cipher; const struct mp_hmac *hmac; @@ -168,6 +171,7 @@ struct mp_cipher { struct rtp_parsed *, u_int64_t); int (*encrypt)(struct mp_crypto_context *, struct mediaproxy_srtp *, struct rtp_parsed *, u_int64_t); + int (*session_key_init)(struct mp_crypto_context *, struct mediaproxy_srtp *); }; struct mp_hmac { @@ -266,6 +270,9 @@ static const struct mp_cipher mp_ciphers[] = { [MPC_AES_F8] = { .name = "AES-F8", .tfm_name = "aes", + .decrypt = srtp_encrypt_aes_f8, + .encrypt = srtp_encrypt_aes_f8, + .session_key_init = aes_f8_session_key_init, }, }; @@ -402,8 +409,12 @@ static struct mediaproxy_table *new_table_link(u_int32_t id) { static void free_crypto_context(struct mp_crypto_context *c) { - if (c->tfm) - crypto_free_cipher(c->tfm); + int i; + + for (i = 0; i < ARRAY_SIZE(c->tfm); i++) { + if (c->tfm[i]) + crypto_free_cipher(c->tfm[i]); + } if (c->shash) crypto_free_shash(c->shash); } @@ -974,6 +985,66 @@ done: ; } +static void aes_f8(unsigned char *in_out, int in_len, + struct crypto_cipher *tfm, struct crypto_cipher *iv_tfm, + const unsigned char *iv) +{ + unsigned char key_block[16], last_key_block[16], /* S(j), S(j-1) */ + ivx[16], /* IV' */ + x[16]; + int i, left; + u_int32_t j; + unsigned char *p; + u_int64_t *pi, *ki, *lki, *xi; + u_int32_t *xu; + + crypto_cipher_encrypt_one(iv_tfm, ivx, iv); + + pi = (void *) in_out; + ki = (void *) key_block; + lki = (void *) last_key_block; + xi = (void *) x; + xu = (void *) x; + left = in_len; + j = 0; + memset(last_key_block, 0, sizeof(last_key_block)); + + while (left) { + /* S(j) = E(k_e, IV' XOR j XOR S(j-1)) */ + memcpy(x, ivx, 16); + + xu[3] ^= htonl(j); + + xi[0] ^= lki[0]; + xi[1] ^= lki[1]; + + crypto_cipher_encrypt_one(tfm, key_block, x); + + if (unlikely(left < 16)) { + p = (void *) pi; + for (i = 0; i < 16; i++) { + *p++ ^= key_block[i]; + left--; + if (!left) + goto done; + } + panic("BUG!"); + } + + *pi++ ^= ki[0]; + *pi++ ^= ki[1]; + left -= 16; + if (!left) + break; + + j++; + memcpy(last_key_block, key_block, 16); + } + +done: + ; +} + static int aes_ctr_128_no_ctx(unsigned char *out, const char *in, int in_len, const unsigned char *key, const unsigned char *iv) { @@ -1032,6 +1103,31 @@ static int gen_session_key(unsigned char *out, int len, struct mediaproxy_srtp * +static int aes_f8_session_key_init(struct mp_crypto_context *c, struct mediaproxy_srtp *s) { + unsigned char m[16]; + int i, ret; + + /* m = k_s || 0x555..5 */ + memcpy(m, c->session_salt, 14); + m[14] = m[15] = 0x55; + /* IV' = E(k_e XOR m, IV) */ + for (i = 0; i < 16; i++) + m[i] ^= c->session_key[i]; + + c->tfm[1] = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(c->tfm[1])) { + ret = PTR_ERR(c->tfm[1]); + c->tfm[1] = NULL; + goto error; + } + crypto_cipher_setkey(c->tfm[1], m, 16); + + return 0; + +error: + return ret; +} + static int gen_session_keys(struct mp_crypto_context *c, struct mediaproxy_srtp *s) { int ret; const char *err; @@ -1051,13 +1147,19 @@ static int gen_session_keys(struct mp_crypto_context *c, struct mediaproxy_srtp if (c->cipher->tfm_name) { err = "failed to load cipher"; - c->tfm = crypto_alloc_cipher(c->cipher->tfm_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(c->tfm)) { - ret = PTR_ERR(c->tfm); - c->tfm = NULL; + c->tfm[0] = crypto_alloc_cipher(c->cipher->tfm_name, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(c->tfm[0])) { + ret = PTR_ERR(c->tfm[0]); + c->tfm[0] = NULL; goto error; } - crypto_cipher_setkey(c->tfm, c->session_key, 16); + crypto_cipher_setkey(c->tfm[0], c->session_key, 16); + } + + if (c->cipher->session_key_init) { + ret = c->cipher->session_key_init(c, s); + if (ret) + goto error; } if (c->hmac->tfm_name) { @@ -1100,10 +1202,7 @@ static int gen_session_keys(struct mp_crypto_context *c, struct mediaproxy_srtp return 0; error: - if (c->tfm) - crypto_free_cipher(c->tfm); - if (c->shash) - crypto_free_shash(c->shash); + free_crypto_context(c); printk(KERN_ERR "Failed to generate session keys: %s\n", err); return ret; } @@ -1798,11 +1897,6 @@ static int srtp_encrypt_aes_cm(struct mp_crypto_context *c, 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; @@ -1814,7 +1908,24 @@ static int srtp_encrypt_aes_cm(struct mp_crypto_context *c, ivi[2] ^= idxh; ivi[3] ^= idxl; - aes_ctr_128(r->payload, r->payload, r->payload_len, c->tfm, iv); + aes_ctr_128(r->payload, r->payload, r->payload_len, c->tfm[0], iv); + + return 0; +} + +static int srtp_encrypt_aes_f8(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 roc; + + iv[0] = 0; + memcpy(&iv[1], &r->header->m_pt, 11); + roc = htonl((pkt_idx & 0xffffffff0000ULL) >> 16); + memcpy(&iv[12], &roc, sizeof(roc)); + + aes_f8(r->payload, r->payload_len, c->tfm[0], c->tfm[1], iv); return 0; }