Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  srtp_driver.c   Sprache: C

 
/*
 * srtp_driver.c
 *
 * a test driver for libSRTP
 *
 * David A. McGrew
 * Cisco Systems, Inc.
 */

/*
 *
 * Copyright (c) 2001-2017, Cisco Systems, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 *   Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 *   Neither the name of the Cisco Systems, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


#include <string.h>   /* for memcpy()          */
#include <time.h>     /* for clock()           */
#include <stdlib.h>   /* for malloc(), free()  */
#include <stdio.h>    /* for print(), fflush() */
#include "getopt_s.h" /* for local getopt()    */

#include "srtp_priv.h"
#include "util.h"

#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H
#include <winsock2.h>
#endif

#define PRINT_REFERENCE_PACKET 1

srtp_err_status_t srtp_validate(void);

srtp_err_status_t srtp_validate_null(void);

#ifdef GCM
srtp_err_status_t srtp_validate_gcm(void);
#endif

srtp_err_status_t srtp_validate_encrypted_extensions_headers(void);

#ifdef GCM
srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void);
#endif

srtp_err_status_t srtp_validate_aes_256(void);

srtp_err_status_t srtp_create_big_policy(srtp_policy_t **list);

srtp_err_status_t srtp_dealloc_big_policy(srtp_policy_t *list);

srtp_err_status_t srtp_test_empty_payload(void);

#ifdef GCM
srtp_err_status_t srtp_test_empty_payload_gcm(void);
#endif

srtp_err_status_t srtp_test_remove_stream(void);

srtp_err_status_t srtp_test_update(void);

srtp_err_status_t srtp_test_protect_trailer_length(void);

srtp_err_status_t srtp_test_protect_rtcp_trailer_length(void);

srtp_err_status_t srtp_test_get_roc(void);

srtp_err_status_t srtp_test_set_receiver_roc(void);

srtp_err_status_t srtp_test_set_sender_roc(void);

double srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy);

double srtp_rejections_per_second(int msg_len_octets,
                                  const srtp_policy_t *policy);

void srtp_do_timing(const srtp_policy_t *policy);

void srtp_do_rejection_timing(const srtp_policy_t *policy);

srtp_err_status_t srtp_test(const srtp_policy_t *policy,
                            int extension_header,
                            int mki_index);

srtp_err_status_t srtcp_test(const srtp_policy_t *policy, int mki_index);

srtp_err_status_t srtp_session_print_policy(srtp_t srtp);

srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy);

char *srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len);

double mips_estimate(int num_trials, int *ignore);

#define TEST_MKI_ID_SIZE 4

extern uint8_t test_key[46];
extern uint8_t test_key_2[46];
extern uint8_t test_mki_id[TEST_MKI_ID_SIZE];
extern uint8_t test_mki_id_2[TEST_MKI_ID_SIZE];

// clang-format off
srtp_master_key_t master_key_1 = {
    test_key,
    test_mki_id,
    TEST_MKI_ID_SIZE
};

srtp_master_key_t master_key_2 = {
    test_key_2,
    test_mki_id_2,
    TEST_MKI_ID_SIZE
};

srtp_master_key_t *test_keys[2] = {
    &master_key_1,
    &master_key_2
};
// clang-format on

void usage(char *prog_name)
{
    printf("usage: %s [ -t ][ -c ][ -v ][ -o ][-d ]* [ -l ]\n"
           " -t run timing test\n"
           " -r run rejection timing test\n"
           " -c run codec timing test\n"
           " -v run validation tests\n"
           " -o output logging to stdout\n"
           " -d turn on debugging module \n"
           " -l list debugging modules\n",
           prog_name);
    exit(1);
}

void log_handler(srtp_log_level_t level, const char *msg, void *data)
{
    char level_char = '?';
    switch (level) {
    case srtp_log_level_error:
        level_char = 'e';
        break;
    case srtp_log_level_warning:
        level_char = 'w';
        break;
    case srtp_log_level_info:
        level_char = 'i';
        break;
    case srtp_log_level_debug:
        level_char = 'd';
        break;
    }
    printf("SRTP-LOG [%c]: %s\n", level_char, msg);
}

/*
 * The policy_array and invalid_policy_array are null-terminated arrays of
 * policy structs. They is declared at the end of this file.
 */


extern const srtp_policy_t *policy_array[];
extern const srtp_policy_t *invalid_policy_array[];

/* the wildcard_policy is declared below; it has a wildcard ssrc */

extern const srtp_policy_t wildcard_policy;

/*
 * mod_driver debug module - debugging module for this test driver
 *
 * we use the crypto_kernel debugging system in this driver, which
 * makes the interface uniform and increases portability
 */


srtp_debug_module_t mod_driver = {
    0,       /* debugging is off by default */
    "driver" /* printable name for module   */
};

