Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 1 | /*
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 2 | Copyright (C) 2008-2012 Werner Dittmann
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 3 |
|
| 4 | This library is free software; you can redistribute it and/or
|
| 5 | modify it under the terms of the GNU Lesser General Public
|
| 6 | License as published by the Free Software Foundation; either
|
| 7 | version 2.1 of the License, or (at your option) any later version.
|
| 8 |
|
| 9 | This library is distributed in the hope that it will be useful,
|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
| 12 | Lesser General Public License for more details.
|
| 13 |
|
| 14 | You should have received a copy of the GNU Lesser General Public
|
| 15 | License along with this library; if not, write to the Free Software
|
| 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
| 17 |
|
| 18 | * In addition, as a special exception, the copyright holders give
|
| 19 | * permission to link the code of portions of this program with the
|
| 20 | * OpenSSL library under certain conditions as described in each
|
| 21 | * individual source file, and distribute linked combinations
|
| 22 | * including the two.
|
| 23 | * You must obey the GNU General Public License in all respects
|
| 24 | * for all of the code used other than OpenSSL. If you modify
|
| 25 | * file(s) with this exception, you may extend this exception to your
|
| 26 | * version of the file(s), but you are not obligated to do so. If you
|
| 27 | * do not wish to do so, delete this exception statement from your
|
| 28 | * version. If you delete this exception statement from all source
|
| 29 | * files in the program, then also delete it here.
|
| 30 | */
|
| 31 |
|
| 32 |
|
| 33 |
|
| 34 | #ifndef SRTPSYMCRYPTO_H
|
| 35 | #define SRTPSYMCRYPTO_H
|
| 36 |
|
| 37 | /**
|
| 38 | * @file SrtpSymCrypto.h
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 39 | * @brief Class which implements SRTP cryptographic functions
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 40 | *
|
| 41 | * @ingroup GNU_ZRTP
|
| 42 | * @{
|
| 43 | */
|
| 44 |
|
| 45 | #include <stdint.h>
|
| 46 | #include <CryptoContext.h>
|
| 47 |
|
| 48 | #ifndef SRTP_BLOCK_SIZE
|
| 49 | #define SRTP_BLOCK_SIZE 16
|
| 50 | #endif
|
| 51 |
|
| 52 | typedef struct _f8_ctx {
|
| 53 | unsigned char *S; ///< Intermetiade buffer
|
| 54 | unsigned char *ivAccent; ///< second IV
|
| 55 | uint32_t J; ///< Counter
|
| 56 | } F8_CIPHER_CTX;
|
| 57 |
|
| 58 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 59 | * @brief Implments the SRTP encryption modes as defined in RFC3711
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 60 | *
|
| 61 | * The SRTP specification defines two encryption modes, AES-CTR
|
| 62 | * (AES Counter mode) and AES-F8 mode. The AES-CTR is required,
|
| 63 | * AES-F8 is optional.
|
| 64 | *
|
| 65 | * Both modes are desinged to encrypt/decrypt data of arbitrary length
|
| 66 | * (with a specified upper limit, refer to RFC 3711). These modes do
|
| 67 | * <em>not</em> require that the amount of data to encrypt is a multiple
|
| 68 | * of the AES blocksize (16 bytes), no padding is necessary.
|
| 69 | *
|
| 70 | * The implementation uses the openSSL library as its cryptographic
|
| 71 | * backend.
|
| 72 | *
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 73 | * @author Werner Dittmann <Werner.Dittmann@t-online.de>
|
| 74 | */
|
| 75 | class SrtpSymCrypto {
|
| 76 | public:
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 77 | /**
|
| 78 | * @brief Constructor that does not initialize key data
|
| 79 | *
|
| 80 | * @param algo
|
| 81 | * The Encryption algorithm to use.Possible values are <code>
|
| 82 | * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8
|
| 83 | * SrtpEncryptionTWOCM, SrtpEncryptionTWOF8</code>. See chapter 4.1.1
|
| 84 | * for CM (Counter mode) and 4.1.2 for F8 mode.
|
| 85 | */
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 86 | SrtpSymCrypto(int algo = SrtpEncryptionAESCM);
|
| 87 |
|
| 88 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 89 | * @brief Constructor that initializes key data
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 90 | *
|
| 91 | * @param key
|
| 92 | * Pointer to key bytes.
|
| 93 | * @param key_length
|
| 94 | * Number of key bytes.
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 95 | * @param algo
|
| 96 | * The Encryption algorithm to use.Possible values are <code>
|
| 97 | * SrtpEncryptionNull, SrtpEncryptionAESCM, SrtpEncryptionAESF8
|
| 98 | * SrtpEncryptionTWOCM, SrtpEncryptionTWOF8</code>. See chapter 4.1.1
|
| 99 | * for CM (Counter mode) and 4.1.2 for F8 mode.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 100 | */
|
| 101 | SrtpSymCrypto(uint8_t* key, int32_t key_length, int algo = SrtpEncryptionAESCM);
|
| 102 |
|
| 103 | ~SrtpSymCrypto();
|
| 104 |
|
| 105 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 106 | * @brief Encrypts the input to the output.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 107 | *
|
| 108 | * Encrypts one input block to one output block. Each block
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 109 | * is 16 bytes according to the encryption algorithms used.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 110 | *
|
| 111 | * @param input
|
| 112 | * Pointer to input block, must be 16 bytes
|
| 113 | *
|
| 114 | * @param output
|
| 115 | * Pointer to output block, must be 16 bytes
|
| 116 | */
|
| 117 | void encrypt( const uint8_t* input, uint8_t* output );
|
| 118 |
|
| 119 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 120 | * @brief Set new key
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 121 | *
|
| 122 | * @param key
|
| 123 | * Pointer to key data, must have at least a size of keyLength
|
| 124 | *
|
| 125 | * @param keyLength
|
| 126 | * Length of the key in bytes, must be 16, 24, or 32
|
| 127 | *
|
| 128 | * @return
|
| 129 | * false if key could not set.
|
| 130 | */
|
| 131 | bool setNewKey(const uint8_t* key, int32_t keyLength);
|
| 132 |
|
| 133 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 134 | * @brief Computes the cipher stream for AES CM mode.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 135 | *
|
| 136 | * @param output
|
| 137 | * Pointer to a buffer that receives the cipher stream. Must be
|
| 138 | * at least <code>length</code> bytes long.
|
| 139 | *
|
| 140 | * @param length
|
| 141 | * Number of cipher stream bytes to produce. Usually the same
|
| 142 | * length as the data to be encrypted.
|
| 143 | *
|
| 144 | * @param iv
|
| 145 | * The initialization vector as input to create the cipher stream.
|
| 146 | * Refer to chapter 4.1.1 in RFC 3711.
|
| 147 | */
|
| 148 | void get_ctr_cipher_stream(uint8_t* output, uint32_t length, uint8_t* iv);
|
| 149 |
|
| 150 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 151 | * @brief Counter-mode encryption.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 152 | *
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 153 | * This method performs the CM encryption.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 154 | *
|
| 155 | * @param input
|
| 156 | * Pointer to input buffer, must be <code>inputLen</code> bytes.
|
| 157 | *
|
| 158 | * @param inputLen
|
| 159 | * Number of bytes to process.
|
| 160 | *
|
| 161 | * @param output
|
| 162 | * Pointer to output buffer, must be <code>inputLen</code> bytes.
|
| 163 | *
|
| 164 | * @param iv
|
| 165 | * The initialization vector as input to create the cipher stream.
|
| 166 | * Refer to chapter 4.1.1 in RFC 3711.
|
| 167 | */
|
| 168 | void ctr_encrypt(const uint8_t* input, uint32_t inputLen, uint8_t* output, uint8_t* iv );
|
| 169 |
|
| 170 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 171 | * @brief Counter-mode encryption, in place.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 172 | *
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 173 | * This method performs the CM encryption.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 174 | *
|
| 175 | * @param data
|
| 176 | * Pointer to input and output block, must be <code>dataLen</code>
|
| 177 | * bytes.
|
| 178 | *
|
| 179 | * @param data_length
|
| 180 | * Number of bytes to process.
|
| 181 | *
|
| 182 | * @param iv
|
| 183 | * The initialization vector as input to create the cipher stream.
|
| 184 | * Refer to chapter 4.1.1 in RFC 3711.
|
| 185 | */
|
| 186 | void ctr_encrypt(uint8_t* data, uint32_t data_length, uint8_t* iv );
|
| 187 |
|
| 188 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 189 | * @brief Derive a cipher context to compute the IV'.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 190 | *
|
| 191 | * See chapter 4.1.2.1 in RFC 3711.
|
| 192 | *
|
| 193 | * @param f8Cipher
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 194 | * Pointer to the cipher context that will be used to encrypt IV to IV'
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 195 | *
|
| 196 | * @param key
|
| 197 | * The master key
|
| 198 | *
|
| 199 | * @param keyLen
|
| 200 | * Length of the master key.
|
| 201 | *
|
| 202 | * @param salt
|
| 203 | * Master salt.
|
| 204 | *
|
| 205 | * @param saltLen
|
| 206 | * length of master salt.
|
| 207 | */
|
| 208 | void f8_deriveForIV(SrtpSymCrypto* f8Cipher, uint8_t* key, int32_t keyLen, uint8_t* salt, int32_t saltLen);
|
| 209 |
|
| 210 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 211 | * @brief F8 mode encryption, in place.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 212 | *
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 213 | * This method performs the F8 encryption, see chapter 4.1.2 in RFC 3711.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 214 | *
|
| 215 | * @param data
|
| 216 | * Pointer to input and output block, must be <code>dataLen</code>
|
| 217 | * bytes.
|
| 218 | *
|
| 219 | * @param dataLen
|
| 220 | * Number of bytes to process.
|
| 221 | *
|
| 222 | * @param iv
|
| 223 | * The initialization vector as input to create the cipher stream.
|
| 224 | * Refer to chapter 4.1.1 in RFC 3711.
|
| 225 | *
|
| 226 | * @param f8Cipher
|
| 227 | * An AES cipher context used to encrypt IV to IV'.
|
| 228 | */
|
| 229 | void f8_encrypt(const uint8_t* data, uint32_t dataLen, uint8_t* iv, SrtpSymCrypto* f8Cipher);
|
| 230 |
|
| 231 | /**
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 232 | * @brief F8 mode encryption.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 233 | *
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 234 | * This method performs the F8 encryption, see chapter 4.1.2 in RFC 3711.
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 235 | *
|
| 236 | * @param data
|
| 237 | * Pointer to input and output block, must be <code>dataLen</code>
|
| 238 | * bytes.
|
| 239 | *
|
| 240 | * @param dataLen
|
| 241 | * Number of bytes to process.
|
| 242 | *
|
| 243 | * @param out
|
| 244 | * Pointer to output buffer, must be <code>dataLen</code> bytes.
|
| 245 | *
|
| 246 | * @param iv
|
| 247 | * The initialization vector as input to create the cipher stream.
|
| 248 | * Refer to chapter 4.1.1 in RFC 3711.
|
| 249 | *
|
| 250 | * @param f8Cipher
|
| 251 | * An AES cipher context used to encrypt IV to IV'.
|
| 252 | */
|
| 253 | void f8_encrypt(const uint8_t* data, uint32_t dataLen, uint8_t* out, uint8_t* iv, SrtpSymCrypto* f8Cipher);
|
| 254 |
|
| 255 | private:
|
| 256 | int processBlock(F8_CIPHER_CTX* f8ctx, const uint8_t* in, int32_t length, uint8_t* out);
|
| 257 | void* key;
|
| 258 | int32_t algorithm;
|
| 259 | };
|
| 260 |
|
| 261 | #pragma GCC visibility push(default)
|
| 262 | int testF8();
|
| 263 | #pragma GCC visibility pop
|
| 264 |
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 265 | /* Only SrtpSymCrypto functions defines the MAKE_F8_TEST */
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 266 | #ifdef MAKE_F8_TEST
|
| 267 |
|
| 268 | #include <cstring>
|
| 269 | #include <iostream>
|
| 270 | #include <cstdio>
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 271 | #include <common/osSpecifics.h>
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 272 |
|
| 273 | using namespace std;
|
| 274 |
|
| 275 | static void hexdump(const char* title, const unsigned char *s, int l)
|
| 276 | {
|
| 277 | int n=0;
|
| 278 |
|
| 279 | if (s == NULL) return;
|
| 280 |
|
| 281 | fprintf(stderr, "%s",title);
|
| 282 | for( ; n < l ; ++n) {
|
| 283 | if((n%16) == 0)
|
| 284 | fprintf(stderr, "\n%04x",n);
|
| 285 | fprintf(stderr, " %02x",s[n]);
|
| 286 | }
|
| 287 | fprintf(stderr, "\n");
|
| 288 | }
|
| 289 |
|
| 290 | /*
|
| 291 | * The F8 test vectors according to RFC3711
|
| 292 | */
|
| 293 | static unsigned char salt[] = {0x32, 0xf2, 0x87, 0x0d};
|
| 294 |
|
| 295 | static unsigned char iv[] = { 0x00, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5,
|
| 296 | 0x5c, 0x62, 0x15, 0x99, 0xd4, 0x62, 0x56, 0x4a};
|
| 297 |
|
| 298 | static unsigned char key[]= { 0x23, 0x48, 0x29, 0x00, 0x84, 0x67, 0xbe, 0x18,
|
| 299 | 0x6c, 0x3d, 0xe1, 0x4a, 0xae, 0x72, 0xd6, 0x2c};
|
| 300 |
|
| 301 | static unsigned char payload[] = {
|
| 302 | 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61,
|
| 303 | 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73,
|
| 304 | 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
|
| 305 | 0x6e, 0x65, 0x78, 0x74, 0x20, 0x62, 0x65, 0x73,
|
| 306 | 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67}; // 39 bytes
|
| 307 |
|
| 308 | static unsigned char cipherText[] = {
|
| 309 | 0x01, 0x9c, 0xe7, 0xa2, 0x6e, 0x78, 0x54, 0x01,
|
| 310 | 0x4a, 0x63, 0x66, 0xaa, 0x95, 0xd4, 0xee, 0xfd,
|
| 311 | 0x1a, 0xd4, 0x17, 0x2a, 0x14, 0xf9, 0xfa, 0xf4,
|
| 312 | 0x55, 0xb7, 0xf1, 0xd4, 0xb6, 0x2b, 0xd0, 0x8f,
|
| 313 | 0x56, 0x2c, 0x0e, 0xef, 0x7c, 0x48, 0x02}; // 39 bytes
|
| 314 |
|
| 315 | // static unsigned char rtpPacketHeader[] = {
|
| 316 | // 0x80, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5,
|
| 317 | // 0x5c, 0x62, 0x15, 0x99};
|
| 318 |
|
| 319 | static unsigned char rtpPacket[] = {
|
| 320 | 0x80, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5,
|
| 321 | 0x5c, 0x62, 0x15, 0x99, // header
|
| 322 | 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61, // payload
|
| 323 | 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73,
|
| 324 | 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
|
| 325 | 0x6e, 0x65, 0x78, 0x74, 0x20, 0x62, 0x65, 0x73,
|
| 326 | 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67};
|
| 327 | static uint32_t ROC = 0xd462564a;
|
| 328 |
|
| 329 | int testF8()
|
| 330 | {
|
| 331 | SrtpSymCrypto* aesCipher = new SrtpSymCrypto(SrtpEncryptionAESF8);
|
| 332 | SrtpSymCrypto* f8AesCipher = new SrtpSymCrypto(SrtpEncryptionAESF8);
|
| 333 |
|
| 334 | aesCipher->setNewKey(key, sizeof(key));
|
| 335 |
|
| 336 | /* Create the F8 IV (refer to chapter 4.1.2.2 in RFC 3711):
|
| 337 | *
|
| 338 | * IV = 0x00 || M || PT || SEQ || TS || SSRC || ROC
|
| 339 | * 8Bit 1bit 7bit 16bit 32bit 32bit 32bit
|
| 340 | * ------------\ /--------------------------------------------------
|
| 341 | * XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
|
| 342 | */
|
| 343 |
|
| 344 | unsigned char derivedIv[16];
|
| 345 | uint32_t* ui32p = (uint32_t*)derivedIv;
|
| 346 |
|
| 347 | memcpy(derivedIv, rtpPacket, 12);
|
| 348 | derivedIv[0] = 0;
|
| 349 |
|
| 350 | // set ROC in network order into IV
|
Alexandre Lision | 7fd5d3d | 2013-12-04 13:06:40 -0500 | [diff] [blame] | 351 | ui32p[3] = zrtpHtonl(ROC);
|
Alexandre Lision | 51140e1 | 2013-12-02 10:54:09 -0500 | [diff] [blame] | 352 |
|
| 353 | int32_t pad = 0;
|
| 354 |
|
| 355 | if (memcmp(iv, derivedIv, 16) != 0) {
|
| 356 | cerr << "Wrong IV constructed" << endl;
|
| 357 | hexdump("derivedIv", derivedIv, 16);
|
| 358 | hexdump("test vector Iv", iv, 16);
|
| 359 | return -1;
|
| 360 | }
|
| 361 |
|
| 362 | aesCipher->f8_deriveForIV(f8AesCipher, key, sizeof(key), salt, sizeof(salt));
|
| 363 |
|
| 364 | // now encrypt the RTP payload data
|
| 365 | aesCipher->f8_encrypt(rtpPacket + 12, sizeof(rtpPacket)-12+pad,
|
| 366 | derivedIv, f8AesCipher);
|
| 367 |
|
| 368 | // compare with test vector cipher data
|
| 369 | if (memcmp(rtpPacket+12, cipherText, sizeof(rtpPacket)-12+pad) != 0) {
|
| 370 | cerr << "cipher data mismatch" << endl;
|
| 371 | hexdump("computed cipher data", rtpPacket+12, sizeof(rtpPacket)-12+pad);
|
| 372 | hexdump("Test vcetor cipher data", cipherText, sizeof(cipherText));
|
| 373 | return -1;
|
| 374 | }
|
| 375 |
|
| 376 | // Now decrypt the data to get the payload data again
|
| 377 | aesCipher->f8_encrypt(rtpPacket+12, sizeof(rtpPacket)-12+pad, derivedIv, f8AesCipher);
|
| 378 |
|
| 379 | // compare decrypted data with test vector payload data
|
| 380 | if (memcmp(rtpPacket+12, payload, sizeof(rtpPacket)-12+pad) != 0) {
|
| 381 | cerr << "payload data mismatch" << endl;
|
| 382 | hexdump("computed payload data", rtpPacket+12, sizeof(rtpPacket)-12+pad);
|
| 383 | hexdump("Test vector payload data", payload, sizeof(payload));
|
| 384 | return -1;
|
| 385 | }
|
| 386 | return 0;
|
| 387 | }
|
| 388 | #endif
|
| 389 |
|
| 390 | /**
|
| 391 | * @}
|
| 392 | */
|
| 393 |
|
| 394 | #endif
|
| 395 |
|