1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3 // Copyright (C) 2015 Cherokees of Idaho.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 //
19 // As a special exception, you may use this file as part of a free software
20 // library without restriction.  Specifically, if other files instantiate
21 // templates or use macros or inline functions from this file, or you compile
22 // this file and link it with other files to produce an executable, this
23 // file does not by itself cause the resulting executable to be covered by
24 // the GNU General Public License.  This exception does not however
25 // invalidate any other reasons why the executable file might be covered by
26 // the GNU General Public License.
27 //
28 // This exception applies only to the code released under the name GNU
29 // ccRTP.  If you copy code from other releases into a copy of GNU
30 // ccRTP, as the General Public License permits, the exception does
31 // not apply to the code that you add in this way.  To avoid misleading
32 // anyone as to the status of such modified files, you must delete
33 // this exception notice from them.
34 //
35 // If you write modifications of your own for GNU ccRTP, it is your choice
36 // whether to permit this exception to apply to your modifications.
37 // If you do not wish that, delete this exception notice.
38 //
39 
40 /**
41  * @file rtppkt.cpp
42  * @short StaticPayloadFormat, DynamicPayloadFormat, RTPPacket,
43  * OutgoingRTPPkt and IncomingRTPPkt classes implementation.
44  **/
45 
46 #include "private.h"
47 #include <ccrtp/rtppkt.h>
48 #include <ccrtp/CryptoContext.h>
49 
50 NAMESPACE_COMMONCPP
51 
52 // Default to 8Khz when no value is specified.
53 const uint32 PayloadFormat::defaultRTPClockRate = 8000;
54 
55 //uint32 PayloadFormat::staticRates[lastStaticPayloadType]
56 uint32 StaticPayloadFormat::staticAudioTypesRates[] = {
57     // audio types:
58     8000,    //  0 - sptPCMU
59     0,       //  1 - reserved
60     8000,    //  2 - sptG726_32
61     8000,    //  3 - sptGSM
62     8000,    //  4 - sptG723
63     8000,    //  5 - sptDVI4_8000
64     16000,   //  6 - sptDVI4_16000
65     8000,    //  7 - sptLPC
66     8000,    //  8 - sptPCMA
67     8000,    //  9 - sptG722
68     44100,   // 10 - sptL16_DUAL
69     44100,   // 11 - sptL16_MONO
70     8000,    // 12 - sptQCELP
71     0,       // 13 - reserved
72     90000,   // 14 - sptMPA
73     8000,    // 15 - sptG728
74     11015,   // 16 - sptDVI4_11025
75     22050,   // 17 - sptDVI4_22050
76     8000     // 18 - sptG729
77 /*  0,       // reserved
78     0,       // unassigned
79     0,       // unassigned
80     0,       // unassigned
81     0        // unassigned
82 */
83     // All video types have 90000 hz RTP clock rate.
84     // If sometime in the future a static video payload type is
85     // defined with a different RTP clock rate (quite
86     // unprobable). This table and/or the StaticPayloadType
87     // constructor must be changed.
88 };
89 
StaticPayloadFormat(StaticPayloadType type)90 StaticPayloadFormat::StaticPayloadFormat(StaticPayloadType type)
91 {
92     setPayloadType( (type <= lastStaticPayloadType)? type : 0);
93     if ( type <= sptG729 ) {
94         // audio static type
95         setRTPClockRate(staticAudioTypesRates[type]);
96     } else {
97         // video static type
98         setRTPClockRate(90000);
99     }
100 }
101 
DynamicPayloadFormat(PayloadType type,uint32 rate)102 DynamicPayloadFormat::DynamicPayloadFormat(PayloadType type, uint32 rate)
103 {
104     PayloadFormat::setPayloadType(type);
105     setRTPClockRate(rate);
106 }
107 
108 // constructor commonly used for incoming packets
RTPPacket(const unsigned char * const block,size_t len,bool duplicate)109 RTPPacket::RTPPacket(const unsigned char* const block, size_t len, bool duplicate) :
110 total((uint32)len), duplicated(duplicate)
111 {
112     const RTPFixedHeader* const header =
113         reinterpret_cast<const RTPFixedHeader*>(block);
114     hdrSize = sizeof(RTPFixedHeader) + (header->cc << 2);
115     if ( header->extension ){
116         RTPHeaderExt *ext = (RTPHeaderExt *)(block + hdrSize);
117                 hdrSize += sizeof(uint32) + (ntohs(ext->length) * 4);
118     }
119     if ( header->padding )
120         len -= block[len - 1];
121     payloadSize = (uint32)(len - hdrSize);
122 
123     if ( duplicate ) {
124         buffer = new unsigned char[len];
125         setbuffer(block,len,0);
126     } else {
127         buffer = const_cast<unsigned char*>(block);
128     }
129 }
130 
131 // constructor commonly used for outgoing packets
RTPPacket(size_t hdrlen,size_t plen,uint8 paddinglen,CryptoContext * pcc)132 RTPPacket::RTPPacket(size_t hdrlen, size_t plen, uint8 paddinglen, CryptoContext* pcc ) :
133 payloadSize((uint32)plen), buffer(NULL), hdrSize((uint32)hdrlen),
134 duplicated(false)
135 {
136     total = (uint32)(hdrlen + payloadSize);
137     // compute if there must be padding
138     uint8 padding = 0;
139     if ( 0 != paddinglen ) {
140         padding = paddinglen - (total % paddinglen);
141         total += padding;
142     }
143     srtpLength = 0;
144     srtpDataOffset = 0;
145     if (pcc != NULL) {
146         // compute additional memory for SRTP data
147         srtpLength = pcc->getTagLength() + pcc->getMkiLength();
148         srtpDataOffset = total; // SRTP data go behind header plus payload plus padding
149     }
150 
151     // now we know the actual total length of the packet, get  some memory
152     // but take SRTP data into account. Don't change total because some RTP
153     // functions rely on the fact that total is the overall size (without
154     // the SRTP data)
155     buffer = new unsigned char[total + srtpLength];
156     *(reinterpret_cast<uint32*>(getHeader())) = 0;
157     getHeader()->version = CCRTP_VERSION;
158     if ( 0 != padding ) {
159         memset(buffer + total - padding,0,padding - 1);
160         buffer[total - 1] = padding;
161         getHeader()->padding = 1;
162     } else {
163         getHeader()->padding = 0;
164     }
165 }
166 
endPacket()167 void RTPPacket::endPacket()
168 {
169 #ifdef  CCXX_EXCEPTIONS
170     try {
171 #endif
172         delete [] buffer;
173 #ifdef  CCXX_EXCEPTIONS
174     } catch (...) { };
175 #endif
176 }
177 
reComputePayLength(bool padding)178 void RTPPacket::reComputePayLength(bool padding)
179 {
180     // If payloadsize was computed without padding set then re-compute
181     // payloadSize after the padding bit was set and set padding flag
182     // in RTP header - option for SRTP
183     if (padding) {
184         size_t len = 0;
185         getHeader()->padding = 1;
186         len -= buffer[payloadSize - 1];
187         payloadSize = (uint32)(payloadSize - len);
188     }
189 }
190 
OutgoingRTPPkt(const uint32 * const csrcs,uint16 numcsrc,const unsigned char * const hdrext,uint32 hdrextlen,const unsigned char * const data,size_t datalen,uint8 paddinglen,CryptoContext * pcc)191 OutgoingRTPPkt::OutgoingRTPPkt(const uint32* const csrcs, uint16 numcsrc,
192 const unsigned char* const hdrext, uint32 hdrextlen,
193 const unsigned char* const data, size_t datalen,
194 uint8 paddinglen, CryptoContext* pcc) :
195 RTPPacket((getSizeOfFixedHeader() + sizeof(uint32) * numcsrc + hdrextlen),datalen,paddinglen, pcc)
196 {
197     uint32 pointer = (uint32)getSizeOfFixedHeader();
198     // add CSCR identifiers (putting them in network order).
199     setCSRCArray(csrcs,numcsrc);
200     pointer += numcsrc * sizeof(uint32);
201 
202     // add header extension.
203     setbuffer(hdrext,hdrextlen,pointer);
204     setExtension(hdrextlen > 0);
205     pointer += hdrextlen;
206 
207     // add data.
208     setbuffer(data,datalen,pointer);
209 }
210 
OutgoingRTPPkt(const uint32 * const csrcs,uint16 numcsrc,const unsigned char * data,size_t datalen,uint8 paddinglen,CryptoContext * pcc)211 OutgoingRTPPkt::OutgoingRTPPkt(const uint32* const csrcs, uint16 numcsrc,
212 const unsigned char* data, size_t datalen, uint8 paddinglen, CryptoContext* pcc) :
213 RTPPacket((getSizeOfFixedHeader() + sizeof(uint32) *numcsrc),datalen, paddinglen, pcc)
214 {
215     uint32 pointer = (uint32)getSizeOfFixedHeader();
216     // add CSCR identifiers (putting them in network order).
217     setCSRCArray(csrcs,numcsrc);
218     pointer += numcsrc * sizeof(uint32);
219 
220     // not needed, as the RTPPacket constructor sets by default
221     // the whole fixed header to 0.
222     // getHeader()->extension = 0;
223 
224     // add data.
225     setbuffer(data,datalen,pointer);
226 }
227 
OutgoingRTPPkt(const unsigned char * data,size_t datalen,uint8 paddinglen,CryptoContext * pcc)228 OutgoingRTPPkt::OutgoingRTPPkt(const unsigned char* data, size_t datalen,
229 uint8 paddinglen, CryptoContext* pcc) :
230 RTPPacket(getSizeOfFixedHeader(),datalen,paddinglen, pcc)
231 {
232     // not needed, as the RTPPacket constructor sets by default
233     // the whole fixed header to 0.
234     //getHeader()->cc = 0;
235     //getHeader()->extension = 0;
236 
237     setbuffer(data,datalen,getSizeOfFixedHeader());
238 }
239 
setCSRCArray(const uint32 * const csrcs,uint16 numcsrc)240 void OutgoingRTPPkt::setCSRCArray(const uint32* const csrcs, uint16 numcsrc)
241 {
242     setbuffer(csrcs, numcsrc * sizeof(uint32),getSizeOfFixedHeader());
243     uint32* csrc = const_cast<uint32*>(getCSRCs());
244     for ( int i = 0; i < numcsrc; i++ )
245         csrc[i] = htonl(csrc[i]);
246     getHeader()->cc = numcsrc;
247 }
248 
protect(uint32 ssrc,CryptoContext * pcc)249 void OutgoingRTPPkt::protect(uint32 ssrc, CryptoContext* pcc)
250 {
251     /* Encrypt the packet */
252     uint64 index = ((uint64)pcc->getRoc() << 16) | (uint64)getSeqNum();
253 
254     pcc->srtpEncrypt(this, index, ssrc);
255 
256     // NO MKI support yet - here we assume MKI is zero. To build in MKI
257     // take MKI length into account when storing the authentication tag.
258 
259     /* Compute MAC */
260     pcc->srtpAuthenticate(this, pcc->getRoc(),
261                                 const_cast<uint8*>(getRawPacket()+srtpDataOffset) );
262     /* Update the ROC if necessary */
263     if (getSeqNum() == 0xFFFF ) {
264         pcc->setRoc(pcc->getRoc() + 1);
265     }
266 }
267 
268 // These masks are valid regardless of endianness.
269 const uint16 IncomingRTPPkt::RTP_INVALID_PT_MASK = (0x7e);
270 const uint16 IncomingRTPPkt::RTP_INVALID_PT_VALUE = (0x48);
271 
IncomingRTPPkt(const unsigned char * const block,size_t len)272 IncomingRTPPkt::IncomingRTPPkt(const unsigned char* const block, size_t len) :
273 RTPPacket(block,len)
274 {
275     // first, perform validity check:
276     // 1) check protocol version
277     // 2) it is not an SR nor an RR
278     // 3) consistent length field value (taking CC value and P and
279     //    X bits into account)
280     if ( getProtocolVersion() != CCRTP_VERSION || (getPayloadType() & RTP_INVALID_PT_MASK) == RTP_INVALID_PT_VALUE) {
281             /*
282          ||
283          getPayloadSize() <= 0 ) {
284             */
285         headerValid = false;
286         return;
287     }
288     headerValid = true;
289     cachedTimestamp = getRawTimestamp();
290     cachedSeqNum = ntohs(getHeader()->sequence);
291     cachedSSRC = ntohl(getHeader()->sources[0]);
292 }
293 
unprotect(CryptoContext * pcc)294 int32 IncomingRTPPkt::unprotect(CryptoContext* pcc)
295 {
296     if (pcc == NULL) {
297         return true;
298     }
299 
300     /*
301      * This is the setting of the packet data when we come to this
302      * point:
303      *
304      * total:       complete length of received data
305      * buffer:      points to data as received from network
306      * hdrSize:     length of header including header extension
307      * payloadSize: length of data excluding hdrSize and padding
308      *
309      * Because this is an SRTP packet we need to adjust some values here.
310      * The SRTP MKI and authentication data is always at the end of a
311      * packet. Thus compute the position of this data.
312      */
313 
314     uint32 srtpDataIndex = total - (pcc->getTagLength() + pcc->getMkiLength());
315 
316     // now adjust total because some RTP functions rely on the fact that
317     // total is the full length of data without SRTP data.
318     total -= pcc->getTagLength() + pcc->getMkiLength();
319 
320     // recompute payloadSize by subtracting SRTP data
321     payloadSize -= pcc->getTagLength() + pcc->getMkiLength();
322 
323     // unused??
324     // const uint8* mki = getRawPacket() + srtpDataIndex;
325     const uint8* tag = getRawPacket() + srtpDataIndex + pcc->getMkiLength();
326 
327     /* Replay control */
328     if (!pcc->checkReplay(cachedSeqNum)) {
329         return -2;
330     }
331     /* Guess the index */
332     uint64 guessedIndex = pcc->guessIndex(cachedSeqNum);
333 
334     uint32 guessedRoc = (uint32)(guessedIndex >> 16);
335     uint8* mac = new uint8[pcc->getTagLength()];
336 
337     pcc->srtpAuthenticate(this, guessedRoc, mac);
338     if (memcmp(tag, mac, pcc->getTagLength()) != 0) {
339         delete[] mac;
340         return -1;
341     }
342     delete[] mac;
343 
344     /* Decrypt the content */
345     pcc->srtpEncrypt( this, guessedIndex, cachedSSRC );
346 
347     /* Update the Crypto-context */
348     pcc->update(cachedSeqNum);
349 
350     return 1;
351 }
352 
353 END_NAMESPACE
354 
355 /** EMACS **
356  * Local variables:
357  * mode: c++
358  * c-basic-offset: 4
359  * End:
360  */
361