int main(int argc, char *argv[])
{
    int q;
    unsigned do_timing_test = 0;
    unsigned do_rejection_test = 0;
    unsigned do_codec_timing = 0;
    unsigned do_validation = 0;
    unsigned do_list_mods = 0;
    unsigned do_log_stdout = 0;
    srtp_err_status_t status;

    /*
     * verify that the compiler has interpreted the header data
     * structure srtp_hdr_t correctly
     */

    if (sizeof(srtp_hdr_t) != 12) {
        printf("error: srtp_hdr_t has incorrect size"
               "(size is %ld bytes, expected 12)\n",
               (long)sizeof(srtp_hdr_t));
        exit(1);
    }

    /* initialize srtp library */
    status = srtp_init();
    if (status) {
        printf("error: srtp init failed with error code %d\n", status);
        exit(1);
    }

    /*  load srtp_driver debug module */
    status = srtp_crypto_kernel_load_debug_module(&mod_driver);
    if (status) {
        printf("error: load of srtp_driver debug module failed "
               "with error code %d\n",
               status);
        exit(1);
    }

    /* process input arguments */
    while (1) {
        q = getopt_s(argc, argv, "trcvold:");
        if (q == -1) {
            break;
        }
        switch (q) {
        case 't':
            do_timing_test = 1;
            break;
        case 'r':
            do_rejection_test = 1;
            break;
        case 'c':
            do_codec_timing = 1;
            break;
        case 'v':
            do_validation = 1;
            break;
        case 'o':
            do_log_stdout = 1;
            break;
        case 'l':
            do_list_mods = 1;
            break;
        case 'd':
            status = srtp_set_debug_module(optarg_s, 1);
            if (status) {
                printf("error: set debug module (%s) failed\n", optarg_s);
                exit(1);
            }
            break;
        default:
            usage(argv[0]);
        }
    }

    if (!do_validation && !do_timing_test && !do_codec_timing &&
        !do_list_mods && !do_rejection_test) {
        usage(argv[0]);
    }

    if (do_log_stdout) {
        status = srtp_install_log_handler(log_handler, NULL);
        if (status) {
            printf("error: install log handler failed\n");
            exit(1);
        }
    }

    if (do_list_mods) {
        status = srtp_list_debug_modules();
        if (status) {
            printf("error: list of debug modules failed\n");
            exit(1);
        }
    }

    if (do_validation) {
        const srtp_policy_t **policy = policy_array;
        srtp_policy_t *big_policy;
        srtp_t srtp_sender;

        /* loop over policy array, testing srtp and srtcp for each policy */
        while (*policy != NULL) {
            printf("testing srtp_protect and srtp_unprotect\n");
            if (srtp_test(*policy, 0, -1) == srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }

            printf("testing srtp_protect and srtp_unprotect with encrypted "
                   "extensions headers\n");
            if (srtp_test(*policy, 1, -1) == srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }
            printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n");
            if (srtcp_test(*policy, -1) == srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }
            printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI "
                   "index set to 0\n");
            if (srtp_test(*policy, 0, 0) == srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }
            printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI "
                   "index set to 1\n");
            if (srtp_test(*policy, 0, 1) == srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }

            printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI "
                   "index set to 0\n");
            if (srtcp_test(*policy, 0) == srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }
            printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI "
                   "index set to 1\n");
            if (srtcp_test(*policy, 1) == srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }
            policy++;
        }

        /* loop over invalid policy array, testing that an SRTP context cannot
         * be created with the policy */

        policy = invalid_policy_array;
        while (*policy != NULL) {
            printf("testing srtp_create fails with invalid policy\n");
            if (srtp_create(&srtp_sender, *policy) != srtp_err_status_ok) {
                printf("passed\n\n");
            } else {
                printf("failed\n");
                exit(1);
            }

            policy++;
        }

        /* create a big policy list and run tests on it */
        status = srtp_create_big_policy(&big_policy);
        if (status) {
            printf("unexpected failure with error code %d\n", status);
            exit(1);
        }
        printf("testing srtp_protect and srtp_unprotect with big policy\n");
        if (srtp_test(big_policy, 0, -1) == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }
        printf("testing srtp_protect and srtp_unprotect with big policy and "
               "encrypted extensions headers\n");
        if (srtp_test(big_policy, 1, -1) == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }
        status = srtp_dealloc_big_policy(big_policy);
        if (status) {
            printf("unexpected failure with error code %d\n", status);
            exit(1);
        }

        /* run test on wildcard policy */
        printf("testing srtp_protect and srtp_unprotect on "
               "wildcard ssrc policy\n");
        if (srtp_test(&wildcard_policy, 0, -1) == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }
        printf("testing srtp_protect and srtp_unprotect on "
               "wildcard ssrc policy and encrypted extensions headers\n");
        if (srtp_test(&wildcard_policy, 1, -1) == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        /*
         * run validation test against the reference packets - note
         * that this test only covers the default policy
         */

        printf("testing srtp_protect and srtp_unprotect against "
               "reference packet\n");
        if (srtp_validate() == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        printf("testing srtp_protect and srtp_unprotect against "
               "reference packet using null cipher and HMAC\n");
        if (srtp_validate_null() == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }

#ifdef GCM
        printf("testing srtp_protect and srtp_unprotect against "
               "reference packet using GCM\n");
        if (srtp_validate_gcm() == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }
#endif

        printf("testing srtp_protect and srtp_unprotect against "
               "reference packet with encrypted extensions headers\n");
        if (srtp_validate_encrypted_extensions_headers() == srtp_err_status_ok)
            printf("passed\n\n");
        else {
            printf("failed\n");
            exit(1);
        }

#ifdef GCM
        printf("testing srtp_protect and srtp_unprotect against "
               "reference packet with encrypted extension headers (GCM)\n");
        if (srtp_validate_encrypted_extensions_headers_gcm() ==
            srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }
#endif

        /*
         * run validation test against the reference packets for
         * AES-256
         */

        printf("testing srtp_protect and srtp_unprotect against "
               "reference packet (AES-256)\n");
        if (srtp_validate_aes_256() == srtp_err_status_ok) {
            printf("passed\n\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        /*
         * test packets with empty payload
         */

        printf("testing srtp_protect and srtp_unprotect against "
               "packet with empty payload\n");
        if (srtp_test_empty_payload() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }
#ifdef GCM
        printf("testing srtp_protect and srtp_unprotect against "
               "packet with empty payload (GCM)\n");
        if (srtp_test_empty_payload_gcm() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }
#endif

        /*
         * test the function srtp_remove_stream()
         */

        printf("testing srtp_remove_stream()...");
        if (srtp_test_remove_stream() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        /*
         * test the function srtp_update()
         */

        printf("testing srtp_update()...");
        if (srtp_test_update() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        /*
         * test the functions srtp_get_protect_trailer_length
         * and srtp_get_protect_rtcp_trailer_length
         */

        printf("testing srtp_get_protect_trailer_length()...");
        if (srtp_test_protect_trailer_length() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        printf("testing srtp_get_protect_rtcp_trailer_length()...");
        if (srtp_test_protect_rtcp_trailer_length() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        printf("testing srtp_test_get_roc()...");
        if (srtp_test_get_roc() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        printf("testing srtp_test_set_receiver_roc()...");
        if (srtp_test_set_receiver_roc() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }

        printf("testing srtp_test_set_sender_roc()...");
        if (srtp_test_set_sender_roc() == srtp_err_status_ok) {
            printf("passed\n");
        } else {
            printf("failed\n");
            exit(1);
        }
    }

    if (do_timing_test) {
        const srtp_policy_t **policy = policy_array;

        /* loop over policies, run timing test for each */
        while (*policy != NULL) {
            srtp_print_policy(*policy);
            srtp_do_timing(*policy);
            policy++;
        }
    }

    if (do_rejection_test) {
        const srtp_policy_t **policy = policy_array;

        /* loop over policies, run rejection timing test for each */
        while (*policy != NULL) {
            srtp_print_policy(*policy);
            srtp_do_rejection_timing(*policy);
            policy++;
        }
    }

    if (do_codec_timing) {
        srtp_policy_t policy;
        int ignore;
        double mips_value = mips_estimate(1000000000, &ignore);

        memset(&policy, 0, sizeof(policy));
        srtp_crypto_policy_set_rtp_default(&policy.rtp);
        srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
        policy.ssrc.type = ssrc_specific;
        policy.ssrc.value = 0xdecafbad;
        policy.key = test_key;
        policy.deprecated_ekt = NULL;
        policy.window_size = 128;
        policy.allow_repeat_tx = 0;
        policy.next = NULL;

        printf("mips estimate: %e\n", mips_value);

        printf("testing srtp processing time for voice codecs:\n");
        printf("codec\t\tlength (octets)\t\tsrtp instructions/second\n");
        printf("G.711\t\t%d\t\t\t%e\n", 80,
               (double)mips_value * (80 * 8) /
                   srtp_bits_per_second(80, &policy) / .01);
        printf("G.711\t\t%d\t\t\t%e\n", 160,
               (double)mips_value * (160 * 8) /
                   srtp_bits_per_second(160, &policy) / .02);
        printf("G.726-32\t%d\t\t\t%e\n", 40,
               (double)mips_value * (40 * 8) /
                   srtp_bits_per_second(40, &policy) / .01);
        printf("G.726-32\t%d\t\t\t%e\n", 80,
               (double)mips_value * (80 * 8) /
                   srtp_bits_per_second(80, &policy) / .02);
        printf("G.729\t\t%d\t\t\t%e\n", 10,
               (double)mips_value * (10 * 8) /
                   srtp_bits_per_second(10, &policy) / .01);
        printf("G.729\t\t%d\t\t\t%e\n", 20,
               (double)mips_value * (20 * 8) /
                   srtp_bits_per_second(20, &policy) / .02);
        printf("Wideband\t%d\t\t\t%e\n", 320,
               (double)mips_value * (320 * 8) /
                   srtp_bits_per_second(320, &policy) / .01);
        printf("Wideband\t%d\t\t\t%e\n", 640,
               (double)mips_value * (640 * 8) /
                   srtp_bits_per_second(640, &policy) / .02);
    }

    status = srtp_shutdown();
    if (status) {
        printf("error: srtp shutdown failed with error code %d\n", status);
        exit(1);
    }

    return 0;
}

/*
 * srtp_create_test_packet(len, ssrc) returns a pointer to a
 * (malloced) example RTP packet whose data field has the length given
 * by pkt_octet_len and the SSRC value ssrc.  The total length of the
 * packet is twelve octets longer, since the header is at the
 * beginning.  There is room at the end of the packet for a trailer,
 * and the four octets following the packet are filled with 0xff
 * values to enable testing for overwrites.
 *
 * note that the location of the test packet can (and should) be
 * deallocated with the free() call once it is no longer needed.
 */


srtp_hdr_t *srtp_create_test_packet(int pkt_octet_len,
                                    uint32_t ssrc,
                                    int *pkt_len)
{
    int i;
    uint8_t *buffer;
    srtp_hdr_t *hdr;
    int bytes_in_hdr = 12;

    /* allocate memory for test packet */
    hdr = (srtp_hdr_t *)malloc(pkt_octet_len + bytes_in_hdr +
                               SRTP_MAX_TRAILER_LEN + 4);
    if (!hdr) {
        return NULL;
    }

    hdr->version = 2;            /* RTP version two     */
    hdr->p = 0;                  /* no padding needed   */
    hdr->x = 0;                  /* no header extension */
    hdr->cc = 0;                 /* no CSRCs            */
    hdr->m = 0;                  /* marker bit          */
    hdr->pt = 0xf;               /* payload type        */
    hdr->seq = htons(0x1234);    /* sequence number     */
    hdr->ts = htonl(0xdecafbad); /* timestamp           */
    hdr->ssrc = htonl(ssrc);     /* synch. source       */

    buffer = (uint8_t *)hdr;
    buffer += bytes_in_hdr;

    /* set RTP data to 0xab */
    for (i = 0; i < pkt_octet_len; i++) {
        *buffer++ = 0xab;
    }

    /* set post-data value to 0xffff to enable overrun checking */
    for (i = 0; i < SRTP_MAX_TRAILER_LEN + 4; i++) {
        *buffer++ = 0xff;
    }

    *pkt_len = bytes_in_hdr + pkt_octet_len;

    return hdr;
}

static srtp_hdr_t *srtp_create_test_packet_extended(int pkt_octet_len,
                                                    uint32_t ssrc,
                                                    uint16_t seq,
                                                    uint32_t ts,
                                                    int *pkt_len)
{
    srtp_hdr_t *hdr;

    hdr = srtp_create_test_packet(pkt_octet_len, ssrc, pkt_len);
    if (hdr == NULL)
        return hdr;

    hdr->seq = htons(seq);
    hdr->ts = htonl(ts);
    return hdr;
}

srtp_hdr_t *srtp_create_test_packet_ext_hdr(int pkt_octet_len,
                                            uint32_t ssrc,
                                            int *pkt_len)
{
    int i;
    uint8_t *buffer;
    srtp_hdr_t *hdr;
    int bytes_in_hdr = 12;
    uint8_t extension_header[12] = { /* one-byte header */
                                     0xbe, 0xde,
                                     /* size */
                                     0x00, 0x02,
                                     /* id 1, length 1 (i.e. 2 bytes) */
                                     0x11,
                                     /* payload */
                                     0xca, 0xfe,
                                     /* padding */
                                     0x00,
                                     /* id 2, length 0 (i.e. 1 byte) */
                                     0x20,
                                     /* payload */
                                     0xba,
                                     /* padding */
                                     0x00, 0x00
    };

    /* allocate memory for test packet */
    hdr = (srtp_hdr_t *)malloc(pkt_octet_len + bytes_in_hdr +
                               sizeof(extension_header) + SRTP_MAX_TRAILER_LEN +
                               4);
    if (!hdr)
        return NULL;

    hdr->version = 2;            /* RTP version two     */
    hdr->p = 0;                  /* no padding needed   */
    hdr->x = 1;                  /* no header extension */
    hdr->cc = 0;                 /* no CSRCs            */
    hdr->m = 0;                  /* marker bit          */
    hdr->pt = 0xf;               /* payload type        */
    hdr->seq = htons(0x1234);    /* sequence number     */
    hdr->ts = htonl(0xdecafbad); /* timestamp           */
    hdr->ssrc = htonl(ssrc);     /* synch. source       */

    buffer = (uint8_t *)hdr;
    buffer += bytes_in_hdr;

    memcpy(buffer, extension_header, sizeof(extension_header));
    buffer += sizeof(extension_header);

    /* set RTP data to 0xab */
    for (i = 0; i < pkt_octet_len; i++)
        *buffer++ = 0xab;

    /* set post-data value to 0xffff to enable overrun checking */
    for (i = 0; i < SRTP_MAX_TRAILER_LEN + 4; i++)
        *buffer++ = 0xff;

    *pkt_len = bytes_in_hdr + sizeof(extension_header) + pkt_octet_len;

    return hdr;
}

void srtp_do_timing(const srtp_policy_t *policy)
{
    int len;

    /*
     * note: the output of this function is formatted so that it
     * can be used in gnuplot.  '#' indicates a comment, and "\r\n"
     * terminates a record
     */


    printf("# testing srtp throughput:\r\n");
    printf("# mesg length (octets)\tthroughput (megabits per second)\r\n");

    for (len = 16; len <= 2048; len *= 2) {
        printf("%d\t\t\t%f\r\n", len,
               srtp_bits_per_second(len, policy) / 1.0E6);
    }

    /* these extra linefeeds let gnuplot know that a dataset is done */
    printf("\r\n\r\n");
}

void srtp_do_rejection_timing(const srtp_policy_t *policy)
{
    int len;

    /*
     * note: the output of this function is formatted so that it
     * can be used in gnuplot.  '#' indicates a comment, and "\r\n"
     * terminates a record
     */


    printf("# testing srtp rejection throughput:\r\n");
    printf("# mesg length (octets)\trejections per second\r\n");

    for (len = 8; len <= 2048; len *= 2) {
        printf("%d\t\t\t%e\r\n", len, srtp_rejections_per_second(len, policy));
    }

    /* these extra linefeeds let gnuplot know that a dataset is done */
    printf("\r\n\r\n");
}

#define MAX_MSG_LEN 1024

double srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy)
{
    srtp_t srtp;
    srtp_hdr_t *mesg;
    int i;
    clock_t timer;
    int num_trials = 100000;
    int input_len, len;
    uint32_t ssrc;
    srtp_err_status_t status;

    /*
     * allocate and initialize an srtp session
     */

    status = srtp_create(&srtp, policy);
    if (status) {
        printf("error: srtp_create() failed with error code %d\n", status);
        exit(1);
    }

    /*
     * if the ssrc is unspecified, use a predetermined one
     */

    if (policy->ssrc.type != ssrc_specific) {
        ssrc = 0xdeadbeef;
    } else {
        ssrc = policy->ssrc.value;
    }

    /*
     * create a test packet
     */

    mesg = srtp_create_test_packet(msg_len_octets, ssrc, &input_len);
    if (mesg == NULL) {
        return 0.0; /* indicate failure by returning zero */
    }
    timer = clock();
    for (i = 0; i < num_trials; i++) {
        len = input_len;
        /* srtp protect message */
        status = srtp_protect(srtp, mesg, &len);
        if (status) {
            printf("error: srtp_protect() failed with error code %d\n", status);
            exit(1);
        }

        /* increment message number */
        {
            /* hack sequence to avoid problems with macros for htons/ntohs on
             * some systems */

            short new_seq = ntohs(mesg->seq) + 1;
            mesg->seq = htons(new_seq);
        }
    }
    timer = clock() - timer;

    free(mesg);

    status = srtp_dealloc(srtp);
    if (status) {
        printf("error: srtp_dealloc() failed with error code %d\n", status);
        exit(1);
    }

    return (double)(msg_len_octets)*8 * num_trials * CLOCKS_PER_SEC / timer;
}

double srtp_rejections_per_second(int msg_len_octets,
                                  const srtp_policy_t *policy)
{
    srtp_ctx_t *srtp;
    srtp_hdr_t *mesg;
    int i;
    int len;
    clock_t timer;
    int num_trials = 1000000;
    uint32_t ssrc = policy->ssrc.value;
    srtp_err_status_t status;

    /*
     * allocate and initialize an srtp session
     */

    status = srtp_create(&srtp, policy);
    if (status) {
        printf("error: srtp_create() failed with error code %d\n", status);
        exit(1);
    }

    mesg = srtp_create_test_packet(msg_len_octets, ssrc, &len);
    if (mesg == NULL) {
        return 0.0; /* indicate failure by returning zero */
    }
    srtp_protect(srtp, (srtp_hdr_t *)mesg, &len);

    timer = clock();
    for (i = 0; i < num_trials; i++) {
        len = msg_len_octets;
        srtp_unprotect(srtp, (srtp_hdr_t *)mesg, &len);
    }
    timer = clock() - timer;

    free(mesg);

    status = srtp_dealloc(srtp);
    if (status) {
        printf("error: srtp_dealloc() failed with error code %d\n", status);
        exit(1);
    }

    return (double)num_trials * CLOCKS_PER_SEC / timer;
}

void err_check(srtp_err_status_t s)
{
    if (s != srtp_err_status_ok) {
        fprintf(stderr, "error: unexpected srtp failure (code %d)\n", s);
        exit(1);
    }
}

srtp_err_status_t srtp_test_call_protect(srtp_t srtp_sender,
                                         srtp_hdr_t *hdr,
                                         int *len,
                                         int mki_index)
{
    if (mki_index == -1) {
        return srtp_protect(srtp_sender, hdr, len);
    } else {
        return srtp_protect_mki(srtp_sender, hdr, len, 1, mki_index);
    }
}

srtp_err_status_t srtp_test_call_protect_rtcp(srtp_t srtp_sender,
                                              srtp_hdr_t *hdr,
                                              int *len,
                                              int mki_index)
{
    if (mki_index == -1) {
        return srtp_protect_rtcp(srtp_sender, hdr, len);
    } else {
        return srtp_protect_rtcp_mki(srtp_sender, hdr, len, 1, mki_index);
    }
}

srtp_err_status_t srtp_test_call_unprotect(srtp_t srtp_sender,
                                           srtp_hdr_t *hdr,
                                           int *len,
                                           int use_mki)
{
    if (use_mki == -1) {
        return srtp_unprotect(srtp_sender, hdr, len);
    } else {
        return srtp_unprotect_mki(srtp_sender, hdr, len, use_mki);
    }
}

srtp_err_status_t srtp_test_call_unprotect_rtcp(srtp_t srtp_sender,
                                                srtp_hdr_t *hdr,
                                                int *len,
                                                int use_mki)
{
    if (use_mki == -1) {
        return srtp_unprotect_rtcp(srtp_sender, hdr, len);
    } else {
        return srtp_unprotect_rtcp_mki(srtp_sender, hdr, len, use_mki);
    }
}

srtp_err_status_t srtp_test(const srtp_policy_t *policy,
                            int extension_header,
                            int mki_index)
{
    int i;
    srtp_t srtp_sender;
    srtp_t srtp_rcvr;
    srtp_err_status_t status = srtp_err_status_ok;
    srtp_hdr_t *hdr, *hdr2;
    uint8_t hdr_enc[64];
    uint8_t *pkt_end;
    int msg_len_octets, msg_len_enc, msg_len;
    int len, len2;
    uint32_t tag_length;
    uint32_t ssrc;
    srtp_policy_t *rcvr_policy;
    srtp_policy_t tmp_policy;
    int header = 1;
    int use_mki = 0;

    if (mki_index >= 0)
        use_mki = 1;

    if (extension_header) {
        memcpy(&tmp_policy, policy, sizeof(srtp_policy_t));
        tmp_policy.enc_xtn_hdr = &header;
        tmp_policy.enc_xtn_hdr_count = 1;
        err_check(srtp_create(&srtp_sender, &tmp_policy));
    } else {
        err_check(srtp_create(&srtp_sender, policy));
    }

    /* print out policy */
    err_check(srtp_session_print_policy(srtp_sender));

    /*
     * initialize data buffer, using the ssrc in the policy unless that
     * value is a wildcard, in which case we'll just use an arbitrary
     * one
     */

    if (policy->ssrc.type != ssrc_specific) {
        ssrc = 0xdecafbad;
    } else {
        ssrc = policy->ssrc.value;
    }
    msg_len_octets = 28;
    if (extension_header) {
        hdr = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc, &len);
        hdr2 = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc, &len2);
    } else {
        hdr = srtp_create_test_packet(msg_len_octets, ssrc, &len);
        hdr2 = srtp_create_test_packet(msg_len_octets, ssrc, &len2);
    }

    /* save original msg len */
    msg_len = len;

    if (hdr == NULL) {
        free(hdr2);
        return srtp_err_status_alloc_fail;
    }
    if (hdr2 == NULL) {
        free(hdr);
        return srtp_err_status_alloc_fail;
    }

    debug_print(mod_driver, "before protection:\n%s",
                srtp_packet_to_string(hdr, len));

#if PRINT_REFERENCE_PACKET
    debug_print(mod_driver, "reference packet before protection:\n%s",
                octet_string_hex_string((uint8_t *)hdr, len));
#endif
    err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index));

    debug_print(mod_driver, "after protection:\n%s",
                srtp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
    debug_print(mod_driver, "after protection:\n%s",
                octet_string_hex_string((uint8_t *)hdr, len));
#endif

    /* save protected message and length */
    memcpy(hdr_enc, hdr, len);
    msg_len_enc = len;

    /*
     * check for overrun of the srtp_protect() function
     *
     * The packet is followed by a value of 0xfffff; if the value of the
     * data following the packet is different, then we know that the
     * protect function is overwriting the end of the packet.
     */

    err_check(srtp_get_protect_trailer_length(srtp_sender, use_mki, mki_index,
                                              &tag_length));
    pkt_end = (uint8_t *)hdr + msg_len + tag_length;
    for (i = 0; i < 4; i++) {
        if (pkt_end[i] != 0xff) {
            fprintf(stdout, "overwrite in srtp_protect() function "
                            "(expected %x, found %x in trailing octet %d)\n",
                    0xff, ((uint8_t *)hdr)[i], i);
            free(hdr);
            free(hdr2);
            return srtp_err_status_algo_fail;
        }
    }

    /*
     * if the policy includes confidentiality, check that ciphertext is
     * different than plaintext
     *
     * Note that this check will give false negatives, with some small
     * probability, especially if the packets are short.  For that
     * reason, we skip this check if the plaintext is less than four
     * octets long.
     */

    if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
        printf("testing that ciphertext is distinct from plaintext...");
        status = srtp_err_status_algo_fail;
        for (i = 12; i < msg_len_octets + 12; i++) {
            if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
                status = srtp_err_status_ok;
            }
        }
        if (status) {
            printf("failed\n");
            free(hdr);
            free(hdr2);
            return status;
        }
        printf("passed\n");
    }

    /*
     * if the policy uses a 'wildcard' ssrc, then we need to make a copy
     * of the policy that changes the direction to inbound
     *
     * we always copy the policy into the rcvr_policy, since otherwise
     * the compiler would fret about the constness of the policy
     */

    rcvr_policy = (srtp_policy_t *)malloc(sizeof(srtp_policy_t));
    if (rcvr_policy == NULL) {
        free(hdr);
        free(hdr2);
        return srtp_err_status_alloc_fail;
    }
    if (extension_header) {
        memcpy(rcvr_policy, &tmp_policy, sizeof(srtp_policy_t));
        if (tmp_policy.ssrc.type == ssrc_any_outbound) {
            rcvr_policy->ssrc.type = ssrc_any_inbound;
        }
    } else {
        memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
        if (policy->ssrc.type == ssrc_any_outbound) {
            rcvr_policy->ssrc.type = ssrc_any_inbound;
        }
    }

    err_check(srtp_create(&srtp_rcvr, rcvr_policy));

    err_check(srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki));

    debug_print(mod_driver, "after unprotection:\n%s",
                srtp_packet_to_string(hdr, len));

    /* verify that the unprotected packet matches the origial one */
    for (i = 0; i < len; i++) {
        if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
            fprintf(stdout, "mismatch at octet %d\n", i);
            status = srtp_err_status_algo_fail;
        }
    }
    if (status) {
        free(hdr);
        free(hdr2);
        free(rcvr_policy);
        return status;
    }

    /*
     * if the policy includes authentication, then test for false positives
     */

    if (policy->rtp.sec_serv & sec_serv_auth) {
        char *data = ((char *)hdr) + (extension_header ? 24 : 12);

        printf("testing for false positives in replay check...");

        /* unprotect a second time - should fail with a replay error */
        status =
            srtp_test_call_unprotect(srtp_rcvr, hdr, &msg_len_enc, use_mki);
        if (status != srtp_err_status_replay_fail) {
            printf("failed with error code %d\n", status);
            free(hdr);
            free(hdr2);
            free(rcvr_policy);
            return status;
        } else {
            printf("passed\n");
        }

        printf("testing for false positives in auth check...");

        /* increment sequence number in header */
        hdr->seq++;

        /* apply protection */
        err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index));

        /* flip bits in packet */
        data[0] ^= 0xff;

        /* unprotect, and check for authentication failure */
        status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki);
        if (status != srtp_err_status_auth_fail) {
            printf("failed\n");
            free(hdr);
            free(hdr2);
            free(rcvr_policy);
            return status;
        } else {
            printf("passed\n");
        }
    }

    err_check(srtp_dealloc(srtp_sender));
    err_check(srtp_dealloc(srtp_rcvr));

    free(hdr);
    free(hdr2);
    free(rcvr_policy);
    return srtp_err_status_ok;
}

