From f7ed27b618507ed1460dbf36183e7a0245a983fd Mon Sep 17 00:00:00 2001 From: doe300 Date: Wed, 29 Jun 2016 17:07:06 +0200 Subject: [PATCH] Added basic support of crypto-attribute RFC 4568 to SDP, see #56 Signed-off-by:doe300 --- include/sip/SDPMessageHandler.h | 16 +++++++- src/crypto/DummyCryptoSuite.cpp | 10 +++++ src/sip/SDPMessageHandler.cpp | 68 +++++++++++++++++++++------------ 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/include/sip/SDPMessageHandler.h b/include/sip/SDPMessageHandler.h index 4421de9..ae301c5 100644 --- a/include/sip/SDPMessageHandler.h +++ b/include/sip/SDPMessageHandler.h @@ -8,12 +8,14 @@ #ifndef SDPMESSAGEHANDLER_H #define SDPMESSAGEHANDLER_H +#include #include #include #include "configuration.h" #include "KeyValuePairs.h" #include "PayloadType.h" +#include "crypto/CryptographicContext.h" #include "sip/SupportedFormats.h" namespace ohmcomm @@ -74,6 +76,8 @@ namespace ohmcomm static const std::string SDP_ATTRIBUTE_FMTP; //specifies RTCP-port, if not consecutive to RTP-port, see RFC 3605 static const std::string SDP_ATTRIBUTE_RTCP; + //SDES cryptographic extension, RFC 4568 + static const std::string SDP_ATTRIBUTE_CRYPTO; static const std::string SDP_MEDIA_RTP; static const std::string SDP_MEDIA_SRTP; @@ -131,9 +135,11 @@ namespace ohmcomm * * \param media An optional list of media-descriptions to use, defaults to the list of supported formats * + * \param cryptoContext An optional cryptographic context to use. When set, SRTP is supported in the media-description + * * \return the generated SDP session-description */ - static std::string createSessionDescription(const std::string& localUserName, const NetworkConfiguration& config, const std::vector& media = {}); + static std::string createSessionDescription(const std::string& localUserName, const NetworkConfiguration& config, const std::vector& media = {}, const std::shared_ptr cryptoContext = nullptr); /*! * Ready the session description from the given message and returns it @@ -193,6 +199,14 @@ namespace ohmcomm * \return whether the given encoding is supported */ static bool isEncodingSupported(const std::string& encoding); + + /*! + * Generates the media-line for the given protocol (RTP/SRTP) and available media-descriptions. + * If no media-descriptions are given, the SupportedFormats are used instead. + * + * \since 1.0 + */ + static std::string generateMediaLine(const NetworkConfiguration& config, const std::string protocol, const std::vector& media = {}); }; } } diff --git a/src/crypto/DummyCryptoSuite.cpp b/src/crypto/DummyCryptoSuite.cpp index 0cf21b5..42e641c 100644 --- a/src/crypto/DummyCryptoSuite.cpp +++ b/src/crypto/DummyCryptoSuite.cpp @@ -21,4 +21,14 @@ std::string CryptoSuite::hashMD5(const std::string& input) { throw std::runtime_error("No crypto library configured!"); } + +std::vector CryptoSuite::createHMAC_SHA1(const void* buffer, const unsigned int bufferSize, const std::shared_ptr cryptoContext) +{ + throw std::runtime_error("No crypto library configured!"); +} + +bool CryptoSuite::verifyHMAC_SHA1(const void* hmacBuffer, const unsigned int hmacBufferSize, const void* buffer, const unsigned int bufferSize, const std::shared_ptr cryptoContext) +{ + throw std::runtime_error("No crypto library configured!"); +} #endif \ No newline at end of file diff --git a/src/sip/SDPMessageHandler.cpp b/src/sip/SDPMessageHandler.cpp index e5b87e7..0d1c9fb 100644 --- a/src/sip/SDPMessageHandler.cpp +++ b/src/sip/SDPMessageHandler.cpp @@ -15,7 +15,6 @@ using namespace ohmcomm::sip; -//clang seems to need the static char-fields to be declared for linker to find them constexpr char SessionDescription::SDP_VERSION; constexpr char SessionDescription::SDP_ORIGIN; constexpr char SessionDescription::SDP_SESSION_NAME; @@ -27,6 +26,7 @@ constexpr char SessionDescription::SDP_ATTRIBUTE; const std::string SessionDescription::SDP_ATTRIBUTE_RTPMAP("rtpmap"); const std::string SessionDescription::SDP_ATTRIBUTE_FMTP("fmtp"); const std::string SessionDescription::SDP_ATTRIBUTE_RTCP("rtcp"); +const std::string SessionDescription::SDP_ATTRIBUTE_CRYPTO("crypto"); const std::string SessionDescription::SDP_MEDIA_RTP("RTP/AVP"); const std::string SessionDescription::SDP_MEDIA_SRTP("RTP/SAVP"); @@ -34,7 +34,7 @@ SDPMessageHandler::SDPMessageHandler() { } -std::string SDPMessageHandler::createSessionDescription(const std::string& localUserName, const ohmcomm::NetworkConfiguration& config, const std::vector& media) +std::string SDPMessageHandler::createSessionDescription(const std::string& localUserName, const ohmcomm::NetworkConfiguration& config, const std::vector& media, const std::shared_ptr cryptoContext) { ohmcomm::rtp::NTPTimestamp now = ohmcomm::rtp::NTPTimestamp::now(); std::string localIP = Utility::getLocalIPAddress(Utility::getNetworkType(config.remoteIPAddress)); @@ -121,25 +121,7 @@ std::string SDPMessageHandler::createSessionDescription(const std::string& local // (SRTP over UDP) // is a media format description [...] If the sub-field is "RTP/AVP" or "RTP/SAVP" the sub-fields contain RTP payload type numbers // we support Opus and PCM, so we send these payload-types - std::string mediaLine = std::string("m=audio ").append(std::to_string(config.localPort)).append(" RTP/AVP "); - if(media.empty()) - { - //suggest all supported media-types - for(const SupportedFormat& format : SupportedFormats::getFormats()) - { - mediaLine.append(std::to_string(format.payloadType)).append(" "); - } - } - else - { - //set only selected media - for(const MediaDescription& format : media) - { - mediaLine.append(std::to_string(format.payloadType)).append(" "); - } - } - lines.push_back(mediaLine); - //XXX media for SRTP + lines.push_back(generateMediaLine(config, SessionDescription::SDP_MEDIA_RTP, media)); //Attributes //a= or a=: @@ -221,10 +203,17 @@ std::string SDPMessageHandler::createSessionDescription(const std::string& local // - FEC_KEY: Master Key for FEC when the FEC stream is sent to a separate address and/or port. // - WSH: Window Size Hint. // - Extensions: Extension parameters can be defined. - if(false) //XXX if SRTP is enabled + if(cryptoContext) { - lines.push_back(std::string("a=crypto:0 ").append(""/* XXX Algorithm*/).append(" inline:").append(""/*XXX Key*/) - .append(" "/*XXX session-params*/)); + //media for SRTP + lines.push_back(generateMediaLine(config, SessionDescription::SDP_MEDIA_SRTP, media)); + //XXX are additional rtpmap-attributes required?? + + const std::string inlineKey = ohmcomm::Utility::encodeBase64(std::string(cryptoContext->masterKey.data(), cryptoContext->masterKey.size()) + std::string(cryptoContext->masterSalt.data(), cryptoContext->masterSalt.size())); + + lines.push_back(std::string("a=crypto:1 ").append(cryptoContext->cryptoMode.name).append(" inline:").append(inlineKey) + .append(" "/*session-params*/)); + } std::string result(""); @@ -465,3 +454,34 @@ bool SDPMessageHandler::isEncodingSupported(const std::string& encoding) } return false; } + +std::string SDPMessageHandler::generateMediaLine(const NetworkConfiguration& config, const std::string protocol, const std::vector& media) +{ + //Media Descriptions + //m= ... + // is the media type. Currently defined media are "audio", "video", "text", "application", and "message" + // is the transport port to which the media stream is sent [...] such as the RTP Control Protocol (RTCP) + // port MAY be derived algorithmically + // is the transport protocol "udp", "RTP/AVP" (RTP with Audio/Video Profile forMinimal Control over UDP), "RTP/SAVP" + // (SRTP over UDP) + // is a media format description [...] If the sub-field is "RTP/AVP" or "RTP/SAVP" the sub-fields contain RTP payload type numbers + // we support Opus and PCM, so we send these payload-types + std::string mediaLine = std::string("m=audio ").append(std::to_string(config.localPort)).append(" ").append(protocol).append(" "); + if(media.empty()) + { + //suggest all supported media-types + for(const SupportedFormat& format : SupportedFormats::getFormats()) + { + mediaLine.append(std::to_string(format.payloadType)).append(" "); + } + } + else + { + //set only selected media + for(const MediaDescription& format : media) + { + mediaLine.append(std::to_string(format.payloadType)).append(" "); + } + } + return mediaLine; +}