|
|
|
|
@ -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];
|
|
|
|
|
|