srtp_err_status_t srtcp_test(const srtp_policy_t *policy, int mki_index)
{
    int i;
    srtp_t srtcp_sender;
    srtp_t srtcp_rcvr;
    srtp_err_status_t status = srtp_err_status_ok;
    srtp_hdr_t *hdr, *hdr2;
    uint8_t hdr_enc[64];
    uint8_t *pkt_end;
    int msg_len_octets, msg_len_enc, msg_len;
    int len, len2;
    uint32_t tag_length;
    uint32_t ssrc;
    srtp_policy_t *rcvr_policy;
    int use_mki = 0;

    if (mki_index >= 0)
        use_mki = 1;

    err_check(srtp_create(&srtcp_sender, policy));

    /* print out policy */
    err_check(srtp_session_print_policy(srtcp_sender));

    /*
     * initialize data buffer, using the ssrc in the policy unless that
     * value is a wildcard, in which case we'll just use an arbitrary
     * one
     */

    if (policy->ssrc.type != ssrc_specific) {
        ssrc = 0xdecafbad;
    } else {
        ssrc = policy->ssrc.value;
    }
    msg_len_octets = 28;
    hdr = srtp_create_test_packet(msg_len_octets, ssrc, &len);
    /* save message len */
    msg_len = len;

    if (hdr == NULL) {
        return srtp_err_status_alloc_fail;
    }
    hdr2 = srtp_create_test_packet(msg_len_octets, ssrc, &len2);
    if (hdr2 == NULL) {
        free(hdr);
        return srtp_err_status_alloc_fail;
    }

    debug_print(mod_driver, "before protection:\n%s",
                srtp_packet_to_string(hdr, len));

#if PRINT_REFERENCE_PACKET
    debug_print(mod_driver, "reference packet before protection:\n%s",
                octet_string_hex_string((uint8_t *)hdr, len));
#endif
    err_check(srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index));

    debug_print(mod_driver, "after protection:\n%s",
                srtp_packet_to_string(hdr, len));
