FFmpeg
srtp.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg 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  * FFmpeg 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 FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <stdint.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include "libavformat/rtpdec.h"
24 #include "libavformat/srtp.h"
25 
26 static const char *aes128_80_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
27 
28 static const uint8_t rtp_aes128_80[] = {
29  // RTP header
30  0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
31  // encrypted payload
32  0x62, 0x69, 0x76, 0xca, 0xc5,
33  // HMAC
34  0xa1, 0xac, 0x1b, 0xb4, 0xa0, 0x1c, 0xd5, 0x49, 0x28, 0x99,
35 };
36 
37 static const uint8_t rtcp_aes128_80[] = {
38  // RTCP header
39  0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
40  // encrypted payload
41  0x8a, 0xac, 0xdc, 0xa5, 0x4c, 0xf6, 0x78, 0xa6, 0x62, 0x8f, 0x24, 0xda,
42  0x6c, 0x09, 0x3f, 0xa9, 0x28, 0x7a, 0xb5, 0x7f, 0x1f, 0x0f, 0xc9, 0x35,
43  // RTCP index
44  0x80, 0x00, 0x00, 0x03,
45  // HMAC
46  0xe9, 0x3b, 0xc0, 0x5c, 0x0c, 0x06, 0x9f, 0xab, 0xc0, 0xde,
47 };
48 
49 static const char *aes128_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
50 
51 static const uint8_t rtp_aes128_32[] = {
52  // RTP header
53  0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
54  // encrypted payload
55  0x62, 0x69, 0x76, 0xca, 0xc5,
56  // HMAC
57  0xa1, 0xac, 0x1b, 0xb4,
58 };
59 
60 static const uint8_t rtcp_aes128_32[] = {
61  // RTCP header
62  0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
63  // encrypted payload
64  0x35, 0xe9, 0xb5, 0xff, 0x0d, 0xd1, 0xde, 0x70, 0x74, 0x10, 0xaa, 0x1b,
65  0xb2, 0x8d, 0xf0, 0x20, 0x02, 0x99, 0x6b, 0x1b, 0x0b, 0xd0, 0x47, 0x34,
66  // RTCP index
67  0x80, 0x00, 0x00, 0x04,
68  // HMAC
69  0x5b, 0xd2, 0xa9, 0x9d,
70 };
71 
72 static const char *aes128_80_32_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn";
73 
74 static const uint8_t rtp_aes128_80_32[] = {
75  // RTP header
76  0x80, 0xe0, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78,
77  // encrypted payload
78  0x62, 0x69, 0x76, 0xca, 0xc5,
79  // HMAC
80  0xa1, 0xac, 0x1b, 0xb4,
81 };
82 
83 static const uint8_t rtcp_aes128_80_32[] = {
84  // RTCP header
85  0x81, 0xc9, 0x00, 0x07, 0x12, 0x34, 0x56, 0x78,
86  // encrypted payload
87  0xd6, 0xae, 0xc1, 0x58, 0x63, 0x70, 0xc9, 0x88, 0x66, 0x26, 0x1c, 0x53,
88  0xff, 0x5d, 0x5d, 0x2b, 0x0f, 0x8c, 0x72, 0x3e, 0xc9, 0x1d, 0x43, 0xf9,
89  // RTCP index
90  0x80, 0x00, 0x00, 0x05,
91  // HMAC
92  0x09, 0x16, 0xb4, 0x27, 0x9a, 0xe9, 0x92, 0x26, 0x4e, 0x10,
93 };
94 
95 static void print_data(const uint8_t *buf, int len)
96 {
97  int i;
98  for (i = 0; i < len; i++)
99  printf("%02x", buf[i]);
100  printf("\n");
101 }
102 
103 static int test_decrypt(struct SRTPContext *srtp, const uint8_t *in, int len,
104  uint8_t *out)
105 {
106  memcpy(out, in, len);
107  if (!ff_srtp_decrypt(srtp, out, &len)) {
108  print_data(out, len);
109  return len;
110  } else
111  return -1;
112 }
113 
114 static void test_encrypt(const uint8_t *data, int in_len, const char *suite,
115  const char *key)
116 {
117  struct SRTPContext enc = { 0 }, dec = { 0 };
118  int len;
119  char buf[RTP_MAX_PACKET_LENGTH];
120  ff_srtp_set_crypto(&enc, suite, key);
121  ff_srtp_set_crypto(&dec, suite, key);
122  len = ff_srtp_encrypt(&enc, data, in_len, buf, sizeof(buf));
123  if (!ff_srtp_decrypt(&dec, buf, &len)) {
124  if (len == in_len && !memcmp(buf, data, len))
125  printf("Decrypted content matches input\n");
126  else
127  printf("Decrypted content doesn't match input\n");
128  } else {
129  printf("Decryption failed\n");
130  }
131  ff_srtp_free(&enc);
132  ff_srtp_free(&dec);
133 }
134 
135 int main(void)
136 {
137  static const char *aes128_80_suite = "AES_CM_128_HMAC_SHA1_80";
138  static const char *aes128_32_suite = "AES_CM_128_HMAC_SHA1_32";
139  static const char *aes128_80_32_suite = "SRTP_AES128_CM_HMAC_SHA1_32";
140  static const char *test_key = "abcdefghijklmnopqrstuvwxyz1234567890ABCD";
142  struct SRTPContext srtp = { 0 };
143  int len;
144  ff_srtp_set_crypto(&srtp, aes128_80_suite, aes128_80_key);
145  len = test_decrypt(&srtp, rtp_aes128_80, sizeof(rtp_aes128_80), buf);
146  test_encrypt(buf, len, aes128_80_suite, test_key);
147  test_encrypt(buf, len, aes128_32_suite, test_key);
148  test_encrypt(buf, len, aes128_80_32_suite, test_key);
149  test_decrypt(&srtp, rtcp_aes128_80, sizeof(rtcp_aes128_80), buf);
150  test_encrypt(buf, len, aes128_80_suite, test_key);
151  test_encrypt(buf, len, aes128_32_suite, test_key);
152  test_encrypt(buf, len, aes128_80_32_suite, test_key);
153  ff_srtp_free(&srtp);
154 
155  memset(&srtp, 0, sizeof(srtp)); // Clear the context
156  ff_srtp_set_crypto(&srtp, aes128_32_suite, aes128_32_key);
157  test_decrypt(&srtp, rtp_aes128_32, sizeof(rtp_aes128_32), buf);
158  test_decrypt(&srtp, rtcp_aes128_32, sizeof(rtcp_aes128_32), buf);
159  ff_srtp_free(&srtp);
160 
161  memset(&srtp, 0, sizeof(srtp)); // Clear the context
162  ff_srtp_set_crypto(&srtp, aes128_80_32_suite, aes128_80_32_key);
163  test_decrypt(&srtp, rtp_aes128_80_32, sizeof(rtp_aes128_80_32), buf);
164  test_decrypt(&srtp, rtcp_aes128_80_32, sizeof(rtcp_aes128_80_32), buf);
165  ff_srtp_free(&srtp);
166  return 0;
167 }
rtp_aes128_32
static const uint8_t rtp_aes128_32[]
Definition: srtp.c:51
out
FILE * out
Definition: movenc.c:54
rtcp_aes128_80_32
static const uint8_t rtcp_aes128_80_32[]
Definition: srtp.c:83
srtp.h
data
const char data[16]
Definition: mxf.c:142
test_key
static const uint8_t test_key[]
Definition: des.c:38
main
int main(void)
Definition: srtp.c:135
SRTPContext
Definition: srtp.h:30
rtp_aes128_80_32
static const uint8_t rtp_aes128_80_32[]
Definition: srtp.c:74
ff_srtp_decrypt
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
Definition: srtp.c:126
rtp_aes128_80
static const uint8_t rtp_aes128_80[]
Definition: srtp.c:28
ff_srtp_encrypt
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, uint8_t *out, int outlen)
Definition: srtp.c:238
aes128_32_key
static const char * aes128_32_key
Definition: srtp.c:49
key
const char * key
Definition: hwcontext_opencl.c:168
print_data
static void print_data(const uint8_t *buf, int len)
Definition: srtp.c:95
rtcp_aes128_32
static const uint8_t rtcp_aes128_32[]
Definition: srtp.c:60
rtpdec.h
suite
FFmpeg currently uses a custom build this text attempts to document some of its obscure features and options Makefile the full command issued by make and its output will be shown on the screen DBG Preprocess x86 external assembler files to a dbg asm file in the object which then gets compiled Helps in developing those assembler files DESTDIR Destination directory for the install useful to prepare packages or install FFmpeg in cross environments GEN Set to ‘1’ to generate the missing or mismatched references Makefile builds all the libraries and the executables fate Run the fate test suite
Definition: build_system.txt:28
test_decrypt
static int test_decrypt(struct SRTPContext *srtp, const uint8_t *in, int len, uint8_t *out)
Definition: srtp.c:103
printf
printf("static const uint8_t my_array[100] = {\n")
ff_srtp_free
void ff_srtp_free(struct SRTPContext *s)
Definition: srtp.c:31
in
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;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);return NULL;} return ac;} 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;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->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);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
Definition: audio_convert.c:326
i
int i
Definition: input.c:407
uint8_t
uint8_t
Definition: audio_convert.c:194
len
int len
Definition: vorbis_enc_data.h:452
ff_srtp_set_crypto
int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, const char *params)
Definition: srtp.c:65
test_encrypt
static void test_encrypt(const uint8_t *data, int in_len, const char *suite, const char *key)
Definition: srtp.c:114
RTP_MAX_PACKET_LENGTH
#define RTP_MAX_PACKET_LENGTH
Definition: rtpdec.h:36
aes128_80_32_key
static const char * aes128_80_32_key
Definition: srtp.c:72
rtcp_aes128_80
static const uint8_t rtcp_aes128_80[]
Definition: srtp.c:37
aes128_80_key
static const char * aes128_80_key
Definition: srtp.c:26