|
|
|
|
@ -26,8 +26,9 @@ static int hmac_sha1_rtp(struct crypto_context *, char *out, str *in, u_int64_t)
|
|
|
|
|
static int hmac_sha1_rtcp(struct crypto_context *, char *out, str *in);
|
|
|
|
|
static int aes_f8_encrypt_rtp(struct crypto_context *c, struct rtp_header *r, str *s, u_int64_t idx);
|
|
|
|
|
static int aes_f8_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r, str *s, u_int64_t idx);
|
|
|
|
|
static int aes_session_key_init(struct crypto_context *c);
|
|
|
|
|
static int aes_session_key_cleanup(struct crypto_context *c);
|
|
|
|
|
static int aes_cm_session_key_init(struct crypto_context *c);
|
|
|
|
|
static int aes_f8_session_key_init(struct crypto_context *c);
|
|
|
|
|
static int evp_session_key_cleanup(struct crypto_context *c);
|
|
|
|
|
|
|
|
|
|
/* all lengths are in bytes */
|
|
|
|
|
const struct crypto_suite crypto_suites[] = {
|
|
|
|
|
@ -51,8 +52,8 @@ const struct crypto_suite crypto_suites[] = {
|
|
|
|
|
.decrypt_rtcp = aes_cm_encrypt_rtcp,
|
|
|
|
|
.hash_rtp = hmac_sha1_rtp,
|
|
|
|
|
.hash_rtcp = hmac_sha1_rtcp,
|
|
|
|
|
.session_key_init = aes_session_key_init,
|
|
|
|
|
.session_key_cleanup = aes_session_key_cleanup,
|
|
|
|
|
.session_key_init = aes_cm_session_key_init,
|
|
|
|
|
.session_key_cleanup = evp_session_key_cleanup,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "AES_CM_128_HMAC_SHA1_32",
|
|
|
|
|
@ -74,8 +75,8 @@ const struct crypto_suite crypto_suites[] = {
|
|
|
|
|
.decrypt_rtcp = aes_cm_encrypt_rtcp,
|
|
|
|
|
.hash_rtp = hmac_sha1_rtp,
|
|
|
|
|
.hash_rtcp = hmac_sha1_rtcp,
|
|
|
|
|
.session_key_init = aes_session_key_init,
|
|
|
|
|
.session_key_cleanup = aes_session_key_cleanup,
|
|
|
|
|
.session_key_init = aes_cm_session_key_init,
|
|
|
|
|
.session_key_cleanup = evp_session_key_cleanup,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.name = "F8_128_HMAC_SHA1_80",
|
|
|
|
|
@ -97,8 +98,8 @@ const struct crypto_suite crypto_suites[] = {
|
|
|
|
|
.decrypt_rtcp = aes_f8_encrypt_rtcp,
|
|
|
|
|
.hash_rtp = hmac_sha1_rtp,
|
|
|
|
|
.hash_rtcp = hmac_sha1_rtcp,
|
|
|
|
|
.session_key_init = aes_session_key_init,
|
|
|
|
|
.session_key_cleanup = aes_session_key_cleanup,
|
|
|
|
|
.session_key_init = aes_f8_session_key_init,
|
|
|
|
|
.session_key_cleanup = evp_session_key_cleanup,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -277,7 +278,7 @@ static int aes_cm_encrypt(struct crypto_context *c, u_int32_t ssrc, str *s, u_in
|
|
|
|
|
ivi[2] ^= idxh;
|
|
|
|
|
ivi[3] ^= idxl;
|
|
|
|
|
|
|
|
|
|
aes_ctr_128(s->s, s, c->session_key_ctx, (char *) iv);
|
|
|
|
|
aes_ctr_128(s->s, s, c->session_key_ctx[0], (char *) iv);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@ -295,37 +296,17 @@ static int aes_cm_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r,
|
|
|
|
|
/* rfc 3711 sections 4.1.2 and 4.1.2.1
|
|
|
|
|
* encrypts in place */
|
|
|
|
|
static void aes_128_f8_encrypt(struct crypto_context *c, unsigned char *iv, str *s) {
|
|
|
|
|
EVP_CIPHER_CTX ecc;
|
|
|
|
|
unsigned char key_block[16], last_key_block[16], /* S(j), S(j-1) */
|
|
|
|
|
ivx[16], /* IV' */
|
|
|
|
|
m[16],
|
|
|
|
|
x[16];
|
|
|
|
|
int i, outlen, left;
|
|
|
|
|
int k_e_len, k_s_len; /* n_e, n_s */
|
|
|
|
|
u_int32_t j;
|
|
|
|
|
unsigned char *p, *key;
|
|
|
|
|
unsigned char *p;
|
|
|
|
|
u_int64_t *pi, *ki, *lki, *xi;
|
|
|
|
|
u_int32_t *xu;
|
|
|
|
|
|
|
|
|
|
k_e_len = c->crypto_suite->session_key_len;
|
|
|
|
|
k_s_len = c->crypto_suite->session_salt_len;
|
|
|
|
|
key = (unsigned char *) c->session_key;
|
|
|
|
|
|
|
|
|
|
/* m = k_s || 0x555..5 */
|
|
|
|
|
memcpy(m, c->session_salt, k_s_len);
|
|
|
|
|
for (i = k_s_len; i < k_e_len; i++)
|
|
|
|
|
m[i] = 0x55;
|
|
|
|
|
|
|
|
|
|
/* IV' = E(k_e XOR m, IV) */
|
|
|
|
|
for (i = 0; i < k_e_len; i++)
|
|
|
|
|
m[i] ^= key[i];
|
|
|
|
|
|
|
|
|
|
EVP_CIPHER_CTX_init(&ecc);
|
|
|
|
|
EVP_EncryptInit_ex(&ecc, EVP_aes_128_ecb(), NULL, m, NULL);
|
|
|
|
|
EVP_EncryptUpdate(&ecc, ivx, &outlen, iv, 16);
|
|
|
|
|
EVP_EncryptUpdate(c->session_key_ctx[1], ivx, &outlen, iv, 16);
|
|
|
|
|
assert(outlen == 16);
|
|
|
|
|
EVP_EncryptFinal_ex(&ecc, key_block, &outlen);
|
|
|
|
|
EVP_CIPHER_CTX_cleanup(&ecc);
|
|
|
|
|
|
|
|
|
|
pi = (void *) s->s;
|
|
|
|
|
ki = (void *) key_block;
|
|
|
|
|
@ -345,7 +326,7 @@ static void aes_128_f8_encrypt(struct crypto_context *c, unsigned char *iv, str
|
|
|
|
|
xi[0] ^= lki[0];
|
|
|
|
|
xi[1] ^= lki[1];
|
|
|
|
|
|
|
|
|
|
EVP_EncryptUpdate(c->session_key_ctx, key_block, &outlen, x, 16);
|
|
|
|
|
EVP_EncryptUpdate(c->session_key_ctx[0], key_block, &outlen, x, 16);
|
|
|
|
|
assert(outlen == 16);
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY(left < 16)) {
|
|
|
|
|
@ -434,26 +415,56 @@ static int hmac_sha1_rtcp(struct crypto_context *c, char *out, str *in) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int aes_session_key_init(struct crypto_context *c) {
|
|
|
|
|
aes_session_key_cleanup(c);
|
|
|
|
|
c->session_key_ctx = g_slice_alloc(sizeof(EVP_CIPHER_CTX));
|
|
|
|
|
EVP_CIPHER_CTX_init(c->session_key_ctx);
|
|
|
|
|
EVP_EncryptInit_ex(c->session_key_ctx, EVP_aes_128_ecb(), NULL,
|
|
|
|
|
static int aes_cm_session_key_init(struct crypto_context *c) {
|
|
|
|
|
evp_session_key_cleanup(c);
|
|
|
|
|
|
|
|
|
|
c->session_key_ctx[0] = g_slice_alloc(sizeof(EVP_CIPHER_CTX));
|
|
|
|
|
EVP_CIPHER_CTX_init(c->session_key_ctx[0]);
|
|
|
|
|
EVP_EncryptInit_ex(c->session_key_ctx[0], EVP_aes_128_ecb(), NULL,
|
|
|
|
|
(unsigned char *) c->session_key, NULL);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int aes_session_key_cleanup(struct crypto_context *c) {
|
|
|
|
|
static int aes_f8_session_key_init(struct crypto_context *c) {
|
|
|
|
|
unsigned char m[16];
|
|
|
|
|
int i;
|
|
|
|
|
int k_e_len, k_s_len; /* n_e, n_s */
|
|
|
|
|
unsigned char *key;
|
|
|
|
|
|
|
|
|
|
aes_cm_session_key_init(c);
|
|
|
|
|
|
|
|
|
|
k_e_len = c->crypto_suite->session_key_len;
|
|
|
|
|
k_s_len = c->crypto_suite->session_salt_len;
|
|
|
|
|
key = (unsigned char *) c->session_key;
|
|
|
|
|
|
|
|
|
|
/* m = k_s || 0x555..5 */
|
|
|
|
|
memcpy(m, c->session_salt, k_s_len);
|
|
|
|
|
for (i = k_s_len; i < k_e_len; i++)
|
|
|
|
|
m[i] = 0x55;
|
|
|
|
|
/* IV' = E(k_e XOR m, IV) */
|
|
|
|
|
for (i = 0; i < k_e_len; i++)
|
|
|
|
|
m[i] ^= key[i];
|
|
|
|
|
|
|
|
|
|
c->session_key_ctx[1] = g_slice_alloc(sizeof(EVP_CIPHER_CTX));
|
|
|
|
|
EVP_CIPHER_CTX_init(c->session_key_ctx[1]);
|
|
|
|
|
EVP_EncryptInit_ex(c->session_key_ctx[1], EVP_aes_128_ecb(), NULL, m, NULL);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int evp_session_key_cleanup(struct crypto_context *c) {
|
|
|
|
|
unsigned char block[16];
|
|
|
|
|
int len;
|
|
|
|
|
int len, i;
|
|
|
|
|
|
|
|
|
|
if (!c->session_key_ctx)
|
|
|
|
|
return 0;
|
|
|
|
|
for (i = 0; i < ARRAYSIZE(c->session_key_ctx); i++) {
|
|
|
|
|
if (!c->session_key_ctx[i])
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
EVP_EncryptFinal_ex(c->session_key_ctx, block, &len);
|
|
|
|
|
EVP_CIPHER_CTX_cleanup(c->session_key_ctx);
|
|
|
|
|
g_slice_free1(sizeof(EVP_CIPHER_CTX), c->session_key_ctx);
|
|
|
|
|
c->session_key_ctx = NULL;
|
|
|
|
|
EVP_EncryptFinal_ex(c->session_key_ctx[i], block, &len);
|
|
|
|
|
EVP_CIPHER_CTX_cleanup(c->session_key_ctx[i]);
|
|
|
|
|
g_slice_free1(sizeof(EVP_CIPHER_CTX), c->session_key_ctx[i]);
|
|
|
|
|
c->session_key_ctx[i] = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|