#if PRINT_REFERENCE_PACKET
    debug_print(mod_driver, "after protection:\n%s",
                octet_string_hex_string((uint8_t *)hdr, len));
#endif

    /* save protected message and length */
    memcpy(hdr_enc, hdr, len);
    msg_len_enc = len;

    /*
     * check for overrun of the srtp_protect() function
     *
     * The packet is followed by a value of 0xfffff; if the value of the
     * data following the packet is different, then we know that the
     * protect function is overwriting the end of the packet.
     */

    srtp_get_protect_rtcp_trailer_length(srtcp_sender, use_mki, mki_index,
                                         &tag_length);
    pkt_end = (uint8_t *)hdr + msg_len + tag_length;
    for (i = 0; i < 4; i++) {
        if (pkt_end[i] != 0xff) {
            fprintf(stdout, "overwrite in srtp_protect_rtcp() function "
                            "(expected %x, found %x in trailing octet %d)\n",
                    0xff, ((uint8_t *)hdr)[i], i);
            free(hdr);
            free(hdr2);
            return srtp_err_status_algo_fail;
        }
    }

    /*
     * if the policy includes confidentiality, check that ciphertext is
     * different than plaintext
     *
     * Note that this check will give false negatives, with some small
     * probability, especially if the packets are short.  For that
     * reason, we skip this check if the plaintext is less than four
     * octets long.
     */

    if ((policy->rtcp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) {
        printf("testing that ciphertext is distinct from plaintext...");
        status = srtp_err_status_algo_fail;
        for (i = 12; i < msg_len_octets + 12; i++) {
            if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
                status = srtp_err_status_ok;
            }
        }
        if (status) {
            printf("failed\n");
            free(hdr);
            free(hdr2);
            return status;
        }
        printf("passed\n");
    }

    /*
     * if the policy uses a 'wildcard' ssrc, then we need to make a copy
     * of the policy that changes the direction to inbound
     *
     * we always copy the policy into the rcvr_policy, since otherwise
     * the compiler would fret about the constness of the policy
     */

    rcvr_policy = (srtp_policy_t *)malloc(sizeof(srtp_policy_t));
    if (rcvr_policy == NULL) {
        free(hdr);
        free(hdr2);
        return srtp_err_status_alloc_fail;
    }
    memcpy(rcvr_policy, policy, sizeof(srtp_policy_t));
    if (policy->ssrc.type == ssrc_any_outbound) {
        rcvr_policy->ssrc.type = ssrc_any_inbound;
    }

    err_check(srtp_create(&srtcp_rcvr, rcvr_policy));

    err_check(srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki));

    debug_print(mod_driver, "after unprotection:\n%s",
                srtp_packet_to_string(hdr, len));

    /* verify that the unprotected packet matches the origial one */
    for (i = 0; i < len; i++) {
        if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) {
            fprintf(stdout, "mismatch at octet %d\n", i);
            status = srtp_err_status_algo_fail;
        }
    }
    if (status) {
        free(hdr);
        free(hdr2);
        free(rcvr_policy);
        return status;
    }

    /*
     * if the policy includes authentication, then test for false positives
     */

    if (policy->rtp.sec_serv & sec_serv_auth) {
        char *data = ((char *)hdr) + 12;

        printf("testing for false positives in replay check...");

        /* unprotect a second time - should fail with a replay error */
        status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &msg_len_enc,
                                               use_mki);
        if (status != srtp_err_status_replay_fail) {
            printf("failed with error code %d\n", status);
            free(hdr);
            free(hdr2);
            free(rcvr_policy);
            return status;
        } else {
            printf("passed\n");
        }

        printf("testing for false positives in auth check...");

        /* increment sequence number in header */
        hdr->seq++;

        /* apply protection */
        err_check(
            srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index));

        /* flip bits in packet */
        data[0] ^= 0xff;

        /* unprotect, and check for authentication failure */
        status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki);
        if (status != srtp_err_status_auth_fail) {
            printf("failed\n");
            free(hdr);
            free(hdr2);
            free(rcvr_policy);
            return status;
        } else {
            printf("passed\n");
        }
    }

    err_check(srtp_dealloc(srtcp_sender));
    err_check(srtp_dealloc(srtcp_rcvr));

    free(hdr);
    free(hdr2);
    free(rcvr_policy);
    return srtp_err_status_ok;
}

