diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 517d42178..5b2a6b57f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -71,9 +71,6 @@ string gen_random_str(int len) return ret; } -const int SRTP_MASTER_KEY_KEY_LEN = 16; -const int SRTP_MASTER_KEY_SALT_LEN = 14; - uint64_t SrsNtp::kMagicNtpFractionalUnit = 1ULL << 32; SrsNtp::SrsNtp() @@ -114,13 +111,9 @@ SrsSecurityTransport::SrsSecurityTransport(SrsRtcSession* s) { session_ = s; - client_key = ""; - server_key = ""; - - srtp_send = NULL; - srtp_recv = NULL; - dtls_ = new SrsDtls((ISrsDtlsCallback*)this); + srtp_send = new SrsSRTP(); + srtp_recv = new SrsSRTP(); handshake_done = false; } @@ -133,11 +126,11 @@ SrsSecurityTransport::~SrsSecurityTransport() } if (srtp_send) { - srtp_dealloc(srtp_send); + srs_freep(srtp_send); } if (srtp_recv) { - srtp_dealloc(srtp_recv); + srs_freep(srtp_recv); } } @@ -200,189 +193,68 @@ srs_error_t SrsSecurityTransport::srtp_initialize() { srs_error_t err = srs_success; - unsigned char material[SRTP_MASTER_KEY_LEN * 2] = {0}; // client(SRTP_MASTER_KEY_KEY_LEN + SRTP_MASTER_KEY_SALT_LEN) + server - static const string dtls_srtp_lable = "EXTRACTOR-dtls_srtp"; + std::string send_key; + std::string recv_key; - if ((err = dtls_->export_keying_material(material, sizeof(material), dtls_srtp_lable.c_str(), dtls_srtp_lable.size(), NULL, 0, 0)) != srs_success) { + if ((err = dtls_->get_srtp_key(recv_key, send_key)) != srs_success) { return err; } - size_t offset = 0; - - std::string client_master_key(reinterpret_cast(material), SRTP_MASTER_KEY_KEY_LEN); - offset += SRTP_MASTER_KEY_KEY_LEN; - std::string server_master_key(reinterpret_cast(material + offset), SRTP_MASTER_KEY_KEY_LEN); - offset += SRTP_MASTER_KEY_KEY_LEN; - std::string client_master_salt(reinterpret_cast(material + offset), SRTP_MASTER_KEY_SALT_LEN); - offset += SRTP_MASTER_KEY_SALT_LEN; - std::string server_master_salt(reinterpret_cast(material + offset), SRTP_MASTER_KEY_SALT_LEN); - - client_key = client_master_key + client_master_salt; - server_key = server_master_key + server_master_salt; - - if ((err = srtp_send_init()) != srs_success) { + if ((err = srtp_send->initialize(send_key, true)) != srs_success) { return srs_error_wrap(err, "srtp send init failed"); } - if ((err = srtp_recv_init()) != srs_success) { + if ((err = srtp_recv->initialize(recv_key, false)) != srs_success) { return srs_error_wrap(err, "srtp recv init failed"); } return err; } -srs_error_t SrsSecurityTransport::srtp_send_init() -{ - srs_error_t err = srs_success; - - srtp_policy_t policy; - bzero(&policy, sizeof(policy)); - - // TODO: Maybe we can use SRTP-GCM in future. - // @see https://bugs.chromium.org/p/chromium/issues/detail?id=713701 - // @see https://groups.google.com/forum/#!topic/discuss-webrtc/PvCbWSetVAQ - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); - - policy.ssrc.type = ssrc_any_outbound; - - policy.ssrc.value = 0; - // TODO: adjust window_size - policy.window_size = 8192; - policy.allow_repeat_tx = 1; - policy.next = NULL; - - uint8_t *key = new uint8_t[server_key.size()]; - memcpy(key, server_key.data(), server_key.size()); - policy.key = key; - - if (srtp_create(&srtp_send, &policy) != srtp_err_status_ok) { - srs_freepa(key); - return srs_error_new(ERROR_RTC_SRTP_INIT, "srtp_create failed"); - } - - srs_freepa(key); - - return err; -} - -srs_error_t SrsSecurityTransport::srtp_recv_init() -{ - srs_error_t err = srs_success; - - srtp_policy_t policy; - bzero(&policy, sizeof(policy)); - - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); - - policy.ssrc.type = ssrc_any_inbound; - - policy.ssrc.value = 0; - // TODO: adjust window_size - policy.window_size = 8192; - policy.allow_repeat_tx = 1; - policy.next = NULL; - - uint8_t *key = new uint8_t[client_key.size()]; - memcpy(key, client_key.data(), client_key.size()); - policy.key = key; - - // TODO: FIXME: Wrap error code. - if (srtp_create(&srtp_recv, &policy) != srtp_err_status_ok) { - srs_freepa(key); - return srs_error_new(ERROR_RTC_SRTP_INIT, "srtp_create failed"); - } - - srs_freepa(key); - - return err; -} - srs_error_t SrsSecurityTransport::protect_rtp(char* out_buf, const char* in_buf, int& nb_out_buf) { - srs_error_t err = srs_success; - - if (srtp_send) { - memcpy(out_buf, in_buf, nb_out_buf); - // TODO: FIXME: Wrap error code. - if (srtp_protect(srtp_send, out_buf, &nb_out_buf) != 0) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); - } - - return err; + if (!srtp_send) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); } - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); + return srtp_send->protect_rtp(out_buf, in_buf, nb_out_buf); } // TODO: FIXME: Merge with protect_rtp. srs_error_t SrsSecurityTransport::protect_rtp2(void* rtp_hdr, int* len_ptr) { - srs_error_t err = srs_success; - if (!srtp_send) { return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); } - // TODO: FIXME: Wrap error code. - if (srtp_protect(srtp_send, rtp_hdr, len_ptr) != 0) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); - } - - return err; + return srtp_send->protect_rtp2(rtp_hdr, len_ptr); } srs_error_t SrsSecurityTransport::unprotect_rtp(char* out_buf, const char* in_buf, int& nb_out_buf) { - srs_error_t err = srs_success; - - if (srtp_recv) { - memcpy(out_buf, in_buf, nb_out_buf); - - srtp_err_status_t r0 = srtp_unprotect(srtp_recv, out_buf, &nb_out_buf); - if (r0 != srtp_err_status_ok) { - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "unprotect r0=%u", r0); - } - - return err; + if (!srtp_recv) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtp unprotect failed"); } - - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtp unprotect failed"); + + return srtp_recv->unprotect_rtp(out_buf, in_buf, nb_out_buf); } srs_error_t SrsSecurityTransport::protect_rtcp(char* out_buf, const char* in_buf, int& nb_out_buf) { - srs_error_t err = srs_success; - - if (srtp_send) { - memcpy(out_buf, in_buf, nb_out_buf); - // TODO: FIXME: Wrap error code. - if (srtp_protect_rtcp(srtp_send, out_buf, &nb_out_buf) != 0) { - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtcp protect failed"); - } - - return err; + if (!srtp_send) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtcp protect failed"); } - return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtcp protect failed"); + return srtp_send->protect_rtcp(out_buf, in_buf, nb_out_buf); } srs_error_t SrsSecurityTransport::unprotect_rtcp(char* out_buf, const char* in_buf, int& nb_out_buf) { - srs_error_t err = srs_success; - - if (srtp_recv) { - memcpy(out_buf, in_buf, nb_out_buf); - // TODO: FIXME: Wrap error code. - if (srtp_unprotect_rtcp(srtp_recv, out_buf, &nb_out_buf) != srtp_err_status_ok) { - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); - } - - return err; + if (!srtp_recv) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); } - return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); + return srtp_recv->unprotect_rtcp(out_buf, in_buf, nb_out_buf); } SrsRtcOutgoingInfo::SrsRtcOutgoingInfo() diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index 97cb4da5b..09e2fe35c 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -44,9 +44,6 @@ #include #include -#include -#include - class SrsUdpMuxSocket; class SrsConsumer; class SrsStunPacket; @@ -114,12 +111,8 @@ class SrsSecurityTransport : public ISrsDtlsCallback private: SrsRtcSession* session_; SrsDtls* dtls_; - - std::string client_key; - std::string server_key; - - srtp_t srtp_send; - srtp_t srtp_recv; + SrsSRTP* srtp_send; + SrsSRTP* srtp_recv; bool handshake_done; public: @@ -143,8 +136,6 @@ public: virtual srs_error_t write_dtls_data(void* data, int size); private: srs_error_t srtp_initialize(); - srs_error_t srtp_send_init(); - srs_error_t srtp_recv_init(); }; // A group of RTP packets for outgoing(send to players). diff --git a/trunk/src/app/srs_app_rtc_dtls.cpp b/trunk/src/app/srs_app_rtc_dtls.cpp index 8e99fba05..4c98b5ab6 100644 --- a/trunk/src/app/srs_app_rtc_dtls.cpp +++ b/trunk/src/app/srs_app_rtc_dtls.cpp @@ -427,13 +427,148 @@ srs_error_t SrsDtls::do_handshake() return handshake(); } -srs_error_t SrsDtls::export_keying_material(unsigned char *out, size_t olen, const char *label, size_t llen, const unsigned char *p, size_t plen, int use_context) +const int SRTP_MASTER_KEY_KEY_LEN = 16; +const int SRTP_MASTER_KEY_SALT_LEN = 14; +srs_error_t SrsDtls::get_srtp_key(std::string& client_key, std::string& server_key) { srs_error_t err = srs_success; - if (!SSL_export_keying_material(dtls, out, olen, label, llen, p, plen, use_context)) { + unsigned char material[SRTP_MASTER_KEY_LEN * 2] = {0}; // client(SRTP_MASTER_KEY_KEY_LEN + SRTP_MASTER_KEY_SALT_LEN) + server + static const string dtls_srtp_lable = "EXTRACTOR-dtls_srtp"; + if (!SSL_export_keying_material(dtls, material, sizeof(material), dtls_srtp_lable.c_str(), dtls_srtp_lable.size(), NULL, 0, 0)) { return srs_error_new(ERROR_RTC_SRTP_INIT, "SSL_export_keying_material failed"); } + size_t offset = 0; + + std::string client_master_key(reinterpret_cast(material), SRTP_MASTER_KEY_KEY_LEN); + offset += SRTP_MASTER_KEY_KEY_LEN; + std::string server_master_key(reinterpret_cast(material + offset), SRTP_MASTER_KEY_KEY_LEN); + offset += SRTP_MASTER_KEY_KEY_LEN; + std::string client_master_salt(reinterpret_cast(material + offset), SRTP_MASTER_KEY_SALT_LEN); + offset += SRTP_MASTER_KEY_SALT_LEN; + std::string server_master_salt(reinterpret_cast(material + offset), SRTP_MASTER_KEY_SALT_LEN); + + client_key = client_master_key + client_master_salt; + server_key = server_master_key + server_master_salt; + + return err; +} + +SrsSRTP::SrsSRTP() +{ + srtp_ctx = NULL; +} + +SrsSRTP::~SrsSRTP() +{ + if (srtp_ctx) { + srtp_dealloc(srtp_ctx); + } +} + +srs_error_t SrsSRTP::initialize(string srtp_key, bool send) +{ + srs_error_t err = srs_success; + + srtp_policy_t policy; + bzero(&policy, sizeof(policy)); + + // TODO: Maybe we can use SRTP-GCM in future. + // @see https://bugs.chromium.org/p/chromium/issues/detail?id=713701 + // @see https://groups.google.com/forum/#!topic/discuss-webrtc/PvCbWSetVAQ + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); + + if (send) { + policy.ssrc.type = ssrc_any_outbound; + } else { + policy.ssrc.type = ssrc_any_inbound; + } + + + policy.ssrc.value = 0; + // TODO: adjust window_size + policy.window_size = 8192; + policy.allow_repeat_tx = 1; + policy.next = NULL; + + //uint8_t *key = new uint8_t[server_key.size()]; + //memcpy(key, server_key.data(), server_key.size()); + uint8_t *key = new uint8_t[srtp_key.size()]; + memcpy(key, srtp_key.data(), srtp_key.size()); + policy.key = key; + + if (srtp_create(&srtp_ctx, &policy) != srtp_err_status_ok) { + srs_freepa(key); + return srs_error_new(ERROR_RTC_SRTP_INIT, "srtp_create failed"); + } + + srs_freepa(key); + + return err; +} + +srs_error_t SrsSRTP::protect_rtp(char* out_buf, const char* in_buf, int& nb_out_buf) +{ + srs_error_t err = srs_success; + + memcpy(out_buf, in_buf, nb_out_buf); + // TODO: FIXME: Wrap error code. + if (srtp_protect(srtp_ctx, out_buf, &nb_out_buf) != 0) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect failed"); + } + + return err; +} + +srs_error_t SrsSRTP::protect_rtp2(void* rtp_hdr, int* len_ptr) +{ + srs_error_t err = srs_success; + + // TODO: FIXME: Wrap error code. + if (srtp_protect(srtp_ctx, rtp_hdr, len_ptr) != 0) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtp protect"); + } + + return err; +} + +srs_error_t SrsSRTP::unprotect_rtp(char* out_buf, const char* in_buf, int& nb_out_buf) +{ + srs_error_t err = srs_success; + + memcpy(out_buf, in_buf, nb_out_buf); + srtp_err_status_t r0 = srtp_unprotect(srtp_ctx, out_buf, &nb_out_buf); + if (r0 != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "unprotect r0=%u", r0); + } + + return err; +} + +srs_error_t SrsSRTP::protect_rtcp(char* out_buf, const char* in_buf, int& nb_out_buf) +{ + srs_error_t err = srs_success; + + memcpy(out_buf, in_buf, nb_out_buf); + // TODO: FIXME: Wrap error code. + if (srtp_protect_rtcp(srtp_ctx, out_buf, &nb_out_buf) != 0) { + return srs_error_new(ERROR_RTC_SRTP_PROTECT, "rtcp protect failed"); + } + + return err; +} + +srs_error_t SrsSRTP::unprotect_rtcp(char* out_buf, const char* in_buf, int& nb_out_buf) +{ + srs_error_t err = srs_success; + + memcpy(out_buf, in_buf, nb_out_buf); + // TODO: FIXME: Wrap error code. + if (srtp_unprotect_rtcp(srtp_ctx, out_buf, &nb_out_buf) != srtp_err_status_ok) { + return srs_error_new(ERROR_RTC_SRTP_UNPROTECT, "rtcp unprotect failed"); + } + return err; } \ No newline at end of file diff --git a/trunk/src/app/srs_app_rtc_dtls.hpp b/trunk/src/app/srs_app_rtc_dtls.hpp index 3a50646ff..ecc1fb389 100644 --- a/trunk/src/app/srs_app_rtc_dtls.hpp +++ b/trunk/src/app/srs_app_rtc_dtls.hpp @@ -31,6 +31,7 @@ class SrsRequest; #include +#include class SrsDtlsCertificate { @@ -93,10 +94,27 @@ public: srs_error_t initialize(SrsRequest* r); srs_error_t do_handshake(); srs_error_t on_dtls(char* data, int nb_data); - srs_error_t export_keying_material(unsigned char *out, size_t olen, const char *label, size_t llen, const unsigned char *p, size_t plen, int use_context); + srs_error_t get_srtp_key(std::string& send_key, std::string& recv_key); private: SSL_CTX* build_dtls_ctx(); srs_error_t handshake(); }; +class SrsSRTP +{ +private: + srtp_t srtp_ctx; +public: + SrsSRTP(); + virtual ~SrsSRTP(); +public: + srs_error_t initialize(std::string srtp_key, bool send); +public: + srs_error_t protect_rtp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); + srs_error_t protect_rtp2(void* rtp_hdr, int* len_ptr); + srs_error_t unprotect_rtp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf); + srs_error_t protect_rtcp(char* protected_buf, const char* ori_buf, int& nb_protected_buf); + srs_error_t unprotect_rtcp(char* unprotected_buf, const char* ori_buf, int& nb_unprotected_buf); +}; + #endif