Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package live555 for openSUSE:Factory checked in at 2022-02-17 00:30:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/live555 (Old) and /work/SRC/openSUSE:Factory/.live555.new.1956 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "live555" Thu Feb 17 00:30:11 2022 rev:30 rq:955058 version:2022.02.07 Changes: -------- --- /work/SRC/openSUSE:Factory/live555/live555.changes 2021-12-21 18:40:23.285860724 +0100 +++ /work/SRC/openSUSE:Factory/.live555.new.1956/live555.changes 2022-02-17 00:30:46.549430763 +0100 @@ -1,0 +2,31 @@ +Tue Feb 15 15:50:24 UTC 2022 - Dominique Leuenberger <dims...@opensuse.org> + +- Update to version 2022.02.07: + + Updated the SRTP packet sending code in "MultiFramedRTPSink.cp" + to not allocate a variable-sized buffer on the stack, because + some compilers can't handle this. + + Ensure that RTSP servers that serve SRTP do not also support + streaming over the TCP connection, because that would add extra + overhead for no benefit. +- Changes from version 2022.01.21: + + Fixed a bug in the "groupsock" library that could cause + outgoing RTP packets to get duplicated when a RTSP "PLAY" + command is sent after a "PAUSE". +- Changes from version 2022.01.20: + + More updates to the code for optional server SRTP streaming. +- Changes from version 2022.01.17: + + More updates to the code in preparation for optional server + SRTP streaming. +- Changes from version 2022.01.11: + + Fixed a minor memory leak in "RTSPClient" when receiving a SRTP + stream. + + Updates to "RTPSink" in preparation for optional server SRTP + streaming. +- Changes from version 2022.01.06: + + Made "GenericMediaServer::addServerMediaSubsession()" a virtual + function, and redefine it in the subclass "RTSPServer" to call + the base function, then set the "ServerMediaSubsession"s + "streamingIsEncrypted" flag (if the RTSP server is streaming + SRTP). + +------------------------------------------------------------------- Old: ---- live.2021.12.18.tar.gz New: ---- live.2022.02.07.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ live555.spec ++++++ --- /var/tmp/diff_new_pack.7isSKn/_old 2022-02-17 00:30:47.161430658 +0100 +++ /var/tmp/diff_new_pack.7isSKn/_new 2022-02-17 00:30:47.173430656 +0100 @@ -1,7 +1,7 @@ # # spec file for package live555 # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # Copyright (c) 2020 Dominique Leuenberger, Ramiswil, Switzerland # # All modifications and additions to the file contributed by third parties @@ -17,10 +17,10 @@ # -%define lmdmaj 102 +%define lmdmaj 106 Name: live555 -Version: 2021.12.18 +Version: 2022.02.07 Release: 0 Summary: LIVE555 Streaming Media License: LGPL-2.1-only ++++++ live.2021.12.18.tar.gz -> live.2022.02.07.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh --- old/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/BasicUsageEnvironment/include/BasicUsageEnvironment_version.hh 2022-02-07 11:35:51.000000000 +0100 @@ -14,12 +14,12 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **********/ // Version information for the "BasicUsageEnvironment" library -// Copyright (c) 1996-2021 Live Networks, Inc. All rights reserved. +// Copyright (c) 1996-2022 Live Networks, Inc. All rights reserved. #ifndef _BASICUSAGEENVIRONMENT_VERSION_HH #define _BASICUSAGEENVIRONMENT_VERSION_HH -#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING "2021.12.18" -#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT 1639785600 +#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_STRING "2022.02.07" +#define BASICUSAGEENVIRONMENT_LIBRARY_VERSION_INT 1644192000 #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/UsageEnvironment/include/UsageEnvironment_version.hh new/live/UsageEnvironment/include/UsageEnvironment_version.hh --- old/live/UsageEnvironment/include/UsageEnvironment_version.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/UsageEnvironment/include/UsageEnvironment_version.hh 2022-02-07 11:35:51.000000000 +0100 @@ -14,12 +14,12 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **********/ // Version information for the "UsageEnvironment" library -// Copyright (c) 1996-2021 Live Networks, Inc. All rights reserved. +// Copyright (c) 1996-2022 Live Networks, Inc. All rights reserved. #ifndef _USAGEENVIRONMENT_VERSION_HH #define _USAGEENVIRONMENT_VERSION_HH -#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING "2021.12.18" -#define USAGEENVIRONMENT_LIBRARY_VERSION_INT 1639785600 +#define USAGEENVIRONMENT_LIBRARY_VERSION_STRING "2022.02.07" +#define USAGEENVIRONMENT_LIBRARY_VERSION_INT 1644192000 #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/config.linux-with-shared-libraries new/live/config.linux-with-shared-libraries --- old/live/config.linux-with-shared-libraries 2021-12-18 23:29:30.000000000 +0100 +++ new/live/config.linux-with-shared-libraries 2022-02-07 11:36:13.000000000 +0100 @@ -3,8 +3,8 @@ # At least one interface changes, or is removed => CURRENT += 1; REVISION = 0; AGE = 0 # One or more interfaces were added, but no existing interfaces were changed or removed => CURRENT += 1; REVISION = 0; AGE += 1 -libliveMedia_VERSION_CURRENT=102 -libliveMedia_VERSION_REVISION=2 +libliveMedia_VERSION_CURRENT=106 +libliveMedia_VERSION_REVISION=1 libliveMedia_VERSION_AGE=0 libliveMedia_LIB_SUFFIX=so.$(shell expr $(libliveMedia_VERSION_CURRENT) - $(libliveMedia_VERSION_AGE)).$(libliveMedia_VERSION_AGE).$(libliveMedia_VERSION_REVISION) @@ -19,7 +19,7 @@ libUsageEnvironment_LIB_SUFFIX=so.$(shell expr $(libUsageEnvironment_VERSION_CURRENT) - $(libUsageEnvironment_VERSION_AGE)).$(libUsageEnvironment_VERSION_AGE).$(libUsageEnvironment_VERSION_REVISION) libgroupsock_VERSION_CURRENT=30 -libgroupsock_VERSION_REVISION=9 +libgroupsock_VERSION_REVISION=10 libgroupsock_VERSION_AGE=0 libgroupsock_LIB_SUFFIX=so.$(shell expr $(libgroupsock_VERSION_CURRENT) - $(libgroupsock_VERSION_AGE)).$(libgroupsock_VERSION_AGE).$(libgroupsock_VERSION_REVISION) ##### diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/groupsock/Groupsock.cpp new/live/groupsock/Groupsock.cpp --- old/live/groupsock/Groupsock.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/groupsock/Groupsock.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -225,7 +225,7 @@ for (destRecord* dest = fDests; dest != NULL; dest = dest->fNext) { if (dest->fSessionId == sessionId && dest->fGroupEId.groupAddress() == addr && - dest->fGroupEId.portNum() == portNum(addr)) { + dest->fGroupEId.portNum() == port.num()) { return; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/groupsock/include/groupsock_version.hh new/live/groupsock/include/groupsock_version.hh --- old/live/groupsock/include/groupsock_version.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/groupsock/include/groupsock_version.hh 2022-02-07 11:35:51.000000000 +0100 @@ -14,12 +14,12 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **********/ // Version information for the "groupsock" library -// Copyright (c) 1996-2021 Live Networks, Inc. All rights reserved. +// Copyright (c) 1996-2022 Live Networks, Inc. All rights reserved. #ifndef _GROUPSOCK_VERSION_HH #define _GROUPSOCK_VERSION_HH -#define GROUPSOCK_LIBRARY_VERSION_STRING "2021.12.18" -#define GROUPSOCK_LIBRARY_VERSION_INT 1639785600 +#define GROUPSOCK_LIBRARY_VERSION_STRING "2022.02.07" +#define GROUPSOCK_LIBRARY_VERSION_INT 1644192000 #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/MIKEY.cpp new/live/liveMedia/MIKEY.cpp --- old/live/liveMedia/MIKEY.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/MIKEY.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -67,10 +67,10 @@ HDR = 255 }; -MIKEYState::MIKEYState() +MIKEYState::MIKEYState(Boolean useEncryption) : // Set default encryption/authentication parameters: - fEncryptSRTP(True), - fEncryptSRTCP(True), + fEncryptSRTP(useEncryption), + fEncryptSRTCP(useEncryption), fMKI(our_random32()), fUseAuthentication(True), @@ -106,7 +106,7 @@ delete fHeaderPayload; // which will delete all the other payloads as well } -MIKEYState* MIKEYState::createNew(u_int8_t* messageToParse, unsigned messageSize) { +MIKEYState* MIKEYState::createNew(u_int8_t const* messageToParse, unsigned messageSize) { Boolean parsedOK; MIKEYState* newMIKEYState = new MIKEYState(messageToParse, messageSize, parsedOK); @@ -115,7 +115,6 @@ newMIKEYState = NULL; } - delete[] messageToParse; return newMIKEYState; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/Makefile.tail new/live/liveMedia/Makefile.tail --- old/live/liveMedia/Makefile.tail 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/Makefile.tail 2022-02-07 11:35:51.000000000 +0100 @@ -241,8 +241,8 @@ include/H265VideoFileSink.hh: include/H264or5VideoFileSink.hh OggFileSink.$(CPP): include/OggFileSink.hh include/OutputFile.hh include/VorbisAudioRTPSource.hh include/MPEG2TransportStreamMultiplexor.hh include/FramedSource.hh include/OggFileSink.hh: include/FileSink.hh -RTPSink.$(CPP): include/RTPSink.hh -include/RTPSink.hh: include/MediaSink.hh include/RTPInterface.hh +RTPSink.$(CPP): include/RTPSink.hh include/Base64.hh +include/RTPSink.hh: include/MediaSink.hh include/RTPInterface.hh include/SRTPCryptographicContext.hh MultiFramedRTPSink.$(CPP): include/MultiFramedRTPSink.hh include/MultiFramedRTPSink.hh: include/RTPSink.hh AudioRTPSink.$(CPP): include/AudioRTPSink.hh diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/MediaSession.cpp new/live/liveMedia/MediaSession.cpp --- old/live/liveMedia/MediaSession.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/MediaSession.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -336,6 +336,7 @@ if (keyMgmtData_decoded == NULL) break; resultMIKEYState = MIKEYState::createNew(keyMgmtData_decoded, keyMgmtData_decodedSize); + delete[] keyMgmtData_decoded; } while (0); delete[] keyMgmtPrtclId; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/MultiFramedRTPSink.cpp new/live/liveMedia/MultiFramedRTPSink.cpp --- old/live/liveMedia/MultiFramedRTPSink.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/MultiFramedRTPSink.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -362,15 +362,40 @@ return fOutBuf->isTooBigForAPacket(numBytes); } +#define MAX_UDP_PACKET_SIZE 65536 + void MultiFramedRTPSink::sendPacketIfNecessary() { if (fNumFramesUsedSoFar > 0) { // Send the packet: #ifdef TEST_LOSS if ((our_random()%10) != 0) // simulate 10% packet loss ##### #endif - if (!fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize())) { - // if failure handler has been specified, call it - if (fOnSendErrorFunc != NULL) (*fOnSendErrorFunc)(fOnSendErrorData); + if (fCrypto != NULL) { // Encrypt/tag the data before sending it: +#ifndef NO_OPENSSL + // Hack: Because the MKI + authentication tag at the end of the packet would + // overwrite any following (still to be sent) frame data, we can't encrypt/tag + // the packet in place. Instead, we have to make a copy (on the stack) of + // the packet, before encrypting/tagging/sending it: + if (fOutBuf->curPacketSize() + SRTP_MKI_LENGTH + SRTP_AUTH_TAG_LENGTH > MAX_UDP_PACKET_SIZE) { + fprintf(stderr, "MultiFramedRTPSink::sendPacketIfNecessary(): Fatal error: packet size %d is too large for SRTP\n", fOutBuf->curPacketSize()); + exit(1); + } + u_int8_t packet[MAX_UDP_PACKET_SIZE]; + memcpy(packet, fOutBuf->packet(), fOutBuf->curPacketSize()); + unsigned newPacketSize; + + if (fCrypto->processOutgoingSRTPPacket(packet, fOutBuf->curPacketSize(), newPacketSize)) { + if (!fRTPInterface.sendPacket(packet, newPacketSize)) { + // if failure handler has been specified, call it + if (fOnSendErrorFunc != NULL) (*fOnSendErrorFunc)(fOnSendErrorData); + } + } +#endif + } else { // unencrypted + if (!fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize())) { + // if failure handler has been specified, call it + if (fOnSendErrorFunc != NULL) (*fOnSendErrorFunc)(fOnSendErrorData); + } } ++fPacketCount; fTotalOctetCount += fOutBuf->curPacketSize(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/OnDemandServerMediaSubsession.cpp new/live/liveMedia/OnDemandServerMediaSubsession.cpp --- old/live/liveMedia/OnDemandServerMediaSubsession.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/OnDemandServerMediaSubsession.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -28,7 +28,8 @@ portNumBits initialPortNum, Boolean multiplexRTCPWithRTP) : ServerMediaSubsession(env), - fSDPLines(NULL), fReuseFirstSource(reuseFirstSource), + fSDPLines(NULL), fMIKEYStateMessage(NULL), fMIKEYStateMessageSize(0), + fReuseFirstSource(reuseFirstSource), fMultiplexRTCPWithRTP(multiplexRTCPWithRTP), fLastStreamToken(NULL), fAppHandlerTask(NULL), fAppHandlerClientData(NULL) { fDestinationsHashTable = HashTable::create(ONE_WORD_HASH_KEYS); @@ -43,6 +44,7 @@ } OnDemandServerMediaSubsession::~OnDemandServerMediaSubsession() { + delete[] fMIKEYStateMessage; delete[] fSDPLines; // Clean out the destinations hash table: @@ -69,10 +71,16 @@ Groupsock* dummyGroupsock = createGroupsock(nullAddress(addressFamily), 0); unsigned char rtpPayloadType = 96 + trackNumber()-1; // if dynamic RTPSink* dummyRTPSink = createNewRTPSink(dummyGroupsock, rtpPayloadType, inputSource); - if (dummyRTPSink != NULL && dummyRTPSink->estimatedBitrate() > 0) estBitrate = dummyRTPSink->estimatedBitrate(); + if (dummyRTPSink != NULL) { + if (fParentSession->streamingUsesSRTP) { + fMIKEYStateMessage = dummyRTPSink->setupForSRTP(fParentSession->streamingIsEncrypted, + fMIKEYStateMessageSize); + } - setSDPLinesFromRTPSink(dummyRTPSink, inputSource, estBitrate); - Medium::close(dummyRTPSink); + if (dummyRTPSink->estimatedBitrate() > 0) estBitrate = dummyRTPSink->estimatedBitrate(); + setSDPLinesFromRTPSink(dummyRTPSink, inputSource, estBitrate); + Medium::close(dummyRTPSink); + } delete dummyGroupsock; closeStreamSource(inputSource); } @@ -167,7 +175,12 @@ unsigned char rtpPayloadType = 96 + trackNumber()-1; // if dynamic rtpSink = mediaSource == NULL ? NULL : createNewRTPSink(rtpGroupsock, rtpPayloadType, mediaSource); - if (rtpSink != NULL && rtpSink->estimatedBitrate() > 0) streamBitrate = rtpSink->estimatedBitrate(); + if (rtpSink != NULL) { + if (fParentSession->streamingUsesSRTP) { + rtpSink->setupForSRTP(fMIKEYStateMessage, fMIKEYStateMessageSize); + } + if (rtpSink->estimatedBitrate() > 0) streamBitrate = rtpSink->estimatedBitrate(); + } } // Turn off the destinations for each groupsock. They'll get set later @@ -420,8 +433,6 @@ void OnDemandServerMediaSubsession ::setSDPLinesFromRTPSink(RTPSink* rtpSink, FramedSource* inputSource, unsigned estBitrate) { - if (rtpSink == NULL) return; - char const* mediaType = rtpSink->sdpMediaType(); unsigned char rtpPayloadType = rtpSink->rtpPayloadType(); struct sockaddr_storage const& addressForSDP = rtpSink->groupsockBeingUsed().groupAddress(); @@ -429,25 +440,28 @@ AddressString ipAddressStr(addressForSDP); char* rtpmapLine = rtpSink->rtpmapLine(); + char* keyMgmtLine = rtpSink->keyMgmtLine(); char const* rtcpmuxLine = fMultiplexRTCPWithRTP ? "a=rtcp-mux\r\n" : ""; char const* rangeLine = rangeSDPLine(); char const* auxSDPLine = getAuxSDPLine(rtpSink, inputSource); if (auxSDPLine == NULL) auxSDPLine = ""; char const* const sdpFmt = - "m=%s %u RTP/AVP %d\r\n" + "m=%s %u RTP/%sAVP %d\r\n" "c=IN %s %s\r\n" "b=AS:%u\r\n" "%s" "%s" "%s" "%s" + "%s" "a=control:%s\r\n"; unsigned sdpFmtSize = strlen(sdpFmt) - + strlen(mediaType) + 5 /* max short len */ + 3 /* max char len */ + + strlen(mediaType) + 5 /* max short len */ + 1 + 3 /* max char len */ + 3/*IP4 or IP6*/ + strlen(ipAddressStr.val()) + 20 /* max int len */ + strlen(rtpmapLine) + + strlen(keyMgmtLine) + strlen(rtcpmuxLine) + strlen(rangeLine) + strlen(auxSDPLine) @@ -456,15 +470,17 @@ sprintf(sdpLines, sdpFmt, mediaType, // m= <media> portNumForSDP, // m= <port> + fParentSession->streamingUsesSRTP ? "S" : "", rtpPayloadType, // m= <fmt list> addressForSDP.ss_family == AF_INET ? "IP4" : "IP6", ipAddressStr.val(), // c= address estBitrate, // b=AS:<bandwidth> rtpmapLine, // a=rtpmap:... (if present) + keyMgmtLine, // a=key-mgmt:... (if present) rtcpmuxLine, // a=rtcp-mux:... (if present) rangeLine, // a=range:... (if present) auxSDPLine, // optional extra SDP line trackId()); // a=control:<track-id> - delete[] (char*)rangeLine; delete[] rtpmapLine; + delete[] (char*)rangeLine; delete[] keyMgmtLine; delete[] rtpmapLine; delete[] fSDPLines; fSDPLines = strDup(sdpLines); delete[] sdpLines; @@ -514,7 +530,7 @@ // Create (and start) a 'RTCP instance' for this RTP sink: fRTCPInstance = fMaster.createRTCP(fRTCPgs, fTotalBW, (unsigned char*)fMaster.fCNAME, fRTPSink); // Note: This starts RTCP running automatically - fRTCPInstance->setAppHandler(fMaster.fAppHandlerTask, fMaster.fAppHandlerClientData); + if (fRTCPInstance != NULL) fRTCPInstance->setAppHandler(fMaster.fAppHandlerTask, fMaster.fAppHandlerClientData); } if (dests->isTCP) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/PassiveServerMediaSubsession.cpp new/live/liveMedia/PassiveServerMediaSubsession.cpp --- old/live/liveMedia/PassiveServerMediaSubsession.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/PassiveServerMediaSubsession.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -71,7 +71,12 @@ PassiveServerMediaSubsession::sdpLines(int /*addressFamily*/) { if (fSDPLines == NULL ) { // Construct a set of SDP lines that describe this subsession: - // Use the components from "rtpSink": + // Use the components from "rtpSink". + if (fParentSession->streamingUsesSRTP) { // Hack to set up for SRTP/SRTCP + fRTPSink.setupForSRTP(fParentSession->streamingIsEncrypted); + if (fRTCPInstance != NULL) fRTCPInstance->setupForSRTCP(); + } + Groupsock const& gs = fRTPSink.groupsockBeingUsed(); AddressString groupAddressStr(gs.groupAddress()); unsigned short portNum = ntohs(gs.port().num()); @@ -81,25 +86,28 @@ unsigned estBitrate = fRTCPInstance == NULL ? 50 : fRTCPInstance->totSessionBW(); char* rtpmapLine = fRTPSink.rtpmapLine(); + char* keyMgmtLine = fRTPSink.keyMgmtLine(); char const* rtcpmuxLine = rtcpIsMuxed() ? "a=rtcp-mux\r\n" : ""; char const* rangeLine = rangeSDPLine(); char const* auxSDPLine = fRTPSink.auxSDPLine(); if (auxSDPLine == NULL) auxSDPLine = ""; char const* const sdpFmt = - "m=%s %d RTP/AVP %d\r\n" + "m=%s %d RTP/%sAVP %d\r\n" "c=IN %s %s/%d\r\n" "b=AS:%u\r\n" "%s" "%s" "%s" "%s" + "%s" "a=control:%s\r\n"; unsigned sdpFmtSize = strlen(sdpFmt) - + strlen(mediaType) + 5 /* max short len */ + 3 /* max char len */ + + strlen(mediaType) + 5 /* max short len */ + 1 + 3 /* max char len */ + 3/*IP4 or IP6*/ + strlen(groupAddressStr.val()) + 3 /* max char len */ + 20 /* max int len */ + strlen(rtpmapLine) + + strlen(keyMgmtLine) + strlen(rtcpmuxLine) + strlen(rangeLine) + strlen(auxSDPLine) @@ -108,17 +116,19 @@ sprintf(sdpLines, sdpFmt, mediaType, // m= <media> portNum, // m= <port> + fParentSession->streamingUsesSRTP ? "S" : "", rtpPayloadType, // m= <fmt list> gs.groupAddress().ss_family == AF_INET ? "IP4" : "IP6", // c= address type groupAddressStr.val(), // c= <connection address> ttl, // c= TTL estBitrate, // b=AS:<bandwidth> rtpmapLine, // a=rtpmap:... (if present) + keyMgmtLine, // a=key-mgmt:... (if present) rtcpmuxLine, // a=rtcp-mux:... (if present) rangeLine, // a=range:... (if present) auxSDPLine, // optional extra SDP line trackId()); // a=control:<track-id> - delete[] (char*)rangeLine; delete[] rtpmapLine; + delete[] (char*)rangeLine; delete[] keyMgmtLine; delete[] rtpmapLine; fSDPLines = strDup(sdpLines); delete[] sdpLines; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/RTCP.cpp new/live/liveMedia/RTCP.cpp --- old/live/liveMedia/RTCP.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/RTCP.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -141,6 +141,8 @@ #ifdef DEBUG fprintf(stderr, "RTCPInstance[%p]::RTCPInstance()\n", this); #endif + setupForSRTCP(); + if (fTotSessionBW == 0) { // not allowed! env << "RTCPInstance::RTCPInstance error: totSessionBW parameter should not be zero!\n"; fTotSessionBW = 1; @@ -281,6 +283,12 @@ return fKnownMembers->numMembers(); } +void RTCPInstance::setupForSRTCP() { + if (fCrypto == NULL && fSink != NULL) { // take crypto state (if any) from the sink instead: + fCrypto = fSink->getCrypto(); + } +} + void RTCPInstance::setByeHandler(TaskFunc* handlerTask, void* clientData, Boolean handleActiveParticipantsOnly) { fByeHandlerTask = handlerTask; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/RTPSink.cpp new/live/liveMedia/RTPSink.cpp --- old/live/liveMedia/RTPSink.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/RTPSink.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -19,6 +19,7 @@ // Implementation #include "RTPSink.hh" +#include "Base64.hh" #include "GroupsockHelper.hh" ////////// RTPSink ////////// @@ -51,6 +52,7 @@ : MediaSink(env), fRTPInterface(this, rtpGS), fRTPPayloadType(rtpPayloadType), fPacketCount(0), fOctetCount(0), fTotalOctetCount(0), + fMIKEYState(NULL), fCrypto(NULL), fTimestampFrequency(rtpTimestampFrequency), fNextTimestampHasBeenPreset(False), fEnableRTCPReports(True), fNumChannels(numChannels), fEstimatedBitrate(0) { fRTPPayloadFormatName @@ -69,6 +71,7 @@ RTPSink::~RTPSink() { delete fTransmissionStatsDB; delete[] (char*)fRTPPayloadFormatName; + delete fCrypto; delete fMIKEYState; fRTPInterface.forgetOurGroupsock(); // so that the "fRTPInterface" destructor doesn't turn off background read handling (in case // its 'groupsock' is being shared with something else that does background read handling). @@ -128,6 +131,28 @@ fInitialPresentationTime.tv_usec = fMostRecentPresentationTime.tv_usec = 0; } +void RTPSink::setupForSRTP(Boolean useEncryption) { + // Set up keying state for streaming via SRTP: + delete fCrypto; delete fMIKEYState; + fMIKEYState = new MIKEYState(useEncryption); + fCrypto = new SRTPCryptographicContext(*fMIKEYState); +} + +u_int8_t* RTPSink::setupForSRTP(Boolean useEncryption, unsigned& resultMIKEYStateMessageSize) { + // Set up keying state for streaming via SRTP: + setupForSRTP(useEncryption); + + u_int8_t* MIKEYStateMessage = fMIKEYState->generateMessage(resultMIKEYStateMessageSize); + return MIKEYStateMessage; +} + +void RTPSink::setupForSRTP(u_int8_t const* MIKEYStateMessage, unsigned MIKEYStateMessageSize) { + // Set up keying state for streaming via SRTP: + delete fCrypto; delete fMIKEYState; + fMIKEYState = MIKEYState::createNew(MIKEYStateMessage, MIKEYStateMessageSize); + fCrypto = new SRTPCryptographicContext(*fMIKEYState); +} + char const* RTPSink::sdpMediaType() const { return "data"; // default SDP media (m=) type, unless redefined by subclasses @@ -143,10 +168,10 @@ encodingParamsPart = strDup(""); } char const* const rtpmapFmt = "a=rtpmap:%d %s/%d%s\r\n"; - unsigned rtpmapFmtSize = strlen(rtpmapFmt) + unsigned rtpmapLineSize = strlen(rtpmapFmt) + 3 /* max char len */ + strlen(rtpPayloadFormatName()) + 20 /* max int len */ + strlen(encodingParamsPart); - char* rtpmapLine = new char[rtpmapFmtSize]; + char* rtpmapLine = new char[rtpmapLineSize]; sprintf(rtpmapLine, rtpmapFmt, rtpPayloadType(), rtpPayloadFormatName(), rtpTimestampFrequency(), encodingParamsPart); @@ -154,7 +179,27 @@ return rtpmapLine; } else { - // The payload format is staic, so there's no "a=rtpmap:" line: + // The payload format is static, so there's no "a=rtpmap:" line: + return strDup(""); + } +} + +char* RTPSink::keyMgmtLine() { + u_int8_t* mikeyMessage; + unsigned mikeyMessageSize; + if (fMIKEYState != NULL && + (mikeyMessage = fMIKEYState->generateMessage(mikeyMessageSize)) != NULL) { + char const* const keyMgmtFmt = "a=key-mgmt:mikey %s\r\n"; + char* base64EncodedData = base64Encode((char*)mikeyMessage, mikeyMessageSize); + delete[] mikeyMessage; + + unsigned keyMgmtLineSize = strlen(keyMgmtFmt) + strlen(base64EncodedData); + char* keyMgmtLine = new char[keyMgmtLineSize]; + sprintf(keyMgmtLine, keyMgmtFmt, base64EncodedData); + delete[] base64EncodedData; + + return keyMgmtLine; + } else { // no "a=key-mgmt:" line return strDup(""); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/RTSPClient.cpp new/live/liveMedia/RTSPClient.cpp --- old/live/liveMedia/RTSPClient.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/RTSPClient.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -1021,8 +1021,9 @@ } else { char const* keyMgmtFmt = "KeyMgmt: prot=mikey; uri=\"%s\"; data=\"%s\"\r\n"; char* base64EncodedData = base64Encode((char*)mikeyMessage, mikeyMessageSize); - unsigned keyMgmtSize = strlen(keyMgmtFmt) - + strlen(url) + strlen(base64EncodedData); + delete[] mikeyMessage; + + unsigned keyMgmtSize = strlen(keyMgmtFmt) + strlen(url) + strlen(base64EncodedData); keyMgmtStr = new char[keyMgmtSize]; sprintf(keyMgmtStr, keyMgmtFmt, url, base64EncodedData); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/RTSPServer.cpp new/live/liveMedia/RTSPServer.cpp --- old/live/liveMedia/RTSPServer.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/RTSPServer.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -133,10 +133,16 @@ } void RTSPServer -::setTLSState(char const* certFileName, char const* privKeyFileName, Boolean weServeSRTP) { +::setTLSState(char const* certFileName, char const* privKeyFileName, + Boolean weServeSRTP, Boolean weEncryptSRTP) { setTLSFileNames(certFileName, privKeyFileName); fOurConnectionsUseTLS = True; fWeServeSRTP = weServeSRTP; + fWeEncryptSRTP = weEncryptSRTP; + + if (fWeServeSRTP) disableStreamingRTPOverTCP(); + // If you want to stream RTP-over-TCP using a secure TCP connection, then stream over TLS, + // but without SRTP (as that would add extra overhead for no benefit). } char const* RTSPServer::allowedCommandNames() { @@ -220,6 +226,14 @@ return True; } +void RTSPServer::addServerMediaSession(ServerMediaSession* serverMediaSession) { + GenericMediaServer::addServerMediaSession(serverMediaSession); + if (serverMediaSession != NULL) { + serverMediaSession->streamingUsesSRTP = fWeServeSRTP; + serverMediaSession->streamingIsEncrypted = fWeEncryptSRTP; + } +} + void RTSPServer::incomingConnectionHandlerHTTPIPv4(void* instance, int /*mask*/) { RTSPServer* server = (RTSPServer*)instance; server->incomingConnectionHandlerHTTPIPv4(); @@ -1564,10 +1578,11 @@ "RTSP/1.0 200 OK\r\n" "CSeq: %s\r\n" "%s" - "Transport: RTP/AVP;multicast;destination=%s;source=%s;port=%d-%d;ttl=%d\r\n" + "Transport: RTP/%s;multicast;destination=%s;source=%s;port=%d-%d;ttl=%d\r\n" "Session: %08X%s\r\n\r\n", fOurClientConnection->fCurrentCSeq, dateHeader(), + fOurRTSPServer.fWeServeSRTP ? "SAVP" : "AVP", destAddrStr.val(), sourceAddrStr.val(), ntohs(serverRTPPort.num()), ntohs(serverRTCPPort.num()), destinationTTL, fOurSessionId, timeoutParameterString); break; @@ -1598,10 +1613,11 @@ "RTSP/1.0 200 OK\r\n" "CSeq: %s\r\n" "%s" - "Transport: RTP/AVP;unicast;destination=%s;source=%s;client_port=%d-%d;server_port=%d-%d\r\n" + "Transport: RTP/%s;unicast;destination=%s;source=%s;client_port=%d-%d;server_port=%d-%d\r\n" "Session: %08X%s\r\n\r\n", fOurClientConnection->fCurrentCSeq, dateHeader(), + fOurRTSPServer.fWeServeSRTP ? "SAVP" : "AVP", destAddrStr.val(), sourceAddrStr.val(), ntohs(clientRTPPort.num()), ntohs(clientRTCPPort.num()), ntohs(serverRTPPort.num()), ntohs(serverRTCPPort.num()), fOurSessionId, timeoutParameterString); break; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/SRTPCryptographicContext.cpp new/live/liveMedia/SRTPCryptographicContext.cpp --- old/live/liveMedia/SRTPCryptographicContext.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/SRTPCryptographicContext.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -33,7 +33,7 @@ ::SRTPCryptographicContext(MIKEYState const& mikeyState) #ifndef NO_OPENSSL : fMIKEYState(mikeyState), - fHaveReceivedSRTPPackets(False), fSRTCPIndex(0) { + fHaveReceivedSRTPPackets(False), fHaveSentSRTPPackets(False), fSRTCPIndex(0) { // Begin by doing a key derivation, to generate the keying data that we need: performKeyDerivation(); #else @@ -74,7 +74,7 @@ if (!fHaveReceivedSRTPPackets) { // First time: - nextROC = thisPacketsROC = fROC = 0; + nextROC = thisPacketsROC = fReceptionROC = 0; nextHighRTPSeqNum = rtpSeqNum; } else { // Check whether the sequence number has rolled over, or is out-of-order: @@ -83,23 +83,23 @@ // normal case, or out-of-order packet that crosses a rollover: if (rtpSeqNum - fPreviousHighRTPSeqNum < SEQ_NUM_THRESHOLD) { // normal case: - nextROC = thisPacketsROC = fROC; + nextROC = thisPacketsROC = fReceptionROC; nextHighRTPSeqNum = rtpSeqNum; } else { - // out-of-order packet that crosses rollover: - nextROC = fROC; - thisPacketsROC = fROC-1; + // out-of-order packet that crosses a rollover: + nextROC = fReceptionROC; + thisPacketsROC = fReceptionROC-1; nextHighRTPSeqNum = fPreviousHighRTPSeqNum; } } else { // rollover, or out-of-order packet that crosses a rollover: if (fPreviousHighRTPSeqNum - rtpSeqNum > SEQ_NUM_THRESHOLD) { // rollover: - nextROC = thisPacketsROC = fROC+1; + nextROC = thisPacketsROC = fReceptionROC+1; nextHighRTPSeqNum = rtpSeqNum; } else { // out-of-order packet (that doesn't cross a rollover): - nextROC = thisPacketsROC = fROC; + nextROC = thisPacketsROC = fReceptionROC; nextHighRTPSeqNum = fPreviousHighRTPSeqNum; } } @@ -120,7 +120,7 @@ } // Now that we've verified the packet, set the 'index values' for next time: - fROC = nextROC; + fReceptionROC = nextROC; fPreviousHighRTPSeqNum = nextHighRTPSeqNum; fHaveReceivedSRTPPackets = True; @@ -139,7 +139,7 @@ #endif break; } - u_int16_t hdrExtLength = (buffer[rtpHeaderSize+2]<<8)|buffer[rtpHeaderSize+3]; + u_int16_t const hdrExtLength = (buffer[rtpHeaderSize+2]<<8)|buffer[rtpHeaderSize+3]; rtpHeaderSize += 4 + hdrExtLength*4; } @@ -235,6 +235,90 @@ } Boolean SRTPCryptographicContext +::processOutgoingSRTPPacket(u_int8_t* buffer, unsigned inPacketSize, + unsigned& outPacketSize) { +#ifndef NO_OPENSSL + do { + unsigned const minRTPHeaderSize = 12; + if (inPacketSize < minRTPHeaderSize) { // packet is too small + // Hack: Let small, non RTCP packets through w/o encryption; they may be used to + // punch through NATs + outPacketSize = inPacketSize; + return True; + } + + // Encrypt the appropriate part of the packet. + if (weEncryptSRTP()) { + // Figure out the RTP header size. This will tell us which bytes to encrypt: + unsigned rtpHeaderSize = 12; // at least the basic 12-byte header + rtpHeaderSize += (buffer[0]&0x0F)*4; // # CSRC identifiers + if ((buffer[0]&0x10) != 0) { + // There's a RTP extension header. Add its size: + if (inPacketSize < rtpHeaderSize + 4) { +#ifdef DEBUG + fprintf(stderr, "SRTPCryptographicContext::processOutgoingSRTPPacket(): Error: Packet size %d is shorter than the minimum specified RTP header size %d!\n", inPacketSize, rtpHeaderSize + 4); +#endif + break; + } + u_int16_t const hdrExtLength = (buffer[rtpHeaderSize+2]<<8)|buffer[rtpHeaderSize+3]; + rtpHeaderSize += 4 + hdrExtLength*4; + } + + unsigned const offsetToEncryptedBytes = rtpHeaderSize; + if (inPacketSize < offsetToEncryptedBytes) { +#ifdef DEBUG + fprintf(stderr, "SRTPCryptographicContext::processOutgoingSRTPPacket(): Error: Packet size %d is too small (should be >= %d)!\n", inPacketSize, offsetToEncryptedBytes); +#endif + break; + } + + // Figure out this packet's 'index' (ROC|rtpSeqNum): + u_int16_t const rtpSeqNum = (buffer[2]<<8)|buffer[3]; + if (!fHaveSentSRTPPackets) { + fSendingROC = 0; + fHaveSentSRTPPackets = True; // for the future + } else { + if (rtpSeqNum == 0) ++fSendingROC; // increment the ROC when the RTP seq num rolls over + } + u_int64_t index = (fSendingROC<<16)|rtpSeqNum; + + unsigned const numEncryptedBytes = inPacketSize - offsetToEncryptedBytes; // ASSERT: >= 0 + u_int32_t const SSRC = (buffer[8]<<24)|(buffer[9]<<16)|(buffer[10]<<8)|buffer[11]; + encryptSRTPPacket(index, SSRC, &buffer[offsetToEncryptedBytes], numEncryptedBytes); + } + + outPacketSize = inPacketSize; // initially + + unsigned const mkiPosition = outPacketSize; // where the MKI will go + + if (weAuthenticate()) { + // Append the ROC to the payload, because it's used to generate the authentication tag. + // (Next, the MKI will take its place.) + buffer[outPacketSize++] = fSendingROC>>24; + buffer[outPacketSize++] = fSendingROC>>16; + buffer[outPacketSize++] = fSendingROC>>8; + buffer[outPacketSize++] = fSendingROC; + + // Generate and add an authentication tag over the whole packet, plus the ROC: + outPacketSize += generateSRTPAuthenticationTag(buffer, outPacketSize, + &buffer[outPacketSize]); + } + + // Add the MKI: + buffer[mkiPosition] = MKI()>>24; + buffer[mkiPosition+1] = MKI()>>16; + buffer[mkiPosition+2] = MKI()>>8; + buffer[mkiPosition+3] = MKI(); + + return True; + } while (0); +#endif + + // An error occurred: + return False; +} + +Boolean SRTPCryptographicContext ::processOutgoingSRTCPPacket(u_int8_t* buffer, unsigned inPacketSize, unsigned& outPacketSize) { #ifndef NO_OPENSSL @@ -286,6 +370,13 @@ #ifndef NO_OPENSSL unsigned SRTPCryptographicContext +::generateSRTPAuthenticationTag(u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, + u_int8_t* resultAuthenticationTag) { + return generateAuthenticationTag(fDerivedKeys.srtp, dataToAuthenticate, numBytesToAuthenticate, + resultAuthenticationTag); +} + +unsigned SRTPCryptographicContext ::generateSRTCPAuthenticationTag(u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, u_int8_t* resultAuthenticationTag) { return generateAuthenticationTag(fDerivedKeys.srtcp, dataToAuthenticate, numBytesToAuthenticate, @@ -343,6 +434,11 @@ } void SRTPCryptographicContext +::encryptSRTPPacket(u_int64_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes) { + cryptData(fDerivedKeys.srtp, index, ssrc, data, numDataBytes); +} + +void SRTPCryptographicContext ::encryptSRTCPPacket(u_int32_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes) { cryptData(fDerivedKeys.srtcp, (u_int64_t)index, ssrc, data, numDataBytes); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/ServerMediaSession.cpp new/live/liveMedia/ServerMediaSession.cpp --- old/live/liveMedia/ServerMediaSession.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/ServerMediaSession.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -63,7 +63,8 @@ char const* info, char const* description, Boolean isSSM, char const* miscSDPLines) - : Medium(env), fIsSSM(isSSM), fSubsessionsHead(NULL), + : Medium(env), streamingUsesSRTP(False), streamingIsEncrypted(False), + fIsSSM(isSSM), fSubsessionsHead(NULL), fSubsessionsTail(NULL), fSubsessionCounter(0), fReferenceCount(0), fDeleteWhenUnreferenced(False) { fStreamName = strDup(streamName == NULL ? "" : streamName); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/GenericMediaServer.hh new/live/liveMedia/include/GenericMediaServer.hh --- old/live/liveMedia/include/GenericMediaServer.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/GenericMediaServer.hh 2022-02-07 11:35:51.000000000 +0100 @@ -43,7 +43,7 @@ class GenericMediaServer: public Medium { public: - void addServerMediaSession(ServerMediaSession* serverMediaSession); + virtual void addServerMediaSession(ServerMediaSession* serverMediaSession); virtual void lookupServerMediaSession(char const* streamName, lookupServerMediaSessionCompletionFunc* completionFunc, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/MIKEY.hh new/live/liveMedia/include/MIKEY.hh --- old/live/liveMedia/include/MIKEY.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/MIKEY.hh 2022-02-07 11:35:51.000000000 +0100 @@ -30,14 +30,12 @@ class MIKEYState { public: - MIKEYState(); // initialize with default parameters + MIKEYState(Boolean useEncryption = True); // initialize with default parameters virtual ~MIKEYState(); - static MIKEYState* createNew(u_int8_t* messageToParse, unsigned messageSize); + static MIKEYState* createNew(u_int8_t const* messageToParse, unsigned messageSize); // (Attempts to) parse a binary MIKEY message, returning a new "MIKEYState" if successful // (or NULL if unsuccessful). - // ("messageToParse" is assumed to have been dynamically allocated; - // this function will delete[] it.) u_int8_t* generateMessage(unsigned& messageSize) const; // Returns a binary message representing the current MIKEY state, of size "messageSize" bytes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/OnDemandServerMediaSubsession.hh new/live/liveMedia/include/OnDemandServerMediaSubsession.hh --- old/live/liveMedia/include/OnDemandServerMediaSubsession.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/OnDemandServerMediaSubsession.hh 2022-02-07 11:35:51.000000000 +0100 @@ -133,6 +133,8 @@ protected: char* fSDPLines; + u_int8_t* fMIKEYStateMessage; // used if we're streaming SRTP + unsigned fMIKEYStateMessageSize; // ditto HashTable* fDestinationsHashTable; // indexed by client session id private: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/RTCP.hh new/live/liveMedia/include/RTCP.hh --- old/live/liveMedia/include/RTCP.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/RTCP.hh 2022-02-07 11:35:51.000000000 +0100 @@ -66,6 +66,8 @@ unsigned numMembers() const; unsigned totSessionBW() const { return fTotSessionBW; } + void setupForSRTCP(); + void setByeHandler(TaskFunc* handlerTask, void* clientData, Boolean handleActiveParticipantsOnly = True); // Assigns a handler routine to be called if a "BYE" arrives. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/RTPSink.hh new/live/liveMedia/include/RTPSink.hh --- old/live/liveMedia/include/RTPSink.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/RTPSink.hh 2022-02-07 11:35:51.000000000 +0100 @@ -27,6 +27,9 @@ #ifndef _RTP_INTERFACE_HH #include "RTPInterface.hh" #endif +#ifndef _SRTP_CRYPTOGRAPHIC_CONTEXT_HH +#include "SRTPCryptographicContext.hh" +#endif class RTPTransmissionStatsDB; // forward @@ -48,8 +51,16 @@ unsigned numChannels() const { return fNumChannels; } + void setupForSRTP(Boolean useEncryption); + // sets up keying/encryption state for streaming via SRTP, using default values. + u_int8_t* setupForSRTP(Boolean useEncryption, unsigned& resultMIKEYStateMessageSize); + // as above, but returns the binary MIKEY state + void setupForSRTP(u_int8_t const* MIKEYStateMessage, unsigned MIKEYStateMessageSize); + // as above, but takes a MIKEY state message as parameter + virtual char const* sdpMediaType() const; // for use in SDP m= lines virtual char* rtpmapLine() const; // returns a string to be delete[]d + virtual char* keyMgmtLine(); // returns a string to be delete[]d virtual char const* auxSDPLine(); // optional SDP line (e.g. a=fmtp:...) @@ -89,6 +100,8 @@ u_int32_t SSRC() const {return fSSRC;} // later need a means of changing the SSRC if there's a collision ##### + SRTPCryptographicContext* getCrypto() const { return fCrypto; } + protected: RTPSink(UsageEnvironment& env, Groupsock* rtpGS, unsigned char rtpPayloadType, @@ -114,6 +127,10 @@ u_int32_t fCurrentTimestamp; u_int16_t fSeqNo; + // Optional key management and crypto state; used if we are streaming SRTP + MIKEYState* fMIKEYState; + SRTPCryptographicContext* fCrypto; + private: // redefined virtual functions: virtual Boolean isRTPSink() const; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/RTSPServer.hh new/live/liveMedia/include/RTSPServer.hh --- old/live/liveMedia/include/RTSPServer.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/RTSPServer.hh 2022-02-07 11:35:51.000000000 +0100 @@ -110,7 +110,7 @@ portNumBits httpServerPortNum() const; // in host byte order. (Returns 0 if not present.) void setTLSState(char const* certFileName, char const* privKeyFileName, - Boolean weServeSRTP = False/*later change to True #####@@@@@*/); + Boolean weServeSRTP = True, Boolean weEncryptSRTP = True); protected: RTSPServer(UsageEnvironment& env, @@ -141,8 +141,9 @@ // - this time after normal digest authentication has already taken place (and would otherwise allow access). // (This test can only be used to further restrict access, not to grant additional access.) -private: // redefined virtual functions +public: // redefined virtual functions virtual Boolean isRTSPServer() const; + virtual void addServerMediaSession(ServerMediaSession* serverMediaSession); public: // should be protected, but some old compilers complain otherwise // The state of a TCP connection used by a RTSP client: @@ -332,6 +333,7 @@ Boolean fAllowStreamingRTPOverTCP; // by default, True Boolean fOurConnectionsUseTLS; // by default, False Boolean fWeServeSRTP; // used only if "fOurConnectionsUseTLS" is True + Boolean fWeEncryptSRTP; // used only if "fWeServeSRTP" is True }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/SRTPCryptographicContext.hh new/live/liveMedia/include/SRTPCryptographicContext.hh --- old/live/liveMedia/include/SRTPCryptographicContext.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/SRTPCryptographicContext.hh 2022-02-07 11:35:51.000000000 +0100 @@ -38,12 +38,14 @@ unsigned& outPacketSize); // Encrypt (if necessary) and add an authentication tag (if necessary) to an outgoing - // RTCP packet. + // RTP and RTCP packet. // Returns True iff the packet is well-formed. // ("outPacketSize" will be >= "inPacketSize"; there must be enough space at the end of - // "buffer" for the extra SRTCP tags (4+4+10 bytes).) + // "buffer" for the extra (4+10 bytes for SRTP; 4+4+10 bytes for SRTCP).) + Boolean processOutgoingSRTPPacket(u_int8_t* buffer, unsigned inPacketSize, + unsigned& outPacketSize); Boolean processOutgoingSRTCPPacket(u_int8_t* buffer, unsigned inPacketSize, - unsigned& outPacketSize); + unsigned& outPacketSize); #ifndef NO_OPENSSL private: @@ -75,6 +77,9 @@ label_srtcp_salt = 0x05 } SRTPKeyDerivationLabel; + unsigned generateSRTPAuthenticationTag(u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, + u_int8_t* resultAuthenticationTag); + // returns the size of the resulting authentication tag unsigned generateSRTCPAuthenticationTag(u_int8_t const* dataToAuthenticate, unsigned numBytesToAuthenticate, u_int8_t* resultAuthenticationTag); // returns the size of the resulting authentication tag @@ -87,6 +92,7 @@ void decryptSRTPPacket(u_int64_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes); void decryptSRTCPPacket(u_int32_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes); + void encryptSRTPPacket(u_int64_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes); void encryptSRTCPPacket(u_int32_t index, u_int32_t ssrc, u_int8_t* data, unsigned numDataBytes); unsigned generateAuthenticationTag(derivedKeys& keysToUse, @@ -132,7 +138,11 @@ // State used for handling the reception of SRTP packets: Boolean fHaveReceivedSRTPPackets; u_int16_t fPreviousHighRTPSeqNum; - u_int32_t fROC; // rollover counter + u_int32_t fReceptionROC; // rollover counter + + // State used for handling the sending of SRTP packets: + Boolean fHaveSentSRTPPackets; + u_int32_t fSendingROC; // State used for handling the sending of SRTCP packets: u_int32_t fSRTCPIndex; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/ServerMediaSession.hh new/live/liveMedia/include/ServerMediaSession.hh --- old/live/liveMedia/include/ServerMediaSession.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/ServerMediaSession.hh 2022-02-07 11:35:51.000000000 +0100 @@ -73,6 +73,9 @@ // you must first close any client connections that use it, // by calling "RTSPServer::closeAllClientSessionsForServerMediaSession()". + Boolean streamingUsesSRTP; // by default, False + Boolean streamingIsEncrypted; // by default, False + protected: ServerMediaSession(UsageEnvironment& env, char const* streamName, char const* info, char const* description, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/liveMedia/include/liveMedia_version.hh new/live/liveMedia/include/liveMedia_version.hh --- old/live/liveMedia/include/liveMedia_version.hh 2021-12-18 23:29:19.000000000 +0100 +++ new/live/liveMedia/include/liveMedia_version.hh 2022-02-07 11:35:51.000000000 +0100 @@ -14,12 +14,12 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA **********/ // Version information for the "liveMedia" library -// Copyright (c) 1996-2021 Live Networks, Inc. All rights reserved. +// Copyright (c) 1996-2022 Live Networks, Inc. All rights reserved. #ifndef _LIVEMEDIA_VERSION_HH #define _LIVEMEDIA_VERSION_HH -#define LIVEMEDIA_LIBRARY_VERSION_STRING "2021.12.18" -#define LIVEMEDIA_LIBRARY_VERSION_INT 1639785600 +#define LIVEMEDIA_LIBRARY_VERSION_STRING "2022.02.07" +#define LIVEMEDIA_LIBRARY_VERSION_INT 1644192000 #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/live/testProgs/announceURL.cpp new/live/testProgs/announceURL.cpp --- old/live/testProgs/announceURL.cpp 2021-12-18 23:29:19.000000000 +0100 +++ new/live/testProgs/announceURL.cpp 2022-02-07 11:35:51.000000000 +0100 @@ -22,7 +22,7 @@ #include <GroupsockHelper.hh> // for "weHaveAnIPv*Address()" void announceURL(RTSPServer* rtspServer, ServerMediaSession* sms) { - if (rtspServer == NULL || sms == NULL) return; // sanuty check + if (rtspServer == NULL || sms == NULL) return; // sanity check UsageEnvironment& env = rtspServer->envir();