srtp_err_status_t srtp_session_print_policy(srtp_t srtp)
{
    char *serv_descr[4] = { "none""confidentiality""authentication",
                            "confidentiality and authentication" };
    char *direction[3] = { "unknown""outbound""inbound" };
    srtp_stream_t stream;
    srtp_session_keys_t *session_keys = NULL;

    /* sanity checking */
    if (srtp == NULL) {
        return srtp_err_status_fail;
    }

    /* if there's a template stream, print it out */
    if (srtp->stream_template != NULL) {
        stream = srtp->stream_template;
        session_keys = &stream->session_keys[0];
        printf("# SSRC: any %s\r\n"
               "# rtp cipher: %s\r\n"
               "# rtp auth: %s\r\n"
               "# rtp services: %s\r\n"
               "# rtcp cipher: %s\r\n"
               "# rtcp auth: %s\r\n"
               "# rtcp services: %s\r\n"
               "# window size: %lu\r\n"
               "# tx rtx allowed:%s\r\n",
               direction[stream->direction],
               session_keys->rtp_cipher->type->description,
               session_keys->rtp_auth->type->description,
               serv_descr[stream->rtp_services],
               session_keys->rtcp_cipher->type->description,
               session_keys->rtcp_auth->type->description,
               serv_descr[stream->rtcp_services],
               srtp_rdbx_get_window_size(&stream->rtp_rdbx),
               stream->allow_repeat_tx ? "true" : "false");

        printf("# Encrypted extension headers: ");
        if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) {
            int *enc_xtn_hdr = stream->enc_xtn_hdr;
            int count = stream->enc_xtn_hdr_count;
            while (count > 0) {
                printf("%d ", *enc_xtn_hdr);
                enc_xtn_hdr++;
                count--;
            }
            printf("\n");
        } else {
            printf("none\n");
        }
    }

    /* loop over streams in session, printing the policy of each */
    stream = srtp->stream_list;
    while (stream != NULL) {
        if (stream->rtp_services > sec_serv_conf_and_auth) {
            return srtp_err_status_bad_param;
        }
        session_keys = &stream->session_keys[0];

        printf("# SSRC: 0x%08x\r\n"
               "# rtp cipher: %s\r\n"
               "# rtp auth: %s\r\n"
               "# rtp services: %s\r\n"
               "# rtcp cipher: %s\r\n"
               "# rtcp auth: %s\r\n"
               "# rtcp services: %s\r\n"
               "# window size: %lu\r\n"
               "# tx rtx allowed:%s\r\n",
               stream->ssrc, session_keys->rtp_cipher->type->description,
               session_keys->rtp_auth->type->description,
               serv_descr[stream->rtp_services],
               session_keys->rtcp_cipher->type->description,
               session_keys->rtcp_auth->type->description,
               serv_descr[stream->rtcp_services],
               srtp_rdbx_get_window_size(&stream->rtp_rdbx),
               stream->allow_repeat_tx ? "true" : "false");

        printf("# Encrypted extension headers: ");
        if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) {
            int *enc_xtn_hdr = stream->enc_xtn_hdr;
            int count = stream->enc_xtn_hdr_count;
            while (count > 0) {
                printf("%d ", *enc_xtn_hdr);
                enc_xtn_hdr++;
                count--;
            }
            printf("\n");
        } else {
            printf("none\n");
        }

        /* advance to next stream in the list */
        stream = stream->next;
    }
    return srtp_err_status_ok;
}

srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy)
{
    srtp_err_status_t status;
    srtp_t session;

    status = srtp_create(&session, policy);
    if (status) {
        return status;
    }
    status = srtp_session_print_policy(session);
    if (status) {
        return status;
    }
    status = srtp_dealloc(session);
    if (status) {
        return status;
    }
    return srtp_err_status_ok;
}

/*
 * srtp_print_packet(...) is for debugging only
 * it prints an RTP packet to the stdout
 *
 * note that this function is *not* threadsafe
 */


#include <stdio.h>

#define MTU 2048

char packet_string[MTU];

char *srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len)
{
    int octets_in_rtp_header = 12;
    uint8_t *data = ((uint8_t *)hdr) + octets_in_rtp_header;
    int hex_len = pkt_octet_len - octets_in_rtp_header;

    /* sanity checking */
    if ((hdr == NULL) || (pkt_octet_len > MTU)) {
        return NULL;
    }

    /* write packet into string */
    sprintf(packet_string, "(s)rtp packet: {\n"
                           " version:\t%d\n"
                           " p:\t\t%d\n"
                           " x:\t\t%d\n"
                           " cc:\t\t%d\n"
                           " m:\t\t%d\n"
                           " pt:\t\t%x\n"
                           " seq:\t\t%x\n"
                           " ts:\t\t%x\n"
                           " ssrc:\t%x\n"
                           " data:\t%s\n"
                           "} (%d octets in total)\n",
            hdr->version, hdr->p, hdr->x, hdr->cc, hdr->m, hdr->pt, hdr->seq,
            hdr->ts, hdr->ssrc, octet_string_hex_string(data, hex_len),
            pkt_octet_len);

    return packet_string;
}

