45 for (i = 0, outpos = 0; outpos < outlen; i++) {
49 for (j = 0; j < 16 && outpos < outlen; j++, outpos++)
50 outbuf[outpos] ^= keystream[j];
58 memcpy(input, salt, 14);
60 input[14 - 7] ^= label;
61 memset(out, 0, outlen);
73 if (!strcmp(suite,
"AES_CM_128_HMAC_SHA1_80") ||
74 !strcmp(suite,
"SRTP_AES128_CM_HMAC_SHA1_80")) {
76 }
else if (!strcmp(suite,
"AES_CM_128_HMAC_SHA1_32")) {
78 }
else if (!strcmp(suite,
"SRTP_AES128_CM_HMAC_SHA1_32")) {
120 for (i = 0; i < 8; i++)
121 iv[6 + i] ^= indexbuf[i];
122 for (i = 0; i < 14; i++)
128 uint8_t iv[16] = { 0 }, hmac[20];
159 if (seq_largest < 32768) {
160 if (seq - seq_largest > 32768)
163 if (seq_largest - 32768 > seq)
167 seq_largest =
FFMAX(seq_largest, seq);
168 }
else if (v == roc + 1) {
172 index = seq + (((uint64_t)v) << 16);
179 if (memcmp(hmac, buf + len - hmac_size, hmac_size)) {
191 uint32_t srtcp_index =
AV_RB32(buf + len - 4);
196 index = srtcp_index & 0x7fffffff;
200 if (!(srtcp_index & 0x80000000))
208 csrc = buf[0] & 0x0f;
223 ext = (
AV_RB16(buf + 2) + 1) * 4;
241 uint8_t iv[16] = { 0 }, hmac[20];
244 int rtcp, hmac_size, padding;
256 if (len + padding > outlen)
259 memcpy(out, in, len);
277 if (seq < s->seq_largest)
280 index = seq + (((uint64_t)s->
roc) << 16);
282 csrc = buf[0] & 0x0f;
296 ext = (
AV_RB16(buf + 2) + 1) * 4;
309 AV_WB32(buf + len, 0x80000000 | index);
322 memcpy(buf + len, hmac, hmac_size);
324 return buf + len -
out;
330 static const char *aes128_80_key =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
332 static const uint8_t rtp_aes128_80[] = {
334 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
336 0x62, 0x69, 0x76, 0xca, 0xc5,
338 0xa1, 0xac, 0x1b, 0xb4, 0xa0, 0x1c, 0xd5, 0x49, 0x28, 0x99,
341 static const uint8_t rtcp_aes128_80[] = {
343 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
345 0x8a, 0xac, 0xdc, 0xa5, 0x4c, 0xf6, 0x78, 0xa6, 0x62, 0x8f, 0x24, 0xda,
346 0x6c, 0x09, 0x3f, 0xa9, 0x28, 0x7a, 0xb5, 0x7f, 0x1f, 0x0f, 0xc9, 0x35,
348 0x80, 0x00, 0x00, 0x03,
350 0xe9, 0x3b, 0xc0, 0x5c, 0x0c, 0x06, 0x9f, 0xab, 0xc0, 0xde,
353 static const char *aes128_32_key =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
355 static const uint8_t rtp_aes128_32[] = {
357 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
359 0x62, 0x69, 0x76, 0xca, 0xc5,
361 0xa1, 0xac, 0x1b, 0xb4,
364 static const uint8_t rtcp_aes128_32[] = {
366 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
368 0x35, 0xe9, 0xb5, 0xff, 0x0d, 0xd1, 0xde, 0x70, 0x74, 0x10, 0xaa, 0x1b,
369 0xb2, 0x8d, 0xf0, 0x20, 0x02, 0x99, 0x6b, 0x1b, 0x0b, 0xd0, 0x47, 0x34,
371 0x80, 0x00, 0x00, 0x04,
373 0x5b, 0xd2, 0xa9, 0x9d,
376 static const char *aes128_80_32_key =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
378 static const uint8_t rtp_aes128_80_32[] = {
380 0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
382 0x62, 0x69, 0x76, 0xca, 0xc5,
384 0xa1, 0xac, 0x1b, 0xb4,
387 static const uint8_t rtcp_aes128_80_32[] = {
389 0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
391 0xd6, 0xae, 0xc1, 0x58, 0x63, 0x70, 0xc9, 0x88, 0x66, 0x26, 0x1c, 0x53,
392 0xff, 0x5d, 0x5d, 0x2b, 0x0f, 0x8c, 0x72, 0x3e, 0xc9, 0x1d, 0x43, 0xf9,
394 0x80, 0x00, 0x00, 0x05,
396 0x09, 0x16, 0xb4, 0x27, 0x9a, 0xe9, 0x92, 0x26, 0x4e, 0x10,
402 for (i = 0; i <
len; i++)
403 printf(
"%02x", buf[i]);
410 memcpy(out, in, len);
412 print_data(out, len);
418 static void test_encrypt(
const uint8_t *
data,
int in_len,
const char *suite,
428 if (len == in_len && !memcmp(buf, data, len))
429 printf(
"Decrypted content matches input\n");
431 printf(
"Decrypted content doesn't match input\n");
433 printf(
"Decryption failed\n");
441 static const char *aes128_80_suite =
"AES_CM_128_HMAC_SHA1_80";
442 static const char *aes128_32_suite =
"AES_CM_128_HMAC_SHA1_32";
443 static const char *aes128_80_32_suite =
"SRTP_AES128_CM_HMAC_SHA1_32";
444 static const char *test_key =
"abcdefghijklmnopqrstuvwxyz1234567890ABCD";
449 len = test_decrypt(&srtp, rtp_aes128_80,
sizeof(rtp_aes128_80), buf);
450 test_encrypt(buf, len, aes128_80_suite, test_key);
451 test_encrypt(buf, len, aes128_32_suite, test_key);
452 test_encrypt(buf, len, aes128_80_32_suite, test_key);
453 test_decrypt(&srtp, rtcp_aes128_80,
sizeof(rtcp_aes128_80), buf);
454 test_encrypt(buf, len, aes128_80_suite, test_key);
455 test_encrypt(buf, len, aes128_32_suite, test_key);
456 test_encrypt(buf, len, aes128_80_32_suite, test_key);
459 memset(&srtp, 0,
sizeof(srtp));
461 test_decrypt(&srtp, rtp_aes128_32,
sizeof(rtp_aes128_32), buf);
462 test_decrypt(&srtp, rtcp_aes128_32,
sizeof(rtcp_aes128_32), buf);
465 memset(&srtp, 0,
sizeof(srtp));
467 test_decrypt(&srtp, rtp_aes128_80_32,
sizeof(rtp_aes128_80_32), buf);
468 test_decrypt(&srtp, rtcp_aes128_80_32,
sizeof(rtcp_aes128_80_32), buf);
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, uint8_t *out, int outlen)
#define RTP_MAX_PACKET_LENGTH
ptrdiff_t const GLvoid * data
AVHMAC * av_hmac_alloc(enum AVHMACType type)
Allocate an AVHMAC context.
#define AV_LOG_WARNING
Something somehow does not look correct.
static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf, int outlen)
void av_aes_crypt(AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt)
Encrypt or decrypt a buffer using a previously initialized context.
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
static void derive_key(struct AVAES *aes, const uint8_t *salt, int label, uint8_t *out, int outlen)
void ff_srtp_free(struct SRTPContext *s)
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
Hash data with the HMAC.
struct AVAES * av_aes_alloc(void)
Allocate an AVAES context.
static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index, uint32_t ssrc)
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
Initialize an AVHMAC context with an authentication key.
int av_aes_init(AVAES *a, const uint8_t *key, int key_bits, int decrypt)
Initialize an AVAES context.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
Finish hashing and output the HMAC digest.
#define RTP_PT_IS_RTCP(x)
void av_hmac_free(AVHMAC *c)
Free an AVHMAC context.
int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, const char *params)
int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
Decode a base64-encoded string.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> out
int main(int argc, char **argv)