避免对外传递 srtp 依赖

This commit is contained in:
Xiaofeng Wang 2022-07-26 00:04:03 +08:00
parent 388bf71813
commit 0fc38bbadb
3 changed files with 251 additions and 270 deletions

View File

@ -20,18 +20,23 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// #define MS_LOG_DEV_LEVEL 3 // #define MS_LOG_DEV_LEVEL 3
#include "SrtpSession.hpp" #include "SrtpSession.hpp"
#include <cstring> // std::memset(), std::memcpy()
#include "logger.h"
#include "Util/util.h"
#include "Util/logger.h" #include "Util/logger.h"
#include "Util/util.h"
#include "logger.h"
#include <srtp2/srtp.h>
#include <cstring> // std::memset(), std::memcpy()
#include <vector>
using namespace toolkit; using namespace toolkit;
namespace RTC namespace RTC {
{
/* Static. */
static std::vector<const char *> errors = { /* Static. */
static std::vector<const char *> errors = {
// From 0 (srtp_err_status_ok) to 24 (srtp_err_status_pfkey_err). // From 0 (srtp_err_status_ok) to 24 (srtp_err_status_pfkey_err).
"success (srtp_err_status_ok)", "success (srtp_err_status_ok)",
"unspecified failure (srtp_err_status_fail)", "unspecified failure (srtp_err_status_fail)",
@ -57,23 +62,36 @@ namespace RTC
"error parsing data (srtp_err_status_parse_err)", "error parsing data (srtp_err_status_parse_err)",
"error encoding data (srtp_err_status_encode_err)", "error encoding data (srtp_err_status_encode_err)",
"error while using semaphores (srtp_err_status_semaphore_err)", "error while using semaphores (srtp_err_status_semaphore_err)",
"error while using pfkey (srtp_err_status_pfkey_err)"}; "error while using pfkey (srtp_err_status_pfkey_err)"
// clang-format on };
/* Static methods. */ /* Static methods. */
const char *DepLibSRTP::GetErrorString(srtp_err_status_t code) { class DepLibSRTP : public std::enable_shared_from_this<DepLibSRTP> {
public:
using Ptr = std::shared_ptr<DepLibSRTP>;
~DepLibSRTP();
static bool IsError(srtp_err_status_t code);
static const char *GetErrorString(srtp_err_status_t code);
static DepLibSRTP &Instance();
private:
DepLibSRTP();
};
const char *DepLibSRTP::GetErrorString(srtp_err_status_t code) {
// This throws out_of_range if the given index is not in the vector. // This throws out_of_range if the given index is not in the vector.
return errors.at(code); return errors.at(code);
} }
bool DepLibSRTP::IsError(srtp_err_status_t code) { bool DepLibSRTP::IsError(srtp_err_status_t code) {
return (code != srtp_err_status_ok); return (code != srtp_err_status_ok);
} }
INSTANCE_IMP(DepLibSRTP); INSTANCE_IMP(DepLibSRTP);
DepLibSRTP::DepLibSRTP(){ DepLibSRTP::DepLibSRTP() {
MS_TRACE(); MS_TRACE();
MS_DEBUG_TAG(info, "libsrtp version: \"%s\"", srtp_get_version_string()); MS_DEBUG_TAG(info, "libsrtp version: \"%s\"", srtp_get_version_string());
@ -102,10 +120,9 @@ namespace RTC
} }
// Set libsrtp event handler. // Set libsrtp event handler.
err = srtp_install_event_handler([](srtp_event_data_t *data){ err = srtp_install_event_handler([](srtp_event_data_t *data) {
MS_TRACE(); MS_TRACE();
switch (data->event) switch (data->event) {
{
case event_ssrc_collision: case event_ssrc_collision:
MS_WARN_TAG(srtp, "SSRC collision occurred"); MS_WARN_TAG(srtp, "SSRC collision occurred");
break; break;
@ -124,23 +141,21 @@ namespace RTC
} }
}); });
if (DepLibSRTP::IsError(err)) if (DepLibSRTP::IsError(err)) {
{
MS_THROW_ERROR("srtp_install_event_handler() failed: %s", DepLibSRTP::GetErrorString(err)); MS_THROW_ERROR("srtp_install_event_handler() failed: %s", DepLibSRTP::GetErrorString(err));
} }
} }
DepLibSRTP::~DepLibSRTP(){ DepLibSRTP::~DepLibSRTP() {
MS_TRACE(); MS_TRACE();
srtp_shutdown(); srtp_shutdown();
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
/* Instance methods. */ /* Instance methods. */
SrtpSession::SrtpSession(Type type, CryptoSuite cryptoSuite, uint8_t* key, size_t keyLen) SrtpSession::SrtpSession(Type type, CryptoSuite cryptoSuite, uint8_t *key, size_t keyLen) {
{
_env = DepLibSRTP::Instance().shared_from_this(); _env = DepLibSRTP::Instance().shared_from_this();
MS_TRACE(); MS_TRACE();
@ -149,18 +164,15 @@ namespace RTC
// Set all policy fields to 0. // Set all policy fields to 0.
std::memset(&policy, 0, sizeof(srtp_policy_t)); std::memset(&policy, 0, sizeof(srtp_policy_t));
switch (cryptoSuite) switch (cryptoSuite) {
{ case CryptoSuite::AES_CM_128_HMAC_SHA1_80: {
case CryptoSuite::AES_CM_128_HMAC_SHA1_80:
{
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
break; break;
} }
case CryptoSuite::AES_CM_128_HMAC_SHA1_32: case CryptoSuite::AES_CM_128_HMAC_SHA1_32: {
{
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
// NOTE: Must be 80 for RTCP. // NOTE: Must be 80 for RTCP.
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
@ -168,34 +180,28 @@ namespace RTC
break; break;
} }
case CryptoSuite::AEAD_AES_256_GCM: case CryptoSuite::AEAD_AES_256_GCM: {
{
srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp); srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp);
break; break;
} }
case CryptoSuite::AEAD_AES_128_GCM: case CryptoSuite::AEAD_AES_128_GCM: {
{
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp);
break; break;
} }
default: default: {
{
MS_ABORT("unknown SRTP crypto suite"); MS_ABORT("unknown SRTP crypto suite");
} }
} }
MS_ASSERT( MS_ASSERT((int)keyLen == policy.rtp.cipher_key_len, "given keyLen does not match policy.rtp.cipher_keyLen");
(int)keyLen == policy.rtp.cipher_key_len,
"given keyLen does not match policy.rtp.cipher_keyLen");
switch (type) switch (type) {
{
case Type::INBOUND: case Type::INBOUND:
policy.ssrc.type = ssrc_any_inbound; policy.ssrc.type = ssrc_any_inbound;
break; break;
@ -217,80 +223,71 @@ namespace RTC
if (DepLibSRTP::IsError(err)) if (DepLibSRTP::IsError(err))
MS_THROW_ERROR("srtp_create() failed: %s", DepLibSRTP::GetErrorString(err)); MS_THROW_ERROR("srtp_create() failed: %s", DepLibSRTP::GetErrorString(err));
} }
SrtpSession::~SrtpSession() SrtpSession::~SrtpSession() {
{
MS_TRACE(); MS_TRACE();
if (this->session != nullptr) if (this->session != nullptr) {
{
srtp_err_status_t err = srtp_dealloc(this->session); srtp_err_status_t err = srtp_dealloc(this->session);
if (DepLibSRTP::IsError(err)) if (DepLibSRTP::IsError(err))
MS_ABORT("srtp_dealloc() failed: %s", DepLibSRTP::GetErrorString(err)); MS_ABORT("srtp_dealloc() failed: %s", DepLibSRTP::GetErrorString(err));
} }
} }
bool SrtpSession::EncryptRtp(uint8_t* data, int* len) bool SrtpSession::EncryptRtp(uint8_t *data, int *len) {
{
MS_TRACE(); MS_TRACE();
srtp_err_status_t err = srtp_err_status_t err = srtp_protect(this->session, static_cast<void *>(data), reinterpret_cast<int *>(len));
srtp_protect(this->session, static_cast<void*>(data), reinterpret_cast<int*>(len));
if (DepLibSRTP::IsError(err)) if (DepLibSRTP::IsError(err)) {
{
WarnL << "srtp_protect() failed:" << DepLibSRTP::GetErrorString(err); WarnL << "srtp_protect() failed:" << DepLibSRTP::GetErrorString(err);
return false; return false;
} }
return true; return true;
} }
bool SrtpSession::DecryptSrtp(uint8_t* data, int* len) bool SrtpSession::DecryptSrtp(uint8_t *data, int *len) {
{
MS_TRACE(); MS_TRACE();
srtp_err_status_t err = srtp_err_status_t err = srtp_unprotect(this->session, static_cast<void *>(data), reinterpret_cast<int *>(len));
srtp_unprotect(this->session, static_cast<void*>(data), reinterpret_cast<int*>(len));
if (DepLibSRTP::IsError(err)) if (DepLibSRTP::IsError(err)) {
{
WarnL << "srtp_unprotect() failed:" << DepLibSRTP::GetErrorString(err); WarnL << "srtp_unprotect() failed:" << DepLibSRTP::GetErrorString(err);
return false; return false;
} }
return true; return true;
} }
bool SrtpSession::EncryptRtcp(uint8_t* data, int* len) bool SrtpSession::EncryptRtcp(uint8_t *data, int *len) {
{
MS_TRACE(); MS_TRACE();
srtp_err_status_t err = srtp_protect_rtcp( srtp_err_status_t err = srtp_protect_rtcp(this->session, static_cast<void *>(data), reinterpret_cast<int *>(len));
this->session, static_cast<void*>(data), reinterpret_cast<int*>(len));
if (DepLibSRTP::IsError(err)) if (DepLibSRTP::IsError(err)) {
{
WarnL << "srtp_protect_rtcp() failed:" << DepLibSRTP::GetErrorString(err); WarnL << "srtp_protect_rtcp() failed:" << DepLibSRTP::GetErrorString(err);
return false; return false;
} }
return true; return true;
} }
bool SrtpSession::DecryptSrtcp(uint8_t* data, int* len) bool SrtpSession::DecryptSrtcp(uint8_t *data, int *len) {
{
MS_TRACE(); MS_TRACE();
srtp_err_status_t err = srtp_err_status_t err = srtp_unprotect_rtcp(this->session, static_cast<void *>(data), reinterpret_cast<int *>(len));
srtp_unprotect_rtcp(this->session, static_cast<void*>(data), reinterpret_cast<int*>(len));
if (DepLibSRTP::IsError(err)) if (DepLibSRTP::IsError(err)) {
{
WarnL << "srtp_unprotect_rtcp() failed:" << DepLibSRTP::GetErrorString(err); WarnL << "srtp_unprotect_rtcp() failed:" << DepLibSRTP::GetErrorString(err);
return false; return false;
} }
return true; return true;
} }
void SrtpSession::RemoveStream(uint32_t ssrc) {
srtp_remove_stream(this->session, uint32_t { htonl(ssrc) });
}
} // namespace RTC } // namespace RTC

View File

@ -20,31 +20,18 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define MS_RTC_SRTP_SESSION_HPP #define MS_RTC_SRTP_SESSION_HPP
#include "Utils.hpp" #include "Utils.hpp"
#include <srtp2/srtp.h>
#include <vector>
#include <memory> #include <memory>
namespace RTC typedef struct srtp_ctx_t_ *srtp_t;
{
class DepLibSRTP : public std::enable_shared_from_this<DepLibSRTP>
{
public:
using Ptr = std::shared_ptr<DepLibSRTP>;
~DepLibSRTP();
static bool IsError(srtp_err_status_t code); namespace RTC {
static const char *GetErrorString(srtp_err_status_t code);
static DepLibSRTP &Instance();
private: class DepLibSRTP;
DepLibSRTP();
};
class SrtpSession class SrtpSession {
{ public:
public: enum class CryptoSuite {
enum class CryptoSuite
{
NONE = 0, NONE = 0,
AES_CM_128_HMAC_SHA1_80 = 1, AES_CM_128_HMAC_SHA1_80 = 1,
AES_CM_128_HMAC_SHA1_32, AES_CM_128_HMAC_SHA1_32,
@ -52,32 +39,26 @@ namespace RTC
AEAD_AES_128_GCM AEAD_AES_128_GCM
}; };
public: public:
enum class Type enum class Type { INBOUND = 1, OUTBOUND };
{
INBOUND = 1,
OUTBOUND
};
public: public:
SrtpSession(Type type, CryptoSuite cryptoSuite, uint8_t* key, size_t keyLen); SrtpSession(Type type, CryptoSuite cryptoSuite, uint8_t *key, size_t keyLen);
~SrtpSession(); ~SrtpSession();
public: public:
bool EncryptRtp(uint8_t* data, int* len); bool EncryptRtp(uint8_t *data, int *len);
bool DecryptSrtp(uint8_t* data, int* len); bool DecryptSrtp(uint8_t *data, int *len);
bool EncryptRtcp(uint8_t* data, int* len); bool EncryptRtcp(uint8_t *data, int *len);
bool DecryptSrtcp(uint8_t* data, int* len); bool DecryptSrtcp(uint8_t *data, int *len);
void RemoveStream(uint32_t ssrc) void RemoveStream(uint32_t ssrc);
{
srtp_remove_stream(this->session, uint32_t{ htonl(ssrc) });
}
private: private:
// Allocated by this. // Allocated by this.
srtp_t session{ nullptr }; srtp_t session { nullptr };
DepLibSRTP::Ptr _env; std::shared_ptr<DepLibSRTP> _env;
}; };
} // namespace RTC } // namespace RTC
#endif #endif

View File

@ -13,6 +13,9 @@
#include "Rtcp/RtcpFCI.h" #include "Rtcp/RtcpFCI.h"
#include "RtpExt.h" #include "RtpExt.h"
#include "Rtsp/RtpReceiver.h" #include "Rtsp/RtpReceiver.h"
#include <srtp2/srtp.h>
#include <iostream> #include <iostream>
#define RTP_SSRC_OFFSET 1 #define RTP_SSRC_OFFSET 1