/*
 * mips_estimate() is a simple function to estimate the number of
 * instructions per second that the host can perform.  note that this
 * function can be grossly wrong; you may want to have a manual sanity
 * check of its output!
 *
 * the 'ignore' pointer is there to convince the compiler to not just
 * optimize away the function
 */


double mips_estimate(int num_trials, int *ignore)
{
    clock_t t;
    volatile int i, sum;

    sum = 0;
    t = clock();
    for (i = 0; i < num_trials; i++) {
        sum += i;
    }
    t = clock() - t;
    if (t < 1) {
        t = 1;
    }

    /*   printf("%d\n", sum); */
    *ignore = sum;

    return (double)num_trials * CLOCKS_PER_SEC / t;
}

/*
 * srtp_validate() verifies the correctness of libsrtp by comparing
 * some computed packets against some pre-computed reference values.
 * These packets were made with the default SRTP policy.
 */


srtp_err_status_t srtp_validate()
{
    // clang-format off
    uint8_t srtp_plaintext_ref[28] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab
    };
    uint8_t srtp_plaintext[38] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    uint8_t srtp_ciphertext[38] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0x4e, 0x55, 0xdc, 0x4c,
        0xe7, 0x99, 0x78, 0xd8, 0x8c, 0xa4, 0xd2, 0x15,
        0x94, 0x9d, 0x24, 0x02, 0xb7, 0x8d, 0x6a, 0xcc,
        0x99, 0xea, 0x17, 0x9b, 0x8d, 0xbb
    };
    uint8_t rtcp_plaintext_ref[24] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
    };
    uint8_t rtcp_plaintext[38] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    uint8_t srtcp_ciphertext[38] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0x71, 0x28, 0x03, 0x5b, 0xe4, 0x87, 0xb9, 0xbd,
        0xbe, 0xf8, 0x90, 0x41, 0xf9, 0x77, 0xa5, 0xa8,
        0x80, 0x00, 0x00, 0x01, 0x99, 0x3e, 0x08, 0xcd,
        0x54, 0xd6, 0xc1, 0x23, 0x07, 0x98
    };
    // clang-format on

    srtp_t srtp_snd, srtp_recv;
    srtp_err_status_t status;
    int len;
    srtp_policy_t policy;

    /*
     * create a session with a single stream using the default srtp
     * policy and with the SSRC value 0xcafebabe
     */

    memset(&policy, 0, sizeof(policy));
    srtp_crypto_policy_set_rtp_default(&policy.rtp);
    srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
    policy.ssrc.type = ssrc_specific;
    policy.ssrc.value = 0xcafebabe;
    policy.key = test_key;
    policy.deprecated_ekt = NULL;
    policy.window_size = 128;
    policy.allow_repeat_tx = 0;
    policy.next = NULL;

    status = srtp_create(&srtp_snd, &policy);
    if (status) {
        return status;
    }

    /*
     * protect plaintext, then compare with ciphertext
     */

    len = 28;
    status = srtp_protect(srtp_snd, srtp_plaintext, &len);
    if (status || (len != 38)) {
        return srtp_err_status_fail;
    }

    debug_print(mod_driver, "ciphertext:\n %s",
                octet_string_hex_string(srtp_plaintext, len));
    debug_print(mod_driver, "ciphertext reference:\n %s",
                octet_string_hex_string(srtp_ciphertext, len));

    if (srtp_octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) {
        return srtp_err_status_fail;
    }

    /*
     * protect plaintext rtcp, then compare with srtcp ciphertext
     */

    len = 24;
    status = srtp_protect_rtcp(srtp_snd, rtcp_plaintext, &len);
    if (status || (len != 38)) {
        return srtp_err_status_fail;
    }

    debug_print(mod_driver, "srtcp ciphertext:\n %s",
                octet_string_hex_string(rtcp_plaintext, len));
    debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
                octet_string_hex_string(srtcp_ciphertext, len));

    if (srtp_octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) {
        return srtp_err_status_fail;
    }

    /*
     * create a receiver session context comparable to the one created
     * above - we need to do this so that the replay checking doesn't
     * complain
     */

    status = srtp_create(&srtp_recv, &policy);
    if (status) {
        return status;
    }

    /*
     * unprotect ciphertext, then compare with plaintext
     */

    status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
    if (status || (len != 28)) {
        return status;
    }

    if (srtp_octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) {
        return srtp_err_status_fail;
    }

    /*
     * unprotect srtcp ciphertext, then compare with rtcp plaintext
     */

    len = 38;
    status = srtp_unprotect_rtcp(srtp_recv, srtcp_ciphertext, &len);
    if (status || (len != 24)) {
        return status;
    }

    if (srtp_octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) {
        return srtp_err_status_fail;
    }

    status = srtp_dealloc(srtp_snd);
    if (status) {
        return status;
    }

    status = srtp_dealloc(srtp_recv);
    if (status) {
        return status;
    }

    return srtp_err_status_ok;
}

/*
 * srtp_validate_null() verifies the correctness of libsrtp by comparing
 * some computed packets against some pre-computed reference values.
 * These packets were made with a policy that applies null encryption
 * and HMAC authentication.
 */


