ZLMediaKit/webrtc/SrtpSession.cpp

311 lines
8.9 KiB
C++
Raw Normal View History

2021-04-06 17:23:13 +08:00
#define MS_CLASS "RTC::SrtpSession"
2021-03-24 16:52:41 +08:00
// #define MS_LOG_DEV_LEVEL 3
2021-03-27 09:13:10 +08:00
#include "SrtpSession.hpp"
2021-03-26 11:07:03 +08:00
#include <cstring> // std::memset(), std::memcpy()
2021-03-24 16:52:41 +08:00
#include "logger.h"
2021-03-27 09:38:13 +08:00
#include "Util/util.h"
2021-03-27 23:42:44 +08:00
#include "Util/logger.h"
2021-03-27 09:38:13 +08:00
using namespace toolkit;
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
namespace RTC
{
/* Static. */
2021-03-27 09:38:13 +08:00
static std::vector<const char *> errors = {
2021-03-26 11:07:03 +08:00
// From 0 (srtp_err_status_ok) to 24 (srtp_err_status_pfkey_err).
"success (srtp_err_status_ok)",
"unspecified failure (srtp_err_status_fail)",
"unsupported parameter (srtp_err_status_bad_param)",
"couldn't allocate memory (srtp_err_status_alloc_fail)",
"couldn't deallocate memory (srtp_err_status_dealloc_fail)",
"couldn't initialize (srtp_err_status_init_fail)",
"cant process as much data as requested (srtp_err_status_terminus)",
"authentication failure (srtp_err_status_auth_fail)",
"cipher failure (srtp_err_status_cipher_fail)",
"replay check failed (bad index) (srtp_err_status_replay_fail)",
"replay check failed (index too old) (srtp_err_status_replay_old)",
"algorithm failed test routine (srtp_err_status_algo_fail)",
"unsupported operation (srtp_err_status_no_such_op)",
"no appropriate context found (srtp_err_status_no_ctx)",
"unable to perform desired validation (srtp_err_status_cant_check)",
"cant use key any more (srtp_err_status_key_expired)",
"error in use of socket (srtp_err_status_socket_err)",
"error in use POSIX signals (srtp_err_status_signal_err)",
"nonce check failed (srtp_err_status_nonce_bad)",
"couldnt read data (srtp_err_status_read_fail)",
"couldnt write data (srtp_err_status_write_fail)",
"error parsing data (srtp_err_status_parse_err)",
"error encoding data (srtp_err_status_encode_err)",
"error while using semaphores (srtp_err_status_semaphore_err)",
"error while using pfkey (srtp_err_status_pfkey_err)"};
2021-03-24 16:52:41 +08:00
// clang-format on
/* Static methods. */
2021-03-27 09:38:13 +08:00
const char *DepLibSRTP::GetErrorString(srtp_err_status_t code) {
// This throws out_of_range if the given index is not in the vector.
return errors.at(code);
}
bool DepLibSRTP::IsError(srtp_err_status_t code) {
return (code != srtp_err_status_ok);
}
INSTANCE_IMP(DepLibSRTP);
DepLibSRTP::DepLibSRTP(){
2021-03-26 11:07:03 +08:00
MS_TRACE();
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
MS_DEBUG_TAG(info, "libsrtp version: \"%s\"", srtp_get_version_string());
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
srtp_err_status_t err = srtp_init();
2021-03-24 16:52:41 +08:00
2021-03-27 23:42:44 +08:00
#if 0
srtp_install_log_handler([](srtp_log_level_t level,
const char *msg,
void *data) {
printf("%s\n", msg);
}, nullptr);
srtp_set_debug_module("srtp", 1);
srtp_set_debug_module("hmac sha-1", 1);
srtp_set_debug_module("aes icm", 1);
srtp_set_debug_module("alloc", 1);
srtp_set_debug_module("stat test", 1);
srtp_set_debug_module("cipher", 1);
srtp_set_debug_module("auth func", 1);
srtp_set_debug_module("crypto kernel", 1);
srtp_list_debug_modules();
#endif
2021-03-27 09:38:13 +08:00
if (DepLibSRTP::IsError(err)) {
2021-03-26 11:07:03 +08:00
MS_THROW_ERROR("srtp_init() failed: %s", DepLibSRTP::GetErrorString(err));
2021-03-27 09:38:13 +08:00
}
// Set libsrtp event handler.
err = srtp_install_event_handler([](srtp_event_data_t *data){
MS_TRACE();
switch (data->event)
{
case event_ssrc_collision:
MS_WARN_TAG(srtp, "SSRC collision occurred");
break;
case event_key_soft_limit:
MS_WARN_TAG(srtp, "stream reached the soft key usage limit and will expire soon");
break;
case event_key_hard_limit:
MS_WARN_TAG(srtp, "stream reached the hard key usage limit and has expired");
break;
case event_packet_index_limit:
MS_WARN_TAG(srtp, "stream reached the hard packet limit (2^48 packets)");
break;
}
});
if (DepLibSRTP::IsError(err))
{
MS_THROW_ERROR("srtp_install_event_handler() failed: %s", DepLibSRTP::GetErrorString(err));
}
2021-03-24 16:52:41 +08:00
}
2021-03-27 09:38:13 +08:00
DepLibSRTP::~DepLibSRTP(){
2021-03-26 11:07:03 +08:00
MS_TRACE();
srtp_shutdown();
2021-03-24 16:52:41 +08:00
}
2021-03-27 09:38:13 +08:00
/////////////////////////////////////////////////////////////////////////////////////
2021-03-26 11:07:03 +08:00
/* Instance methods. */
SrtpSession::SrtpSession(Type type, CryptoSuite cryptoSuite, uint8_t* key, size_t keyLen)
{
2021-03-27 09:38:13 +08:00
_env = DepLibSRTP::Instance().shared_from_this();
2021-03-26 11:07:03 +08:00
MS_TRACE();
srtp_policy_t policy; // NOLINT(cppcoreguidelines-pro-type-member-init)
// Set all policy fields to 0.
std::memset(&policy, 0, sizeof(srtp_policy_t));
switch (cryptoSuite)
{
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.rtcp);
break;
}
case CryptoSuite::AES_CM_128_HMAC_SHA1_32:
{
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
// NOTE: Must be 80 for RTCP.
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
break;
}
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.rtcp);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
break;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
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.rtcp);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
break;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
default:
{
MS_ABORT("unknown SRTP crypto suite");
}
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
MS_ASSERT(
(int)keyLen == policy.rtp.cipher_key_len,
"given keyLen does not match policy.rtp.cipher_keyLen");
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
switch (type)
{
case Type::INBOUND:
policy.ssrc.type = ssrc_any_inbound;
break;
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
case Type::OUTBOUND:
policy.ssrc.type = ssrc_any_outbound;
break;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
policy.ssrc.value = 0;
policy.key = key;
// Required for sending RTP retransmission without RTX.
policy.allow_repeat_tx = 1;
policy.window_size = 1024;
policy.next = nullptr;
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
// Set the SRTP session.
srtp_err_status_t err = srtp_create(&this->session, &policy);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
if (DepLibSRTP::IsError(err))
MS_THROW_ERROR("srtp_create() failed: %s", DepLibSRTP::GetErrorString(err));
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
SrtpSession::~SrtpSession()
{
MS_TRACE();
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
if (this->session != nullptr)
{
srtp_err_status_t err = srtp_dealloc(this->session);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
if (DepLibSRTP::IsError(err))
MS_ABORT("srtp_dealloc() failed: %s", DepLibSRTP::GetErrorString(err));
}
}
2021-03-24 16:52:41 +08:00
bool SrtpSession::EncryptRtp(const uint8_t** data, size_t* len, uint8_t pt)
2021-03-26 11:07:03 +08:00
{
MS_TRACE();
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
// Ensure that the resulting SRTP packet fits into the encrypt buffer.
if (*len + SRTP_MAX_TRAILER_LEN > EncryptBufferSize)
{
MS_WARN_TAG(srtp, "cannot encrypt RTP packet, size too big (%zu bytes)", *len);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return false;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
std::memcpy(EncryptBuffer, *data, *len);
EncryptBuffer[1] |= (pt & 0x7F);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
srtp_err_status_t err =
srtp_protect(this->session, static_cast<void*>(EncryptBuffer), reinterpret_cast<int*>(len));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
if (DepLibSRTP::IsError(err))
{
MS_WARN_TAG(srtp, "srtp_protect() failed: %s", DepLibSRTP::GetErrorString(err));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return false;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
// Update the given data pointer.
*data = (const uint8_t*)EncryptBuffer;
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return true;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
bool SrtpSession::DecryptSrtp(uint8_t* data, size_t* len)
{
MS_TRACE();
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
srtp_err_status_t err =
srtp_unprotect(this->session, static_cast<void*>(data), reinterpret_cast<int*>(len));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
if (DepLibSRTP::IsError(err))
{
MS_DEBUG_TAG(srtp, "srtp_unprotect() failed: %s", DepLibSRTP::GetErrorString(err));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return false;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return true;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
bool SrtpSession::EncryptRtcp(const uint8_t** data, size_t* len)
{
MS_TRACE();
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
// Ensure that the resulting SRTCP packet fits into the encrypt buffer.
if (*len + SRTP_MAX_TRAILER_LEN > EncryptBufferSize)
{
MS_WARN_TAG(srtp, "cannot encrypt RTCP packet, size too big (%zu bytes)", *len);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return false;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
std::memcpy(EncryptBuffer, *data, *len);
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
srtp_err_status_t err = srtp_protect_rtcp(
this->session, static_cast<void*>(EncryptBuffer), reinterpret_cast<int*>(len));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
if (DepLibSRTP::IsError(err))
{
MS_WARN_TAG(srtp, "srtp_protect_rtcp() failed: %s", DepLibSRTP::GetErrorString(err));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return false;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
// Update the given data pointer.
*data = (const uint8_t*)EncryptBuffer;
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return true;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
bool SrtpSession::DecryptSrtcp(uint8_t* data, size_t* len)
{
MS_TRACE();
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
srtp_err_status_t err =
srtp_unprotect_rtcp(this->session, static_cast<void*>(data), reinterpret_cast<int*>(len));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
if (DepLibSRTP::IsError(err))
{
MS_DEBUG_TAG(srtp, "srtp_unprotect_rtcp() failed: %s", DepLibSRTP::GetErrorString(err));
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return false;
}
2021-03-24 16:52:41 +08:00
2021-03-26 11:07:03 +08:00
return true;
}
} // namespace RTC