1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade libsrtp from 2.0.0 to 2.3.0, with source code. 4.0.79

This commit is contained in:
winlin 2021-03-02 14:29:06 +08:00
parent 3749d4d833
commit 8089fc004c
111 changed files with 45307 additions and 5 deletions

View file

@ -0,0 +1,713 @@
/*
* CUTest -- C/C++ Unit Test facility
* <http://github.com/mity/cutest>
*
* Copyright (c) 2013-2017 Martin Mitas
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef CUTEST_H__
#define CUTEST_H__
/************************
*** Public interface ***
************************/
/* By default, <cutest.h> provides the main program entry point (function
* main()). However, if the test suite is composed of multiple source files
* which include <cutest.h>, then this causes a problem of multiple main()
* definitions. To avoid this problem, #define macro TEST_NO_MAIN in all
* compilation units but one.
*/
/* Macro to specify list of unit tests in the suite.
* The unit test implementation MUST provide list of unit tests it implements
* with this macro:
*
* TEST_LIST = {
* { "test1_name", test1_func_ptr },
* { "test2_name", test2_func_ptr },
* ...
* { 0 }
* };
*
* The list specifies names of each test (must be unique) and pointer to
* a function implementing it. The function does not take any arguments
* and has no return values, i.e. every test function has tp be compatible
* with this prototype:
*
* void test_func(void);
*/
#define TEST_LIST const struct test__ test_list__[]
/* Macros for testing whether an unit test succeeds or fails. These macros
* can be used arbitrarily in functions implementing the unit tests.
*
* If any condition fails throughout execution of a test, the test fails.
*
* TEST_CHECK takes only one argument (the condition), TEST_CHECK_ allows
* also to specify an error message to print out if the condition fails.
* (It expects printf-like format string and its parameters). The macros
* return non-zero (condition passes) or 0 (condition fails).
*
* That can be useful when more conditions should be checked only if some
* preceding condition passes, as illustrated in this code snippet:
*
* SomeStruct* ptr = allocate_some_struct();
* if(TEST_CHECK(ptr != NULL)) {
* TEST_CHECK(ptr->member1 < 100);
* TEST_CHECK(ptr->member2 > 200);
* }
*/
#define TEST_CHECK_(cond, ...) \
test_check__((cond), __FILE__, __LINE__, __VA_ARGS__)
#define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, "%s", #cond)
/**********************
*** Implementation ***
**********************/
/* The unit test files should not rely on anything below. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__)
#define CUTEST_UNIX__ 1
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#endif
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
#define CUTEST_WIN__ 1
#include <windows.h>
#include <io.h>
#endif
#ifdef __cplusplus
#include <exception>
#endif
/* Note our global private identifiers end with '__' to mitigate risk of clash
* with the unit tests implementation. */
#ifdef __cplusplus
extern "C" {
#endif
struct test__ {
const char *name;
void (*func)(void);
};
extern const struct test__ test_list__[];
int test_check__(int cond, const char *file, int line, const char *fmt, ...);
#ifndef TEST_NO_MAIN
static char *test_argv0__ = NULL;
static int test_count__ = 0;
static int test_no_exec__ = 0;
static int test_no_summary__ = 0;
static int test_skip_mode__ = 0;
static int test_stat_failed_units__ = 0;
static int test_stat_run_units__ = 0;
static const struct test__ *test_current_unit__ = NULL;
static int test_current_already_logged__ = 0;
static int test_verbose_level__ = 2;
static int test_current_failures__ = 0;
static int test_colorize__ = 0;
#define CUTEST_COLOR_DEFAULT__ 0
#define CUTEST_COLOR_GREEN__ 1
#define CUTEST_COLOR_RED__ 2
#define CUTEST_COLOR_DEFAULT_INTENSIVE__ 3
#define CUTEST_COLOR_GREEN_INTENSIVE__ 4
#define CUTEST_COLOR_RED_INTENSIVE__ 5
static size_t test_print_in_color__(int color, const char *fmt, ...)
{
va_list args;
char buffer[256];
size_t n;
va_start(args, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
buffer[sizeof(buffer) - 1] = '\0';
if (!test_colorize__) {
return printf("%s", buffer);
}
#if defined CUTEST_UNIX__
{
const char *col_str;
switch (color) {
case CUTEST_COLOR_GREEN__:
col_str = "\033[0;32m";
break;
case CUTEST_COLOR_RED__:
col_str = "\033[0;31m";
break;
case CUTEST_COLOR_GREEN_INTENSIVE__:
col_str = "\033[1;32m";
break;
case CUTEST_COLOR_RED_INTENSIVE__:
col_str = "\033[1;30m";
break;
case CUTEST_COLOR_DEFAULT_INTENSIVE__:
col_str = "\033[1m";
break;
default:
col_str = "\033[0m";
break;
}
printf("%s", col_str);
n = printf("%s", buffer);
printf("\033[0m");
return n;
}
#elif defined CUTEST_WIN__
{
HANDLE h;
CONSOLE_SCREEN_BUFFER_INFO info;
WORD attr;
h = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(h, &info);
switch (color) {
case CUTEST_COLOR_GREEN__:
attr = FOREGROUND_GREEN;
break;
case CUTEST_COLOR_RED__:
attr = FOREGROUND_RED;
break;
case CUTEST_COLOR_GREEN_INTENSIVE__:
attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break;
case CUTEST_COLOR_RED_INTENSIVE__:
attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
case CUTEST_COLOR_DEFAULT_INTENSIVE__:
attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED |
FOREGROUND_INTENSITY;
break;
default:
attr = 0;
break;
}
if (attr != 0)
SetConsoleTextAttribute(h, attr);
n = printf("%s", buffer);
SetConsoleTextAttribute(h, info.wAttributes);
return n;
}
#else
n = printf("%s", buffer);
return n;
#endif
}
int test_check__(int cond, const char *file, int line, const char *fmt, ...)
{
const char *result_str;
int result_color;
int verbose_level;
if (cond) {
result_str = "ok";
result_color = CUTEST_COLOR_GREEN__;
verbose_level = 3;
} else {
if (!test_current_already_logged__ && test_current_unit__ != NULL) {
printf("[ ");
test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, "FAILED");
printf(" ]\n");
}
result_str = "failed";
result_color = CUTEST_COLOR_RED__;
verbose_level = 2;
test_current_failures__++;
test_current_already_logged__++;
}
if (test_verbose_level__ >= verbose_level) {
size_t n = 0;
va_list args;
printf(" ");
if (file != NULL)
n += printf("%s:%d: Check ", file, line);
va_start(args, fmt);
n += vprintf(fmt, args);
va_end(args);
printf("... ");
test_print_in_color__(result_color, result_str);
printf("\n");
test_current_already_logged__++;
}
return (cond != 0);
}
static void test_list_names__(void)
{
const struct test__ *test;
printf("Unit tests:\n");
for (test = &test_list__[0]; test->func != NULL; test++)
printf(" %s\n", test->name);
}
static const struct test__ *test_by_name__(const char *name)
{
const struct test__ *test;
for (test = &test_list__[0]; test->func != NULL; test++) {
if (strcmp(test->name, name) == 0)
return test;
}
return NULL;
}
/* Call directly the given test unit function. */
static int test_do_run__(const struct test__ *test)
{
test_current_unit__ = test;
test_current_failures__ = 0;
test_current_already_logged__ = 0;
if (test_verbose_level__ >= 3) {
test_print_in_color__(CUTEST_COLOR_DEFAULT_INTENSIVE__, "Test %s:\n",
test->name);
test_current_already_logged__++;
} else if (test_verbose_level__ >= 1) {
size_t n;
char spaces[32];
n = test_print_in_color__(CUTEST_COLOR_DEFAULT_INTENSIVE__,
"Test %s... ", test->name);
memset(spaces, ' ', sizeof(spaces));
if (n < sizeof(spaces))
printf("%.*s", (int)(sizeof(spaces) - n), spaces);
} else {
test_current_already_logged__ = 1;
}
#ifdef __cplusplus
try {
#endif
/* This is good to do for case the test unit e.g. crashes. */
fflush(stdout);
fflush(stderr);
test->func();
#ifdef __cplusplus
} catch (std::exception &e) {
const char *what = e.what();
if (what != NULL)
test_check__(0, NULL, 0, "Threw std::exception: %s", what);
else
test_check__(0, NULL, 0, "Threw std::exception");
} catch (...) {
test_check__(0, NULL, 0, "Threw an exception");
}
#endif
if (test_verbose_level__ >= 3) {
switch (test_current_failures__) {
case 0:
test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__,
" All conditions have passed.\n\n");
break;
case 1:
test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__,
" One condition has FAILED.\n\n");
break;
default:
test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__,
" %d conditions have FAILED.\n\n",
test_current_failures__);
break;
}
} else if (test_verbose_level__ >= 1 && test_current_failures__ == 0) {
printf("[ ");
test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__, "OK");
printf(" ]\n");
}
test_current_unit__ = NULL;
return (test_current_failures__ == 0) ? 0 : -1;
}
#if defined(CUTEST_UNIX__) || defined(CUTEST_WIN__)
/* Called if anything goes bad in cutest, or if the unit test ends in other
* way then by normal returning from its function (e.g. exception or some
* abnormal child process termination). */
static void test_error__(const char *fmt, ...)
{
va_list args;
if (test_verbose_level__ == 0)
return;
if (test_verbose_level__ <= 2 && !test_current_already_logged__ &&
test_current_unit__ != NULL) {
printf("[ ");
test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, "FAILED");
printf(" ]\n");
}
if (test_verbose_level__ >= 2) {
test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, " Error: ");
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
printf("\n");
}
}
#endif
/* Trigger the unit test. If possible (and not suppressed) it starts a child
* process who calls test_do_run__(), otherwise it calls test_do_run__()
* directly. */
static void test_run__(const struct test__ *test)
{
int failed = 1;
test_current_unit__ = test;
test_current_already_logged__ = 0;
if (!test_no_exec__) {
#if defined(CUTEST_UNIX__)
pid_t pid;
int exit_code;
pid = fork();
if (pid == (pid_t)-1) {
test_error__("Cannot fork. %s [%d]", strerror(errno), errno);
failed = 1;
} else if (pid == 0) {
/* Child: Do the test. */
failed = (test_do_run__(test) != 0);
exit(failed ? 1 : 0);
} else {
/* Parent: Wait until child terminates and analyze its exit code. */
waitpid(pid, &exit_code, 0);
if (WIFEXITED(exit_code)) {
switch (WEXITSTATUS(exit_code)) {
case 0:
failed = 0;
break; /* test has passed. */
case 1: /* noop */
break; /* "normal" failure. */
default:
test_error__("Unexpected exit code [%d]",
WEXITSTATUS(exit_code));
}
} else if (WIFSIGNALED(exit_code)) {
char tmp[32];
const char *signame;
switch (WTERMSIG(exit_code)) {
case SIGINT:
signame = "SIGINT";
break;
case SIGHUP:
signame = "SIGHUP";
break;
case SIGQUIT:
signame = "SIGQUIT";
break;
case SIGABRT:
signame = "SIGABRT";
break;
case SIGKILL:
signame = "SIGKILL";
break;
case SIGSEGV:
signame = "SIGSEGV";
break;
case SIGILL:
signame = "SIGILL";
break;
case SIGTERM:
signame = "SIGTERM";
break;
default:
sprintf(tmp, "signal %d", WTERMSIG(exit_code));
signame = tmp;
break;
}
test_error__("Test interrupted by %s", signame);
} else {
test_error__("Test ended in an unexpected way [%d]", exit_code);
}
}
#elif defined(CUTEST_WIN__)
char buffer[512] = { 0 };
STARTUPINFOA startupInfo = { 0 };
PROCESS_INFORMATION processInfo;
DWORD exitCode;
/* Windows has no fork(). So we propagate all info into the child
* through a command line arguments. */
_snprintf(buffer, sizeof(buffer) - 1,
"%s --no-exec --no-summary --verbose=%d --color=%s -- \"%s\"",
test_argv0__, test_verbose_level__,
test_colorize__ ? "always" : "never", test->name);
startupInfo.cb = sizeof(STARTUPINFO);
if (CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL,
&startupInfo, &processInfo)) {
WaitForSingleObject(processInfo.hProcess, INFINITE);
GetExitCodeProcess(processInfo.hProcess, &exitCode);
CloseHandle(processInfo.hThread);
CloseHandle(processInfo.hProcess);
failed = (exitCode != 0);
} else {
test_error__("Cannot create unit test subprocess [%ld].",
GetLastError());
failed = 1;
}
#else
/* A platform where we don't know how to run child process. */
failed = (test_do_run__(test) != 0);
#endif
} else {
/* Child processes suppressed through --no-exec. */
failed = (test_do_run__(test) != 0);
}
test_current_unit__ = NULL;
test_stat_run_units__++;
if (failed)
test_stat_failed_units__++;
}
#if defined(CUTEST_WIN__)
/* Callback for SEH events. */
static LONG CALLBACK test_exception_filter__(EXCEPTION_POINTERS *ptrs)
{
test_error__("Unhandled SEH exception %08lx at %p.",
ptrs->ExceptionRecord->ExceptionCode,
ptrs->ExceptionRecord->ExceptionAddress);
fflush(stdout);
fflush(stderr);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
static void test_help__(void)
{
printf("Usage: %s [options] [test...]\n", test_argv0__);
printf("Run the specified unit tests; or if the option '--skip' is used, "
"run all\n");
printf("tests in the suite but those listed. By default, if no tests are "
"specified\n");
printf("on the command line, all unit tests in the suite are run.\n");
printf("\n");
printf("Options:\n");
printf(
" -s, --skip Execute all unit tests but the listed ones\n");
printf(" --no-exec Do not execute unit tests as child "
"processes\n");
printf(
" --no-summary Suppress printing of test results summary\n");
printf(" -l, --list List unit tests in the suite and exit\n");
printf(" -v, --verbose Enable more verbose output\n");
printf(" --verbose=LEVEL Set verbose level to LEVEL:\n");
printf(" 0 ... Be silent\n");
printf(" 1 ... Output one line per test (and "
"summary)\n");
printf(" 2 ... As 1 and failed conditions (this "
"is default)\n");
printf(" 3 ... As 1 and all conditions (and "
"extended summary)\n");
printf(" --color=WHEN Enable colorized output (WHEN is one of "
"'auto', 'always', 'never')\n");
printf(" -h, --help Display this help and exit\n");
printf("\n");
test_list_names__();
}
int main(int argc, char **argv)
{
const struct test__ **tests = NULL;
int i, j, n = 0;
int seen_double_dash = 0;
test_argv0__ = argv[0];
#if defined CUTEST_UNIX__
test_colorize__ = isatty(STDOUT_FILENO);
#elif defined CUTEST_WIN__
test_colorize__ = _isatty(_fileno(stdout));
#else
test_colorize__ = 0;
#endif
/* Parse options */
for (i = 1; i < argc; i++) {
if (seen_double_dash || argv[i][0] != '-') {
tests = (const struct test__ **)realloc(
(void *)tests, (n + 1) * sizeof(const struct test__ *));
if (tests == NULL) {
fprintf(stderr, "Out of memory.\n");
exit(2);
}
tests[n] = test_by_name__(argv[i]);
if (tests[n] == NULL) {
fprintf(stderr, "%s: Unrecognized unit test '%s'\n", argv[0],
argv[i]);
fprintf(stderr, "Try '%s --list' for list of unit tests.\n",
argv[0]);
exit(2);
}
n++;
} else if (strcmp(argv[i], "--") == 0) {
seen_double_dash = 1;
} else if (strcmp(argv[i], "--help") == 0 ||
strcmp(argv[i], "-h") == 0) {
test_help__();
exit(0);
} else if (strcmp(argv[i], "--verbose") == 0 ||
strcmp(argv[i], "-v") == 0) {
test_verbose_level__++;
} else if (strncmp(argv[i], "--verbose=", 10) == 0) {
test_verbose_level__ = atoi(argv[i] + 10);
} else if (strcmp(argv[i], "--color=auto") == 0) {
/* noop (set from above) */
} else if (strcmp(argv[i], "--color=always") == 0 ||
strcmp(argv[i], "--color") == 0) {
test_colorize__ = 1;
} else if (strcmp(argv[i], "--color=never") == 0) {
test_colorize__ = 0;
} else if (strcmp(argv[i], "--skip") == 0 ||
strcmp(argv[i], "-s") == 0) {
test_skip_mode__ = 1;
} else if (strcmp(argv[i], "--no-exec") == 0) {
test_no_exec__ = 1;
} else if (strcmp(argv[i], "--no-summary") == 0) {
test_no_summary__ = 1;
} else if (strcmp(argv[i], "--list") == 0 ||
strcmp(argv[i], "-l") == 0) {
test_list_names__();
exit(0);
} else {
fprintf(stderr, "%s: Unrecognized option '%s'\n", argv[0], argv[i]);
fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
exit(2);
}
}
#if defined(CUTEST_WIN__)
SetUnhandledExceptionFilter(test_exception_filter__);
#endif
/* Count all test units */
test_count__ = 0;
for (i = 0; test_list__[i].func != NULL; i++)
test_count__++;
/* Run the tests */
if (n == 0) {
/* Run all tests */
for (i = 0; test_list__[i].func != NULL; i++)
test_run__(&test_list__[i]);
} else if (!test_skip_mode__) {
/* Run the listed tests */
for (i = 0; i < n; i++)
test_run__(tests[i]);
} else {
/* Run all tests except those listed */
for (i = 0; test_list__[i].func != NULL; i++) {
int want_skip = 0;
for (j = 0; j < n; j++) {
if (tests[j] == &test_list__[i]) {
want_skip = 1;
break;
}
}
if (!want_skip)
test_run__(&test_list__[i]);
}
}
/* Write a summary */
if (!test_no_summary__ && test_verbose_level__ >= 1) {
test_print_in_color__(CUTEST_COLOR_DEFAULT_INTENSIVE__, "\nSummary:\n");
if (test_verbose_level__ >= 3) {
printf(" Count of all unit tests: %4d\n", test_count__);
printf(" Count of run unit tests: %4d\n",
test_stat_run_units__);
printf(" Count of failed unit tests: %4d\n",
test_stat_failed_units__);
printf(" Count of skipped unit tests: %4d\n",
test_count__ - test_stat_run_units__);
}
if (test_stat_failed_units__ == 0) {
test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__,
" SUCCESS: All unit tests have passed.\n");
} else {
test_print_in_color__(
CUTEST_COLOR_RED_INTENSIVE__,
" FAILED: %d of %d unit tests have failed.\n",
test_stat_failed_units__, test_stat_run_units__);
}
}
if (tests != NULL)
free((void *)tests);
return (test_stat_failed_units__ == 0) ? 0 : 1;
}
#endif /* #ifndef TEST_NO_MAIN */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* #ifndef CUTEST_H__ */

View file

@ -0,0 +1,261 @@
/*
* dtls_srtp_driver.c
*
* test driver for DTLS-SRTP functions
*
* David 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 <stdio.h> /* for printf() */
#include "getopt_s.h" /* for local getopt() */
#include "srtp_priv.h"
srtp_err_status_t test_dtls_srtp(void);
srtp_hdr_t *srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc);
void usage(char *prog_name)
{
printf("usage: %s [ -t ][ -c ][ -v ][-d <debug_module> ]* [ -l ]\n"
" -d <mod> turn on debugging module <mod>\n"
" -l list debugging modules\n",
prog_name);
exit(1);
}
int main(int argc, char *argv[])
{
unsigned do_list_mods = 0;
int q;
srtp_err_status_t err;
printf("dtls_srtp_driver\n");
/* initialize srtp library */
err = srtp_init();
if (err) {
printf("error: srtp init failed with error code %d\n", err);
exit(1);
}
/* process input arguments */
while (1) {
q = getopt_s(argc, argv, "ld:");
if (q == -1)
break;
switch (q) {
case 'l':
do_list_mods = 1;
break;
case 'd':
err = srtp_crypto_kernel_set_debug_module(optarg_s, 1);
if (err) {
printf("error: set debug module (%s) failed\n", optarg_s);
exit(1);
}
break;
default:
usage(argv[0]);
}
}
if (do_list_mods) {
err = srtp_crypto_kernel_list_debug_modules();
if (err) {
printf("error: list of debug modules failed\n");
exit(1);
}
}
printf("testing dtls_srtp...");
err = test_dtls_srtp();
if (err) {
printf("\nerror (code %d)\n", err);
exit(1);
}
printf("passed\n");
/* shut down srtp library */
err = srtp_shutdown();
if (err) {
printf("error: srtp shutdown failed with error code %d\n", err);
exit(1);
}
return 0;
}
srtp_err_status_t test_dtls_srtp(void)
{
srtp_hdr_t *test_packet;
int test_packet_len = 80;
srtp_t s;
srtp_policy_t policy;
uint8_t key[SRTP_MAX_KEY_LEN];
uint8_t salt[SRTP_MAX_KEY_LEN];
unsigned int key_len, salt_len;
srtp_profile_t profile;
srtp_err_status_t err;
memset(&policy, 0x0, sizeof(srtp_policy_t));
/* create a 'null' SRTP session */
err = srtp_create(&s, NULL);
if (err)
return err;
/*
* verify that packet-processing functions behave properly - we
* expect that these functions will return srtp_err_status_no_ctx
*/
test_packet = srtp_create_test_packet(80, 0xa5a5a5a5);
if (test_packet == NULL)
return srtp_err_status_alloc_fail;
err = srtp_protect(s, test_packet, &test_packet_len);
if (err != srtp_err_status_no_ctx) {
printf("wrong return value from srtp_protect() (got code %d)\n", err);
return srtp_err_status_fail;
}
err = srtp_unprotect(s, test_packet, &test_packet_len);
if (err != srtp_err_status_no_ctx) {
printf("wrong return value from srtp_unprotect() (got code %d)\n", err);
return srtp_err_status_fail;
}
err = srtp_protect_rtcp(s, test_packet, &test_packet_len);
if (err != srtp_err_status_no_ctx) {
printf("wrong return value from srtp_protect_rtcp() (got code %d)\n",
err);
return srtp_err_status_fail;
}
err = srtp_unprotect_rtcp(s, test_packet, &test_packet_len);
if (err != srtp_err_status_no_ctx) {
printf("wrong return value from srtp_unprotect_rtcp() (got code %d)\n",
err);
return srtp_err_status_fail;
}
/*
* set keys to known values for testing
*/
profile = srtp_profile_aes128_cm_sha1_80;
key_len = srtp_profile_get_master_key_length(profile);
salt_len = srtp_profile_get_master_salt_length(profile);
memset(key, 0xff, key_len);
memset(salt, 0xee, salt_len);
srtp_append_salt_to_key(key, key_len, salt, salt_len);
policy.key = key;
/* initialize SRTP policy from profile */
err = srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile);
if (err)
return err;
err = srtp_crypto_policy_set_from_profile_for_rtcp(&policy.rtcp, profile);
if (err)
return err;
policy.ssrc.type = ssrc_any_inbound;
policy.ekt = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.next = NULL;
err = srtp_add_stream(s, &policy);
if (err)
return err;
err = srtp_dealloc(s);
if (err)
return err;
free(test_packet);
return srtp_err_status_ok;
}
/*
* 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 i;
uint8_t *buffer;
srtp_hdr_t *hdr;
int bytes_in_hdr = 12;
/* allocate memory for test packet */
hdr = 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;
return hdr;
}

View file

@ -0,0 +1,109 @@
/*
* getopt.c
*
* a minimal implementation of the getopt() function, written so that
* test applications that use that function can run on non-POSIX
* platforms
*
*/
/*
*
* 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 <stdlib.h> /* for NULL */
int optind_s = 0;
char *optarg_s;
#define GETOPT_FOUND_WITHOUT_ARGUMENT 2
#define GETOPT_FOUND_WITH_ARGUMENT 1
#define GETOPT_NOT_FOUND 0
static int getopt_check_character(char c, const char *string)
{
unsigned int max_string_len = 128;
while (*string != 0) {
if (max_string_len == 0) {
return GETOPT_NOT_FOUND;
}
max_string_len--;
if (*string++ == c) {
if (*string == ':') {
return GETOPT_FOUND_WITH_ARGUMENT;
} else {
return GETOPT_FOUND_WITHOUT_ARGUMENT;
}
}
}
return GETOPT_NOT_FOUND;
}
int getopt_s(int argc, char *const argv[], const char *optstring)
{
while (optind_s + 1 < argc) {
char *string;
/* move 'string' on to next argument */
optind_s++;
string = argv[optind_s];
if (string == NULL)
return '?'; /* NULL argument string */
if (string[0] != '-')
return -1; /* found an unexpected character */
switch (getopt_check_character(string[1], optstring)) {
case GETOPT_FOUND_WITH_ARGUMENT:
if (optind_s + 1 < argc) {
optind_s++;
optarg_s = argv[optind_s];
return string[1];
} else {
return '?'; /* argument missing */
}
case GETOPT_FOUND_WITHOUT_ARGUMENT:
return string[1];
case GETOPT_NOT_FOUND:
default:
return '?'; /* didn't find expected character */
break;
}
}
return -1;
}

View file

@ -0,0 +1,360 @@
/*
* rdbx_driver.c
*
* driver for the rdbx implementation (replay database with extended range)
*
* 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h> /* for printf() */
#include "getopt_s.h" /* for local getopt() */
#include "rdbx.h"
#include "cipher_priv.h"
#ifdef ROC_TEST
#error "srtp_rdbx_t won't work with ROC_TEST - bitmask same size as seq_median"
#endif
#include "ut_sim.h"
srtp_err_status_t test_replay_dbx(int num_trials, unsigned long ws);
double rdbx_check_adds_per_second(int num_trials, unsigned long ws);
void usage(char *prog_name)
{
printf("usage: %s [ -t | -v ]\n", prog_name);
exit(255);
}
int main(int argc, char *argv[])
{
double rate;
srtp_err_status_t status;
int q;
unsigned do_timing_test = 0;
unsigned do_validation = 0;
/* process input arguments */
while (1) {
q = getopt_s(argc, argv, "tv");
if (q == -1)
break;
switch (q) {
case 't':
do_timing_test = 1;
break;
case 'v':
do_validation = 1;
break;
default:
usage(argv[0]);
}
}
printf("rdbx (replay database w/ extended range) test driver\n"
"David A. McGrew\n"
"Cisco Systems, Inc.\n");
if (!do_validation && !do_timing_test)
usage(argv[0]);
if (do_validation) {
printf("testing srtp_rdbx_t (ws=128)...\n");
status = test_replay_dbx(1 << 12, 128);
if (status) {
printf("failed\n");
exit(1);
}
printf("passed\n");
printf("testing srtp_rdbx_t (ws=1024)...\n");
status = test_replay_dbx(1 << 12, 1024);
if (status) {
printf("failed\n");
exit(1);
}
printf("passed\n");
}
if (do_timing_test) {
rate = rdbx_check_adds_per_second(1 << 18, 128);
printf("rdbx_check/replay_adds per second (ws=128): %e\n", rate);
rate = rdbx_check_adds_per_second(1 << 18, 1024);
printf("rdbx_check/replay_adds per second (ws=1024): %e\n", rate);
}
return 0;
}
void print_rdbx(srtp_rdbx_t *rdbx)
{
char buf[2048];
printf("rdbx: {%llu, %s}\n", (unsigned long long)(rdbx->index),
bitvector_bit_string(&rdbx->bitmask, buf, sizeof(buf)));
}
/*
* rdbx_check_add(rdbx, idx) checks a known-to-be-good idx against
* rdbx, then adds it. if a failure is detected (i.e., the check
* indicates that the value is already in rdbx) then
* srtp_err_status_algo_fail is returned.
*
*/
srtp_err_status_t rdbx_check_add(srtp_rdbx_t *rdbx, uint32_t idx)
{
int delta;
srtp_xtd_seq_num_t est;
delta = srtp_index_guess(&rdbx->index, &est, idx);
if (srtp_rdbx_check(rdbx, delta) != srtp_err_status_ok) {
printf("replay_check failed at index %u\n", idx);
return srtp_err_status_algo_fail;
}
/*
* in practice, we'd authenticate the packet containing idx, using
* the estimated value est, at this point
*/
if (srtp_rdbx_add_index(rdbx, delta) != srtp_err_status_ok) {
printf("rdbx_add_index failed at index %u\n", idx);
return srtp_err_status_algo_fail;
}
return srtp_err_status_ok;
}
/*
* rdbx_check_expect_failure(srtp_rdbx_t *rdbx, uint32_t idx)
*
* checks that a sequence number idx is in the replay database
* and thus will be rejected
*/
srtp_err_status_t rdbx_check_expect_failure(srtp_rdbx_t *rdbx, uint32_t idx)
{
int delta;
srtp_xtd_seq_num_t est;
srtp_err_status_t status;
delta = srtp_index_guess(&rdbx->index, &est, idx);
status = srtp_rdbx_check(rdbx, delta);
if (status == srtp_err_status_ok) {
printf("delta: %d ", delta);
printf("replay_check failed at index %u (false positive)\n", idx);
return srtp_err_status_algo_fail;
}
return srtp_err_status_ok;
}
srtp_err_status_t rdbx_check_add_unordered(srtp_rdbx_t *rdbx, uint32_t idx)
{
int delta;
srtp_xtd_seq_num_t est;
srtp_err_status_t rstat;
delta = srtp_index_guess(&rdbx->index, &est, idx);
rstat = srtp_rdbx_check(rdbx, delta);
if ((rstat != srtp_err_status_ok) &&
(rstat != srtp_err_status_replay_old)) {
printf("replay_check_add_unordered failed at index %u\n", idx);
return srtp_err_status_algo_fail;
}
if (rstat == srtp_err_status_replay_old) {
return srtp_err_status_ok;
}
if (srtp_rdbx_add_index(rdbx, delta) != srtp_err_status_ok) {
printf("rdbx_add_index failed at index %u\n", idx);
return srtp_err_status_algo_fail;
}
return srtp_err_status_ok;
}
srtp_err_status_t test_replay_dbx(int num_trials, unsigned long ws)
{
srtp_rdbx_t rdbx;
uint32_t idx, ircvd;
ut_connection utc;
srtp_err_status_t status;
int num_fp_trials;
status = srtp_rdbx_init(&rdbx, ws);
if (status) {
printf("replay_init failed with error code %d\n", status);
exit(1);
}
/*
* test sequential insertion
*/
printf("\ttesting sequential insertion...");
for (idx = 0; (int)idx < num_trials; idx++) {
status = rdbx_check_add(&rdbx, idx);
if (status)
return status;
}
printf("passed\n");
/*
* test for false positives by checking all of the index
* values which we've just added
*
* note that we limit the number of trials here, since allowing the
* rollover counter to roll over would defeat this test
*/
num_fp_trials = num_trials % 0x10000;
if (num_fp_trials == 0) {
printf("warning: no false positive tests performed\n");
}
printf("\ttesting for false positives...");
for (idx = 0; (int)idx < num_fp_trials; idx++) {
status = rdbx_check_expect_failure(&rdbx, idx);
if (status)
return status;
}
printf("passed\n");
/* re-initialize */
srtp_rdbx_dealloc(&rdbx);
if (srtp_rdbx_init(&rdbx, ws) != srtp_err_status_ok) {
printf("replay_init failed\n");
return srtp_err_status_init_fail;
}
/*
* test non-sequential insertion
*
* this test covers only fase negatives, since the values returned
* by ut_next_index(...) are distinct
*/
ut_init(&utc);
printf("\ttesting non-sequential insertion...");
for (idx = 0; (int)idx < num_trials; idx++) {
ircvd = ut_next_index(&utc);
status = rdbx_check_add_unordered(&rdbx, ircvd);
if (status)
return status;
status = rdbx_check_expect_failure(&rdbx, ircvd);
if (status)
return status;
}
printf("passed\n");
/* re-initialize */
srtp_rdbx_dealloc(&rdbx);
if (srtp_rdbx_init(&rdbx, ws) != srtp_err_status_ok) {
printf("replay_init failed\n");
return srtp_err_status_init_fail;
}
/*
* test insertion with large gaps.
* check for false positives for each insertion.
*/
printf("\ttesting insertion with large gaps...");
for (idx = 0, ircvd = 0; (int)idx < num_trials;
idx++, ircvd += (1 << (srtp_cipher_rand_u32_for_tests() % 12))) {
status = rdbx_check_add(&rdbx, ircvd);
if (status)
return status;
status = rdbx_check_expect_failure(&rdbx, ircvd);
if (status)
return status;
}
printf("passed\n");
srtp_rdbx_dealloc(&rdbx);
return srtp_err_status_ok;
}
#include <time.h> /* for clock() */
double rdbx_check_adds_per_second(int num_trials, unsigned long ws)
{
uint32_t i;
int delta;
srtp_rdbx_t rdbx;
srtp_xtd_seq_num_t est;
clock_t timer;
int failures; /* count number of failures */
if (srtp_rdbx_init(&rdbx, ws) != srtp_err_status_ok) {
printf("replay_init failed\n");
exit(1);
}
failures = 0;
timer = clock();
for (i = 0; (int)i < num_trials; i++) {
delta = srtp_index_guess(&rdbx.index, &est, i);
if (srtp_rdbx_check(&rdbx, delta) != srtp_err_status_ok)
++failures;
else if (srtp_rdbx_add_index(&rdbx, delta) != srtp_err_status_ok)
++failures;
}
timer = clock() - timer;
if (timer < 1) {
timer = 1;
}
printf("number of failures: %d \n", failures);
srtp_rdbx_dealloc(&rdbx);
return (double)CLOCKS_PER_SEC * num_trials / timer;
}

View file

@ -0,0 +1,285 @@
/*
* replay_driver.c
*
* A driver for the replay_database implementation
*
* 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include "rdb.h"
#include "ut_sim.h"
#include "cipher_priv.h"
/*
* num_trials defines the number of trials that are used in the
* validation functions below
*/
unsigned num_trials = 1 << 16;
srtp_err_status_t test_rdb_db(void);
double rdb_check_adds_per_second(void);
int main(void)
{
srtp_err_status_t err;
printf("testing anti-replay database (srtp_rdb_t)...\n");
err = test_rdb_db();
if (err) {
printf("failed\n");
exit(1);
}
printf("done\n");
printf("rdb_check/rdb_adds per second: %e\n", rdb_check_adds_per_second());
return 0;
}
void print_rdb(srtp_rdb_t *rdb)
{
printf("rdb: {%u, %s}\n", rdb->window_start,
v128_bit_string(&rdb->bitmask));
}
srtp_err_status_t rdb_check_add(srtp_rdb_t *rdb, uint32_t idx)
{
if (srtp_rdb_check(rdb, idx) != srtp_err_status_ok) {
printf("rdb_check failed at index %u\n", idx);
return srtp_err_status_fail;
}
if (srtp_rdb_add_index(rdb, idx) != srtp_err_status_ok) {
printf("rdb_add_index failed at index %u\n", idx);
return srtp_err_status_fail;
}
return srtp_err_status_ok;
}
srtp_err_status_t rdb_check_expect_failure(srtp_rdb_t *rdb, uint32_t idx)
{
srtp_err_status_t err;
err = srtp_rdb_check(rdb, idx);
if ((err != srtp_err_status_replay_old) &&
(err != srtp_err_status_replay_fail)) {
printf("rdb_check failed at index %u (false positive)\n", idx);
return srtp_err_status_fail;
}
return srtp_err_status_ok;
}
srtp_err_status_t rdb_check_add_unordered(srtp_rdb_t *rdb, uint32_t idx)
{
srtp_err_status_t rstat;
/* printf("index: %u\n", idx); */
rstat = srtp_rdb_check(rdb, idx);
if ((rstat != srtp_err_status_ok) &&
(rstat != srtp_err_status_replay_old)) {
printf("rdb_check_add_unordered failed at index %u\n", idx);
return rstat;
}
if (rstat == srtp_err_status_replay_old) {
return srtp_err_status_ok;
}
if (srtp_rdb_add_index(rdb, idx) != srtp_err_status_ok) {
printf("rdb_add_index failed at index %u\n", idx);
return srtp_err_status_fail;
}
return srtp_err_status_ok;
}
srtp_err_status_t test_rdb_db()
{
srtp_rdb_t rdb;
uint32_t idx, ircvd;
ut_connection utc;
srtp_err_status_t err;
if (srtp_rdb_init(&rdb) != srtp_err_status_ok) {
printf("rdb_init failed\n");
return srtp_err_status_init_fail;
}
/* test sequential insertion */
for (idx = 0; idx < num_trials; idx++) {
err = rdb_check_add(&rdb, idx);
if (err)
return err;
}
/* test for false positives */
for (idx = 0; idx < num_trials; idx++) {
err = rdb_check_expect_failure(&rdb, idx);
if (err)
return err;
}
/* re-initialize */
if (srtp_rdb_init(&rdb) != srtp_err_status_ok) {
printf("rdb_init failed\n");
return srtp_err_status_fail;
}
/* test non-sequential insertion */
ut_init(&utc);
for (idx = 0; idx < num_trials; idx++) {
ircvd = ut_next_index(&utc);
err = rdb_check_add_unordered(&rdb, ircvd);
if (err)
return err;
err = rdb_check_expect_failure(&rdb, ircvd);
if (err)
return err;
}
/* re-initialize */
if (srtp_rdb_init(&rdb) != srtp_err_status_ok) {
printf("rdb_init failed\n");
return srtp_err_status_fail;
}
/* test insertion with large gaps */
for (idx = 0, ircvd = 0; idx < num_trials;
idx++, ircvd += (1 << (srtp_cipher_rand_u32_for_tests() % 10))) {
err = rdb_check_add(&rdb, ircvd);
if (err)
return err;
err = rdb_check_expect_failure(&rdb, ircvd);
if (err)
return err;
}
/* re-initialize */
if (srtp_rdb_init(&rdb) != srtp_err_status_ok) {
printf("rdb_init failed\n");
return srtp_err_status_fail;
}
/* test loss of first 513 packets */
for (idx = 0; idx < num_trials; idx++) {
err = rdb_check_add(&rdb, idx + 513);
if (err)
return err;
}
/* test for false positives */
for (idx = 0; idx < num_trials + 513; idx++) {
err = rdb_check_expect_failure(&rdb, idx);
if (err)
return err;
}
/* test for key expired */
if (srtp_rdb_init(&rdb) != srtp_err_status_ok) {
printf("rdb_init failed\n");
return srtp_err_status_fail;
}
rdb.window_start = 0x7ffffffe;
if (srtp_rdb_increment(&rdb) != srtp_err_status_ok) {
printf("srtp_rdb_increment of 0x7ffffffe failed\n");
return srtp_err_status_fail;
}
if (srtp_rdb_get_value(&rdb) != 0x7fffffff) {
printf("rdb valiue was not 0x7fffffff\n");
return srtp_err_status_fail;
}
if (srtp_rdb_increment(&rdb) != srtp_err_status_key_expired) {
printf("srtp_rdb_increment of 0x7fffffff did not return "
"srtp_err_status_key_expired\n");
return srtp_err_status_fail;
}
if (srtp_rdb_get_value(&rdb) != 0x7fffffff) {
printf("rdb valiue was not 0x7fffffff\n");
return srtp_err_status_fail;
}
return srtp_err_status_ok;
}
#include <time.h> /* for clock() */
#include <stdlib.h> /* for random() */
#define REPLAY_NUM_TRIALS 10000000
double rdb_check_adds_per_second(void)
{
uint32_t i;
srtp_rdb_t rdb;
clock_t timer;
int failures = 0; /* count number of failures */
if (srtp_rdb_init(&rdb) != srtp_err_status_ok) {
printf("rdb_init failed\n");
exit(1);
}
timer = clock();
for (i = 0; i < REPLAY_NUM_TRIALS; i += 3) {
if (srtp_rdb_check(&rdb, i + 2) != srtp_err_status_ok)
++failures;
if (srtp_rdb_add_index(&rdb, i + 2) != srtp_err_status_ok)
++failures;
if (srtp_rdb_check(&rdb, i + 1) != srtp_err_status_ok)
++failures;
if (srtp_rdb_add_index(&rdb, i + 1) != srtp_err_status_ok)
++failures;
if (srtp_rdb_check(&rdb, i) != srtp_err_status_ok)
++failures;
if (srtp_rdb_add_index(&rdb, i) != srtp_err_status_ok)
++failures;
}
timer = clock() - timer;
return (double)CLOCKS_PER_SEC * REPLAY_NUM_TRIALS / timer;
}

View file

@ -0,0 +1,170 @@
/*
* roc_driver.c
*
* test driver for rollover counter replay implementation
*
* 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
/*
* defining ROC_TEST causes small datatypes to be used in
* srtp_xtd_seq_num_t - this allows the functions to be exhaustively tested.
*/
#if ROC_NEEDS_TO_BE_TESTED
#define ROC_TEST
#endif
#include "rdbx.h"
#include "ut_sim.h"
srtp_err_status_t roc_test(int num_trials);
int main(void)
{
srtp_err_status_t status;
printf("rollover counter test driver\n"
"David A. McGrew\n"
"Cisco Systems, Inc.\n");
printf("testing index functions...");
status = roc_test(1 << 18);
if (status) {
printf("failed\n");
exit(status);
}
printf("passed\n");
return 0;
}
#define ROC_VERBOSE 0
srtp_err_status_t roc_test(int num_trials)
{
srtp_xtd_seq_num_t local, est, ref;
ut_connection utc;
int i, num_bad_est = 0;
int delta;
uint32_t ircvd;
double failure_rate;
srtp_index_init(&local);
srtp_index_init(&ref);
srtp_index_init(&est);
printf("\n\ttesting sequential insertion...");
for (i = 0; i < 2048; i++) {
srtp_index_guess(&local, &est, (uint16_t)ref);
#if ROC_VERBOSE
printf("%lld, %lld, %d\n", ref, est, i);
#endif
if (ref != est) {
#if ROC_VERBOSE
printf(" *bad estimate*\n");
#endif
++num_bad_est;
}
srtp_index_advance(&ref, 1);
}
failure_rate = (double)num_bad_est / num_trials;
if (failure_rate > 0.01) {
printf("error: failure rate too high (%d bad estimates in %d trials)\n",
num_bad_est, num_trials);
return srtp_err_status_algo_fail;
}
printf("done\n");
printf("\ttesting non-sequential insertion...");
srtp_index_init(&local);
srtp_index_init(&ref);
srtp_index_init(&est);
ut_init(&utc);
for (i = 0; i < num_trials; i++) {
/* get next seq num from unreliable transport simulator */
ircvd = ut_next_index(&utc);
/* set ref to value of ircvd */
ref = ircvd;
/* estimate index based on low bits of ircvd */
delta = srtp_index_guess(&local, &est, (uint16_t)ref);
#if ROC_VERBOSE
printf("ref: %lld, local: %lld, est: %lld, ircvd: %d, delta: %d\n", ref,
local, est, ircvd, delta);
#endif
if (local + delta != est) {
printf(" *bad delta*: local %llu + delta %d != est %llu\n",
(unsigned long long)local, delta, (unsigned long long)est);
return srtp_err_status_algo_fail;
}
/* now update local srtp_xtd_seq_num_t as necessary */
if (delta > 0)
srtp_index_advance(&local, delta);
if (ref != est) {
#if ROC_VERBOSE
printf(" *bad estimate*\n");
#endif
/* record failure event */
++num_bad_est;
/* reset local value to correct value */
local = ref;
}
}
failure_rate = (double)num_bad_est / num_trials;
if (failure_rate > 0.01) {
printf("error: failure rate too high (%d bad estimates in %d trials)\n",
num_bad_est, num_trials);
return srtp_err_status_algo_fail;
}
printf("done\n");
return srtp_err_status_ok;
}

229
trunk/3rdparty/libsrtp-2-fit/test/rtp.c vendored Normal file
View file

@ -0,0 +1,229 @@
/*
* rtp.c
*
* library functions for the real-time transport protocol
*
* 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 "rtp.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include "cipher_priv.h"
#define PRINT_DEBUG 0 /* set to 1 to print out debugging data */
#define VERBOSE_DEBUG 0 /* set to 1 to print out more data */
int rtp_sendto(rtp_sender_t sender, const void *msg, int len)
{
int octets_sent;
srtp_err_status_t stat;
int pkt_len = len + RTP_HEADER_LEN;
/* marshal data */
strncpy(sender->message.body, msg, len);
/* update header */
sender->message.header.seq = ntohs(sender->message.header.seq) + 1;
sender->message.header.seq = htons(sender->message.header.seq);
sender->message.header.ts = ntohl(sender->message.header.ts) + 1;
sender->message.header.ts = htonl(sender->message.header.ts);
/* apply srtp */
stat = srtp_protect(sender->srtp_ctx, &sender->message.header, &pkt_len);
if (stat) {
#if PRINT_DEBUG
fprintf(stderr, "error: srtp protection failed with code %d\n", stat);
#endif
return -1;
}
#if VERBOSE_DEBUG
srtp_print_packet(&sender->message.header, pkt_len);
#endif
octets_sent =
sendto(sender->socket, (void *)&sender->message, pkt_len, 0,
(struct sockaddr *)&sender->addr, sizeof(struct sockaddr_in));
if (octets_sent != pkt_len) {
#if PRINT_DEBUG
fprintf(stderr, "error: couldn't send message %s", (char *)msg);
perror("");
#endif
}
return octets_sent;
}
int rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len)
{
int octets_recvd;
srtp_err_status_t stat;
octets_recvd = recvfrom(receiver->socket, (void *)&receiver->message, *len,
0, (struct sockaddr *)NULL, 0);
if (octets_recvd == -1) {
*len = 0;
return -1;
}
/* verify rtp header */
if (receiver->message.header.version != 2) {
*len = 0;
return -1;
}
#if PRINT_DEBUG
fprintf(stderr, "%d octets received from SSRC %u\n", octets_recvd,
receiver->message.header.ssrc);
#endif
#if VERBOSE_DEBUG
srtp_print_packet(&receiver->message.header, octets_recvd);
#endif
/* apply srtp */
stat = srtp_unprotect(receiver->srtp_ctx, &receiver->message.header,
&octets_recvd);
if (stat) {
fprintf(stderr, "error: srtp unprotection failed with code %d%s\n",
stat,
stat == srtp_err_status_replay_fail
? " (replay check failed)"
: stat == srtp_err_status_auth_fail ? " (auth check failed)"
: "");
return -1;
}
strncpy(msg, receiver->message.body, octets_recvd);
return octets_recvd;
}
int rtp_sender_init(rtp_sender_t sender,
int sock,
struct sockaddr_in addr,
unsigned int ssrc)
{
/* set header values */
sender->message.header.ssrc = htonl(ssrc);
sender->message.header.ts = 0;
sender->message.header.seq = (uint16_t)srtp_cipher_rand_u32_for_tests();
sender->message.header.m = 0;
sender->message.header.pt = 0x1;
sender->message.header.version = 2;
sender->message.header.p = 0;
sender->message.header.x = 0;
sender->message.header.cc = 0;
/* set other stuff */
sender->socket = sock;
sender->addr = addr;
return 0;
}
int rtp_receiver_init(rtp_receiver_t rcvr,
int sock,
struct sockaddr_in addr,
unsigned int ssrc)
{
/* set header values */
rcvr->message.header.ssrc = htonl(ssrc);
rcvr->message.header.ts = 0;
rcvr->message.header.seq = 0;
rcvr->message.header.m = 0;
rcvr->message.header.pt = 0x1;
rcvr->message.header.version = 2;
rcvr->message.header.p = 0;
rcvr->message.header.x = 0;
rcvr->message.header.cc = 0;
/* set other stuff */
rcvr->socket = sock;
rcvr->addr = addr;
return 0;
}
int rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy)
{
return srtp_create(&sender->srtp_ctx, policy);
}
int rtp_sender_deinit_srtp(rtp_sender_t sender)
{
return srtp_dealloc(sender->srtp_ctx);
}
int rtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy)
{
return srtp_create(&sender->srtp_ctx, policy);
}
int rtp_receiver_deinit_srtp(rtp_receiver_t sender)
{
return srtp_dealloc(sender->srtp_ctx);
}
rtp_sender_t rtp_sender_alloc(void)
{
return (rtp_sender_t)malloc(sizeof(rtp_sender_ctx_t));
}
void rtp_sender_dealloc(rtp_sender_t rtp_ctx)
{
free(rtp_ctx);
}
rtp_receiver_t rtp_receiver_alloc(void)
{
return (rtp_receiver_t)malloc(sizeof(rtp_receiver_ctx_t));
}
void rtp_receiver_dealloc(rtp_receiver_t rtp_ctx)
{
free(rtp_ctx);
}

155
trunk/3rdparty/libsrtp-2-fit/test/rtp.h vendored Normal file
View file

@ -0,0 +1,155 @@
/*
* rtp.h
*
* rtp interface for srtp reference implementation
*
* David A. McGrew
* Cisco Systems, Inc.
*
* data types:
*
* rtp_msg_t an rtp message (the data that goes on the wire)
* rtp_sender_t sender side socket and rtp info
* rtp_receiver_t receiver side socket and rtp info
*
*/
/*
*
* 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.
*
*/
#ifndef SRTP_RTP_H
#define SRTP_RTP_H
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H
#include <winsock2.h>
#endif
#include "srtp_priv.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* RTP_HEADER_LEN indicates the size of an RTP header
*/
#define RTP_HEADER_LEN 12
/*
* RTP_MAX_BUF_LEN defines the largest RTP packet in the rtp.c implementation
*/
#define RTP_MAX_BUF_LEN 16384
typedef srtp_hdr_t rtp_hdr_t;
typedef struct {
srtp_hdr_t header;
char body[RTP_MAX_BUF_LEN];
} rtp_msg_t;
typedef struct rtp_sender_ctx_t {
rtp_msg_t message;
int socket;
srtp_ctx_t *srtp_ctx;
struct sockaddr_in addr; /* reciever's address */
} rtp_sender_ctx_t;
typedef struct rtp_receiver_ctx_t {
rtp_msg_t message;
int socket;
srtp_ctx_t *srtp_ctx;
struct sockaddr_in addr; /* receiver's address */
} rtp_receiver_ctx_t;
typedef struct rtp_sender_ctx_t *rtp_sender_t;
typedef struct rtp_receiver_ctx_t *rtp_receiver_t;
int rtp_sendto(rtp_sender_t sender, const void *msg, int len);
int rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len);
int rtp_receiver_init(rtp_receiver_t rcvr,
int sock,
struct sockaddr_in addr,
unsigned int ssrc);
int rtp_sender_init(rtp_sender_t sender,
int sock,
struct sockaddr_in addr,
unsigned int ssrc);
/*
* srtp_sender_init(...) initializes an rtp_sender_t
*/
int srtp_sender_init(
rtp_sender_t rtp_ctx, /* structure to be init'ed */
struct sockaddr_in name, /* socket name */
srtp_sec_serv_t security_services, /* sec. servs. to be used */
unsigned char *input_key /* master key/salt in hex */
);
int srtp_receiver_init(
rtp_receiver_t rtp_ctx, /* structure to be init'ed */
struct sockaddr_in name, /* socket name */
srtp_sec_serv_t security_services, /* sec. servs. to be used */
unsigned char *input_key /* master key/salt in hex */
);
int rtp_sender_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy);
int rtp_sender_deinit_srtp(rtp_sender_t sender);
int rtp_receiver_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy);
int rtp_receiver_deinit_srtp(rtp_receiver_t sender);
rtp_sender_t rtp_sender_alloc(void);
void rtp_sender_dealloc(rtp_sender_t rtp_ctx);
rtp_receiver_t rtp_receiver_alloc(void);
void rtp_receiver_dealloc(rtp_receiver_t rtp_ctx);
#ifdef __cplusplus
}
#endif
#endif /* SRTP_RTP_H */

View file

@ -0,0 +1,785 @@
/*
* rtp_decoder.c
*
* decoder structures and functions for SRTP pcap decoder
*
* Example:
* $ wget --no-check-certificate \
* https://raw.githubusercontent.com/gteissier/srtp-decrypt/master/marseillaise-srtp.pcap
* $ ./test/rtp_decoder -a -t 10 -e 128 -b \
* aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz \
* < ~/marseillaise-srtp.pcap \
* | text2pcap -t "%M:%S." -u 10000,10000 - - \
* > ./marseillaise-rtp.pcap
*
* There is also a different way of setting up key size and tag size
* based upon RFC 4568 crypto suite specification, i.e.:
*
* $ ./test/rtp_decoder -s AES_CM_128_HMAC_SHA1_80 -b \
* aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz ...
*
* Audio can be extracted using extractaudio utility from the RTPproxy
* package:
*
* $ extractaudio -A ./marseillaise-rtp.pcap ./marseillaise-out.wav
*
* Bernardo Torres <bernardo@torresautomacao.com.br>
*
* Some structure and code from https://github.com/gteissier/srtp-decrypt
*/
/*
*
* 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 "getopt_s.h" /* for local getopt() */
#include <assert.h> /* for assert() */
#include <pcap.h>
#include "rtp_decoder.h"
#include "util.h"
#ifndef timersub
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
#define MAX_KEY_LEN 96
#define MAX_FILTER 256
#define MAX_FILE 255
struct srtp_crypto_suite {
const char *can_name;
int gcm_on;
int key_size;
int tag_size;
};
static struct srtp_crypto_suite srtp_crypto_suites[] = {
#if 0
{.can_name = "F8_128_HMAC_SHA1_32", .gcm_on = 0, .key_size = 128, .tag_size = 4},
#endif
{.can_name = "AES_CM_128_HMAC_SHA1_32",
.gcm_on = 0,
.key_size = 128,
.tag_size = 4 },
{.can_name = "AES_CM_128_HMAC_SHA1_80",
.gcm_on = 0,
.key_size = 128,
.tag_size = 10 },
{.can_name = "AES_192_CM_HMAC_SHA1_32",
.gcm_on = 0,
.key_size = 192,
.tag_size = 4 },
{.can_name = "AES_192_CM_HMAC_SHA1_80",
.gcm_on = 0,
.key_size = 192,
.tag_size = 10 },
{.can_name = "AES_256_CM_HMAC_SHA1_32",
.gcm_on = 0,
.key_size = 256,
.tag_size = 4 },
{.can_name = "AES_256_CM_HMAC_SHA1_80",
.gcm_on = 0,
.key_size = 256,
.tag_size = 10 },
{.can_name = "AEAD_AES_128_GCM",
.gcm_on = 1,
.key_size = 128,
.tag_size = 16 },
{.can_name = "AEAD_AES_256_GCM",
.gcm_on = 1,
.key_size = 256,
.tag_size = 16 },
{.can_name = NULL }
};
void rtp_decoder_srtp_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;
}
fprintf(stderr, "SRTP-LOG [%c]: %s\n", level_char, msg);
}
int main(int argc, char *argv[])
{
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 pcap_net = 0;
pcap_t *pcap_handle;
#if BEW
struct sockaddr_in local;
#endif
srtp_sec_serv_t sec_servs = sec_serv_none;
int c;
struct srtp_crypto_suite scs, *i_scsp;
scs.key_size = 128;
scs.tag_size = 0;
int gcm_on = 0;
char *input_key = NULL;
int b64_input = 0;
char key[MAX_KEY_LEN];
struct bpf_program fp;
char filter_exp[MAX_FILTER] = "";
char pcap_file[MAX_FILE] = "-";
int rtp_packet_offset = DEFAULT_RTP_OFFSET;
rtp_decoder_t dec;
srtp_policy_t policy = { { 0 } };
rtp_decoder_mode_t mode = mode_rtp;
srtp_err_status_t status;
int len;
int expected_len;
int do_list_mods = 0;
fprintf(stderr, "Using %s [0x%x]\n", srtp_get_version_string(),
srtp_get_version());
/* initialize srtp library */
status = srtp_init();
if (status) {
fprintf(stderr,
"error: srtp initialization failed with error code %d\n",
status);
exit(1);
}
status = srtp_install_log_handler(rtp_decoder_srtp_log_handler, NULL);
if (status) {
fprintf(stderr, "error: install log handler failed\n");
exit(1);
}
/* check args */
while (1) {
c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:s:m:p:o:");
if (c == -1) {
break;
}
switch (c) {
case 'b':
b64_input = 1;
/* fall thru */
case 'k':
input_key = optarg_s;
break;
case 'e':
scs.key_size = atoi(optarg_s);
if (scs.key_size != 128 && scs.key_size != 192 &&
scs.key_size != 256) {
fprintf(
stderr,
"error: encryption key size must be 128, 192 or 256 (%d)\n",
scs.key_size);
exit(1);
}
input_key = malloc(scs.key_size);
sec_servs |= sec_serv_conf;
break;
case 't':
scs.tag_size = atoi(optarg_s);
break;
case 'a':
sec_servs |= sec_serv_auth;
break;
case 'g':
gcm_on = 1;
sec_servs |= sec_serv_auth;
break;
case 'd':
status = srtp_set_debug_module(optarg_s, 1);
if (status) {
fprintf(stderr, "error: set debug module (%s) failed\n",
optarg_s);
exit(1);
}
break;
case 'f':
if (strlen(optarg_s) > MAX_FILTER) {
fprintf(stderr, "error: filter bigger than %d characters\n",
MAX_FILTER);
exit(1);
}
fprintf(stderr, "Setting filter as %s\n", optarg_s);
strcpy(filter_exp, optarg_s);
break;
case 'l':
do_list_mods = 1;
break;
case 's':
for (i_scsp = &srtp_crypto_suites[0]; i_scsp->can_name != NULL;
i_scsp++) {
if (strcasecmp(i_scsp->can_name, optarg_s) == 0) {
break;
}
}
if (i_scsp->can_name == NULL) {
fprintf(stderr, "Unknown/unsupported crypto suite name %s\n",
optarg_s);
exit(1);
}
scs = *i_scsp;
input_key = malloc(scs.key_size);
sec_servs |= sec_serv_conf | sec_serv_auth;
gcm_on = scs.gcm_on;
break;
case 'm':
if (strcasecmp("rtp", optarg_s) == 0) {
mode = mode_rtp;
} else if (strcasecmp("rtcp", optarg_s) == 0) {
mode = mode_rtcp;
} else if (strcasecmp("rtcp-mux", optarg_s) == 0) {
mode = mode_rtcp_mux;
} else {
fprintf(stderr, "Unknown/unsupported mode %s\n", optarg_s);
exit(1);
}
break;
case 'p':
if (strlen(optarg_s) > MAX_FILE) {
fprintf(stderr,
"error: pcap file path bigger than %d characters\n",
MAX_FILE);
exit(1);
}
strcpy(pcap_file, optarg_s);
break;
case 'o':
rtp_packet_offset = atoi(optarg_s);
break;
default:
usage(argv[0]);
}
}
if (scs.tag_size == 0) {
if (gcm_on) {
scs.tag_size = 16;
} else {
scs.tag_size = 10;
}
}
if (gcm_on && scs.tag_size != 8 && scs.tag_size != 16) {
fprintf(stderr, "error: GCM tag size must be 8 or 16 (%d)\n",
scs.tag_size);
exit(1);
}
if (!gcm_on && scs.tag_size != 4 && scs.tag_size != 10) {
fprintf(stderr, "error: non GCM tag size must be 4 or 10 (%d)\n",
scs.tag_size);
exit(1);
}
if (do_list_mods) {
status = srtp_list_debug_modules();
if (status) {
fprintf(stderr, "error: list of debug modules failed\n");
exit(1);
}
return 0;
}
if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
/*
* a key must be provided if and only if security services have
* been requested
*/
if (input_key == NULL) {
fprintf(stderr, "key not provided\n");
}
if (!sec_servs) {
fprintf(stderr, "no secservs\n");
}
fprintf(stderr, "provided\n");
usage(argv[0]);
}
/* report security services selected on the command line */
fprintf(stderr, "security services: ");
if (sec_servs & sec_serv_conf)
fprintf(stderr, "confidentiality ");
if (sec_servs & sec_serv_auth)
fprintf(stderr, "message authentication");
if (sec_servs == sec_serv_none)
fprintf(stderr, "none");
fprintf(stderr, "\n");
/* set up the srtp policy and master key */
if (sec_servs) {
/*
* create policy structure, using the default mechanisms but
* with only the security services requested on the command line,
* using the right SSRC value
*/
switch (sec_servs) {
case sec_serv_conf_and_auth:
if (gcm_on) {
#ifdef OPENSSL
switch (scs.key_size) {
case 128:
if (scs.tag_size == 16) {
srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_16_auth(
&policy.rtcp);
} else {
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
}
break;
case 256:
if (scs.tag_size == 16) {
srtp_crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_256_16_auth(
&policy.rtcp);
} else {
srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
}
break;
}
#else
fprintf(stderr, "error: GCM mode only supported when using the "
"OpenSSL crypto engine.\n");
return 0;
#endif
} else {
switch (scs.key_size) {
case 128:
if (scs.tag_size == 4) {
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(
&policy.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
&policy.rtcp);
} else {
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
&policy.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
&policy.rtcp);
}
break;
case 192:
#ifdef OPENSSL
if (scs.tag_size == 4) {
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(
&policy.rtp);
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
&policy.rtcp);
} else {
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
&policy.rtp);
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
&policy.rtcp);
}
#else
fprintf(stderr,
"error: AES 192 mode only supported when using the "
"OpenSSL crypto engine.\n");
return 0;
#endif
break;
case 256:
if (scs.tag_size == 4) {
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(
&policy.rtp);
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
&policy.rtcp);
} else {
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
&policy.rtp);
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
&policy.rtcp);
}
break;
}
}
break;
case sec_serv_conf:
if (gcm_on) {
fprintf(
stderr,
"error: GCM mode must always be used with auth enabled\n");
return -1;
} else {
switch (scs.key_size) {
case 128:
srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(
&policy.rtcp);
break;
case 192:
#ifdef OPENSSL
srtp_crypto_policy_set_aes_cm_192_null_auth(&policy.rtp);
srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(
&policy.rtcp);
#else
fprintf(stderr,
"error: AES 192 mode only supported when using the "
"OpenSSL crypto engine.\n");
return 0;
#endif
break;
case 256:
srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(
&policy.rtcp);
break;
}
}
break;
case sec_serv_auth:
if (gcm_on) {
#ifdef OPENSSL
switch (scs.key_size) {
case 128:
srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_8_only_auth(
&policy.rtcp);
break;
case 256:
srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_256_8_only_auth(
&policy.rtcp);
break;
}
#else
printf("error: GCM mode only supported when using the OpenSSL "
"crypto engine.\n");
return 0;
#endif
} else {
srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
}
break;
default:
fprintf(stderr, "error: unknown security service requested\n");
return -1;
}
policy.key = (uint8_t *)key;
policy.ekt = NULL;
policy.next = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.rtp.sec_serv = sec_servs;
policy.rtcp.sec_serv =
sec_servs; // sec_serv_none; /* we don't do RTCP anyway */
fprintf(stderr, "setting tag len %d\n", scs.tag_size);
policy.rtp.auth_tag_len = scs.tag_size;
if (gcm_on && scs.tag_size != 8) {
fprintf(stderr, "set tag len %d\n", scs.tag_size);
policy.rtp.auth_tag_len = scs.tag_size;
}
/*
* read key from hexadecimal or base64 on command line into an octet
* string
*/
if (b64_input) {
int pad;
expected_len = policy.rtp.cipher_key_len * 4 / 3;
len = base64_string_to_octet_string(key, &pad, input_key,
strlen(input_key));
} else {
expected_len = policy.rtp.cipher_key_len * 2;
len = hex_string_to_octet_string(key, input_key, expected_len);
}
/* check that hex string is the right length */
if (len < expected_len) {
fprintf(stderr, "error: too few digits in key/salt "
"(should be %d digits, found %d)\n",
expected_len, len);
exit(1);
}
if (strlen(input_key) > policy.rtp.cipher_key_len * 2) {
fprintf(stderr, "error: too many digits in key/salt "
"(should be %d hexadecimal digits, found %u)\n",
policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key));
exit(1);
}
int key_octets = (scs.key_size / 8);
int salt_octets = policy.rtp.cipher_key_len - key_octets;
fprintf(stderr, "set master key/salt to %s/",
octet_string_hex_string(key, key_octets));
fprintf(stderr, "%s\n",
octet_string_hex_string(key + key_octets, salt_octets));
} else {
fprintf(stderr,
"error: neither encryption or authentication were selected\n");
exit(1);
}
pcap_handle = pcap_open_offline(pcap_file, errbuf);
if (!pcap_handle) {
fprintf(stderr, "libpcap failed to open file '%s'\n", errbuf);
exit(1);
}
assert(pcap_handle != NULL);
if ((pcap_compile(pcap_handle, &fp, filter_exp, 1, pcap_net)) == -1) {
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp,
pcap_geterr(pcap_handle));
return (2);
}
if (pcap_setfilter(pcap_handle, &fp) == -1) {
fprintf(stderr, "couldn't install filter %s: %s\n", filter_exp,
pcap_geterr(pcap_handle));
return (2);
}
dec = rtp_decoder_alloc();
if (dec == NULL) {
fprintf(stderr, "error: malloc() failed\n");
exit(1);
}
fprintf(stderr, "Starting decoder\n");
if (rtp_decoder_init(dec, policy, mode, rtp_packet_offset)) {
fprintf(stderr, "error: init failed\n");
exit(1);
}
pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec);
if (dec->mode == mode_rtp || dec->mode == mode_rtcp_mux) {
fprintf(stderr, "RTP packets decoded: %d\n", dec->rtp_cnt);
}
if (dec->mode == mode_rtcp || dec->mode == mode_rtcp_mux) {
fprintf(stderr, "RTCP packets decoded: %d\n", dec->rtcp_cnt);
}
fprintf(stderr, "Packet decode errors: %d\n", dec->error_cnt);
rtp_decoder_deinit(dec);
rtp_decoder_dealloc(dec);
status = srtp_shutdown();
if (status) {
fprintf(stderr, "error: srtp shutdown failed with error code %d\n",
status);
exit(1);
}
return 0;
}
void usage(char *string)
{
fprintf(
stderr,
"usage: %s [-d <debug>]* [[-k][-b] <key>] [-a][-t][-e] [-s "
"<srtp-crypto-suite>] [-m <mode>]\n"
"or %s -l\n"
"where -a use message authentication\n"
" -e <key size> use encryption (use 128 or 256 for key size)\n"
" -g Use AES-GCM mode (must be used with -e)\n"
" -t <tag size> Tag size to use (in GCM mode use 8 or 16)\n"
" -k <key> sets the srtp master key given in hexadecimal\n"
" -b <key> sets the srtp master key given in base64\n"
" -l list debug modules\n"
" -f \"<pcap filter>\" to filter only the desired SRTP packets\n"
" -d <debug> turn on debugging for module <debug>\n"
" -s \"<srtp-crypto-suite>\" to set both key and tag size based\n"
" on RFC4568-style crypto suite specification\n"
" -m <mode> set the mode to be one of [rtp]|rtcp|rtcp-mux\n"
" -p <pcap file> path to pcap file (defaults to stdin)\n"
" -o byte offset of RTP packet in capture (defaults to 42)\n",
string, string);
exit(1);
}
rtp_decoder_t rtp_decoder_alloc(void)
{
return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t));
}
void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx)
{
free(rtp_ctx);
}
int rtp_decoder_deinit(rtp_decoder_t decoder)
{
if (decoder->srtp_ctx) {
return srtp_dealloc(decoder->srtp_ctx);
}
return 0;
}
int rtp_decoder_init(rtp_decoder_t dcdr,
srtp_policy_t policy,
rtp_decoder_mode_t mode,
int rtp_packet_offset)
{
dcdr->rtp_offset = rtp_packet_offset;
dcdr->srtp_ctx = NULL;
dcdr->start_tv.tv_usec = 0;
dcdr->start_tv.tv_sec = 0;
dcdr->frame_nr = -1;
dcdr->error_cnt = 0;
dcdr->rtp_cnt = 0;
dcdr->rtcp_cnt = 0;
dcdr->mode = mode;
dcdr->policy = policy;
dcdr->policy.ssrc.type = ssrc_any_inbound;
if (srtp_create(&dcdr->srtp_ctx, &dcdr->policy)) {
return 1;
}
return 0;
}
/*
* decodes key as base64
*/
void hexdump(const void *ptr, size_t size)
{
int i, j;
const unsigned char *cptr = ptr;
for (i = 0; i < size; i += 16) {
fprintf(stdout, "%04x ", i);
for (j = 0; j < 16 && i + j < size; j++) {
fprintf(stdout, "%02x ", cptr[i + j]);
}
fprintf(stdout, "\n");
}
}
void rtp_decoder_handle_pkt(u_char *arg,
const struct pcap_pkthdr *hdr,
const u_char *bytes)
{
rtp_decoder_t dcdr = (rtp_decoder_t)arg;
rtp_msg_t message;
int rtp;
int pktsize;
struct timeval delta;
int octets_recvd;
srtp_err_status_t status;
dcdr->frame_nr++;
if ((dcdr->start_tv.tv_sec == 0) && (dcdr->start_tv.tv_usec == 0)) {
dcdr->start_tv = hdr->ts;
}
if (hdr->caplen < dcdr->rtp_offset) {
return;
}
const void *rtp_packet = bytes + dcdr->rtp_offset;
memcpy((void *)&message, rtp_packet, hdr->caplen - dcdr->rtp_offset);
pktsize = hdr->caplen - dcdr->rtp_offset;
octets_recvd = pktsize;
if (octets_recvd == -1) {
return;
}
if (dcdr->mode == mode_rtp) {
rtp = 1;
} else if (dcdr->mode == mode_rtcp) {
rtp = 0;
} else {
rtp = 1;
if (octets_recvd >= 2) {
/* rfc5761 */
u_char payload_type = *(bytes + dcdr->rtp_offset + 1) & 0x7f;
rtp = payload_type < 64 || payload_type > 95;
}
}
if (rtp) {
/* verify rtp header */
if (message.header.version != 2) {
return;
}
status = srtp_unprotect(dcdr->srtp_ctx, &message, &octets_recvd);
if (status) {
dcdr->error_cnt++;
return;
}
dcdr->rtp_cnt++;
} else {
status = srtp_unprotect_rtcp(dcdr->srtp_ctx, &message, &octets_recvd);
if (status) {
dcdr->error_cnt++;
return;
}
dcdr->rtcp_cnt++;
}
timersub(&hdr->ts, &dcdr->start_tv, &delta);
fprintf(stdout, "%02ld:%02ld.%06ld\n", delta.tv_sec / 60, delta.tv_sec % 60,
(long)delta.tv_usec);
hexdump(&message, octets_recvd);
}
void rtp_print_error(srtp_err_status_t status, char *message)
{
// clang-format off
fprintf(stderr,
"error: %s %d%s\n", message, status,
status == srtp_err_status_replay_fail ? " (replay check failed)" :
status == srtp_err_status_bad_param ? " (bad param)" :
status == srtp_err_status_no_ctx ? " (no context)" :
status == srtp_err_status_cipher_fail ? " (cipher failed)" :
status == srtp_err_status_key_expired ? " (key expired)" :
status == srtp_err_status_auth_fail ? " (auth check failed)" : "");
// clang-format on
}

View file

@ -0,0 +1,122 @@
/*
* rtp_decoder.h
*
* decoder structures and functions for SRTP pcap decoder
*
* Bernardo Torres <bernardo@torresautomacao.com.br>
*
* Some structure and code from https://github.com/gteissier/srtp-decrypt
*
*/
/*
*
* 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.
*
*/
#ifndef RTP_DECODER_H
#define RTP_DECODER_H
#include "srtp_priv.h"
#include "rtp.h"
#define DEFAULT_RTP_OFFSET 42
typedef enum {
mode_rtp = 0,
mode_rtcp,
mode_rtcp_mux,
} rtp_decoder_mode_t;
typedef struct rtp_decoder_ctx_t {
srtp_policy_t policy;
srtp_ctx_t *srtp_ctx;
rtp_decoder_mode_t mode;
int rtp_offset;
struct timeval start_tv;
int frame_nr;
int error_cnt;
int rtp_cnt;
int rtcp_cnt;
} rtp_decoder_ctx_t;
typedef struct rtp_decoder_ctx_t *rtp_decoder_t;
/*
* error to string
*/
void rtp_print_error(srtp_err_status_t status, char *message);
/*
* prints the output of a random buffer in hexadecimal
*/
void hexdump(const void *ptr, size_t size);
/*
* the function usage() prints an error message describing how this
* program should be called, then calls exit()
*/
void usage(char *prog_name);
/*
* transforms base64 key into octet
*/
char *decode_sdes(char *in, char *out);
/*
* pcap handling
*/
void rtp_decoder_handle_pkt(u_char *arg,
const struct pcap_pkthdr *hdr,
const u_char *bytes);
rtp_decoder_t rtp_decoder_alloc(void);
void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx);
int rtp_decoder_init(rtp_decoder_t dcdr,
srtp_policy_t policy,
rtp_decoder_mode_t mode,
int rtp_packet_offset);
int rtp_decoder_deinit(rtp_decoder_t decoder);
void rtp_decoder_srtp_log_handler(srtp_log_level_t level,
const char *msg,
void *data);
void rtp_decoder_srtp_log_handler(srtp_log_level_t level,
const char *msg,
void *data);
#endif /* RTP_DECODER_H */

701
trunk/3rdparty/libsrtp-2-fit/test/rtpw.c vendored Normal file
View file

@ -0,0 +1,701 @@
/*
* rtpw.c
*
* rtp word sender/receiver
*
* David A. McGrew
* Cisco Systems, Inc.
*
* This app is a simple RTP application intended only for testing
* libsrtp. It reads one word at a time from words.txt (or
* whatever file is specified as DICT_FILE or with -w), and sends one word out
* each USEC_RATE microseconds. Secure RTP protections can be
* applied. See the usage() function for more details.
*
*/
/*
*
* 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "getopt_s.h" /* for local getopt() */
#include <stdio.h> /* for printf, fprintf */
#include <stdlib.h> /* for atoi() */
#include <errno.h>
#include <signal.h> /* for signal() */
#include <string.h> /* for strncpy() */
#include <time.h> /* for usleep() */
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* for close() */
#elif defined(_MSC_VER)
#include <io.h> /* for _close() */
#define close _close
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#elif defined HAVE_WINSOCK2_H
#include <winsock2.h>
#include <ws2tcpip.h>
#define RTPW_USE_WINSOCK2 1
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include "srtp.h"
#include "rtp.h"
#include "util.h"
#define DICT_FILE "words.txt"
#define USEC_RATE (5e5)
#define MAX_WORD_LEN 128
#define ADDR_IS_MULTICAST(a) IN_MULTICAST(htonl(a))
#define MAX_KEY_LEN 96
#ifndef HAVE_USLEEP
#ifdef HAVE_WINDOWS_H
#define usleep(us) Sleep((us) / 1000)
#else
#define usleep(us) sleep((us) / 1000000)
#endif
#endif
/*
* the function usage() prints an error message describing how this
* program should be called, then calls exit()
*/
void usage(char *prog_name);
/*
* leave_group(...) de-registers from a multicast group
*/
void leave_group(int sock, struct ip_mreq mreq, char *name);
/*
* setup_signal_handler() sets up a signal handler to trigger
* cleanups after an interrupt
*/
int setup_signal_handler(char *name);
/*
* handle_signal(...) handles interrupt signal to trigger cleanups
*/
volatile int interrupted = 0;
/*
* program_type distinguishes the [s]rtp sender and receiver cases
*/
typedef enum { sender, receiver, unknown } program_type;
int main(int argc, char *argv[])
{
char *dictfile = DICT_FILE;
FILE *dict;
char word[MAX_WORD_LEN];
int sock, ret;
struct in_addr rcvr_addr;
struct sockaddr_in name;
struct ip_mreq mreq;
#if BEW
struct sockaddr_in local;
#endif
program_type prog_type = unknown;
srtp_sec_serv_t sec_servs = sec_serv_none;
unsigned char ttl = 5;
int c;
int key_size = 128;
int tag_size = 8;
int gcm_on = 0;
char *input_key = NULL;
int b64_input = 0;
char *address = NULL;
char key[MAX_KEY_LEN];
unsigned short port = 0;
rtp_sender_t snd;
srtp_policy_t policy;
srtp_err_status_t status;
int len;
int expected_len;
int do_list_mods = 0;
uint32_t ssrc = 0xdeadbeef; /* ssrc value hardcoded for now */
#ifdef RTPW_USE_WINSOCK2
WORD wVersionRequested = MAKEWORD(2, 0);
WSADATA wsaData;
ret = WSAStartup(wVersionRequested, &wsaData);
if (ret != 0) {
fprintf(stderr, "error: WSAStartup() failed: %d\n", ret);
exit(1);
}
#endif
memset(&policy, 0x0, sizeof(srtp_policy_t));
printf("Using %s [0x%x]\n", srtp_get_version_string(), srtp_get_version());
if (setup_signal_handler(argv[0]) != 0) {
exit(1);
}
/* initialize srtp library */
status = srtp_init();
if (status) {
printf("error: srtp initialization failed with error code %d\n",
status);
exit(1);
}
/* check args */
while (1) {
c = getopt_s(argc, argv, "b:k:rsgt:ae:ld:w:");
if (c == -1) {
break;
}
switch (c) {
case 'b':
b64_input = 1;
/* fall thru */
case 'k':
input_key = optarg_s;
break;
case 'e':
key_size = atoi(optarg_s);
if (key_size != 128 && key_size != 256) {
printf("error: encryption key size must be 128 or 256 (%d)\n",
key_size);
exit(1);
}
sec_servs |= sec_serv_conf;
break;
case 't':
tag_size = atoi(optarg_s);
if (tag_size != 8 && tag_size != 16) {
printf("error: GCM tag size must be 8 or 16 (%d)\n", tag_size);
exit(1);
}
break;
case 'a':
sec_servs |= sec_serv_auth;
break;
case 'g':
gcm_on = 1;
sec_servs |= sec_serv_auth;
break;
case 'r':
prog_type = receiver;
break;
case 's':
prog_type = sender;
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;
case 'l':
do_list_mods = 1;
break;
case 'w':
dictfile = optarg_s;
break;
default:
usage(argv[0]);
}
}
if (prog_type == unknown) {
if (do_list_mods) {
status = srtp_list_debug_modules();
if (status) {
printf("error: list of debug modules failed\n");
exit(1);
}
return 0;
} else {
printf("error: neither sender [-s] nor receiver [-r] specified\n");
usage(argv[0]);
}
}
if ((sec_servs && !input_key) || (!sec_servs && input_key)) {
/*
* a key must be provided if and only if security services have
* been requested
*/
usage(argv[0]);
}
if (argc != optind_s + 2) {
/* wrong number of arguments */
usage(argv[0]);
}
/* get address from arg */
address = argv[optind_s++];
/* get port from arg */
port = atoi(argv[optind_s++]);
/* set address */
#ifdef HAVE_INET_ATON
if (0 == inet_aton(address, &rcvr_addr)) {
fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0],
address);
exit(1);
}
if (rcvr_addr.s_addr == INADDR_NONE) {
fprintf(stderr, "%s: address error", argv[0]);
exit(1);
}
#else
rcvr_addr.s_addr = inet_addr(address);
if (0xffffffff == rcvr_addr.s_addr) {
fprintf(stderr, "%s: cannot parse IP v4 address %s\n", argv[0],
address);
exit(1);
}
#endif
/* open socket */
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0) {
int err;
#ifdef RTPW_USE_WINSOCK2
err = WSAGetLastError();
#else
err = errno;
#endif
fprintf(stderr, "%s: couldn't open socket: %d\n", argv[0], err);
exit(1);
}
memset(&name, 0, sizeof(struct sockaddr_in));
name.sin_addr = rcvr_addr;
name.sin_family = PF_INET;
name.sin_port = htons(port);
if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
if (prog_type == sender) {
ret = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
sizeof(ttl));
if (ret < 0) {
fprintf(stderr, "%s: Failed to set TTL for multicast group",
argv[0]);
perror("");
exit(1);
}
}
mreq.imr_multiaddr.s_addr = rcvr_addr.s_addr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq,
sizeof(mreq));
if (ret < 0) {
fprintf(stderr, "%s: Failed to join multicast group", argv[0]);
perror("");
exit(1);
}
}
/* report security services selected on the command line */
printf("security services: ");
if (sec_servs & sec_serv_conf)
printf("confidentiality ");
if (sec_servs & sec_serv_auth)
printf("message authentication");
if (sec_servs == sec_serv_none)
printf("none");
printf("\n");
/* set up the srtp policy and master key */
if (sec_servs) {
/*
* create policy structure, using the default mechanisms but
* with only the security services requested on the command line,
* using the right SSRC value
*/
switch (sec_servs) {
case sec_serv_conf_and_auth:
if (gcm_on) {
#ifdef GCM
switch (key_size) {
case 128:
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp);
break;
case 256:
srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_256_8_auth(&policy.rtcp);
break;
}
#else
printf("error: GCM mode only supported when using the OpenSSL "
"or NSS crypto engine.\n");
return 0;
#endif
} else {
switch (key_size) {
case 128:
srtp_crypto_policy_set_rtp_default(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
break;
case 256:
srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
break;
}
}
break;
case sec_serv_conf:
if (gcm_on) {
printf(
"error: GCM mode must always be used with auth enabled\n");
return -1;
} else {
switch (key_size) {
case 128:
srtp_crypto_policy_set_aes_cm_128_null_auth(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
break;
case 256:
srtp_crypto_policy_set_aes_cm_256_null_auth(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
break;
}
}
break;
case sec_serv_auth:
if (gcm_on) {
#ifdef GCM
switch (key_size) {
case 128:
srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_128_8_only_auth(
&policy.rtcp);
break;
case 256:
srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&policy.rtp);
srtp_crypto_policy_set_aes_gcm_256_8_only_auth(
&policy.rtcp);
break;
}
#else
printf("error: GCM mode only supported when using the OpenSSL "
"crypto engine.\n");
return 0;
#endif
} else {
srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
}
break;
default:
printf("error: unknown security service requested\n");
return -1;
}
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = ssrc;
policy.key = (uint8_t *)key;
policy.ekt = NULL;
policy.next = NULL;
policy.window_size = 128;
policy.allow_repeat_tx = 0;
policy.rtp.sec_serv = sec_servs;
policy.rtcp.sec_serv = sec_serv_none; /* we don't do RTCP anyway */
if (gcm_on && tag_size != 8) {
policy.rtp.auth_tag_len = tag_size;
}
/*
* read key from hexadecimal or base64 on command line into an octet
* string
*/
if (b64_input) {
int pad;
expected_len = (policy.rtp.cipher_key_len * 4) / 3;
len = base64_string_to_octet_string(key, &pad, input_key,
expected_len);
if (pad != 0) {
fprintf(stderr, "error: padding in base64 unexpected\n");
exit(1);
}
} else {
expected_len = policy.rtp.cipher_key_len * 2;
len = hex_string_to_octet_string(key, input_key, expected_len);
}
/* check that hex string is the right length */
if (len < expected_len) {
fprintf(stderr, "error: too few digits in key/salt "
"(should be %d digits, found %d)\n",
expected_len, len);
exit(1);
}
if ((int)strlen(input_key) > policy.rtp.cipher_key_len * 2) {
fprintf(stderr, "error: too many digits in key/salt "
"(should be %d hexadecimal digits, found %u)\n",
policy.rtp.cipher_key_len * 2, (unsigned)strlen(input_key));
exit(1);
}
printf("set master key/salt to %s/", octet_string_hex_string(key, 16));
printf("%s\n", octet_string_hex_string(key + 16, 14));
} else {
/*
* we're not providing security services, so set the policy to the
* null policy
*
* Note that this policy does not conform to the SRTP
* specification, since RTCP authentication is required. However,
* the effect of this policy is to turn off SRTP, so that this
* application is now a vanilla-flavored RTP application.
*/
srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtp);
srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtcp);
policy.key = (uint8_t *)key;
policy.ssrc.type = ssrc_specific;
policy.ssrc.value = ssrc;
policy.window_size = 0;
policy.allow_repeat_tx = 0;
policy.ekt = NULL;
policy.next = NULL;
}
if (prog_type == sender) {
#if BEW
/* bind to local socket (to match crypto policy, if need be) */
memset(&local, 0, sizeof(struct sockaddr_in));
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(port);
ret = bind(sock, (struct sockaddr *)&local, sizeof(struct sockaddr_in));
if (ret < 0) {
fprintf(stderr, "%s: bind failed\n", argv[0]);
perror("");
exit(1);
}
#endif /* BEW */
/* initialize sender's rtp and srtp contexts */
snd = rtp_sender_alloc();
if (snd == NULL) {
fprintf(stderr, "error: malloc() failed\n");
exit(1);
}
rtp_sender_init(snd, sock, name, ssrc);
status = rtp_sender_init_srtp(snd, &policy);
if (status) {
fprintf(stderr, "error: srtp_create() failed with code %d\n",
status);
exit(1);
}
/* open dictionary */
dict = fopen(dictfile, "r");
if (dict == NULL) {
fprintf(stderr, "%s: couldn't open file %s\n", argv[0], dictfile);
if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
leave_group(sock, mreq, argv[0]);
}
exit(1);
}
/* read words from dictionary, then send them off */
while (!interrupted && fgets(word, MAX_WORD_LEN, dict) != NULL) {
len = strlen(word) + 1; /* plus one for null */
if (len > MAX_WORD_LEN)
printf("error: word %s too large to send\n", word);
else {
rtp_sendto(snd, word, len);
printf("sending word: %s", word);
}
usleep(USEC_RATE);
}
rtp_sender_deinit_srtp(snd);
rtp_sender_dealloc(snd);
fclose(dict);
} else { /* prog_type == receiver */
rtp_receiver_t rcvr;
if (bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
close(sock);
fprintf(stderr, "%s: socket bind error\n", argv[0]);
perror(NULL);
if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
leave_group(sock, mreq, argv[0]);
}
exit(1);
}
rcvr = rtp_receiver_alloc();
if (rcvr == NULL) {
fprintf(stderr, "error: malloc() failed\n");
exit(1);
}
rtp_receiver_init(rcvr, sock, name, ssrc);
status = rtp_receiver_init_srtp(rcvr, &policy);
if (status) {
fprintf(stderr, "error: srtp_create() failed with code %d\n",
status);
exit(1);
}
/* get next word and loop */
while (!interrupted) {
len = MAX_WORD_LEN;
if (rtp_recvfrom(rcvr, word, &len) > -1)
printf("\tword: %s\n", word);
}
rtp_receiver_deinit_srtp(rcvr);
rtp_receiver_dealloc(rcvr);
}
if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) {
leave_group(sock, mreq, argv[0]);
}
#ifdef RTPW_USE_WINSOCK2
ret = closesocket(sock);
#else
ret = close(sock);
#endif
if (ret < 0) {
fprintf(stderr, "%s: Failed to close socket", argv[0]);
perror("");
}
status = srtp_shutdown();
if (status) {
printf("error: srtp shutdown failed with error code %d\n", status);
exit(1);
}
#ifdef RTPW_USE_WINSOCK2
WSACleanup();
#endif
return 0;
}
void usage(char *string)
{
printf("usage: %s [-d <debug>]* [-k <key> [-a][-e]] "
"[-s | -r] dest_ip dest_port\n"
"or %s -l\n"
"where -a use message authentication\n"
" -e <key size> use encryption (use 128 or 256 for key size)\n"
" -g Use AES-GCM mode (must be used with -e)\n"
" -t <tag size> Tag size to use in GCM mode (use 8 or 16)\n"
" -k <key> sets the srtp master key given in hexadecimal\n"
" -b <key> sets the srtp master key given in base64\n"
" -s act as rtp sender\n"
" -r act as rtp receiver\n"
" -l list debug modules\n"
" -d <debug> turn on debugging for module <debug>\n"
" -w <wordsfile> use <wordsfile> for input, rather than %s\n",
string, string, DICT_FILE);
exit(1);
}
void leave_group(int sock, struct ip_mreq mreq, char *name)
{
int ret;
ret = setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreq,
sizeof(mreq));
if (ret < 0) {
fprintf(stderr, "%s: Failed to leave multicast group", name);
perror("");
}
}
void handle_signal(int signum)
{
interrupted = 1;
/* Reset handler explicitly, in case we don't have sigaction() (and signal()
has BSD semantics), or we don't have SA_RESETHAND */
signal(signum, SIG_DFL);
}
int setup_signal_handler(char *name)
{
#if HAVE_SIGACTION
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = handle_signal;
sigemptyset(&act.sa_mask);
#if defined(SA_RESETHAND)
act.sa_flags = SA_RESETHAND;
#else
act.sa_flags = 0;
#endif
/* Note that we're not setting SA_RESTART; we want recvfrom to return
* EINTR when we signal the receiver. */
if (sigaction(SIGTERM, &act, NULL) != 0) {
fprintf(stderr, "%s: error setting up signal handler", name);
perror("");
return -1;
}
#else
if (signal(SIGTERM, handle_signal) == SIG_ERR) {
fprintf(stderr, "%s: error setting up signal handler", name);
perror("");
return -1;
}
#endif
return 0;
}

176
trunk/3rdparty/libsrtp-2-fit/test/rtpw_test.sh vendored Executable file
View file

@ -0,0 +1,176 @@
#!/bin/sh
#
# usage: rtpw_test <rtpw_commands>
#
# tests the rtpw sender and receiver functions
#
# 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.
#
case $(uname -s) in
*CYGWIN*|*MINGW*)
EXE=".exe"
;;
*Linux*)
EXE=""
export LD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
*Darwin*)
EXE=""
export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
esac
RTPW=./rtpw$EXE
DEST_PORT=9999
DURATION=3
key=Ky7cUDT2GnI0XKWYbXv9AYmqbcLsqzL9mvdN9t/G
ARGS="-b $key -a -e 128"
# First, we run "killall" to get rid of all existing rtpw processes.
# This step also enables this script to clean up after itself; if this
# script is interrupted after the rtpw processes are started but before
# they are killed, those processes will linger. Re-running the script
# will get rid of them.
killall rtpw 2>/dev/null
if test -x $RTPW; then
echo $0 ": starting rtpw receiver process... "
$RTPW $* $ARGS -r 0.0.0.0 $DEST_PORT &
receiver_pid=$!
echo $0 ": receiver PID = $receiver_pid"
sleep 1
# verify that the background job is running
ps -e | grep -q $receiver_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 254
fi
echo $0 ": starting rtpw sender process..."
$RTPW $* $ARGS -s 127.0.0.1 $DEST_PORT &
sender_pid=$!
echo $0 ": sender PID = $sender_pid"
# verify that the background job is running
ps -e | grep -q $sender_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 255
fi
sleep $DURATION
kill $receiver_pid
kill $sender_pid
wait $receiver_pid 2>/dev/null
wait $sender_pid 2>/dev/null
key=033490ba9e82994fc21013395739038992b2edc5034f61a72345ca598d7bfd0189aa6dc2ecab32fd9af74df6dfc6
ARGS="-k $key -a -e 256"
echo $0 ": starting rtpw receiver process... "
$RTPW $* $ARGS -r 0.0.0.0 $DEST_PORT &
receiver_pid=$!
echo $0 ": receiver PID = $receiver_pid"
sleep 1
# verify that the background job is running
ps -e | grep -q $receiver_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 254
fi
echo $0 ": starting rtpw sender process..."
$RTPW $* $ARGS -s 127.0.0.1 $DEST_PORT &
sender_pid=$!
echo $0 ": sender PID = $sender_pid"
# verify that the background job is running
ps -e | grep -q $sender_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 255
fi
sleep $DURATION
kill $receiver_pid
kill $sender_pid
wait $receiver_pid 2>/dev/null
wait $sender_pid 2>/dev/null
echo $0 ": done (test passed)"
else
echo "error: can't find executable" $RTPW
exit 1
fi
# EOF

View file

@ -0,0 +1,260 @@
#!/bin/sh
#
# usage: rtpw_test <rtpw_commands>
#
# tests the rtpw sender and receiver functions
#
# 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.
#
case $(uname -s) in
*CYGWIN*|*MINGW*)
EXE=".exe"
;;
*Linux*)
EXE=""
export LD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
*Darwin*)
EXE=""
export DYLD_LIBRARY_PATH=$CRYPTO_LIBDIR
;;
esac
RTPW=./rtpw$EXE
DEST_PORT=9999
DURATION=3
# First, we run "killall" to get rid of all existing rtpw processes.
# This step also enables this script to clean up after itself; if this
# script is interrupted after the rtpw processes are started but before
# they are killed, those processes will linger. Re-running the script
# will get rid of them.
killall rtpw 2>/dev/null
if test -x $RTPW; then
GCMARGS128="-k 01234567890123456789012345678901234567890123456789012345 -g -e 128"
echo $0 ": starting GCM mode 128-bit rtpw receiver process... "
exec $RTPW $* $GCMARGS128 -r 127.0.0.1 $DEST_PORT &
receiver_pid=$!
echo $0 ": receiver PID = $receiver_pid"
sleep 1
# verify that the background job is running
ps -e | grep -q $receiver_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 254
fi
echo $0 ": starting GCM 128-bit rtpw sender process..."
exec $RTPW $* $GCMARGS128 -s 127.0.0.1 $DEST_PORT &
sender_pid=$!
echo $0 ": sender PID = $sender_pid"
# verify that the background job is running
ps -e | grep -q $sender_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 255
fi
sleep $DURATION
kill $receiver_pid
kill $sender_pid
wait $receiver_pid 2>/dev/null
wait $sender_pid 2>/dev/null
GCMARGS128="-k 01234567890123456789012345678901234567890123456789012345 -g -t 16 -e 128"
echo $0 ": starting GCM mode 128-bit (16 byte tag) rtpw receiver process... "
exec $RTPW $* $GCMARGS128 -r 127.0.0.1 $DEST_PORT &
receiver_pid=$!
echo $0 ": receiver PID = $receiver_pid"
sleep 1
# verify that the background job is running
ps -e | grep -q $receiver_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 254
fi
echo $0 ": starting GCM 128-bit (16 byte tag) rtpw sender process..."
exec $RTPW $* $GCMARGS128 -s 127.0.0.1 $DEST_PORT &
sender_pid=$!
echo $0 ": sender PID = $sender_pid"
# verify that the background job is running
ps -e | grep -q $sender_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 255
fi
sleep $DURATION
kill $receiver_pid
kill $sender_pid
wait $receiver_pid 2>/dev/null
wait $sender_pid 2>/dev/null
GCMARGS256="-k 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 -g -e 256"
echo $0 ": starting GCM mode 256-bit rtpw receiver process... "
exec $RTPW $* $GCMARGS256 -r 127.0.0.1 $DEST_PORT &
receiver_pid=$!
echo $0 ": receiver PID = $receiver_pid"
sleep 1
# verify that the background job is running
ps -e | grep -q $receiver_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 254
fi
echo $0 ": starting GCM 256-bit rtpw sender process..."
exec $RTPW $* $GCMARGS256 -s 127.0.0.1 $DEST_PORT &
sender_pid=$!
echo $0 ": sender PID = $sender_pid"
# verify that the background job is running
ps -e | grep -q $sender_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 255
fi
sleep $DURATION
kill $receiver_pid
kill $sender_pid
wait $receiver_pid 2>/dev/null
wait $sender_pid 2>/dev/null
GCMARGS256="-k a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567 -g -t 16 -e 256"
echo $0 ": starting GCM mode 256-bit (16 byte tag) rtpw receiver process... "
exec $RTPW $* $GCMARGS256 -r 127.0.0.1 $DEST_PORT &
receiver_pid=$!
echo $0 ": receiver PID = $receiver_pid"
sleep 1
# verify that the background job is running
ps -e | grep -q $receiver_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 254
fi
echo $0 ": starting GCM 256-bit (16 byte tag) rtpw sender process..."
exec $RTPW $* $GCMARGS256 -s 127.0.0.1 $DEST_PORT &
sender_pid=$!
echo $0 ": sender PID = $sender_pid"
# verify that the background job is running
ps -e | grep -q $sender_pid
retval=$?
echo $retval
if [ $retval != 0 ]; then
echo $0 ": error"
exit 255
fi
sleep $DURATION
kill $receiver_pid
kill $sender_pid
wait $receiver_pid 2>/dev/null
wait $sender_pid 2>/dev/null
echo $0 ": done (test passed)"
else
echo "error: can't find executable" $RTPW
exit 1
fi
# EOF

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,185 @@
/*
* test_srtp.c
*
* Unit tests for internal srtp functions
*
* Cisco Systems, Inc.
*
*/
/*
*
* Copyright (c) 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.
*
*/
/*
* libSRTP specific.
*/
#include "../srtp/srtp.c" // Get access to static functions
/*
* Test specific.
*/
#include "cutest.h"
/*
* Standard library.
*/
/*
* Forward declarations for all tests.
*/
void srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output(void);
void srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param(void);
void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number(void);
/*
* NULL terminated array of tests.
* The first item in the array is a char[] which give some information about
* what is being tested and is displayed to the user during runtime, the second
* item is the test function.
*/
TEST_LIST = { { "srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output()",
srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output },
{ "srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param()",
srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param },
{ "srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number()",
srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number },
{ NULL } /* End of tests */ };
/*
* Implementation.
*/
void srtp_calc_aead_iv_srtcp_all_zero_input_yield_zero_output()
{
// Preconditions
srtp_session_keys_t session_keys;
v128_t init_vector;
srtcp_hdr_t header;
uint32_t sequence_num;
// Postconditions
srtp_err_status_t status;
const v128_t zero_vector;
memset((v128_t *)&zero_vector, 0, sizeof(v128_t));
// Given
memset(&session_keys, 0, sizeof(srtp_session_keys_t));
memset(&init_vector, 0, sizeof(v128_t));
memset(&header, 0, sizeof(srtcp_hdr_t));
sequence_num = 0x0UL;
// When
status = srtp_calc_aead_iv_srtcp(&session_keys, &init_vector, sequence_num,
&header);
// Then
TEST_CHECK(status == srtp_err_status_ok);
TEST_CHECK(memcmp(&zero_vector, &init_vector, sizeof(v128_t)) == 0);
}
void srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param()
{
// Preconditions
srtp_session_keys_t session_keys;
v128_t init_vector;
srtcp_hdr_t header;
uint32_t sequence_num;
// Postconditions
srtp_err_status_t status;
// Given
memset(&session_keys, 0, sizeof(srtp_session_keys_t));
memset(&init_vector, 0, sizeof(v128_t));
memset(&header, 0, sizeof(srtcp_hdr_t));
sequence_num = 0x7FFFFFFFUL + 0x1UL;
// When
status = srtp_calc_aead_iv_srtcp(&session_keys, &init_vector, sequence_num,
&header);
// Then
TEST_CHECK(status == srtp_err_status_bad_param);
}
/*
* Regression test for issue #256:
* Srtcp IV calculation incorrectly masks high bit of sequence number for
* little-endian platforms.
* Ensure that for each valid sequence number where the most significant bit is
* high that we get an expected and unique IV.
*/
void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number()
{
#define SAMPLE_COUNT (3)
// Preconditions
// Test each significant bit high in each full byte.
srtp_session_keys_t session_keys;
srtcp_hdr_t header;
v128_t output_iv[SAMPLE_COUNT];
uint32_t sequence_num[SAMPLE_COUNT];
v128_t final_iv[SAMPLE_COUNT];
size_t i = 0;
memset(&output_iv, 0, SAMPLE_COUNT * sizeof(v128_t));
sequence_num[0] = 0xFF;
sequence_num[1] = 0xFF00;
sequence_num[2] = 0xFF0000;
// Postconditions
memset(&final_iv, 0, SAMPLE_COUNT * sizeof(v128_t));
final_iv[0].v8[11] = 0xFF;
final_iv[1].v8[10] = 0xFF;
final_iv[2].v8[9] = 0xFF;
// Given
memset(&session_keys, 0, sizeof(srtp_session_keys_t));
memset(&header, 0, sizeof(srtcp_hdr_t));
// When
for (i = 0; i < SAMPLE_COUNT; i++) {
TEST_CHECK(srtp_calc_aead_iv_srtcp(&session_keys, &output_iv[i],
sequence_num[i],
&header) == srtp_err_status_ok);
}
// Then all IVs are as expected
for (i = 0; i < SAMPLE_COUNT; i++) {
TEST_CHECK(memcmp(&final_iv[i], &output_iv[i], sizeof(v128_t)) == 0);
}
#undef SAMPLE_COUNT
}

212
trunk/3rdparty/libsrtp-2-fit/test/util.c vendored Normal file
View file

@ -0,0 +1,212 @@
/*
* util.c
*
* Utilities used by the test apps
*
* John A. Foley
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2014-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 "config.h"
#include "util.h"
#include <string.h>
#include <stdint.h>
/* include space for null terminator */
char bit_string[MAX_PRINT_STRING_LEN + 1];
static inline int hex_char_to_nibble(uint8_t c)
{
switch (c) {
case ('0'):
return 0x0;
case ('1'):
return 0x1;
case ('2'):
return 0x2;
case ('3'):
return 0x3;
case ('4'):
return 0x4;
case ('5'):
return 0x5;
case ('6'):
return 0x6;
case ('7'):
return 0x7;
case ('8'):
return 0x8;
case ('9'):
return 0x9;
case ('a'):
return 0xa;
case ('A'):
return 0xa;
case ('b'):
return 0xb;
case ('B'):
return 0xb;
case ('c'):
return 0xc;
case ('C'):
return 0xc;
case ('d'):
return 0xd;
case ('D'):
return 0xd;
case ('e'):
return 0xe;
case ('E'):
return 0xe;
case ('f'):
return 0xf;
case ('F'):
return 0xf;
default:
return -1; /* this flags an error */
}
/* NOTREACHED */
return -1; /* this keeps compilers from complaining */
}
uint8_t nibble_to_hex_char(uint8_t nibble)
{
char buf[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
return buf[nibble & 0xF];
}
/*
* hex_string_to_octet_string converts a hexadecimal string
* of length 2 * len to a raw octet string of length len
*/
int hex_string_to_octet_string(char *raw, char *hex, int len)
{
uint8_t x;
int tmp;
int hex_len;
hex_len = 0;
while (hex_len < len) {
tmp = hex_char_to_nibble(hex[0]);
if (tmp == -1) {
return hex_len;
}
x = (tmp << 4);
hex_len++;
tmp = hex_char_to_nibble(hex[1]);
if (tmp == -1) {
return hex_len;
}
x |= (tmp & 0xff);
hex_len++;
*raw++ = x;
hex += 2;
}
return hex_len;
}
char *octet_string_hex_string(const void *s, int length)
{
const uint8_t *str = (const uint8_t *)s;
int i;
/* double length, since one octet takes two hex characters */
length *= 2;
/* truncate string if it would be too long */
if (length > MAX_PRINT_STRING_LEN) {
length = MAX_PRINT_STRING_LEN;
}
for (i = 0; i < length; i += 2) {
bit_string[i] = nibble_to_hex_char(*str >> 4);
bit_string[i + 1] = nibble_to_hex_char(*str++ & 0xF);
}
bit_string[i] = 0; /* null terminate string */
return bit_string;
}
static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789+/";
static int base64_block_to_octet_triple(char *out, char *in)
{
unsigned char sextets[4] = { 0 };
int j = 0;
int i;
for (i = 0; i < 4; i++) {
char *p = strchr(b64chars, in[i]);
if (p != NULL) {
sextets[i] = p - b64chars;
} else {
j++;
}
}
out[0] = (sextets[0] << 2) | (sextets[1] >> 4);
if (j < 2) {
out[1] = (sextets[1] << 4) | (sextets[2] >> 2);
}
if (j < 1) {
out[2] = (sextets[2] << 6) | sextets[3];
}
return j;
}
int base64_string_to_octet_string(char *out, int *pad, char *in, int len)
{
int k = 0;
int i = 0;
int j = 0;
if (len % 4 != 0) {
return 0;
}
while (i < len && j == 0) {
j = base64_block_to_octet_triple(out + k, in + i);
k += 3;
i += 4;
}
*pad = j;
return i;
}

View file

@ -0,0 +1,53 @@
/*
* util.h
*
* Utilities used by the test apps
*
* John A. Foley
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2014-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.
*
*/
#ifndef SRTP_TEST_UTIL_H
#define SRTP_TEST_UTIL_H
#define MAX_PRINT_STRING_LEN 1024
int hex_string_to_octet_string(char *raw, char *hex, int len);
char *octet_string_hex_string(const void *s, int length);
int base64_string_to_octet_string(char *raw, int *pad, char *base64, int len);
#endif

View file

@ -0,0 +1,250 @@
abducing
acidheads
acidness
actons
admixtures
affidavit
agelastic
alated
alimentary
alleviated
allseed
annexure
arragonite
atonements
autacoid
axe
axon
ayres
beathing
blazonry
bottom
braising
brehon
brindisi
broadcasts
buds
bulnbulns
bushcraft
calamander
calipee
casing
caveat
chaffings
citifies
clappers
claques
clavate
colonial
colonials
commonalty
compares
consequent
consumed
contango
courtierly
creamery
cruddiest
cue
cultish
cumin
cyclus
dahlias
dentitions
derailers
devitrify
dibs
diphysite
disjunes
drolleries
dubitated
dupion
earliness
eductor
elenctic
empresses
entames
epaulettes
epicanthic
epochal
estated
eurhythmic
exfoliated
extremity
fayence
figgery
flaming
foes
forelays
forewings
forfeits
fratches
gardened
gentile
glumpish
glyph
goatherd
grow
gulden
gumming
hackling
hanapers
hared
hatters
hectare
hedger
heel
heterodox
hidden
histologic
howe
inglobe
inliers
inuredness
iotacism
japed
jelled
jiffy
jollies
judgeship
karite
kart
kenophobia
kittens
lactarian
lancets
leasable
leep
leming
licorice
listing
lividly
lobectomy
lysosome
madders
maderizing
manacle
mangels
marshiest
maulstick
meliorates
mercy
mikados
monarchise
moultings
mucro
munnions
mystic
myxoedemic
nointing
nong
nonsense
ochidore
octuor
officering
opaqued
oragious
outtell
oxeye
pads
palamae
pansophy
parazoa
pepsines
perimetric
pheasant
phonotypy
pitarah
plaintful
poinders
poke
politer
poonces
populism
pouty
praedial
presence
prompter
pummelled
punishing
quippish
radicality
radiuses
rebuffing
recorded
redips
regulators
replay
retrocedes
rigors
risen
rootstocks
rotenone
rudenesses
ruggedest
runabout
ruthfully
sagacious
scapes
sclera
sclerotium
scumbering
secondi
serial
shampoo
showed
sights
sirenised
sized
slave
socle
solidness
some
spetches
spiels
squiring
staminode
stay
stewpot
stunsails
subhumid
subprogram
supawn
surplusage
swimming
swineherd
tabun
talliths
taroks
tensed
thinnings
three
tipper
toko
tomahawks
tombolos
torpefy
torulae
touns
travails
tsarist
unbeseems
unblamably
unbooked
unnailed
updates
valorise
viability
virtue
vulturns
vulvate
warran
weakness
westernise
whingeings
wrenching
written
yak
yate
yaupon
zendiks