|
|
|
@ -21,6 +21,8 @@ static int aes_cm_encrypt_rtp(struct crypto_context *, struct rtp_header *, str |
|
|
|
static int aes_cm_encrypt_rtcp(struct crypto_context *, struct rtcp_packet *, str *, u_int64_t); |
|
|
|
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); |
|
|
|
|
|
|
|
/* all lengths are in bits, some code assumes everything to be multiples of 8 */ |
|
|
|
const struct crypto_suite crypto_suites[] = { |
|
|
|
@ -83,6 +85,10 @@ const struct crypto_suite crypto_suites[] = { |
|
|
|
.srtcp_auth_tag = 80, |
|
|
|
.srtp_auth_key_len = 160, |
|
|
|
.srtcp_auth_key_len = 160, |
|
|
|
.encrypt_rtp = aes_f8_encrypt_rtp, |
|
|
|
.decrypt_rtp = aes_f8_encrypt_rtp, |
|
|
|
.encrypt_rtcp = aes_f8_encrypt_rtcp, |
|
|
|
.decrypt_rtcp = aes_f8_encrypt_rtcp, |
|
|
|
.hash_rtp = hmac_sha1_rtp, |
|
|
|
.hash_rtcp = hmac_sha1_rtcp, |
|
|
|
}, |
|
|
|
@ -262,6 +268,108 @@ static int aes_cm_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r, |
|
|
|
return aes_cm_encrypt(c, r->ssrc, s, idx); |
|
|
|
} |
|
|
|
|
|
|
|
/* 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; |
|
|
|
|
|
|
|
k_e_len = c->crypto_suite->session_key_len / 8; |
|
|
|
k_s_len = c->crypto_suite->session_salt_len / 8; |
|
|
|
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); |
|
|
|
assert(outlen == 16); |
|
|
|
EVP_EncryptFinal_ex(&ecc, key_block, &outlen); |
|
|
|
EVP_CIPHER_CTX_cleanup(&ecc); |
|
|
|
|
|
|
|
p = (unsigned char *) s->s; |
|
|
|
left = s->len; |
|
|
|
j = 0; |
|
|
|
ZERO(last_key_block); |
|
|
|
|
|
|
|
EVP_CIPHER_CTX_init(&ecc); |
|
|
|
EVP_EncryptInit_ex(&ecc, EVP_aes_128_ecb(), NULL, (unsigned char *) c->session_key, NULL); |
|
|
|
|
|
|
|
while (left) { |
|
|
|
/* S(j) = E(k_e, IV' XOR j XOR S(j-1)) */ |
|
|
|
memcpy(x, ivx, 16); |
|
|
|
|
|
|
|
x[12] ^= ((j >> 24) & 0xff); |
|
|
|
x[13] ^= ((j >> 16) & 0xff); |
|
|
|
x[14] ^= ((j >> 8) & 0xff); |
|
|
|
x[15] ^= ((j >> 0) & 0xff); |
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) |
|
|
|
x[i] ^= last_key_block[i]; |
|
|
|
|
|
|
|
EVP_EncryptUpdate(&ecc, key_block, &outlen, x, 16); |
|
|
|
assert(outlen == 16); |
|
|
|
|
|
|
|
for (i = 0; i < 16; i++) { |
|
|
|
*p ^= key_block[i]; |
|
|
|
p++; |
|
|
|
left--; |
|
|
|
if (!left) |
|
|
|
goto done; |
|
|
|
} |
|
|
|
|
|
|
|
j++; |
|
|
|
memcpy(last_key_block, key_block, 16); |
|
|
|
} |
|
|
|
|
|
|
|
done: |
|
|
|
EVP_EncryptFinal_ex(&ecc, key_block, &outlen); |
|
|
|
EVP_CIPHER_CTX_cleanup(&ecc); |
|
|
|
} |
|
|
|
|
|
|
|
/* rfc 3711 section 4.1.2.2 */ |
|
|
|
static int aes_f8_encrypt_rtp(struct crypto_context *c, struct rtp_header *r, str *s, u_int64_t idx) { |
|
|
|
unsigned char iv[16]; |
|
|
|
u_int32_t roc; |
|
|
|
|
|
|
|
iv[0] = '\0'; |
|
|
|
memcpy(&iv[1], &r->m_pt, 11); /* m, pt, seq, ts, ssrc */ |
|
|
|
roc = htonl((idx & 0xffffffff0000ULL) >> 16); |
|
|
|
memcpy(&iv[12], &roc, sizeof(roc)); |
|
|
|
|
|
|
|
aes_128_f8_encrypt(c, iv, s); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* rfc 3711 section 4.1.2.3 */ |
|
|
|
static int aes_f8_encrypt_rtcp(struct crypto_context *c, struct rtcp_packet *r, str *s, u_int64_t idx) { |
|
|
|
unsigned char iv[16]; |
|
|
|
u_int32_t i; |
|
|
|
|
|
|
|
memset(iv, 0, 4); |
|
|
|
i = htonl(0x80000000ULL | idx); |
|
|
|
memcpy(&iv[4], &i, 4); |
|
|
|
memcpy(&iv[8], &r->header.v_p_x, 8); /* v, p, rc, pt, length, ssrc */ |
|
|
|
|
|
|
|
aes_128_f8_encrypt(c, iv, s); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
/* rfc 3711, sections 4.2 and 4.2.1 */ |
|
|
|
static int hmac_sha1_rtp(struct crypto_context *c, char *out, str *in, u_int64_t index) { |
|
|
|
unsigned char hmac[20]; |
|
|
|
|