tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rtp_decoder.c (26470B)


      1 /*
      2 * rtp_decoder.c
      3 *
      4 * decoder structures and functions for SRTP pcap decoder
      5 *
      6 * Example:
      7 * $ wget --no-check-certificate \
      8 *     https://raw.githubusercontent.com/gteissier/srtp-decrypt/master/marseillaise-srtp.pcap
      9 * $ ./test/rtp_decoder -a -t 10 -e 128 -b \
     10 *     aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz \
     11 *         < ~/marseillaise-srtp.pcap \
     12 *         | text2pcap -t "%M:%S." -u 10000,10000 - - \
     13 *         > ./marseillaise-rtp.pcap
     14 *
     15 * There is also a different way of setting up key size and tag size
     16 * based upon RFC 4568 crypto suite specification, i.e.:
     17 *
     18 * $ ./test/rtp_decoder -s AES_CM_128_HMAC_SHA1_80 -b \
     19 *     aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz ...
     20 *
     21 * Audio can be extracted using extractaudio utility from the RTPproxy
     22 * package:
     23 *
     24 * $ extractaudio -A ./marseillaise-rtp.pcap ./marseillaise-out.wav
     25 *
     26 * Bernardo Torres <bernardo@torresautomacao.com.br>
     27 *
     28 * Some structure and code from https://github.com/gteissier/srtp-decrypt
     29 */
     30 /*
     31 *
     32 * Copyright (c) 2001-2017 Cisco Systems, Inc.
     33 * All rights reserved.
     34 *
     35 * Redistribution and use in source and binary forms, with or without
     36 * modification, are permitted provided that the following conditions
     37 * are met:
     38 *
     39 *   Redistributions of source code must retain the above copyright
     40 *   notice, this list of conditions and the following disclaimer.
     41 *
     42 *   Redistributions in binary form must reproduce the above
     43 *   copyright notice, this list of conditions and the following
     44 *   disclaimer in the documentation and/or other materials provided
     45 *   with the distribution.
     46 *
     47 *   Neither the name of the Cisco Systems, Inc. nor the names of its
     48 *   contributors may be used to endorse or promote products derived
     49 *   from this software without specific prior written permission.
     50 *
     51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     54 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     55 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     56 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     57 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     58 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     60 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     62 * OF THE POSSIBILITY OF SUCH DAMAGE.
     63 *
     64 */
     65 #include "getopt_s.h" /* for local getopt()  */
     66 #include <assert.h>   /* for assert()  */
     67 
     68 #include <pcap.h>
     69 #include "rtp_decoder.h"
     70 #include "util.h"
     71 
     72 #ifndef timersub
     73 #define timersub(a, b, result)                                                 \
     74    do {                                                                       \
     75        (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                          \
     76        (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                       \
     77        if ((result)->tv_usec < 0) {                                           \
     78            --(result)->tv_sec;                                                \
     79            (result)->tv_usec += 1000000;                                      \
     80        }                                                                      \
     81    } while (0)
     82 #endif
     83 
     84 #define MAX_KEY_LEN 96
     85 #define MAX_FILTER 256
     86 #define MAX_FILE 255
     87 
     88 struct srtp_crypto_suite {
     89    const char *can_name;
     90    int gcm_on;
     91    int key_size;
     92    int tag_size;
     93 };
     94 
     95 static struct srtp_crypto_suite srtp_crypto_suites[] = {
     96 #if 0
     97  {.can_name = "F8_128_HMAC_SHA1_32", .gcm_on = 0, .key_size = 128, .tag_size = 4},
     98 #endif
     99    { .can_name = "AES_CM_128_HMAC_SHA1_32",
    100      .gcm_on = 0,
    101      .key_size = 128,
    102      .tag_size = 4 },
    103    { .can_name = "AES_CM_128_HMAC_SHA1_80",
    104      .gcm_on = 0,
    105      .key_size = 128,
    106      .tag_size = 10 },
    107    { .can_name = "AES_192_CM_HMAC_SHA1_32",
    108      .gcm_on = 0,
    109      .key_size = 192,
    110      .tag_size = 4 },
    111    { .can_name = "AES_192_CM_HMAC_SHA1_80",
    112      .gcm_on = 0,
    113      .key_size = 192,
    114      .tag_size = 10 },
    115    { .can_name = "AES_256_CM_HMAC_SHA1_32",
    116      .gcm_on = 0,
    117      .key_size = 256,
    118      .tag_size = 4 },
    119    { .can_name = "AES_256_CM_HMAC_SHA1_80",
    120      .gcm_on = 0,
    121      .key_size = 256,
    122      .tag_size = 10 },
    123    { .can_name = "AEAD_AES_128_GCM",
    124      .gcm_on = 1,
    125      .key_size = 128,
    126      .tag_size = 16 },
    127    { .can_name = "AEAD_AES_256_GCM",
    128      .gcm_on = 1,
    129      .key_size = 256,
    130      .tag_size = 16 },
    131    { .can_name = NULL }
    132 };
    133 
    134 void rtp_decoder_srtp_log_handler(srtp_log_level_t level,
    135                                  const char *msg,
    136                                  void *data)
    137 {
    138    (void)data;
    139    char level_char = '?';
    140    switch (level) {
    141    case srtp_log_level_error:
    142        level_char = 'e';
    143        break;
    144    case srtp_log_level_warning:
    145        level_char = 'w';
    146        break;
    147    case srtp_log_level_info:
    148        level_char = 'i';
    149        break;
    150    case srtp_log_level_debug:
    151        level_char = 'd';
    152        break;
    153    }
    154    fprintf(stderr, "SRTP-LOG [%c]: %s\n", level_char, msg);
    155 }
    156 
    157 int main(int argc, char *argv[])
    158 {
    159    char errbuf[PCAP_ERRBUF_SIZE];
    160    bpf_u_int32 pcap_net = 0;
    161    pcap_t *pcap_handle;
    162 #if BEW
    163    struct sockaddr_in local;
    164 #endif
    165    srtp_sec_serv_t sec_servs = sec_serv_none;
    166    int c;
    167    struct srtp_crypto_suite scs, *i_scsp;
    168    scs.key_size = 128;
    169    scs.tag_size = 0;
    170    int gcm_on = 0;
    171    char *input_key = NULL;
    172    int b64_input = 0;
    173    char key[MAX_KEY_LEN];
    174    struct bpf_program fp;
    175    char filter_exp[MAX_FILTER] = "";
    176    char pcap_file[MAX_FILE] = "-";
    177    size_t rtp_packet_offset = DEFAULT_RTP_OFFSET;
    178    rtp_decoder_t dec;
    179    srtp_policy_t policy = { 0 };
    180    rtp_decoder_mode_t mode = mode_rtp;
    181    srtp_ssrc_t ssrc = { ssrc_any_inbound, 0 };
    182    uint32_t roc = 0;
    183    srtp_err_status_t status;
    184    int len;
    185    int expected_len;
    186    int do_list_mods = 0;
    187 
    188    fprintf(stderr, "Using %s [0x%x]\n", srtp_get_version_string(),
    189            srtp_get_version());
    190 
    191    /* initialize srtp library */
    192    status = srtp_init();
    193    if (status) {
    194        fprintf(stderr,
    195                "error: srtp initialization failed with error code %d\n",
    196                status);
    197        exit(1);
    198    }
    199 
    200    status = srtp_install_log_handler(rtp_decoder_srtp_log_handler, NULL);
    201    if (status) {
    202        fprintf(stderr, "error: install log handler failed\n");
    203        exit(1);
    204    }
    205 
    206    /* check args */
    207    while (1) {
    208        c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:c:m:p:o:s:r:");
    209        if (c == -1) {
    210            break;
    211        }
    212        switch (c) {
    213        case 'b':
    214            b64_input = 1;
    215        /* fall thru */
    216        case 'k':
    217            input_key = optarg_s;
    218            break;
    219        case 'e':
    220            scs.key_size = atoi(optarg_s);
    221            if (scs.key_size != 128 && scs.key_size != 192 &&
    222                scs.key_size != 256) {
    223                fprintf(
    224                    stderr,
    225                    "error: encryption key size must be 128, 192 or 256 (%d)\n",
    226                    scs.key_size);
    227                exit(1);
    228            }
    229            input_key = malloc(scs.key_size);
    230            sec_servs |= sec_serv_conf;
    231            break;
    232        case 't':
    233            scs.tag_size = atoi(optarg_s);
    234            break;
    235        case 'a':
    236            sec_servs |= sec_serv_auth;
    237            break;
    238        case 'g':
    239            gcm_on = 1;
    240            sec_servs |= sec_serv_auth;
    241            break;
    242        case 'd':
    243            status = srtp_set_debug_module(optarg_s, 1);
    244            if (status) {
    245                fprintf(stderr, "error: set debug module (%s) failed\n",
    246                        optarg_s);
    247                exit(1);
    248            }
    249            break;
    250        case 'f':
    251            if (strlen(optarg_s) > MAX_FILTER) {
    252                fprintf(stderr, "error: filter bigger than %d characters\n",
    253                        MAX_FILTER);
    254                exit(1);
    255            }
    256            fprintf(stderr, "Setting filter as %s\n", optarg_s);
    257            strcpy(filter_exp, optarg_s);
    258            break;
    259        case 'l':
    260            do_list_mods = 1;
    261            break;
    262        case 'c':
    263            for (i_scsp = &srtp_crypto_suites[0]; i_scsp->can_name != NULL;
    264                 i_scsp++) {
    265                if (strcasecmp(i_scsp->can_name, optarg_s) == 0) {
    266                    break;
    267                }
    268            }
    269            if (i_scsp->can_name == NULL) {
    270                fprintf(stderr, "Unknown/unsupported crypto suite name %s\n",
    271                        optarg_s);
    272                exit(1);
    273            }
    274            scs = *i_scsp;
    275            input_key = malloc(scs.key_size);
    276            sec_servs |= sec_serv_conf | sec_serv_auth;
    277            gcm_on = scs.gcm_on;
    278            break;
    279        case 'm':
    280            if (strcasecmp("rtp", optarg_s) == 0) {
    281                mode = mode_rtp;
    282            } else if (strcasecmp("rtcp", optarg_s) == 0) {
    283                mode = mode_rtcp;
    284            } else if (strcasecmp("rtcp-mux", optarg_s) == 0) {
    285                mode = mode_rtcp_mux;
    286            } else {
    287                fprintf(stderr, "Unknown/unsupported mode %s\n", optarg_s);
    288                exit(1);
    289            }
    290            break;
    291        case 'p':
    292            if (strlen(optarg_s) > MAX_FILE) {
    293                fprintf(stderr,
    294                        "error: pcap file path bigger than %d characters\n",
    295                        MAX_FILE);
    296                exit(1);
    297            }
    298            strcpy(pcap_file, optarg_s);
    299            break;
    300        case 'o':
    301            rtp_packet_offset = atoi(optarg_s);
    302            break;
    303        case 's':
    304            ssrc.type = ssrc_specific;
    305            ssrc.value = strtol(optarg_s, NULL, 0);
    306            break;
    307        case 'r':
    308            roc = atoi(optarg_s);
    309            break;
    310        default:
    311            usage(argv[0]);
    312        }
    313    }
    314 
    315    if (scs.tag_size == 0) {
    316        if (gcm_on) {
    317            scs.tag_size = 16;
    318        } else {
    319            scs.tag_size = 10;
    320        }
    321    }
    322 
    323    if (gcm_on && scs.tag_size != 8 && scs.tag_size != 16) {
    324        fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n",
    325                scs.tag_size);
    326        exit(1);
    327    }
    328 
    329    if (!gcm_on && scs.tag_size != 4 && scs.tag_size != 10) {
    330        fprintf(stderr, "error: non GCM tag size must be 4 or 10 (%d)\n",
    331                scs.tag_size);
    332        exit(1);
    333    }
    334 
    335    if (do_list_mods) {
    336        status = srtp_list_debug_modules();
    337        if (status) {
    338            fprintf(stderr, "error: list of debug modules failed\n");
    339            exit(1);
    340        }
    341        return 0;
    342    }
    343 
    344    if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
    345        /*
    346         * a key must be provided if and only if security services have
    347         * been requested
    348         */
    349        if (input_key == NULL) {
    350            fprintf(stderr, "key not provided\n");
    351        }
    352        if (!sec_servs) {
    353            fprintf(stderr, "no secservs\n");
    354        }
    355        fprintf(stderr, "provided\n");
    356        usage(argv[0]);
    357    }
    358 
    359    /* report security services selected on the command line */
    360    fprintf(stderr, "security services: ");
    361    if (sec_servs & sec_serv_conf)
    362        fprintf(stderr, "confidentiality ");
    363    if (sec_servs & sec_serv_auth)
    364        fprintf(stderr, "message authentication");
    365    if (sec_servs == sec_serv_none)
    366        fprintf(stderr, "none");
    367    fprintf(stderr, "\n");
    368 
    369    /* set up the srtp policy and master key */
    370    if (sec_servs) {
    371        /*
    372         * create policy structure, using the default mechanisms but
    373         * with only the security services requested on the command line,
    374         * using the right SSRC value
    375         */
    376        switch (sec_servs) {
    377        case sec_serv_conf_and_auth:
    378            if (gcm_on) {
    379 #ifdef OPENSSL
    380                switch (scs.key_size) {
    381                case 128:
    382                    if (scs.tag_size == 16) {
    383                        srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
    384                        srtp_crypto_policy_set_aes_gcm_128_16_auth(
    385                            &policy.rtcp);
    386                    } else {
    387                        srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
    388                        srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
    389                    }
    390                    break;
    391                case 256:
    392                    if (scs.tag_size == 16) {
    393                        srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp);
    394                        srtp_crypto_policy_set_aes_gcm_256_16_auth(
    395                            &policy.rtcp);
    396                    } else {
    397                        srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
    398                        srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
    399                    }
    400                    break;
    401                }
    402 #else
    403                fprintf(stderr, "error: GCM mode only supported when using the "
    404                                "OpenSSL crypto engine.\n");
    405                return 0;
    406 #endif
    407            } else {
    408                switch (scs.key_size) {
    409                case 128:
    410                    if (scs.tag_size == 4) {
    411                        srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(
    412                            &policy.rtp);
    413                        srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
    414                            &policy.rtcp);
    415                    } else {
    416                        srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
    417                            &policy.rtp);
    418                        srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
    419                            &policy.rtcp);
    420                    }
    421                    break;
    422                case 192:
    423 #ifdef OPENSSL
    424                    if (scs.tag_size == 4) {
    425                        srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(
    426                            &policy.rtp);
    427                        srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
    428                            &policy.rtcp);
    429                    } else {
    430                        srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
    431                            &policy.rtp);
    432                        srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
    433                            &policy.rtcp);
    434                    }
    435 #else
    436                    fprintf(stderr,
    437                            "error: AES 192 mode only supported when using the "
    438                            "OpenSSL crypto engine.\n");
    439                    return 0;
    440 
    441 #endif
    442                    break;
    443                case 256:
    444                    if (scs.tag_size == 4) {
    445                        srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(
    446                            &policy.rtp);
    447                        srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
    448                            &policy.rtcp);
    449                    } else {
    450                        srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
    451                            &policy.rtp);
    452                        srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
    453                            &policy.rtcp);
    454                    }
    455                    break;
    456                }
    457            }
    458            break;
    459        case sec_serv_conf:
    460            if (gcm_on) {
    461                fprintf(
    462                    stderr,
    463                    "error: GCM mode must always be used with auth enabled\n");
    464                return -1;
    465            } else {
    466                switch (scs.key_size) {
    467                case 128:
    468                    srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
    469                    srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
    470                        &policy.rtcp);
    471                    break;
    472                case 192:
    473 #ifdef OPENSSL
    474                    srtp_crypto_policy_set_aes_cm_192_null_auth(&policy.rtp);
    475                    srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
    476                        &policy.rtcp);
    477 #else
    478                    fprintf(stderr,
    479                            "error: AES 192 mode only supported when using the "
    480                            "OpenSSL crypto engine.\n");
    481                    return 0;
    482 
    483 #endif
    484                    break;
    485                case 256:
    486                    srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
    487                    srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
    488                        &policy.rtcp);
    489                    break;
    490                }
    491            }
    492            break;
    493        case sec_serv_auth:
    494            if (gcm_on) {
    495 #ifdef OPENSSL
    496                switch (scs.key_size) {
    497                case 128:
    498                    srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
    499                    srtp_crypto_policy_set_aes_gcm_128_8_only_auth(
    500                        &policy.rtcp);
    501                    break;
    502                case 256:
    503                    srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
    504                    srtp_crypto_policy_set_aes_gcm_256_8_only_auth(
    505                        &policy.rtcp);
    506                    break;
    507                }
    508 #else
    509                printf("error: GCM mode only supported when using the OpenSSL "
    510                       "crypto engine.\n");
    511                return 0;
    512 #endif
    513            } else {
    514                srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
    515                srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
    516            }
    517            break;
    518        default:
    519            fprintf(stderr, "error: unknown security service requested\n");
    520            return -1;
    521        }
    522 
    523        policy.key = (uint8_t *)key;
    524        policy.next = NULL;
    525        policy.window_size = 128;
    526        policy.allow_repeat_tx = 0;
    527        policy.rtp.sec_serv = sec_servs;
    528        policy.rtcp.sec_serv =
    529            sec_servs; // sec_serv_none;  /* we don't do RTCP anyway */
    530        fprintf(stderr, "setting tag len %d\n", scs.tag_size);
    531        policy.rtp.auth_tag_len = scs.tag_size;
    532 
    533        if (gcm_on && scs.tag_size != 8) {
    534            fprintf(stderr, "set tag len %d\n", scs.tag_size);
    535            policy.rtp.auth_tag_len = scs.tag_size;
    536        }
    537 
    538        /*
    539         * read key from hexadecimal or base64 on command line into an octet
    540         * string
    541         */
    542        if (b64_input) {
    543            int pad;
    544            expected_len = policy.rtp.cipher_key_len * 4 / 3;
    545            len = base64_string_to_octet_string(key, &pad, input_key,
    546                                                strlen(input_key));
    547        } else {
    548            expected_len = policy.rtp.cipher_key_len * 2;
    549            len = hex_string_to_octet_string(key, input_key, expected_len);
    550        }
    551        /* check that hex string is the right length */
    552        if (len < expected_len) {
    553            fprintf(stderr,
    554                    "error: too few digits in key/salt "
    555                    "(should be %d digits, found %d)\n",
    556                    expected_len, len);
    557            exit(1);
    558        }
    559        if (strlen(input_key) > (size_t)policy.rtp.cipher_key_len * 2) {
    560            fprintf(stderr,
    561                    "error: too many digits in key/salt "
    562                    "(should be %d hexadecimal digits, found %u)\n",
    563                    policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key));
    564            exit(1);
    565        }
    566 
    567        int key_octets = (scs.key_size / 8);
    568        int salt_octets = policy.rtp.cipher_key_len - key_octets;
    569        fprintf(stderr, "set master key/salt to %s/",
    570                octet_string_hex_string(key, key_octets));
    571        fprintf(stderr, "%s\n",
    572                octet_string_hex_string(key + key_octets, salt_octets));
    573 
    574    } else {
    575        fprintf(stderr,
    576                "error: neither encryption or authentication were selected\n");
    577        exit(1);
    578    }
    579 
    580    policy.ssrc = ssrc;
    581 
    582    if (roc != 0 && policy.ssrc.type != ssrc_specific) {
    583        fprintf(stderr, "error: setting ROC (-r) requires -s <ssrc>\n");
    584        exit(1);
    585    }
    586 
    587    pcap_handle = pcap_open_offline(pcap_file, errbuf);
    588 
    589    if (!pcap_handle) {
    590        fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf);
    591        exit(1);
    592    }
    593    assert(pcap_handle != NULL);
    594    if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1) {
    595        fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp,
    596                pcap_geterr(pcap_handle));
    597        return (2);
    598    }
    599    if (pcap_setfilter(pcap_handle, &fp) == -1) {
    600        fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp,
    601                pcap_geterr(pcap_handle));
    602        return (2);
    603    }
    604    dec = rtp_decoder_alloc();
    605    if (dec == NULL) {
    606        fprintf(stderr, "error: malloc() failed\n");
    607        exit(1);
    608    }
    609    fprintf(stderr, "Starting decoder\n");
    610    if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset, roc)) {
    611        fprintf(stderr, "error: init failed\n");
    612        exit(1);
    613    }
    614 
    615    pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec);
    616 
    617    if (dec->mode == mode_rtp || dec->mode == mode_rtcp_mux) {
    618        fprintf(stderr, "RTP packets decoded: %d\n", dec->rtp_cnt);
    619    }
    620    if (dec->mode == mode_rtcp || dec->mode == mode_rtcp_mux) {
    621        fprintf(stderr, "RTCP packets decoded: %d\n", dec->rtcp_cnt);
    622    }
    623    fprintf(stderr, "Packet decode errors: %d\n", dec->error_cnt);
    624 
    625    rtp_decoder_deinit(dec);
    626    rtp_decoder_dealloc(dec);
    627 
    628    status = srtp_shutdown();
    629    if (status) {
    630        fprintf(stderr, "error: srtp shutdown failed with error code %d\n",
    631                status);
    632        exit(1);
    633    }
    634 
    635    return 0;
    636 }
    637 
    638 void usage(char *string)
    639 {
    640    fprintf(
    641        stderr,
    642        "usage: %s [-d <debug>]* [[-k][-b] <key>] [-a][-t][-e] [-c "
    643        "<srtp-crypto-suite>] [-m <mode>] [-s <ssrc> [-r <roc>]]\n"
    644        "or     %s -l\n"
    645        "where  -a use message authentication\n"
    646        "       -e <key size> use encryption (use 128 or 256 for key size)\n"
    647        "       -g Use AES-GCM mode (must be used with -e)\n"
    648        "       -t <tag size> Tag size to use (in GCM mode use 8 or 16)\n"
    649        "       -k <key>  sets the srtp master key given in hexadecimal\n"
    650        "       -b <key>  sets the srtp master key given in base64\n"
    651        "       -l list debug modules\n"
    652        "       -f \"<pcap filter>\" to filter only the desired SRTP packets\n"
    653        "       -d <debug> turn on debugging for module <debug>\n"
    654        "       -c \"<srtp-crypto-suite>\" to set both key and tag size based\n"
    655        "          on RFC4568-style crypto suite specification\n"
    656        "       -m <mode> set the mode to be one of [rtp]|rtcp|rtcp-mux\n"
    657        "       -p <pcap file> path to pcap file (defaults to stdin)\n"
    658        "       -o byte offset of RTP packet in capture (defaults to 42)\n"
    659        "       -s <ssrc> restrict decrypting to the given SSRC (in host byte "
    660        "order)\n"
    661        "       -r <roc> initial rollover counter, requires -s <ssrc> "
    662        "(defaults to 0)\n",
    663        string, string);
    664    exit(1);
    665 }
    666 
    667 rtp_decoder_t rtp_decoder_alloc(void)
    668 {
    669    return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t));
    670 }
    671 
    672 void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx)
    673 {
    674    free(rtp_ctx);
    675 }
    676 
    677 int rtp_decoder_deinit(rtp_decoder_t decoder)
    678 {
    679    if (decoder->srtp_ctx) {
    680        return srtp_dealloc(decoder->srtp_ctx);
    681    }
    682    return 0;
    683 }
    684 
    685 int rtp_decoder_init(rtp_decoder_t dcdr,
    686                     srtp_policy_t policy,
    687                     rtp_decoder_mode_t mode,
    688                     size_t rtp_packet_offset,
    689                     uint32_t roc)
    690 {
    691    dcdr->rtp_offset = rtp_packet_offset;
    692    dcdr->srtp_ctx = NULL;
    693    dcdr->start_tv.tv_usec = 0;
    694    dcdr->start_tv.tv_sec = 0;
    695    dcdr->frame_nr = -1;
    696    dcdr->error_cnt = 0;
    697    dcdr->rtp_cnt = 0;
    698    dcdr->rtcp_cnt = 0;
    699    dcdr->mode = mode;
    700    dcdr->policy = policy;
    701 
    702    if (srtp_create(&dcdr->srtp_ctx, &dcdr->policy)) {
    703        return 1;
    704    }
    705 
    706    if (policy.ssrc.type == ssrc_specific && roc != 0) {
    707        if (srtp_set_stream_roc(dcdr->srtp_ctx, policy.ssrc.value, roc)) {
    708            return 1;
    709        }
    710    }
    711    return 0;
    712 }
    713 
    714 /*
    715 * decodes key as base64
    716 */
    717 
    718 void hexdump(const void *ptr, size_t size)
    719 {
    720    size_t i, j;
    721    const unsigned char *cptr = ptr;
    722 
    723    for (i = 0; i < size; i += 16) {
    724        fprintf(stdout, "%04x ", (unsigned int)i);
    725        for (j = 0; j < 16 && i + j < size; j++) {
    726            fprintf(stdout, "%02x ", cptr[i + j]);
    727        }
    728        fprintf(stdout, "\n");
    729    }
    730 }
    731 
    732 void rtp_decoder_handle_pkt(u_char *arg,
    733                            const struct pcap_pkthdr *hdr,
    734                            const u_char *bytes)
    735 {
    736    rtp_decoder_t dcdr = (rtp_decoder_t)arg;
    737    rtp_msg_t message;
    738    int rtp;
    739    int pktsize;
    740    struct timeval delta;
    741    int octets_recvd;
    742    srtp_err_status_t status;
    743    dcdr->frame_nr++;
    744 
    745    if ((dcdr->start_tv.tv_sec == 0) && (dcdr->start_tv.tv_usec == 0)) {
    746        dcdr->start_tv = hdr->ts;
    747    }
    748 
    749    if (hdr->caplen < dcdr->rtp_offset) {
    750        return;
    751    }
    752    const void *rtp_packet = bytes + dcdr->rtp_offset;
    753 
    754    memcpy((void *)&message, rtp_packet, hdr->caplen - dcdr->rtp_offset);
    755    pktsize = hdr->caplen - dcdr->rtp_offset;
    756    octets_recvd = pktsize;
    757 
    758    if (octets_recvd == -1) {
    759        return;
    760    }
    761 
    762    if (dcdr->mode == mode_rtp) {
    763        rtp = 1;
    764    } else if (dcdr->mode == mode_rtcp) {
    765        rtp = 0;
    766    } else {
    767        rtp = 1;
    768        if (octets_recvd >= 2) {
    769            /* rfc5761 */
    770            u_char payload_type = *(bytes + dcdr->rtp_offset + 1) & 0x7f;
    771            rtp = payload_type < 64 || payload_type > 95;
    772        }
    773    }
    774 
    775    if (rtp) {
    776        /* verify rtp header */
    777        if (message.header.version != 2) {
    778            return;
    779        }
    780 
    781        status = srtp_unprotect(dcdr->srtp_ctx, &message, &octets_recvd);
    782        if (status) {
    783            dcdr->error_cnt++;
    784            return;
    785        }
    786        dcdr->rtp_cnt++;
    787    } else {
    788        status = srtp_unprotect_rtcp(dcdr->srtp_ctx, &message, &octets_recvd);
    789        if (status) {
    790            dcdr->error_cnt++;
    791            return;
    792        }
    793        dcdr->rtcp_cnt++;
    794    }
    795    timersub(&hdr->ts, &dcdr->start_tv, &delta);
    796    fprintf(stdout, "%02ld:%02d.%06ld\n", (long)(delta.tv_sec / 60),
    797            (int)(delta.tv_sec % 60), (long)delta.tv_usec);
    798    hexdump(&message, octets_recvd);
    799 }