Skip to content

Commit

Permalink
SRTP keying material を取得できるようにする
Browse files Browse the repository at this point in the history
  • Loading branch information
melpon committed Nov 19, 2023
1 parent a8c78cf commit 507ecd9
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ target_sources(sora
src/sora_signaling.cpp
src/sora_video_decoder_factory.cpp
src/sora_video_encoder_factory.cpp
src/srtp_keying_material_exporter.cpp
src/ssl_verifier.cpp
src/url_parts.cpp
src/version.cpp
Expand Down
1 change: 1 addition & 0 deletions include/sora/sora_signaling.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ class SoraSignaling : public std::enable_shared_from_this<SoraSignaling>,
std::lock_guard<std::mutex> lock(m);
this->s = s;
}

private:
std::string s;
mutable std::mutex m;
Expand Down
24 changes: 24 additions & 0 deletions include/sora/srtp_keying_material_exporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef SORA_SRTP_KEYING_MATERIAL_EXPORTER_H_
#define SORA_SRTP_KEYING_MATERIAL_EXPORTER_H_

#include <string>

#include <absl/types/optional.h>
#include <api/peer_connection_interface.h>

namespace sora {

struct KeyingMaterial {
std::vector<uint8_t> client_write_key;
std::vector<uint8_t> server_write_key;
std::vector<uint8_t> client_write_salt;
std::vector<uint8_t> server_write_salt;
};

absl::optional<KeyingMaterial> ExportKeyingMaterial(
rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc,
const std::string& mid);

} // namespace sora

#endif
25 changes: 25 additions & 0 deletions src/sora_signaling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "sora/rtc_ssl_verifier.h"
#include "sora/rtc_stats.h"
#include "sora/session_description.h"
#include "sora/srtp_keying_material_exporter.h"
#include "sora/url_parts.h"
#include "sora/version.h"
#include "sora/zlib_helper.h"
Expand Down Expand Up @@ -1470,6 +1471,30 @@ void SoraSignaling::OnConnectionChange(
SoraSignalingErrorCode::PEER_CONNECTION_STATE_FAILED,
"PeerConnectionState::kFailed");
}

if (new_state ==
webrtc::PeerConnectionInterface::PeerConnectionState::kConnected) {
auto km = ExportKeyingMaterial(self->pc_, self->video_mid_);
if (!km) {
RTC_LOG(LS_ERROR) << "Failed to ExportKeyingMaterial";
} else {
auto to_hex = [](const std::vector<uint8_t>& buf) {
std::string str;
const char hex[] = "0123456789abcdef";
for (auto n : buf) {
str += hex[(n >> 4) & 0xf];
str += hex[n & 0xf];
}
return str;
};
std::stringstream ss;
ss << "SRTP_CLIENT_KEY " << to_hex(km->client_write_key) << "\n";
ss << "SRTP_CLIENT_SALT " << to_hex(km->client_write_salt) << "\n";
ss << "SRTP_SERVER_KEY " << to_hex(km->server_write_key) << "\n";
ss << "SRTP_SERVER_SALT " << to_hex(km->server_write_salt) << "\n";
printf("%s", ss.str().c_str());
}
}
});
}

Expand Down
78 changes: 78 additions & 0 deletions src/srtp_keying_material_exporter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "sora/srtp_keying_material_exporter.h"

#include <p2p/base/dtls_transport.h>
#include <pc/dtls_transport.h>
#include <rtc_base/logging.h>
#include <rtc_base/ssl_stream_adapter.h>

namespace sora {

// Value specified in RFC 5764.
static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";

absl::optional<KeyingMaterial> ExportKeyingMaterial(
rtc::scoped_refptr<webrtc::PeerConnectionInterface> pc,
const std::string& mid) {
rtc::scoped_refptr<webrtc::DtlsTransportInterface> dtls_interface =
pc->LookupDtlsTransportByMid(mid);
if (dtls_interface == nullptr) {
RTC_LOG(LS_ERROR) << "Failed to lookup DtlsTransportInterface";
return absl::nullopt;
}

// shiguredo-webrtc-build/webrtc-build の libwebrtc は
// RTTI を有効にしてるので dynamic_cast ができる
webrtc::DtlsTransport* dtls_impl =
dynamic_cast<webrtc::DtlsTransport*>(dtls_interface.get());
if (dtls_impl == nullptr) {
RTC_LOG(LS_ERROR) << "Failed to cast webrtc::DtlsTransport";
return absl::nullopt;
}

cricket::DtlsTransport* dtls =
dynamic_cast<cricket::DtlsTransport*>(dtls_impl->internal());
if (dtls == nullptr) {
RTC_LOG(LS_ERROR) << "Failed to cast cricket::DtlsTransport";
return absl::nullopt;
}

int crypto_suite;
if (!dtls->GetSrtpCryptoSuite(&crypto_suite)) {
RTC_LOG(LS_ERROR) << "Failed to get SrtpCryptoSuite";
return absl::nullopt;
}

int key_len;
int salt_len;
if (!rtc::GetSrtpKeyAndSaltLengths(crypto_suite, &key_len, &salt_len)) {
RTC_LOG(LS_ERROR) << "Failed to get SrtpKeyAndSaltLengths";
return absl::nullopt;
}

std::vector<uint8_t> buf(key_len * 2 + salt_len * 2);

if (!dtls->ExportKeyingMaterial(kDtlsSrtpExporterLabel, nullptr, 0, false,
buf.data(), buf.size())) {
RTC_LOG(LS_ERROR) << "Failed to ExportKeyingMaterial";
return absl::nullopt;
};

KeyingMaterial km;
km.client_write_key.resize(key_len);
km.server_write_key.resize(key_len);
km.client_write_salt.resize(salt_len);
km.server_write_salt.resize(salt_len);
int n = 0;
memcpy(km.client_write_key.data(), buf.data() + n, key_len);
n += key_len;
memcpy(km.server_write_key.data(), buf.data() + n, key_len);
n += key_len;
memcpy(km.client_write_salt.data(), buf.data() + n, salt_len);
n += salt_len;
memcpy(km.server_write_salt.data(), buf.data() + n, salt_len);
n += salt_len;

return km;
}

} // namespace sora

0 comments on commit 507ecd9

Please sign in to comment.