srtp_err_status_t srtp_validate_null()
{
    // clang-format off
    uint8_t srtp_plaintext_ref[28] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab
    };
    uint8_t srtp_plaintext[38] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    uint8_t srtp_ciphertext[38] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xa1, 0x36, 0x27,
        0x0b, 0x67, 0x91, 0x34, 0xce, 0x9b
    };
    uint8_t rtcp_plaintext_ref[24] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
    };
    uint8_t rtcp_plaintext[38] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    uint8_t srtcp_ciphertext[38] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0x00, 0x00, 0x00, 0x01, 0xfe, 0x88, 0xc7, 0xfd,
        0xfd, 0x37, 0xeb, 0xce, 0x61, 0x5d,
    };
    // clang-format on

    srtp_t srtp_snd, srtp_recv;
    srtp_err_status_t status;
    int len;
    srtp_policy_t policy;

    /*
     * create a session with a single stream using the default srtp
     * policy and with the SSRC value 0xcafebabe
     */

    memset(&policy, 0, sizeof(policy));
    srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
    srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtcp);
    policy.ssrc.type = ssrc_specific;
    policy.ssrc.value = 0xcafebabe;
    policy.key = test_key;
    policy.deprecated_ekt = NULL;
    policy.window_size = 128;
    policy.allow_repeat_tx = 0;
    policy.next = NULL;

    status = srtp_create(&srtp_snd, &policy);
    if (status) {
        return status;
    }

    /*
     * protect plaintext, then compare with ciphertext
     */

    len = 28;
    status = srtp_protect(srtp_snd, srtp_plaintext, &len);
    if (status || (len != 38)) {
        return srtp_err_status_fail;
    }

    debug_print(mod_driver, "ciphertext:\n %s",
                octet_string_hex_string(srtp_plaintext, len));
    debug_print(mod_driver, "ciphertext reference:\n %s",
                octet_string_hex_string(srtp_ciphertext, len));

    if (srtp_octet_string_is_eq(srtp_plaintext, srtp_ciphertext, len)) {
        return srtp_err_status_fail;
    }

    /*
     * protect plaintext rtcp, then compare with srtcp ciphertext
     */

    len = 24;
    status = srtp_protect_rtcp(srtp_snd, rtcp_plaintext, &len);
    if (status || (len != 38)) {
        return srtp_err_status_fail;
    }

    debug_print(mod_driver, "srtcp ciphertext:\n %s",
                octet_string_hex_string(rtcp_plaintext, len));
    debug_print(mod_driver, "srtcp ciphertext reference:\n %s",
                octet_string_hex_string(srtcp_ciphertext, len));

    if (srtp_octet_string_is_eq(rtcp_plaintext, srtcp_ciphertext, len)) {
        return srtp_err_status_fail;
    }

    /*
     * create a receiver session context comparable to the one created
     * above - we need to do this so that the replay checking doesn't
     * complain
     */

    status = srtp_create(&srtp_recv, &policy);
    if (status) {
        return status;
    }

    /*
     * unprotect ciphertext, then compare with plaintext
     */

    status = srtp_unprotect(srtp_recv, srtp_ciphertext, &len);
    if (status || (len != 28)) {
        return status;
    }

    if (srtp_octet_string_is_eq(srtp_ciphertext, srtp_plaintext_ref, len)) {
        return srtp_err_status_fail;
    }

    /*
     * unprotect srtcp ciphertext, then compare with rtcp plaintext
     */

    len = 38;
    status = srtp_unprotect_rtcp(srtp_recv, srtcp_ciphertext, &len);
    if (status || (len != 24)) {
        return status;
    }

    if (srtp_octet_string_is_eq(srtcp_ciphertext, rtcp_plaintext_ref, len)) {
        return srtp_err_status_fail;
    }

    status = srtp_dealloc(srtp_snd);
    if (status) {
        return status;
    }

    status = srtp_dealloc(srtp_recv);
    if (status) {
        return status;
    }

    return srtp_err_status_ok;
}

#ifdef GCM
/*
 * srtp_validate_gcm() verifies the correctness of libsrtp by comparing
 * an computed packet against the known ciphertext for the plaintext.
 */

srtp_err_status_t srtp_validate_gcm()
{
    // clang-format off
    unsigned char test_key_gcm[28] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
        0xa8, 0xa9, 0xaa, 0xab
    };
    uint8_t rtp_plaintext_ref[28] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab
    };
    uint8_t rtp_plaintext[44] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    };
    uint8_t srtp_ciphertext[44] = {
        0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad,
        0xca, 0xfe, 0xba, 0xbe, 0xc5, 0x00, 0x2e, 0xde,
        0x04, 0xcf, 0xdd, 0x2e, 0xb9, 0x11, 0x59, 0xe0,
        0x88, 0x0a, 0xa0, 0x6e, 0xd2, 0x97, 0x68, 0x26,
        0xf7, 0x96, 0xb2, 0x01, 0xdf, 0x31, 0x31, 0xa1,
        0x27, 0xe8, 0xa3, 0x92
    };
    uint8_t rtcp_plaintext_ref[24] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
    };
    uint8_t rtcp_plaintext[44] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    };
    uint8_t srtcp_ciphertext[44] = {
        0x81, 0xc8, 0x00, 0x0b, 0xca, 0xfe, 0xba, 0xbe,
        0xc9, 0x8b, 0x8b, 0x5d, 0xf0, 0x39, 0x2a, 0x55,
        0x85, 0x2b, 0x6c, 0x21, 0xac, 0x8e, 0x70, 0x25,
        0xc5, 0x2c, 0x6f, 0xbe, 0xa2, 0xb3, 0xb4, 0x46,
        0xea, 0x31, 0x12, 0x3b, 0xa8, 0x8c, 0xe6, 0x1e,
        0x80, 0x00, 0x00, 0x01
    };
    // clang-format on

    srtp_t srtp_snd, srtp_recv;
    srtp_err_status_t status;
    int len;
    srtp_policy_t policy;

    /*
     * create a session with a single stream using the default srtp
     * policy and with the SSRC value 0xcafebabe
     */

    memset(&policy, 0, sizeof(policy));
    srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
    srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp);
    policy.ssrc.type = ssrc_specific;
    policy.ssrc.value = 0xcafebabe;
    policy.key = test_key_gcm;
    policy.deprecated_ekt = NULL;
    policy.window_size = 128;
    policy.allow_repeat_tx = 0;
    policy.next = NULL;

    status = srtp_create(&srtp_snd, &policy);
    if (status) {
        return status;
    }

    /*
     * protect plaintext rtp, then compare with srtp ciphertext
     */

    len = 28;
    status = srtp_protect(srtp_snd, rtp_plaintext, &len);
    if (status || (len != 44)) {
        return srtp_err_status_fail;
    }

    debug_print(mod_driver, "srtp ciphertext:\n %s",
                octet_string_hex_string(rtp_plaintext, len));
    debug_print(mod_driver, "srtp ciphertext reference:\n %s",
                octet_string_hex_string(srtp_ciphertext, len));

    if (srtp_octet_string_is_eq(rtp_plaintext, srtp_ciphertext, len)) {
        return srtp_err_status_fail;
    }

    /*
     * protect plaintext rtcp, then compare with srtcp ciphertext
     */

    len = 24;
    status = srtp_protect_rtcp(srtp_snd, rtcp_plaintext, &len);
    if (status || (len != 44)) {
        return srtp_err_status_fail;
    }

--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=92 G=92

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge