Create separate SRTP and SRTCP objects for each MediaStream

This commit is contained in:
Aaro Altonen 2020-09-02 09:34:52 +03:00
parent 9cb5b9fe45
commit 85bb4c6eef
7 changed files with 88 additions and 76 deletions

View File

@ -75,14 +75,14 @@ namespace uvg_rtp {
struct {
uint8_t enc_key[AES_KEY_LENGTH];
uint8_t auth_key[AES_KEY_LENGTH];
uint8_t salt_key[SALT_LENGTH];
uint8_t salt_key[AES_KEY_LENGTH]; /* TODO: make sure this is correct */
} local;
/* Used to decrypt/Authenticate packets sent by remote */
struct {
uint8_t enc_key[AES_KEY_LENGTH];
uint8_t auth_key[AES_KEY_LENGTH];
uint8_t salt_key[SALT_LENGTH];
uint8_t salt_key[AES_KEY_LENGTH];
} remote;
} srtp_key_ctx_t;
@ -142,13 +142,7 @@ namespace uvg_rtp {
bool authenticate_rtp();
/* Get reference to the SRTP context (including session keys) */
srtp_ctx_t& get_ctx();
/* Decrypt the payload and verify authentication tag (if enabled) */
static rtp_error_t recv_packet_handler(void *arg, int flags, frame::rtp_frame **out);
/* Encrypt the payload and add authentication tag (if enabled) */
static rtp_error_t send_packet_handler(void *arg, buf_vec& buffers);
srtp_ctx_t *get_ctx();
#endif
protected:
@ -164,8 +158,8 @@ namespace uvg_rtp {
/* Internal init method that initialize the SRTP context using values in key_ctx_.master */
rtp_error_t init(int type, int flags);
#endif
srtp_ctx_t srtp_ctx_;
/* SRTP context containing all session information and keys */
srtp_ctx_t *srtp_ctx_;
/* If NULL cipher is enabled, it means that RTP packets are not
* encrypted but other security mechanisms described in RFC 3711 may be used */

View File

@ -9,6 +9,7 @@ namespace uvg_rtp {
srtp();
~srtp();
#ifdef __RTP_CRYPTO__
/* TODO: */
rtp_error_t encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer, size_t len);
@ -20,5 +21,6 @@ namespace uvg_rtp {
/* Encrypt the payload of an RTP packet and add authentication tag (if enabled) */
static rtp_error_t send_packet_handler(void *arg, buf_vec& buffers);
#endif
};
};

View File

@ -188,7 +188,7 @@ rtp_error_t uvg_rtp::media_stream::init(uvg_rtp::zrtp *zrtp)
return ret;
}
if ((srtp_ = new uvg_rtp::srtp()) == nullptr)
if (!(srtp_ = new uvg_rtp::srtp()))
return RTP_MEMORY_ERROR;
if ((ret = srtp_->init_zrtp(SRTP, ctx_config_.flags, rtp_, zrtp)) != RTP_OK) {
@ -196,8 +196,11 @@ rtp_error_t uvg_rtp::media_stream::init(uvg_rtp::zrtp *zrtp)
return ret;
}
if (!(srtcp_ = new uvg_rtp::srtcp()))
return RTP_MEMORY_ERROR;
if ((ret = srtcp_->init_zrtp(SRTCP, ctx_config_.flags, rtp_, zrtp)) != RTP_OK) {
LOG_ERROR("Failed to initialize SRTP for media stream!");
LOG_ERROR("Failed to initialize SRTCP for media stream!");
return ret;
}
@ -272,7 +275,7 @@ rtp_error_t uvg_rtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
return RTP_MEMORY_ERROR;
}
if ((srtp_ = new uvg_rtp::srtp()) == nullptr)
if (!(srtp_ = new uvg_rtp::srtp()))
return RTP_MEMORY_ERROR;
if ((ret = srtp_->init_user(SRTP, ctx_config_.flags, key, salt)) != RTP_OK) {
@ -280,6 +283,14 @@ rtp_error_t uvg_rtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
return ret;
}
if (!(srtcp_ = new uvg_rtp::srtcp()))
return RTP_MEMORY_ERROR;
if ((ret = srtcp_->init_user(SRTCP, ctx_config_.flags, key, salt)) != RTP_OK) {
LOG_WARN("Failed to initialize SRTCP for media stream!");
return ret;
}
if (!(rtcp_ = new uvg_rtp::rtcp(rtp_, srtcp_, ctx_config_.flags))) {
delete rtp_;
delete pkt_dispatcher_;

View File

@ -30,10 +30,17 @@ uvg_rtp::rtcp::rtcp(uvg_rtp::rtp *rtp, int flags):
clock_start_ = 0;
rtp_ts_start_ = 0;
runner_ = nullptr;
srtcp_ = nullptr;
zero_stats(&our_stats);
}
uvg_rtp::rtcp::rtcp(uvg_rtp::rtp *rtp, uvg_rtp::srtcp *srtcp, int flags):
rtcp(rtp, flags)
{
srtcp_ = srtcp;
}
uvg_rtp::rtcp::~rtcp()
{
}

View File

@ -9,7 +9,7 @@
#endif
uvg_rtp::base_srtp::base_srtp():
srtp_ctx_(),
srtp_ctx_(new uvg_rtp::srtp_ctx_t),
use_null_cipher_(false),
authenticate_rtp_(false)
{
@ -30,7 +30,7 @@ bool uvg_rtp::base_srtp::authenticate_rtp()
return authenticate_rtp_;
}
uvg_rtp::srtp_ctx_t& uvg_rtp::base_srtp::get_ctx()
uvg_rtp::srtp_ctx_t *uvg_rtp::base_srtp::get_ctx()
{
return srtp_ctx_;
}
@ -72,24 +72,24 @@ rtp_error_t uvg_rtp::base_srtp::create_iv(uint8_t *out, uint32_t ssrc, uint64_t
rtp_error_t uvg_rtp::base_srtp::init(int type, int flags)
{
srtp_ctx_.roc = 0;
srtp_ctx_.type = type;
srtp_ctx_.enc = AES_128;
srtp_ctx_.hmac = HMAC_SHA1;
srtp_ctx_->roc = 0;
srtp_ctx_->type = type;
srtp_ctx_->enc = AES_128;
srtp_ctx_->hmac = HMAC_SHA1;
srtp_ctx_.mki_size = 0;
srtp_ctx_.mki_present = false;
srtp_ctx_.mki = nullptr;
srtp_ctx_->mki_size = 0;
srtp_ctx_->mki_present = false;
srtp_ctx_->mki = nullptr;
srtp_ctx_.master_key = srtp_ctx_.key_ctx.master.local_key;
srtp_ctx_.master_salt = srtp_ctx_.key_ctx.master.local_salt;
srtp_ctx_.mk_cnt = 0;
srtp_ctx_->master_key = srtp_ctx_->key_ctx.master.local_key;
srtp_ctx_->master_salt = srtp_ctx_->key_ctx.master.local_salt;
srtp_ctx_->mk_cnt = 0;
srtp_ctx_.n_e = AES_KEY_LENGTH;
srtp_ctx_.n_a = HMAC_KEY_LENGTH;
srtp_ctx_->n_e = AES_KEY_LENGTH;
srtp_ctx_->n_a = HMAC_KEY_LENGTH;
srtp_ctx_.s_l = 0;
srtp_ctx_.replay = nullptr;
srtp_ctx_->s_l = 0;
srtp_ctx_->replay = nullptr;
use_null_cipher_ = !!(flags & RCE_SRTP_NULL_CIPHER);
authenticate_rtp_ = !!(flags & RCE_SRTP_AUTHENTICATE_RTP);
@ -111,46 +111,46 @@ rtp_error_t uvg_rtp::base_srtp::init(int type, int flags)
/* Local aka encryption keys */
(void)derive_key(
label_enc,
srtp_ctx_.key_ctx.master.local_key,
srtp_ctx_.key_ctx.master.local_salt,
srtp_ctx_.key_ctx.local.enc_key,
srtp_ctx_->key_ctx.master.local_key,
srtp_ctx_->key_ctx.master.local_salt,
srtp_ctx_->key_ctx.local.enc_key,
AES_KEY_LENGTH
);
(void)derive_key(
label_auth,
srtp_ctx_.key_ctx.master.local_key,
srtp_ctx_.key_ctx.master.local_salt,
srtp_ctx_.key_ctx.local.auth_key,
srtp_ctx_->key_ctx.master.local_key,
srtp_ctx_->key_ctx.master.local_salt,
srtp_ctx_->key_ctx.local.auth_key,
AES_KEY_LENGTH
);
(void)derive_key(
label_salt,
srtp_ctx_.key_ctx.master.local_key,
srtp_ctx_.key_ctx.master.local_salt,
srtp_ctx_.key_ctx.local.salt_key,
srtp_ctx_->key_ctx.master.local_key,
srtp_ctx_->key_ctx.master.local_salt,
srtp_ctx_->key_ctx.local.salt_key,
SALT_LENGTH
);
/* Remote aka decryption keys */
(void)derive_key(
label_enc,
srtp_ctx_.key_ctx.master.remote_key,
srtp_ctx_.key_ctx.master.remote_salt,
srtp_ctx_.key_ctx.remote.enc_key,
srtp_ctx_->key_ctx.master.remote_key,
srtp_ctx_->key_ctx.master.remote_salt,
srtp_ctx_->key_ctx.remote.enc_key,
AES_KEY_LENGTH
);
(void)derive_key(
label_auth,
srtp_ctx_.key_ctx.master.remote_key,
srtp_ctx_.key_ctx.master.remote_salt,
srtp_ctx_.key_ctx.remote.auth_key,
srtp_ctx_->key_ctx.master.remote_key,
srtp_ctx_->key_ctx.master.remote_salt,
srtp_ctx_->key_ctx.remote.auth_key,
AES_KEY_LENGTH
);
(void)derive_key(
label_salt,
srtp_ctx_.key_ctx.master.remote_key,
srtp_ctx_.key_ctx.master.remote_salt,
srtp_ctx_.key_ctx.remote.salt_key,
srtp_ctx_->key_ctx.master.remote_key,
srtp_ctx_->key_ctx.master.remote_salt,
srtp_ctx_->key_ctx.remote.salt_key,
SALT_LENGTH
);
@ -166,10 +166,10 @@ rtp_error_t uvg_rtp::base_srtp::init_zrtp(int type, int flags, uvg_rtp::rtp *rtp
/* ZRTP key derivation function expects the keys lengths to be given in bits */
rtp_error_t ret = zrtp->get_srtp_keys(
srtp_ctx_.key_ctx.master.local_key, AES_KEY_LENGTH * 8,
srtp_ctx_.key_ctx.master.remote_key, AES_KEY_LENGTH * 8,
srtp_ctx_.key_ctx.master.local_salt, SALT_LENGTH * 8,
srtp_ctx_.key_ctx.master.remote_salt, SALT_LENGTH * 8
srtp_ctx_->key_ctx.master.local_key, AES_KEY_LENGTH * 8,
srtp_ctx_->key_ctx.master.remote_key, AES_KEY_LENGTH * 8,
srtp_ctx_->key_ctx.master.local_salt, SALT_LENGTH * 8,
srtp_ctx_->key_ctx.master.remote_salt, SALT_LENGTH * 8
);
if (ret != RTP_OK) {
@ -185,12 +185,11 @@ rtp_error_t uvg_rtp::base_srtp::init_user(int type, int flags, uint8_t *key, uin
if (!key || !salt)
return RTP_INVALID_VALUE;
memcpy(srtp_ctx_.key_ctx.master.local_key, key, AES_KEY_LENGTH);
memcpy(srtp_ctx_.key_ctx.master.remote_key, key, AES_KEY_LENGTH);
memcpy(srtp_ctx_.key_ctx.master.local_salt, salt, SALT_LENGTH);
memcpy(srtp_ctx_.key_ctx.master.remote_salt, salt, SALT_LENGTH);
memcpy(srtp_ctx_->key_ctx.master.local_key, key, AES_KEY_LENGTH);
memcpy(srtp_ctx_->key_ctx.master.remote_key, key, AES_KEY_LENGTH);
memcpy(srtp_ctx_->key_ctx.master.local_salt, salt, SALT_LENGTH);
memcpy(srtp_ctx_->key_ctx.master.remote_salt, salt, SALT_LENGTH);
/* TODO: why srtp keys are derived using zrtp kdf? */
return init(type, flags);
}
#endif

View File

@ -24,12 +24,12 @@ rtp_error_t uvg_rtp::srtcp::encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer
uint8_t iv[16] = { 0 };
if (create_iv(iv, ssrc, seq, srtp_ctx_.key_ctx.local.salt_key) != RTP_OK) {
if (create_iv(iv, ssrc, seq, srtp_ctx_->key_ctx.local.salt_key) != RTP_OK) {
LOG_ERROR("Failed to create IV, unable to encrypt the RTP packet!");
return RTP_INVALID_VALUE;
}
uvg_rtp::crypto::aes::ctr ctr(srtp_ctx_.key_ctx.local.enc_key, sizeof(srtp_ctx_.key_ctx.local.enc_key), iv);
uvg_rtp::crypto::aes::ctr ctr(srtp_ctx_->key_ctx.local.enc_key, sizeof(srtp_ctx_->key_ctx.local.enc_key), iv);
ctr.encrypt(buffer, buffer, len);
return RTP_OK;
@ -40,16 +40,16 @@ rtp_error_t uvg_rtp::srtcp::decrypt(uint32_t ssrc, uint32_t seq, uint8_t *buffer
uint8_t iv[16] = { 0 };
uint64_t digest = 0;
if (create_iv(iv, ssrc, seq, srtp_ctx_.key_ctx.remote.salt_key) != RTP_OK) {
if (create_iv(iv, ssrc, seq, srtp_ctx_->key_ctx.remote.salt_key) != RTP_OK) {
LOG_ERROR("Failed to create IV, unable to encrypt the RTP packet!");
return RTP_INVALID_VALUE;
}
uvg_rtp::crypto::aes::ctr ctr(srtp_ctx_.key_ctx.remote.enc_key, sizeof(srtp_ctx_.key_ctx.remote.enc_key), iv);
uvg_rtp::crypto::aes::ctr ctr(srtp_ctx_->key_ctx.remote.enc_key, sizeof(srtp_ctx_->key_ctx.remote.enc_key), iv);
/* ... otherwise calculate authentication tag for the packet
* and compare it against the one we received */
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(srtp_ctx_.key_ctx.remote.auth_key, AES_KEY_LENGTH);
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(srtp_ctx_->key_ctx.remote.auth_key, AES_KEY_LENGTH);
hmac_sha1.update(buffer, size - AUTH_TAG_LENGTH - SRTCP_INDEX_LENGTH);
hmac_sha1.final((uint8_t *)&digest);

View File

@ -1,7 +1,6 @@
#include <cstring>
#include <iostream>
/* #include "srtp.hh" */
#include "srtp/base.hh"
#include "srtp/srtp.hh"
@ -25,18 +24,18 @@ rtp_error_t uvg_rtp::srtp::encrypt(uint32_t ssrc, uint16_t seq, uint8_t *buffer,
return RTP_OK;
uint8_t iv[16] = { 0 };
uint64_t index = (((uint64_t)srtp_ctx_.roc) << 16) + seq;
uint64_t index = (((uint64_t)srtp_ctx_->roc) << 16) + seq;
/* Sequence number has wrapped around, update Roll-over Counter */
if (seq == 0xffff)
srtp_ctx_.roc++;
srtp_ctx_->roc++;
if (create_iv(iv, ssrc, index, srtp_ctx_.key_ctx.local.salt_key) != RTP_OK) {
if (create_iv(iv, ssrc, index, srtp_ctx_->key_ctx.local.salt_key) != RTP_OK) {
LOG_ERROR("Failed to create IV, unable to encrypt the RTP packet!");
return RTP_INVALID_VALUE;
}
uvg_rtp::crypto::aes::ctr ctr(srtp_ctx_.key_ctx.local.enc_key, sizeof(srtp_ctx_.key_ctx.local.enc_key), iv);
uvg_rtp::crypto::aes::ctr ctr(srtp_ctx_->key_ctx.local.enc_key, sizeof(srtp_ctx_->key_ctx.local.enc_key), iv);
ctr.encrypt(buffer, buffer, len);
return RTP_OK;
@ -47,7 +46,7 @@ rtp_error_t uvg_rtp::srtp::recv_packet_handler(void *arg, int flags, frame::rtp_
(void)flags;
uvg_rtp::srtp *srtp = (uvg_rtp::srtp *)arg;
uvg_rtp::srtp_ctx_t ctx = srtp->get_ctx();
uvg_rtp::srtp_ctx_t *ctx = srtp->get_ctx();
uvg_rtp::frame::rtp_frame *frame = *out;
if (srtp->use_null_cipher())
@ -56,19 +55,19 @@ rtp_error_t uvg_rtp::srtp::recv_packet_handler(void *arg, int flags, frame::rtp_
uint8_t iv[16] = { 0 };
uint16_t seq = frame->header.seq;
uint32_t ssrc = frame->header.ssrc;
uint64_t index = (((uint64_t)ctx.roc) << 16) + seq;
uint64_t index = (((uint64_t)ctx->roc) << 16) + seq;
uint64_t digest = 0;
/* Sequence number has wrapped around, update Roll-over Counter */
if (seq == 0xffff)
ctx.roc++;
ctx->roc++;
if (srtp->create_iv(iv, ssrc, index, ctx.key_ctx.remote.salt_key) != RTP_OK) {
if (srtp->create_iv(iv, ssrc, index, ctx->key_ctx.remote.salt_key) != RTP_OK) {
LOG_ERROR("Failed to create IV, unable to encrypt the RTP packet!");
return RTP_INVALID_VALUE;
}
uvg_rtp::crypto::aes::ctr ctr(ctx.key_ctx.remote.enc_key, sizeof(ctx.key_ctx.remote.enc_key), iv);
uvg_rtp::crypto::aes::ctr ctr(ctx->key_ctx.remote.enc_key, sizeof(ctx->key_ctx.remote.enc_key), iv);
/* exit early if RTP packet authentication is disabled... */
if (!srtp->authenticate_rtp()) {
@ -78,10 +77,10 @@ rtp_error_t uvg_rtp::srtp::recv_packet_handler(void *arg, int flags, frame::rtp_
/* ... otherwise calculate authentication tag for the packet
* and compare it against the one we received */
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(ctx.key_ctx.remote.auth_key, AES_KEY_LENGTH);
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(ctx->key_ctx.remote.auth_key, AES_KEY_LENGTH);
hmac_sha1.update((uint8_t *)frame, frame->payload_len - AUTH_TAG_LENGTH);
hmac_sha1.update((uint8_t *)&ctx.roc, sizeof(ctx.roc));
hmac_sha1.update((uint8_t *)&ctx->roc, sizeof(ctx->roc));
hmac_sha1.final((uint8_t *)&digest);
if (memcmp(&digest, &frame[frame->payload_len - AUTH_TAG_LENGTH], AUTH_TAG_LENGTH)) {
@ -122,12 +121,12 @@ rtp_error_t uvg_rtp::srtp::send_packet_handler(void *arg, uvg_rtp::buf_vec& buff
return RTP_OK;
/* create authentication tag for the packet and push it to the vector buffer */
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(ctx.key_ctx.local.auth_key, AES_KEY_LENGTH);
auto hmac_sha1 = uvg_rtp::crypto::hmac::sha1(ctx->key_ctx.local.auth_key, AES_KEY_LENGTH);
for (size_t i = 0; i < buffers.size() - 1; ++i)
hmac_sha1.update((uint8_t *)buffers[i].second, buffers[i].first);
hmac_sha1.update((uint8_t *)&ctx.roc, sizeof(ctx.roc));
hmac_sha1.update((uint8_t *)&ctx->roc, sizeof(ctx->roc));
hmac_sha1.final((uint8_t *)buffers[buffers.size() - 1].second);
return ret;