From f82321ee0c7e390a9828a604c3acb61db1ddffe0 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Fri, 26 Apr 2019 15:31:40 +0400 Subject: [PATCH] FS-11816: [Build-System] Update libsrtp to 2.2.0 --- libs/srtp/.clang-format | 79 + libs/srtp/.gitignore | 50 + libs/srtp/.travis.yml | 131 + libs/srtp/.update | 2 +- libs/srtp/CHANGES | 62 +- libs/srtp/COPYING | 35 - libs/srtp/INSTALL | 236 - libs/srtp/Makefile.am | 5 +- libs/srtp/README.md | 27 + libs/srtp/TODO | 66 - libs/srtp/VERSION | 1 - libs/srtp/acsite.m4 | 6 - libs/srtp/config.hw | 1 - libs/srtp/config.hw.orig | 182 - libs/srtp/configure.ac | 2 +- libs/srtp/crypto/Makefile.in | 29 +- libs/srtp/crypto/cipher/aes.c | 573 +- libs/srtp/crypto/cipher/aes_gcm_ossl.c | 133 +- libs/srtp/crypto/cipher/aes_icm.c | 203 +- libs/srtp/crypto/cipher/aes_icm_ossl.c | 226 +- libs/srtp/crypto/cipher/cipher.c | 280 +- libs/srtp/crypto/cipher/null_cipher.c | 73 +- libs/srtp/crypto/hash/auth.c | 41 +- libs/srtp/crypto/hash/hmac.c | 89 +- libs/srtp/crypto/hash/hmac_ossl.c | 103 +- libs/srtp/crypto/hash/null_auth.c | 82 +- libs/srtp/crypto/hash/sha1.c | 202 +- libs/srtp/crypto/include/aes.h | 6 +- libs/srtp/crypto/include/aes_gcm_ossl.h | 3 +- libs/srtp/crypto/include/aes_icm.h | 13 +- libs/srtp/crypto/include/aes_icm_ossl.h | 7 +- libs/srtp/crypto/include/alloc.h | 31 +- libs/srtp/crypto/include/auth.h | 71 +- libs/srtp/crypto/include/cipher.h | 126 +- .../include/cipher_types.h} | 79 +- libs/srtp/crypto/include/crypto_kernel.h | 43 +- libs/srtp/crypto/include/crypto_types.h | 52 +- libs/srtp/crypto/include/datatypes.h | 391 +- libs/srtp/crypto/include/err.h | 30 +- libs/srtp/crypto/include/integers.h | 90 +- libs/srtp/crypto/include/key.h | 8 +- libs/srtp/crypto/include/null_cipher.h | 1 - libs/srtp/crypto/include/rdb.h | 22 +- libs/srtp/crypto/include/rdbx.h | 44 +- libs/srtp/crypto/include/sha1.h | 33 +- libs/srtp/crypto/include/stat.h | 19 +- libs/srtp/crypto/kernel/alloc.c | 60 +- libs/srtp/crypto/kernel/crypto_kernel.c | 168 +- libs/srtp/crypto/kernel/err.c | 18 +- libs/srtp/crypto/kernel/key.c | 20 +- libs/srtp/crypto/math/datatypes.c | 708 +- libs/srtp/crypto/math/stat.c | 285 +- libs/srtp/crypto/replay/rdb.c | 24 +- libs/srtp/crypto/replay/rdbx.c | 110 +- libs/srtp/crypto/replay/ut_sim.c | 87 +- libs/srtp/crypto/test/aes_calc.c | 183 +- libs/srtp/crypto/test/cipher_driver.c | 755 +- libs/srtp/crypto/test/datatypes_driver.c | 272 +- libs/srtp/crypto/test/env.c | 50 +- libs/srtp/crypto/test/kernel_driver.c | 136 +- libs/srtp/crypto/test/sha1_driver.c | 767 +- libs/srtp/crypto/test/stat_driver.c | 347 +- libs/srtp/doc/libsrtp.pdf | Bin 234575 -> 0 bytes libs/srtp/format.sh | 35 + libs/srtp/include/ekt.h | 99 +- libs/srtp/include/getopt_s.h | 23 +- libs/srtp/include/rtp.h | 139 - libs/srtp/include/srtp.h | 828 +-- libs/srtp/include/srtp_priv.h | 190 +- libs/srtp/include/ut_sim.h | 30 +- libs/srtp/libsrtp.2017.vcxproj | 1 + libs/srtp/srtp-1.42.pc.in | 10 - libs/srtp/srtp/ekt.c | 311 +- libs/srtp/srtp/srtp.c | 6491 +++++++++-------- libs/srtp/srtp2.vcxproj | 3 +- libs/srtp/srtp2.vcxproj.filters | 5 +- libs/srtp/test/cutest.h | 432 +- libs/srtp/test/dtls_srtp_driver.c | 356 +- libs/srtp/test/getopt_s.c | 112 +- libs/srtp/test/rdbx_driver.c | 491 +- libs/srtp/test/replay_driver.c | 383 +- libs/srtp/test/roc_driver.c | 197 +- libs/srtp/test/rtp.c | 268 +- libs/srtp/test/rtp.h | 118 +- libs/srtp/test/rtp_decoder.c | 835 ++- libs/srtp/test/rtp_decoder.h | 39 +- libs/srtp/test/rtpw.c | 1105 +-- libs/srtp/test/srtp_driver.c | 2427 +++--- libs/srtp/test/test_srtp.c | 22 +- libs/srtp/test/util.c | 91 +- libs/srtp/test/util.h | 2 +- w32/Library/FreeSwitchCore.2017.vcxproj | 1 + w32/openssl.props | 2 +- 93 files changed, 11420 insertions(+), 11604 deletions(-) create mode 100644 libs/srtp/.clang-format create mode 100644 libs/srtp/.gitignore create mode 100644 libs/srtp/.travis.yml delete mode 100644 libs/srtp/COPYING delete mode 100644 libs/srtp/INSTALL delete mode 100644 libs/srtp/TODO delete mode 100644 libs/srtp/VERSION delete mode 100644 libs/srtp/acsite.m4 delete mode 100644 libs/srtp/config.hw.orig rename libs/srtp/{include/rtp_priv.h => crypto/include/cipher_types.h} (57%) delete mode 100644 libs/srtp/doc/libsrtp.pdf create mode 100644 libs/srtp/format.sh delete mode 100644 libs/srtp/include/rtp.h delete mode 100644 libs/srtp/srtp-1.42.pc.in diff --git a/libs/srtp/.clang-format b/libs/srtp/.clang-format new file mode 100644 index 0000000000..358e22272c --- /dev/null +++ b/libs/srtp/.clang-format @@ -0,0 +1,79 @@ +AccessModifierOffset: -4 + +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true + +AllowAllParametersOfDeclarationOnNextLine: false + +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false + +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false + +BinPackArguments: true +BinPackParameters: false +BraceWrapping: + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true + +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +ContinuationIndentWidth: 4 +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false + +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false + +KeepEmptyLinesAtTheStartOfBlocks: false + +MaxEmptyLinesToKeep: 1 + +PenaltyBreakBeforeFirstCallParameter: 16 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000 +PenaltyReturnTypeOnItsOwnLine: 9000 + +Cpp11BracedListStyle: false + +PointerAlignment: Right + +ReflowComments: true + +SortIncludes: false + +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Never diff --git a/libs/srtp/.gitignore b/libs/srtp/.gitignore new file mode 100644 index 0000000000..a5ccf852db --- /dev/null +++ b/libs/srtp/.gitignore @@ -0,0 +1,50 @@ +# Misc crap +*~ +old +old? +*.pc + +# Object files +*.o + +# Libraries +*.lib +*.a + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app + +# srtp things +Debug +Makefile +Root +autom4te.cache +config.log +config.status +crypto/include/config.h +crypto/test/aes_calc +crypto/test/cipher_driver +crypto/test/datatypes_driver +crypto/test/env +crypto/test/kernel_driver +crypto/test/rand_gen +crypto/test/sha1_driver +crypto/test/stat_driver +crypto/test/rand_gen_soak +tables/aes_tables +test/dtls_srtp_driver +test/rdbx_driver +test/replay_driver +test/roc_driver +test/rtp_decoder +test/rtpw +test/srtp_driver +test/test_srtp diff --git a/libs/srtp/.travis.yml b/libs/srtp/.travis.yml new file mode 100644 index 0000000000..e0a7983de2 --- /dev/null +++ b/libs/srtp/.travis.yml @@ -0,0 +1,131 @@ +dist: trusty +sudo: false +language: c + +env: + global: + - secure: "QD09MuUxftXRXtz7ZrB7S0NV/3O9yVhjvIlCSbXN8B87rNSDC8wxMThKMT7iZewnqGk53m+Up19PiMw5ERlHose5tm2cmY1FO/l+c9oAyWZaAL+4XNXryq6zI5F5FX5I61NbfqV3xcnfLTI2QIJF6WqDojNxhPjTbNzQGxIDuqw=" + +matrix: + include: + + # default linux build with gcc + - os: linux + env: + - TEST="linux gcc" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-6 + script: + - CC=gcc-6 EXTRA_CFLAGS=-Werror ./configure + - make + - make runtest + + # linux build with openssl and gcc + - os: linux + env: + - TEST="linux gcc (openssl)" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-6 + script: + - CC=gcc-6 EXTRA_CFLAGS=-Werror ./configure --enable-openssl + - make + - make runtest + + # linux build with openssl and clang + - os: linux + env: + - TEST="linux clang (openssl)" + addons: + apt: + packages: + - clang + script: + - CC=clang EXTRA_CFLAGS=-Werror ./configure --enable-openssl + - make + - make runtest + + # default osx build with xcode (clang) + - os: osx + env: + - TEST="osx XCode 8.2" + osx_image: xcode8.2 + script: + - EXTRA_CFLAGS=-Werror ./configure + - make + - make runtest + + # code format check + - os: linux + env: + - TEST="clang-format" + addons: + apt: + packages: + - clang-format-3.9 + script: + - CLANG_FORMAT=clang-format-3.9 ./format.sh -d + + # valgrind + - os: linux + env: + - TEST="valgrind (openssl)" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-6 + - valgrind + script: + - CC=gcc-6 ./configure --enable-openssl + - make + - make runtest-valgrind + + # big-endian + - os: linux + sudo: true + env: + - TEST="big-endian" + services: + - docker + addons: + apt: + packages: + - qemu-user-static + - qemu-system-mips + before_install: + - sudo docker run --volume $(pwd):/src --workdir /src --name mipsX --tty --detach ubuntu:16.04 tail + - sudo docker exec --tty mipsX apt-get update + - sudo docker exec --tty mipsX apt-get install build-essential -y + - sudo docker exec --tty mipsX apt-get install gcc-mips-linux-gnu -y + script: + - sudo docker exec --tty mipsX bash -c 'EXTRA_CFLAGS=-static CC=mips-linux-gnu-gcc ./configure --host=mips-linux-gnu' + - sudo docker exec --tty mipsX make + - sudo docker kill mipsX + - file test/srtp_driver + - make runtest + + # coverity scan + - os: linux + env: + - TEST="Coverity Scan" + addons: + coverity_scan: + project: + name: "cisco-libSRTP" + description: "Build submitted via Travis CI" + version: 2 + notification_email: pabuhler@cisco.com + build_command_prepend: "./configure" + build_command: "make" + branch_pattern: master + script: + - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- diff --git a/libs/srtp/.update b/libs/srtp/.update index 7f2b55f7ef..c6e9146e26 100644 --- a/libs/srtp/.update +++ b/libs/srtp/.update @@ -1 +1 @@ -Wed Apr 9 03:14:42 CDT 2014 +Fri Apr 26 00:00:02 CDT 2019 diff --git a/libs/srtp/CHANGES b/libs/srtp/CHANGES index a323af1965..caa2b61139 100644 --- a/libs/srtp/CHANGES +++ b/libs/srtp/CHANGES @@ -1,5 +1,65 @@ Changelog +2.2.0-pre (This version) + +Major changes + +All code has been reformatted to be consistent. A .clang-format file and format.sh script has been added that can be use to verify and enforce consistent formatting. An automated check on code formatting is now part of travis build. + +Other changes + +PR #409 - Compatibilty with LibreSSL + +PR #406 - Fix unprotect when pktlen < (2*mki_size + tag_len) + +PR #405 - Prevent potential double free + +PR #404 - Add back extern to global variables + +PR #403 - Set gcm IV directly with EVP_CipherInit_ex + +PR #401 - Fix memory access issue in srtp_get_session_keys() + +PR #398 - Fix memory access fixes when invalid profiles where used + +PR #391 - Return NULL when allocating memory of size zero + +PR #390 - Bitvector of length zero is not valid + +PR #385 - Treat warnings as errors on travis builds + +PR #388 - Moved externs from crypto_kernel into its own header + +PR #379 - Fixed several compiler warnings from Firefox builds + +PR #377 - Removed variable init code in rdbx which never gets used + +PR #381 - Added error in case the platform is not detected + +PR #376 - Add coverity scan to travis builds + +PR #374 - Add a big endian build on travis + +PR #373 - Fixed buffer size issue in test/srtp_driver.c + +PR #372 - Make rtp_decoder compile on MinGW + +PR #367 - Rename configure.in to configure.ac + +PR #365 - Replace calls to free() with srtp_crypto_free() + +PR #364 - Add valgrind to travis and fix leaks in tests + +PR #363 - Change smtp_crypto_alloc to initialize memory to zero + +PR #354 - Fix potential leak if cloning of stream fails + +PR #340 - Fix potential leak in srtp_add_stream() + +PR #323 - Fix running test in out of source builds + +Issue #316 - Remove VERSION file + 2.1.0 Compatibility changes @@ -164,4 +224,4 @@ Other changes PR #302 - Fix warning regarding unused variable - PR #303 - Makefile.in: Add gnu as match for shared lib suffix \ No newline at end of file + PR #303 - Makefile.in: Add gnu as match for shared lib suffix diff --git a/libs/srtp/COPYING b/libs/srtp/COPYING deleted file mode 100644 index d1ff4e8559..0000000000 --- a/libs/srtp/COPYING +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * Copyright (c) 2001-2005 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. - * - */ diff --git a/libs/srtp/INSTALL b/libs/srtp/INSTALL deleted file mode 100644 index 23e5f25d0e..0000000000 --- a/libs/srtp/INSTALL +++ /dev/null @@ -1,236 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free -Software Foundation, Inc. - -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - -These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. (Caching is -disabled by default to prevent problems with accidental use of stale -cache files.) - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You only need -`configure.ac' if you want to change it or regenerate `configure' using -a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes awhile. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - -You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not support the `VPATH' -variable, you have to compile the package for one architecture at a -time in the source code directory. After you have installed the -package for one architecture, use `make distclean' before reconfiguring -for another architecture. - -Installation Names -================== - -By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - -Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). Here is a another example: - - /bin/bash ./configure CONFIG_SHELL=/bin/bash - -Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent -configuration-related scripts to be executed by `/bin/bash'. - -`configure' Invocation -====================== - -`configure' recognizes the following options to control how it operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/libs/srtp/Makefile.am b/libs/srtp/Makefile.am index fc34a04ad3..caff627c76 100644 --- a/libs/srtp/Makefile.am +++ b/libs/srtp/Makefile.am @@ -34,7 +34,8 @@ libsrtp_la_SOURCES += gdoi/srtp+gdoi.c endif library_includedir = $(prefix)/include/srtp -library_include_HEADERS = include/rtp.h include/srtp.h include/ut_sim.h crypto/include/auth.h \ +library_include_HEADERS = include/srtp.h include/ut_sim.h crypto/include/auth.h \ + crypto/include/cipher_types.h \ crypto/include/datatypes.h crypto/include/integers.h crypto/include/null_cipher.h \ crypto/include/rdbx.h crypto/include/aes_icm.h crypto/include/cipher.h crypto/include/crypto_types.h \ crypto/include/err.h crypto/include/sha1.h \ @@ -43,4 +44,4 @@ library_include_HEADERS = include/rtp.h include/srtp.h include/ut_sim.h crypto/i crypto/include/hmac.h crypto/include/null_auth.h crypto/include/rdb.h pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = srtp-1.42.pc +pkgconfig_DATA = libsrtp2.pc diff --git a/libs/srtp/README.md b/libs/srtp/README.md index b63267ac50..3f1e5bbfde 100644 --- a/libs/srtp/README.md +++ b/libs/srtp/README.md @@ -1,3 +1,6 @@ +[![Build Status](https://travis-ci.org/cisco/libsrtp.svg?branch=master)](https://travis-ci.org/cisco/libsrtp) +[![Coverity Scan Build Status](https://scan.coverity.com/projects/14274/badge.svg)](https://scan.coverity.com/projects/cisco-libsrtp) + # Introduction to libSRTP @@ -51,6 +54,7 @@ because it does its work behind the scenes. - [Supported Features](#supported-features) - [Implementation Notes](#implementation-notes) - [Installing and Building libSRTP](#installing-and-building-libsrtp) + - [Changing Build Configuration](#changing-build-configuration) - [Applications](#applications) - [Example Code](#example-code) - [Credits](#credits) @@ -291,6 +295,26 @@ OpenBSD (sparc-unknown-openbsd2.7). -------------------------------------------------------------------------------- + +## Changing Build Configuration + +To build the `./configure` script mentioned above, libSRTP relies on the +[automake](https://www.gnu.org/software/automake/) toolchain. Since +`./configure` is built from `configure.in` by automake, if you make changes in +how `./configure` works (e.g., to add a new library dependency), you will need +to rebuild `./configure` and commit the updated version. In addition to +automake itself, you will need to have the `pkgconfig` tools installed as well. + +For example, on macOS: + +``` +brew install automake pkgconfig +# Edit configure.in +autoremake -ivf +``` + +-------------------------------------------------------------------------------- + # Applications @@ -397,6 +421,9 @@ uint8_t key[30] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // initialize libSRTP srtp_init(); +// default policy values +memset(&policy, 0x0, sizeof(srtp_policy_t)); + // set policy to describe a policy for an SRTP stream crypto_policy_set_rtp_default(&policy.rtp); crypto_policy_set_rtcp_default(&policy.rtcp); diff --git a/libs/srtp/TODO b/libs/srtp/TODO deleted file mode 100644 index 18846e8ad0..0000000000 --- a/libs/srtp/TODO +++ /dev/null @@ -1,66 +0,0 @@ -TODO List - -1.4.1 - - - document which fields are in NBO/HBO, and check for consistency. - - - move HAVE_U_LONG_LONG inside of datatypes.c, or some other - separate file - - - re-write configure.in to make cross-compilation easier - - - eliminate GENERIC_AESICM by generalizing the code a bit - -Older comments - - - add tests for key_limit_t datatype - - - move octet_get_weight() from datatypes.c to math.c (any other - funcs?) - -Changes and additions planned - - Make cipher and auth dealloc() functions zeroize the key-storage - areas before calling free(). - - Eliminate key_len from auth_init() - - Doucument internal APIs (cipher, auth, srtp_protect, ...) - - -SRTP options not (yet) included in this libaray: - - - the aes-f8-mode cipher - - the Master Key Index - - re-keying using the key derivation function (only the initial - use of the PRF has been implemented, as it's sufficient - for most uses) - - -(OLD) PLANNED CHANGES - - strip out test/lfsr.c - - Write new documentation!!! - - Fix the x86 assembly code in aes.c. - - Eliminate /* DAM */ - there's one in srtp.c - - Change debugging so that it can print more than one line. Or perhaps - just change it so that a single check of the debug-enabled flag is - needed. - - Improve interface between cipher and rdbx - perhaps generalize rdbx - into 'nonce' datatype. - - Make rijndael_icm accept variable sized keys. - - Add rdbx functions that allow different-sized explicit sequence - numbers to be used. - - Write uniform byte-buffering code for PRFs, preferably as macros. - - Consider eliminating low-level alloc functions in favor of len() - functions, so that there need not be multiple allocations within a - particular alloc() function. diff --git a/libs/srtp/VERSION b/libs/srtp/VERSION deleted file mode 100644 index 44e5be2f08..0000000000 --- a/libs/srtp/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.1.0-pre diff --git a/libs/srtp/acsite.m4 b/libs/srtp/acsite.m4 deleted file mode 100644 index 80f8cf4138..0000000000 --- a/libs/srtp/acsite.m4 +++ /dev/null @@ -1,6 +0,0 @@ -m4_include([build/config/ax_compiler_vendor.m4]) -m4_include([build/config/ax_cflags_warn_all_ansi.m4]) -m4_include([build/config/ax_cc_maxopt.m4]) -m4_include([build/config/ax_check_compiler_flags.m4]) -m4_include([build/config/ac_gcc_archflag.m4]) -m4_include([build/config/ac_gcc_x86_cpuid.m4]) diff --git a/libs/srtp/config.hw b/libs/srtp/config.hw index 33ad189fb3..44dba2a2d5 100644 --- a/libs/srtp/config.hw +++ b/libs/srtp/config.hw @@ -181,5 +181,4 @@ typedef __int64 int64_t; #ifdef _MSC_VER #pragma warning(disable:4311) -#define OPENSSL #endif diff --git a/libs/srtp/config.hw.orig b/libs/srtp/config.hw.orig deleted file mode 100644 index 6fc65df677..0000000000 --- a/libs/srtp/config.hw.orig +++ /dev/null @@ -1,182 +0,0 @@ -/* crypto/include/config.h. Generated by configure. */ -/* config_in.h. Generated from configure.in by autoheader. */ - -#if (_MSC_VER >= 1400) -# define HAVE_RAND_S 1 -# define _CRT_RAND_S -#endif - -/* Define if building for a CISC machine (e.g. Intel). */ -#define CPU_CISC 1 - -/* Define if building for a RISC machine (assume slow byte access). */ -/* #undef CPU_RISC */ - -/* Define to enabled debug logging for all mudules. */ -#undef ENABLE_DEBUG_LOGGING - -/* Logging statments will be writen to this file. */ -/* #undef ERR_REPORTING_FILE */ - -/* Define to redirect logging to stdout. */ -#undef ERR_REPORTING_STDOUT - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ARPA_INET_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_BYTESWAP_H */ - -/* Define to 1 if you have the `inet_aton' function. */ -/* #undef HAVE_INET_ATON */ - -/* Define to 1 if the system has the type `int16_t'. */ -#define HAVE_INT16_T 1 - -/* Define to 1 if the system has the type `int32_t'. */ -#define HAVE_INT32_T 1 - -/* Define to 1 if the system has the type `int8_t'. */ -#define HAVE_INT8_T 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_INTTYPES_H */ - -/* Define to 1 if you have the `socket' library (-lsocket). */ -/* #undef HAVE_LIBSOCKET */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_TYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_NETINET_IN_H */ - -/* Define to 1 if you have the `socket' function. */ -/* #undef HAVE_SOCKET */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_STDINT_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_INT_TYPES_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_UIO_H */ - -/* Define to 1 if the system has the type `uint16_t'. */ -#define HAVE_UINT16_T 1 - -/* Define to 1 if the system has the type `uint32_t'. */ -#define HAVE_UINT32_T 1 - -/* Define to 1 if the system has the type `uint64_t'. */ -#define HAVE_UINT64_T 1 - -/* Define to 1 if the system has the type `uint8_t'. */ -#define HAVE_UINT8_T 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_UNISTD_H */ - -/* Define to 1 if you have the `usleep' function. */ -/* #undef HAVE_USLEEP */ - -/* Define to 1 if you have the header file. */ -#define HAVE_WINDOWS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WINSOCK2_H 1 - -/* Define to use X86 inlined assembly code */ -/* #undef HAVE_X86 */ - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* The size of a `unsigned long', as computed by sizeof. */ -#define SIZEOF_UNSIGNED_LONG 4 - -/* The size of a `unsigned long long', as computed by sizeof. */ -#define SIZEOF_UNSIGNED_LONG_LONG 8 - -/* Define to use GDOI. */ -/* #undef SRTP_GDOI */ - -/* Define to compile for kernel contexts. */ -/* #undef SRTP_KERNEL */ - -/* Define to compile for Linux kernel context. */ -/* #undef SRTP_KERNEL_LINUX */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define 'inline' to nothing, since the MSVC compiler doesn't support it. */ -#define inline - -/* Define to `unsigned' if does not define. */ -/* #undef size_t */ - -#if (_MSC_VER >= 1400) // VC8+ -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif -#endif // VC8+ - -#ifndef uint32_t -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -#endif - -#ifdef _MSC_VER -#pragma warning(disable:4311) -#endif diff --git a/libs/srtp/configure.ac b/libs/srtp/configure.ac index 35803dac97..288d0e970a 100644 --- a/libs/srtp/configure.ac +++ b/libs/srtp/configure.ac @@ -333,7 +333,7 @@ AM_CONDITIONAL([GDOI],[test "SRTP_GDOI" = "1"]) AC_CONFIG_HEADERS(crypto/include/config.h:config_in.h) -AC_OUTPUT(Makefile crypto/Makefile doc/Makefile test/Makefile srtp-1.42.pc) +AC_OUTPUT(Makefile crypto/Makefile doc/Makefile test/Makefile libsrtp2.pc) # This is needed when building outside the source dir. AS_MKDIR_P(crypto/cipher) diff --git a/libs/srtp/crypto/Makefile.in b/libs/srtp/crypto/Makefile.in index c93d9b1672..faaa991a09 100644 --- a/libs/srtp/crypto/Makefile.in +++ b/libs/srtp/crypto/Makefile.in @@ -1,4 +1,4 @@ -# Makefile for libcryptomodule.a +# Makefile for crypto test suite # # David A. McGrew # Cisco Systems, Inc. @@ -9,14 +9,14 @@ top_builddir = @top_builddir@ VPATH = @srcdir@ CC = @CC@ -INCDIR = -Iinclude -I$(srcdir)/include +INCDIR = -Iinclude -I$(srcdir)/include -I$(top_srcdir)/include DEFS = @DEFS@ CPPFLAGS= @CPPFLAGS@ CFLAGS = @CFLAGS@ LIBS = @LIBS@ LDFLAGS = @LDFLAGS@ -L. -L.. COMPILE = $(CC) $(DEFS) $(INCDIR) $(CPPFLAGS) $(CFLAGS) -CRYPTOLIB = -lsrtp +CRYPTOLIB = -lsrtp2 RANLIB = @RANLIB@ @@ -37,16 +37,16 @@ endif .PHONY: dummy all runtest clean superclean -dummy : all runtest +dummy : all runtest -# test applications +# test applications ifneq (1, $(USE_OPENSSL)) AES_CALC = test/aes_calc$(EXE) endif testapp = test/cipher_driver$(EXE) test/datatypes_driver$(EXE) \ test/stat_driver$(EXE) test/sha1_driver$(EXE) \ - test/kernel_driver$(EXE) $(AES_CALC) test/rand_gen$(EXE) \ + test/kernel_driver$(EXE) $(AES_CALC) \ test/env$(EXE) # data values used to test the aes_calc application for AES-128 @@ -73,7 +73,6 @@ endif test/stat_driver$(EXE) >/dev/null test/sha1_driver$(EXE) -v >/dev/null test/kernel_driver$(EXE) -v >/dev/null - test/rand_gen$(EXE) -n 256 >/dev/null @echo "crypto test applications passed." @@ -82,16 +81,15 @@ endif %.o: %.c $(COMPILE) -c $< -o $@ -%$(EXE): %.c - $(COMPILE) $(LDFLAGS) $< -o $@ $(CRYPTOLIB) $(LIBS) +%$(EXE): %.c $(srcdir)/../test/getopt_s.c + $(COMPILE) $(LDFLAGS) $< $(srcdir)/../test/getopt_s.c -o $@ $(CRYPTOLIB) $(LIBS) all: $(testapp) # housekeeping functions clean: - rm -f libcryptomodule.a - rm -f $(testapp) *.o */*.o + rm -f $(testapp) *.o */*.o for a in * .* */*; do if [ -f "$$a~" ] ; then rm $$a~; fi; done; rm -f `find . -name "*.[ch]~*~"` rm -rf latex @@ -99,13 +97,4 @@ clean: superclean: clean rm -f *core TAGS ktrace.out - -# the target 'package' builds a compressed tar archive of the source code - -distname = crypto-$(shell cat VERSION) - -package: superclean - cd ..; tar cvzf $(distname).tgz crypto/ - - # EOF diff --git a/libs/srtp/crypto/cipher/aes.c b/libs/srtp/crypto/cipher/aes.c index a4d6bb630e..c9cd774201 100644 --- a/libs/srtp/crypto/cipher/aes.c +++ b/libs/srtp/crypto/cipher/aes.c @@ -44,7 +44,7 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "aes.h" @@ -63,7 +63,7 @@ */ #ifndef WORDS_BIGENDIAN - +/* clang-format off */ static const uint32_t T0[256] = { 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, @@ -130,7 +130,9 @@ static const uint32_t T0[256] = { 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t T1[256] = { 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, @@ -197,7 +199,9 @@ static const uint32_t T1[256] = { 0x414182c3, 0x999929b0, 0x2d2d5a77, 0xf0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t T2[256] = { 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, @@ -264,7 +268,9 @@ static const uint32_t T2[256] = { 0x4182c341, 0x9929b099, 0x2d5a772d, 0xf1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t T3[256] = { 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, @@ -331,7 +337,9 @@ static const uint32_t T3[256] = { 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U0[256] = { 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, @@ -398,7 +406,9 @@ static const uint32_t U0[256] = { 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U1[256] = { 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb, 0x459d1ff1, 0x58faacab, 0x3e34b93, @@ -465,7 +475,9 @@ static const uint32_t U1[256] = { 0x1a83971, 0xb30c08de, 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U2[256] = { 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b, 0x9d1ff145, 0xfaacab58, 0xe34b9303, @@ -532,7 +544,9 @@ static const uint32_t U2[256] = { 0xa8397101, 0xc08deb3, 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U3[256] = { 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, 0xacab58fa, 0x4b9303e3, @@ -599,9 +613,10 @@ static const uint32_t U3[256] = { 0x397101a8, 0x8deb30c, 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8, }; +/* clang-format on */ #else /* assume big endian */ - +/* clang-format off */ static const uint32_t T0[256] = { 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, @@ -668,7 +683,9 @@ static const uint32_t T0[256] = { 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t T1[256] = { 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0xdfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, @@ -735,7 +752,9 @@ static const uint32_t T1[256] = { 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t T2[256] = { 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, @@ -802,7 +821,9 @@ static const uint32_t T2[256] = { 0x41c38241, 0x99b02999, 0x2d775a2d, 0xf111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t T3[256] = { 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, @@ -869,7 +890,9 @@ static const uint32_t T3[256] = { 0x4141c382, 0x9999b029, 0x2d2d775a, 0xf0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U0[256] = { 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, @@ -936,7 +959,9 @@ static const uint32_t U0[256] = { 0x39a80171, 0x80cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U1[256] = { 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, @@ -1003,7 +1028,9 @@ static const uint32_t U1[256] = { 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857 }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U2[256] = { 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x3934be3, @@ -1070,7 +1097,9 @@ static const uint32_t U2[256] = { 0x17139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8 }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U3[256] = { 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, @@ -1137,16 +1166,15 @@ static const uint32_t U3[256] = { 0xa8017139, 0xcb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0 }; - +/* clang-format on */ #endif /* * the following tables (aes_sbox, aes_inv_sbox, T4, U4) are * endian-neutral */ - -static const uint8_t - aes_sbox[256] = { +/* clang-format off */ +static const uint8_t aes_sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, @@ -1180,10 +1208,11 @@ static const uint8_t 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; +/* clang-format on */ #ifndef CPU_RISC -static const uint8_t - aes_inv_sbox[256] = { +/* clang-format off */ +static const uint8_t aes_inv_sbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, @@ -1217,11 +1246,12 @@ static const uint8_t 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; +/* clang-format on */ #endif /* ! CPU_RISC */ #ifdef CPU_RISC -static const uint32_t - T4[256] = { +/* clang-format off */ +static const uint32_t T4[256] = { 0x63636363, 0x7c7c7c7c, 0x77777777, 0x7b7b7b7b, 0xf2f2f2f2, 0x6b6b6b6b, 0x6f6f6f6f, 0xc5c5c5c5, 0x30303030, 0x01010101, 0x67676767, 0x2b2b2b2b, @@ -1287,7 +1317,9 @@ static const uint32_t 0x41414141, 0x99999999, 0x2d2d2d2d, 0x0f0f0f0f, 0xb0b0b0b0, 0x54545454, 0xbbbbbbbb, 0x16161616 }; +/* clang-format on */ +/* clang-format off */ static const uint32_t U4[256] = { 0x52525252, 0x9090909, 0x6a6a6a6a, 0xd5d5d5d5, 0x30303030, 0x36363636, 0xa5a5a5a5, 0x38383838, @@ -1354,6 +1386,7 @@ static const uint32_t U4[256] = { 0xe1e1e1e1, 0x69696969, 0x14141414, 0x63636363, 0x55555555, 0x21212121, 0xc0c0c0c, 0x7d7d7d7d }; +/* clang-format on */ #endif /* CPU_RISC */ #define gf2_8_field_polynomial 0x1B @@ -1363,16 +1396,13 @@ static const uint32_t U4[256] = { * next gf2_8 value in the cyclic representation of that field. The * value z should be an uint8_t. */ -#define gf2_8_shift(z) (((z) & 128) ? \ - (((z) << 1) ^ gf2_8_field_polynomial) : ((z) << 1)) +#define gf2_8_shift(z) \ + (((z)&128) ? (((z) << 1) ^ gf2_8_field_polynomial) : ((z) << 1)) /* aes internals */ -extern srtp_debug_module_t srtp_mod_aes_icm; - -static void -aes_128_expand_encryption_key (const uint8_t *key, - srtp_aes_expanded_key_t *expanded_key) +static void aes_128_expand_encryption_key(const uint8_t *key, + srtp_aes_expanded_key_t *expanded_key) { int i; uint8_t rc; @@ -1391,14 +1421,17 @@ aes_128_expand_encryption_key (const uint8_t *key, /* loop over round keys */ for (i = 1; i < 11; i++) { - /* munge first word of round key */ - expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i - 1].v8[13]] ^ rc; - expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i - 1].v8[14]]; - expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i - 1].v8[15]]; - expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i - 1].v8[12]]; + expanded_key->round[i].v8[0] = + aes_sbox[expanded_key->round[i - 1].v8[13]] ^ rc; + expanded_key->round[i].v8[1] = + aes_sbox[expanded_key->round[i - 1].v8[14]]; + expanded_key->round[i].v8[2] = + aes_sbox[expanded_key->round[i - 1].v8[15]]; + expanded_key->round[i].v8[3] = + aes_sbox[expanded_key->round[i - 1].v8[12]]; - expanded_key->round[i].v32[0] ^= expanded_key->round[i - 1].v32[0]; + expanded_key->round[i].v32[0] ^= expanded_key->round[i - 1].v32[0]; /* set remaining 32 bit words to the exor of the one previous with * the one four words previous */ @@ -1419,13 +1452,11 @@ aes_128_expand_encryption_key (const uint8_t *key, /* modify round constant */ rc = gf2_8_shift(rc); - } } -static void -aes_256_expand_encryption_key (const unsigned char *key, - srtp_aes_expanded_key_t *expanded_key) +static void aes_256_expand_encryption_key(const unsigned char *key, + srtp_aes_expanded_key_t *expanded_key) { int i; uint8_t rc; @@ -1447,24 +1478,31 @@ aes_256_expand_encryption_key (const unsigned char *key, /* loop over rest of round keys */ for (i = 2; i < 15; i++) { - /* munge first word of round key */ if ((i & 1) == 0) { - expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i - 1].v8[13]] ^ rc; - expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i - 1].v8[14]]; - expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i - 1].v8[15]]; - expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i - 1].v8[12]]; + expanded_key->round[i].v8[0] = + aes_sbox[expanded_key->round[i - 1].v8[13]] ^ rc; + expanded_key->round[i].v8[1] = + aes_sbox[expanded_key->round[i - 1].v8[14]]; + expanded_key->round[i].v8[2] = + aes_sbox[expanded_key->round[i - 1].v8[15]]; + expanded_key->round[i].v8[3] = + aes_sbox[expanded_key->round[i - 1].v8[12]]; /* modify round constant */ rc = gf2_8_shift(rc); - }else { - expanded_key->round[i].v8[0] = aes_sbox[expanded_key->round[i - 1].v8[12]]; - expanded_key->round[i].v8[1] = aes_sbox[expanded_key->round[i - 1].v8[13]]; - expanded_key->round[i].v8[2] = aes_sbox[expanded_key->round[i - 1].v8[14]]; - expanded_key->round[i].v8[3] = aes_sbox[expanded_key->round[i - 1].v8[15]]; + } else { + expanded_key->round[i].v8[0] = + aes_sbox[expanded_key->round[i - 1].v8[12]]; + expanded_key->round[i].v8[1] = + aes_sbox[expanded_key->round[i - 1].v8[13]]; + expanded_key->round[i].v8[2] = + aes_sbox[expanded_key->round[i - 1].v8[14]]; + expanded_key->round[i].v8[3] = + aes_sbox[expanded_key->round[i - 1].v8[15]]; } - expanded_key->round[i].v32[0] ^= expanded_key->round[i - 2].v32[0]; + expanded_key->round[i].v32[0] ^= expanded_key->round[i - 2].v32[0]; /* set remaining 32 bit words to the exor of the one previous with * the one eight words previous */ @@ -1482,31 +1520,32 @@ aes_256_expand_encryption_key (const unsigned char *key, debug_print2(srtp_mod_aes_icm, "expanded key[%d]: %s", i, v128_hex_string(&expanded_key->round[i])); #endif - } } -srtp_err_status_t srtp_aes_expand_encryption_key (const uint8_t *key, - int key_len, - srtp_aes_expanded_key_t *expanded_key) +srtp_err_status_t srtp_aes_expand_encryption_key( + const uint8_t *key, + int key_len, + srtp_aes_expanded_key_t *expanded_key) { if (key_len == 16) { aes_128_expand_encryption_key(key, expanded_key); return srtp_err_status_ok; - }else if (key_len == 24) { + } else if (key_len == 24) { /* AES-192 not yet supported */ return srtp_err_status_bad_param; - }else if (key_len == 32) { + } else if (key_len == 32) { aes_256_expand_encryption_key(key, expanded_key); return srtp_err_status_ok; - }else { + } else { return srtp_err_status_bad_param; } } -srtp_err_status_t srtp_aes_expand_decryption_key (const uint8_t *key, - int key_len, - srtp_aes_expanded_key_t *expanded_key) +srtp_err_status_t srtp_aes_expand_decryption_key( + const uint8_t *key, + int key_len, + srtp_aes_expanded_key_t *expanded_key) { int i; srtp_err_status_t status; @@ -1521,7 +1560,8 @@ srtp_err_status_t srtp_aes_expand_decryption_key (const uint8_t *key, for (i = 0; i < num_rounds / 2; i++) { v128_t tmp; v128_copy(&tmp, &expanded_key->round[num_rounds - i]); - v128_copy(&expanded_key->round[num_rounds - i], &expanded_key->round[i]); + v128_copy(&expanded_key->round[num_rounds - i], + &expanded_key->round[i]); v128_copy(&expanded_key->round[i], &tmp); } @@ -1538,6 +1578,7 @@ srtp_err_status_t srtp_aes_expand_decryption_key (const uint8_t *key, uint32_t tmp; #ifdef WORDS_BIGENDIAN + /* clang-format off */ tmp = expanded_key->round[i].v32[0]; expanded_key->round[i].v32[0] = U0[T4[(tmp >> 24) ] & 0xff] ^ @@ -1593,31 +1634,32 @@ srtp_err_status_t srtp_aes_expand_decryption_key (const uint8_t *key, U2[T4[(tmp >> 16) & 0xff] & 0xff] ^ U1[T4[(tmp >> 8) & 0xff] & 0xff] ^ U0[T4[(tmp) & 0xff] & 0xff]; -#endif /* WORDS_BIGENDIAN */ +/* clang-format on */ +#endif /* WORDS_BIGENDIAN */ #else /* assume CPU_CISC */ uint32_t c0, c1, c2, c3; - c0 = U0[aes_sbox[expanded_key->round[i].v8[0]]] - ^ U1[aes_sbox[expanded_key->round[i].v8[1]]] - ^ U2[aes_sbox[expanded_key->round[i].v8[2]]] - ^ U3[aes_sbox[expanded_key->round[i].v8[3]]]; + c0 = U0[aes_sbox[expanded_key->round[i].v8[0]]] ^ + U1[aes_sbox[expanded_key->round[i].v8[1]]] ^ + U2[aes_sbox[expanded_key->round[i].v8[2]]] ^ + U3[aes_sbox[expanded_key->round[i].v8[3]]]; - c1 = U0[aes_sbox[expanded_key->round[i].v8[4]]] - ^ U1[aes_sbox[expanded_key->round[i].v8[5]]] - ^ U2[aes_sbox[expanded_key->round[i].v8[6]]] - ^ U3[aes_sbox[expanded_key->round[i].v8[7]]]; + c1 = U0[aes_sbox[expanded_key->round[i].v8[4]]] ^ + U1[aes_sbox[expanded_key->round[i].v8[5]]] ^ + U2[aes_sbox[expanded_key->round[i].v8[6]]] ^ + U3[aes_sbox[expanded_key->round[i].v8[7]]]; - c2 = U0[aes_sbox[expanded_key->round[i].v8[8]]] - ^ U1[aes_sbox[expanded_key->round[i].v8[9]]] - ^ U2[aes_sbox[expanded_key->round[i].v8[10]]] - ^ U3[aes_sbox[expanded_key->round[i].v8[11]]]; + c2 = U0[aes_sbox[expanded_key->round[i].v8[8]]] ^ + U1[aes_sbox[expanded_key->round[i].v8[9]]] ^ + U2[aes_sbox[expanded_key->round[i].v8[10]]] ^ + U3[aes_sbox[expanded_key->round[i].v8[11]]]; - c3 = U0[aes_sbox[expanded_key->round[i].v8[12]]] - ^ U1[aes_sbox[expanded_key->round[i].v8[13]]] - ^ U2[aes_sbox[expanded_key->round[i].v8[14]]] - ^ U3[aes_sbox[expanded_key->round[i].v8[15]]]; + c3 = U0[aes_sbox[expanded_key->round[i].v8[12]]] ^ + U1[aes_sbox[expanded_key->round[i].v8[13]]] ^ + U2[aes_sbox[expanded_key->round[i].v8[14]]] ^ + U3[aes_sbox[expanded_key->round[i].v8[15]]]; expanded_key->round[i].v32[0] = c0; expanded_key->round[i].v32[1] = c1; @@ -1632,61 +1674,57 @@ srtp_err_status_t srtp_aes_expand_decryption_key (const uint8_t *key, #ifdef CPU_CISC - -static inline void aes_round (v128_t *state, const v128_t *round_key) +static inline void aes_round(v128_t *state, const v128_t *round_key) { uint32_t column0, column1, column2, column3; /* compute the columns of the output square in terms of the octets of state, using the tables T0, T1, T2, T3 */ - column0 = T0[state->v8[0]] ^ T1[state->v8[5]] - ^ T2[state->v8[10]] ^ T3[state->v8[15]]; + column0 = T0[state->v8[0]] ^ T1[state->v8[5]] ^ T2[state->v8[10]] ^ + T3[state->v8[15]]; - column1 = T0[state->v8[4]] ^ T1[state->v8[9]] - ^ T2[state->v8[14]] ^ T3[state->v8[3]]; + column1 = T0[state->v8[4]] ^ T1[state->v8[9]] ^ T2[state->v8[14]] ^ + T3[state->v8[3]]; - column2 = T0[state->v8[8]] ^ T1[state->v8[13]] - ^ T2[state->v8[2]] ^ T3[state->v8[7]]; + column2 = T0[state->v8[8]] ^ T1[state->v8[13]] ^ T2[state->v8[2]] ^ + T3[state->v8[7]]; - column3 = T0[state->v8[12]] ^ T1[state->v8[1]] - ^ T2[state->v8[6]] ^ T3[state->v8[11]]; + column3 = T0[state->v8[12]] ^ T1[state->v8[1]] ^ T2[state->v8[6]] ^ + T3[state->v8[11]]; state->v32[0] = column0 ^ round_key->v32[0]; state->v32[1] = column1 ^ round_key->v32[1]; state->v32[2] = column2 ^ round_key->v32[2]; state->v32[3] = column3 ^ round_key->v32[3]; - } - -static inline void aes_inv_round (v128_t *state, const v128_t *round_key) +static inline void aes_inv_round(v128_t *state, const v128_t *round_key) { uint32_t column0, column1, column2, column3; /* compute the columns of the output square in terms of the octets of state, using the tables U0, U1, U2, U3 */ - column0 = U0[state->v8[0]] ^ U1[state->v8[13]] - ^ U2[state->v8[10]] ^ U3[state->v8[7]]; + column0 = U0[state->v8[0]] ^ U1[state->v8[13]] ^ U2[state->v8[10]] ^ + U3[state->v8[7]]; - column1 = U0[state->v8[4]] ^ U1[state->v8[1]] - ^ U2[state->v8[14]] ^ U3[state->v8[11]]; + column1 = U0[state->v8[4]] ^ U1[state->v8[1]] ^ U2[state->v8[14]] ^ + U3[state->v8[11]]; - column2 = U0[state->v8[8]] ^ U1[state->v8[5]] - ^ U2[state->v8[2]] ^ U3[state->v8[15]]; + column2 = U0[state->v8[8]] ^ U1[state->v8[5]] ^ U2[state->v8[2]] ^ + U3[state->v8[15]]; - column3 = U0[state->v8[12]] ^ U1[state->v8[9]] - ^ U2[state->v8[6]] ^ U3[state->v8[3]]; + column3 = U0[state->v8[12]] ^ U1[state->v8[9]] ^ U2[state->v8[6]] ^ + U3[state->v8[3]]; state->v32[0] = column0 ^ round_key->v32[0]; state->v32[1] = column1 ^ round_key->v32[1]; state->v32[2] = column2 ^ round_key->v32[2]; state->v32[3] = column3 ^ round_key->v32[3]; - } -static inline void aes_final_round (v128_t *state, const v128_t *round_key) +static inline void aes_final_round(v128_t *state, const v128_t *round_key) { uint8_t tmp; @@ -1722,7 +1760,7 @@ static inline void aes_final_round (v128_t *state, const v128_t *round_key) v128_xor_eq(state, round_key); } -static inline void aes_inv_final_round (v128_t *state, const v128_t *round_key) +static inline void aes_inv_final_round(v128_t *state, const v128_t *round_key) { uint8_t tmp; @@ -1758,201 +1796,143 @@ static inline void aes_inv_final_round (v128_t *state, const v128_t *round_key) v128_xor_eq(state, round_key); } - #elif CPU_RISC -static inline void aes_round (v128_t *state, const v128_t *round_key) +static inline void aes_round(v128_t *state, const v128_t *round_key) { uint32_t column0, column1, column2, column3; - /* compute the columns of the output square in terms of the octets - of state, using the tables T0, T1, T2, T3 */ +/* compute the columns of the output square in terms of the octets + of state, using the tables T0, T1, T2, T3 */ #ifdef WORDS_BIGENDIAN - column0 = T0[state->v32[0] >> 24] ^ T1[(state->v32[1] >> 16) & 0xff] - ^ T2[(state->v32[2] >> 8) & 0xff] ^ T3[state->v32[3] & 0xff]; + column0 = T0[state->v32[0] >> 24] ^ T1[(state->v32[1] >> 16) & 0xff] ^ + T2[(state->v32[2] >> 8) & 0xff] ^ T3[state->v32[3] & 0xff]; - column1 = T0[state->v32[1] >> 24] ^ T1[(state->v32[2] >> 16) & 0xff] - ^ T2[(state->v32[3] >> 8) & 0xff] ^ T3[state->v32[0] & 0xff]; + column1 = T0[state->v32[1] >> 24] ^ T1[(state->v32[2] >> 16) & 0xff] ^ + T2[(state->v32[3] >> 8) & 0xff] ^ T3[state->v32[0] & 0xff]; - column2 = T0[state->v32[2] >> 24] ^ T1[(state->v32[3] >> 16) & 0xff] - ^ T2[(state->v32[0] >> 8) & 0xff] ^ T3[state->v32[1] & 0xff]; + column2 = T0[state->v32[2] >> 24] ^ T1[(state->v32[3] >> 16) & 0xff] ^ + T2[(state->v32[0] >> 8) & 0xff] ^ T3[state->v32[1] & 0xff]; - column3 = T0[state->v32[3] >> 24] ^ T1[(state->v32[0] >> 16) & 0xff] - ^ T2[(state->v32[1] >> 8) & 0xff] ^ T3[state->v32[2] & 0xff]; + column3 = T0[state->v32[3] >> 24] ^ T1[(state->v32[0] >> 16) & 0xff] ^ + T2[(state->v32[1] >> 8) & 0xff] ^ T3[state->v32[2] & 0xff]; #else - column0 = T0[state->v32[0] & 0xff] ^ T1[(state->v32[1] >> 8) & 0xff] - ^ T2[(state->v32[2] >> 16) & 0xff] ^ T3[state->v32[3] >> 24]; + column0 = T0[state->v32[0] & 0xff] ^ T1[(state->v32[1] >> 8) & 0xff] ^ + T2[(state->v32[2] >> 16) & 0xff] ^ T3[state->v32[3] >> 24]; - column1 = T0[state->v32[1] & 0xff] ^ T1[(state->v32[2] >> 8) & 0xff] - ^ T2[(state->v32[3] >> 16) & 0xff] ^ T3[state->v32[0] >> 24]; + column1 = T0[state->v32[1] & 0xff] ^ T1[(state->v32[2] >> 8) & 0xff] ^ + T2[(state->v32[3] >> 16) & 0xff] ^ T3[state->v32[0] >> 24]; - column2 = T0[state->v32[2] & 0xff] ^ T1[(state->v32[3] >> 8) & 0xff] - ^ T2[(state->v32[0] >> 16) & 0xff] ^ T3[state->v32[1] >> 24]; + column2 = T0[state->v32[2] & 0xff] ^ T1[(state->v32[3] >> 8) & 0xff] ^ + T2[(state->v32[0] >> 16) & 0xff] ^ T3[state->v32[1] >> 24]; - column3 = T0[state->v32[3] & 0xff] ^ T1[(state->v32[0] >> 8) & 0xff] - ^ T2[(state->v32[1] >> 16) & 0xff] ^ T3[state->v32[2] >> 24]; + column3 = T0[state->v32[3] & 0xff] ^ T1[(state->v32[0] >> 8) & 0xff] ^ + T2[(state->v32[1] >> 16) & 0xff] ^ T3[state->v32[2] >> 24]; #endif /* WORDS_BIGENDIAN */ state->v32[0] = column0 ^ round_key->v32[0]; state->v32[1] = column1 ^ round_key->v32[1]; state->v32[2] = column2 ^ round_key->v32[2]; state->v32[3] = column3 ^ round_key->v32[3]; - } -static inline void aes_inv_round (v128_t *state, const v128_t *round_key) +static inline void aes_inv_round(v128_t *state, const v128_t *round_key) { uint32_t column0, column1, column2, column3; - /* compute the columns of the output square in terms of the octets - of state, using the tables U0, U1, U2, U3 */ +/* compute the columns of the output square in terms of the octets + of state, using the tables U0, U1, U2, U3 */ #ifdef WORDS_BIGENDIAN - column0 = U0[state->v32[0] >> 24] ^ U1[(state->v32[3] >> 16) & 0xff] - ^ U2[(state->v32[2] >> 8) & 0xff] ^ U3[state->v32[1] & 0xff]; + column0 = U0[state->v32[0] >> 24] ^ U1[(state->v32[3] >> 16) & 0xff] ^ + U2[(state->v32[2] >> 8) & 0xff] ^ U3[state->v32[1] & 0xff]; - column1 = U0[state->v32[1] >> 24] ^ U1[(state->v32[0] >> 16) & 0xff] - ^ U2[(state->v32[3] >> 8) & 0xff] ^ U3[state->v32[2] & 0xff]; + column1 = U0[state->v32[1] >> 24] ^ U1[(state->v32[0] >> 16) & 0xff] ^ + U2[(state->v32[3] >> 8) & 0xff] ^ U3[state->v32[2] & 0xff]; - column2 = U0[state->v32[2] >> 24] ^ U1[(state->v32[1] >> 16) & 0xff] - ^ U2[(state->v32[0] >> 8) & 0xff] ^ U3[state->v32[3] & 0xff]; + column2 = U0[state->v32[2] >> 24] ^ U1[(state->v32[1] >> 16) & 0xff] ^ + U2[(state->v32[0] >> 8) & 0xff] ^ U3[state->v32[3] & 0xff]; - column3 = U0[state->v32[3] >> 24] ^ U1[(state->v32[2] >> 16) & 0xff] - ^ U2[(state->v32[1] >> 8) & 0xff] ^ U3[state->v32[0] & 0xff]; + column3 = U0[state->v32[3] >> 24] ^ U1[(state->v32[2] >> 16) & 0xff] ^ + U2[(state->v32[1] >> 8) & 0xff] ^ U3[state->v32[0] & 0xff]; #else - column0 = U0[state->v32[0] & 0xff] ^ U1[(state->v32[3] >> 8) & 0xff] - ^ U2[(state->v32[2] >> 16) & 0xff] ^ U3[(state->v32[1] >> 24) & 0xff]; + column0 = U0[state->v32[0] & 0xff] ^ U1[(state->v32[3] >> 8) & 0xff] ^ + U2[(state->v32[2] >> 16) & 0xff] ^ + U3[(state->v32[1] >> 24) & 0xff]; - column1 = U0[state->v32[1] & 0xff] ^ U1[(state->v32[0] >> 8) & 0xff] - ^ U2[(state->v32[3] >> 16) & 0xff] ^ U3[(state->v32[2] >> 24) & 0xff]; + column1 = U0[state->v32[1] & 0xff] ^ U1[(state->v32[0] >> 8) & 0xff] ^ + U2[(state->v32[3] >> 16) & 0xff] ^ + U3[(state->v32[2] >> 24) & 0xff]; - column2 = U0[state->v32[2] & 0xff] ^ U1[(state->v32[1] >> 8) & 0xff] - ^ U2[(state->v32[0] >> 16) & 0xff] ^ U3[(state->v32[3] >> 24) & 0xff]; + column2 = U0[state->v32[2] & 0xff] ^ U1[(state->v32[1] >> 8) & 0xff] ^ + U2[(state->v32[0] >> 16) & 0xff] ^ + U3[(state->v32[3] >> 24) & 0xff]; - column3 = U0[state->v32[3] & 0xff] ^ U1[(state->v32[2] >> 8) & 0xff] - ^ U2[(state->v32[1] >> 16) & 0xff] ^ U3[(state->v32[0] >> 24) & 0xff]; + column3 = U0[state->v32[3] & 0xff] ^ U1[(state->v32[2] >> 8) & 0xff] ^ + U2[(state->v32[1] >> 16) & 0xff] ^ + U3[(state->v32[0] >> 24) & 0xff]; #endif /* WORDS_BIGENDIAN */ state->v32[0] = column0 ^ round_key->v32[0]; state->v32[1] = column1 ^ round_key->v32[1]; state->v32[2] = column2 ^ round_key->v32[2]; state->v32[3] = column3 ^ round_key->v32[3]; - } -static inline void aes_final_round (v128_t *state, const v128_t *round_key) +static inline void aes_final_round(v128_t *state, const v128_t *round_key) { uint32_t tmp0, tmp1, tmp2, tmp3; #ifdef WORDS_BIGENDIAN - tmp0 = (T4[(state->v32[0] >> 24)] & 0xff000000) - ^ (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[3] ) & 0xff] & 0x000000ff) - ^ round_key->v32[0]; + /* clang-format off */ + tmp0 = (T4[(state->v32[0] >> 24)] & 0xff000000) ^ + (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[3] ) & 0xff] & 0x000000ff) ^ + round_key->v32[0]; - tmp1 = (T4[(state->v32[1] >> 24)] & 0xff000000) - ^ (T4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[0] ) & 0xff] & 0x000000ff) - ^ round_key->v32[1]; + tmp1 = (T4[(state->v32[1] >> 24)] & 0xff000000) ^ + (T4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[0] ) & 0xff] & 0x000000ff) ^ + round_key->v32[1]; - tmp2 = (T4[(state->v32[2] >> 24)] & 0xff000000) - ^ (T4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[1] ) & 0xff] & 0x000000ff) - ^ round_key->v32[2]; + tmp2 = (T4[(state->v32[2] >> 24)] & 0xff000000) ^ + (T4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[1] ) & 0xff] & 0x000000ff) ^ + round_key->v32[2]; - tmp3 = (T4[(state->v32[3] >> 24)] & 0xff000000) - ^ (T4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[2] ) & 0xff] & 0x000000ff) - ^ round_key->v32[3]; + tmp3 = (T4[(state->v32[3] >> 24)] & 0xff000000) ^ + (T4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[2] ) & 0xff] & 0x000000ff) ^ + round_key->v32[3]; #else - tmp0 = (T4[(state->v32[3] >> 24)] & 0xff000000) - ^ (T4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[0] ) & 0xff] & 0x000000ff) - ^ round_key->v32[0]; + tmp0 = (T4[(state->v32[3] >> 24)] & 0xff000000) ^ + (T4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[0] ) & 0xff] & 0x000000ff) ^ + round_key->v32[0]; - tmp1 = (T4[(state->v32[0] >> 24)] & 0xff000000) - ^ (T4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[1] ) & 0xff] & 0x000000ff) - ^ round_key->v32[1]; + tmp1 = (T4[(state->v32[0] >> 24)] & 0xff000000) ^ + (T4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[1] ) & 0xff] & 0x000000ff) ^ + round_key->v32[1]; - tmp2 = (T4[(state->v32[1] >> 24)] & 0xff000000) - ^ (T4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[2] ) & 0xff] & 0x000000ff) - ^ round_key->v32[2]; + tmp2 = (T4[(state->v32[1] >> 24)] & 0xff000000) ^ + (T4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[2] ) & 0xff] & 0x000000ff) ^ + round_key->v32[2]; - tmp3 = (T4[(state->v32[2] >> 24)] & 0xff000000) - ^ (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) - ^ (T4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) - ^ (T4[(state->v32[3] ) & 0xff] & 0x000000ff) - ^ round_key->v32[3]; -#endif /* WORDS_BIGENDIAN */ - - state->v32[0] = tmp0; - state->v32[1] = tmp1; - state->v32[2] = tmp2; - state->v32[3] = tmp3; - -} - -static inline void aes_inv_final_round (v128_t *state, const v128_t *round_key) -{ - uint32_t tmp0, tmp1, tmp2, tmp3; - -#ifdef WORDS_BIGENDIAN - tmp0 = (U4[(state->v32[0] >> 24)] & 0xff000000) - ^ (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[1] ) & 0xff] & 0x000000ff) - ^ round_key->v32[0]; - - tmp1 = (U4[(state->v32[1] >> 24)] & 0xff000000) - ^ (U4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[2] ) & 0xff] & 0x000000ff) - ^ round_key->v32[1]; - - tmp2 = (U4[(state->v32[2] >> 24)] & 0xff000000) - ^ (U4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[3] ) & 0xff] & 0x000000ff) - ^ round_key->v32[2]; - - tmp3 = (U4[(state->v32[3] >> 24)] & 0xff000000) - ^ (U4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[0] ) & 0xff] & 0x000000ff) - ^ round_key->v32[3]; -#else - tmp0 = (U4[(state->v32[1] >> 24)] & 0xff000000) - ^ (U4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[0] ) & 0xff] & 0x000000ff) - ^ round_key->v32[0]; - - tmp1 = (U4[(state->v32[2] >> 24)] & 0xff000000) - ^ (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[1] ) & 0xff] & 0x000000ff) - ^ round_key->v32[1]; - - tmp2 = (U4[(state->v32[3] >> 24)] & 0xff000000) - ^ (U4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[2] ) & 0xff] & 0x000000ff) - ^ round_key->v32[2]; - - tmp3 = (U4[(state->v32[0] >> 24)] & 0xff000000) - ^ (U4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) - ^ (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) - ^ (U4[(state->v32[3] ) & 0xff] & 0x000000ff) - ^ round_key->v32[3]; + tmp3 = (T4[(state->v32[2] >> 24)] & 0xff000000) ^ + (T4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) ^ + (T4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) ^ + (T4[(state->v32[3] ) & 0xff] & 0x000000ff) ^ + round_key->v32[3]; +/* clang-format on */ #endif /* WORDS_BIGENDIAN */ state->v32[0] = tmp0; @@ -1961,62 +1941,120 @@ static inline void aes_inv_final_round (v128_t *state, const v128_t *round_key) state->v32[3] = tmp3; } -#elif CPU_16 /* assume 16-bit word size on processor */ +static inline void aes_inv_final_round(v128_t *state, const v128_t *round_key) +{ + uint32_t tmp0, tmp1, tmp2, tmp3; -static inline void aes_round (v128_t *state, const v128_t *round_key) +#ifdef WORDS_BIGENDIAN + /* clang-format off */ + tmp0 = (U4[(state->v32[0] >> 24)] & 0xff000000) ^ + (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[1] ) & 0xff] & 0x000000ff) ^ + round_key->v32[0]; + + tmp1 = (U4[(state->v32[1] >> 24)] & 0xff000000) ^ + (U4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[2] ) & 0xff] & 0x000000ff) ^ + round_key->v32[1]; + + tmp2 = (U4[(state->v32[2] >> 24)] & 0xff000000) ^ + (U4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[3] ) & 0xff] & 0x000000ff) ^ + round_key->v32[2]; + + tmp3 = (U4[(state->v32[3] >> 24)] & 0xff000000) ^ + (U4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[0] ) & 0xff] & 0x000000ff) ^ + round_key->v32[3]; +#else + tmp0 = (U4[(state->v32[1] >> 24)] & 0xff000000) ^ + (U4[(state->v32[2] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[3] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[0] ) & 0xff] & 0x000000ff) ^ + round_key->v32[0]; + + tmp1 = (U4[(state->v32[2] >> 24)] & 0xff000000) ^ + (U4[(state->v32[3] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[0] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[1] ) & 0xff] & 0x000000ff) ^ + round_key->v32[1]; + + tmp2 = (U4[(state->v32[3] >> 24)] & 0xff000000) ^ + (U4[(state->v32[0] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[1] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[2] ) & 0xff] & 0x000000ff) ^ + round_key->v32[2]; + + tmp3 = (U4[(state->v32[0] >> 24)] & 0xff000000) ^ + (U4[(state->v32[1] >> 16) & 0xff] & 0x00ff0000) ^ + (U4[(state->v32[2] >> 8) & 0xff] & 0x0000ff00) ^ + (U4[(state->v32[3] ) & 0xff] & 0x000000ff) ^ + round_key->v32[3]; +/* clang-format on */ +#endif /* WORDS_BIGENDIAN */ + + state->v32[0] = tmp0; + state->v32[1] = tmp1; + state->v32[2] = tmp2; + state->v32[3] = tmp3; +} + +#elif CPU_16 /* assume 16-bit word size on processor */ + +static inline void aes_round(v128_t *state, const v128_t *round_key) { uint32_t column0, column1, column2, column3; - uint16_t c /* compute the columns of the output square in terms of the octets of state, using the tables T0, T1, T2, T3 */ - column0 = T0[state->v8[0]] ^ T1[state->v8[5]] - ^ T2[state->v8[10]] ^ T3[state->v8[15]]; + column0 = T0[state->v8[0]] ^ T1[state->v8[5]] ^ T2[state->v8[10]] ^ + T3[state->v8[15]]; - column1 = T0[state->v8[4]] ^ T1[state->v8[9]] - ^ T2[state->v8[14]] ^ T3[state->v8[3]]; + column1 = T0[state->v8[4]] ^ T1[state->v8[9]] ^ T2[state->v8[14]] ^ + T3[state->v8[3]]; - column2 = T0[state->v8[8]] ^ T1[state->v8[13]] - ^ T2[state->v8[2]] ^ T3[state->v8[7]]; + column2 = T0[state->v8[8]] ^ T1[state->v8[13]] ^ T2[state->v8[2]] ^ + T3[state->v8[7]]; - column3 = T0[state->v8[12]] ^ T1[state->v8[1]] - ^ T2[state->v8[6]] ^ T3[state->v8[11]]; + column3 = T0[state->v8[12]] ^ T1[state->v8[1]] ^ T2[state->v8[6]] ^ + T3[state->v8[11]]; state->v32[0] = column0 ^ round_key->v32[0]; state->v32[1] = column1 ^ round_key->v32[1]; state->v32[2] = column2 ^ round_key->v32[2]; state->v32[3] = column3 ^ round_key->v32[3]; - } - -static inline void aes_inv_round (v128_t *state, const v128_t *round_key) +static inline void aes_inv_round(v128_t *state, const v128_t *round_key) { uint32_t column0, column1, column2, column3; /* compute the columns of the output square in terms of the octets of state, using the tables U0, U1, U2, U3 */ - column0 = U0[state->v8[0]] ^ U1[state->v8[5]] - ^ U2[state->v8[10]] ^ U3[state->v8[15]]; + column0 = U0[state->v8[0]] ^ U1[state->v8[5]] ^ U2[state->v8[10]] ^ + U3[state->v8[15]]; - column1 = U0[state->v8[4]] ^ U1[state->v8[9]] - ^ U2[state->v8[14]] ^ U3[state->v8[3]]; + column1 = U0[state->v8[4]] ^ U1[state->v8[9]] ^ U2[state->v8[14]] ^ + U3[state->v8[3]]; - column2 = U0[state->v8[8]] ^ U1[state->v8[13]] - ^ U2[state->v8[2]] ^ U3[state->v8[7]]; + column2 = U0[state->v8[8]] ^ U1[state->v8[13]] ^ U2[state->v8[2]] ^ + U3[state->v8[7]]; - column3 = U0[state->v8[12]] ^ U1[state->v8[1]] - ^ U2[state->v8[6]] ^ U3[state->v8[11]]; + column3 = U0[state->v8[12]] ^ U1[state->v8[1]] ^ U2[state->v8[6]] ^ + U3[state->v8[11]]; state->v32[0] = column0 ^ round_key->v32[0]; state->v32[1] = column1 ^ round_key->v32[1]; state->v32[2] = column2 ^ round_key->v32[2]; state->v32[3] = column3 ^ round_key->v32[3]; - } -static inline void aes_final_round (v128_t *state, const v128_t *round_key) +static inline void aes_final_round(v128_t *state, const v128_t *round_key) { uint8_t tmp; @@ -2052,7 +2090,7 @@ static inline void aes_final_round (v128_t *state, const v128_t *round_key) v128_xor_eq(state, round_key); } -static inline void aes_inv_final_round (v128_t *state, const v128_t *round_key) +static inline void aes_inv_final_round(v128_t *state, const v128_t *round_key) { uint8_t tmp; @@ -2088,12 +2126,10 @@ static inline void aes_inv_final_round (v128_t *state, const v128_t *round_key) v128_xor_eq(state, round_key); } -#endif /* CPU type */ +#endif /* CPU type */ - -void srtp_aes_encrypt (v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key) +void srtp_aes_encrypt(v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key) { - /* add in the subkey */ v128_xor_eq(plaintext, &exp_key->round[0]); @@ -2109,11 +2145,11 @@ void srtp_aes_encrypt (v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key aes_round(plaintext, &exp_key->round[9]); if (exp_key->num_rounds == 10) { aes_final_round(plaintext, &exp_key->round[10]); - }else if (exp_key->num_rounds == 12) { + } else if (exp_key->num_rounds == 12) { aes_round(plaintext, &exp_key->round[10]); aes_round(plaintext, &exp_key->round[11]); aes_final_round(plaintext, &exp_key->round[12]); - }else if (exp_key->num_rounds == 14) { + } else if (exp_key->num_rounds == 14) { aes_round(plaintext, &exp_key->round[10]); aes_round(plaintext, &exp_key->round[11]); aes_round(plaintext, &exp_key->round[12]); @@ -2122,9 +2158,8 @@ void srtp_aes_encrypt (v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key } } -void srtp_aes_decrypt (v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key) +void srtp_aes_decrypt(v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key) { - /* add in the subkey */ v128_xor_eq(plaintext, &exp_key->round[0]); @@ -2140,11 +2175,11 @@ void srtp_aes_decrypt (v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key aes_inv_round(plaintext, &exp_key->round[9]); if (exp_key->num_rounds == 10) { aes_inv_final_round(plaintext, &exp_key->round[10]); - }else if (exp_key->num_rounds == 12) { + } else if (exp_key->num_rounds == 12) { aes_inv_round(plaintext, &exp_key->round[10]); aes_inv_round(plaintext, &exp_key->round[11]); aes_inv_final_round(plaintext, &exp_key->round[12]); - }else if (exp_key->num_rounds == 14) { + } else if (exp_key->num_rounds == 14) { aes_inv_round(plaintext, &exp_key->round[10]); aes_inv_round(plaintext, &exp_key->round[11]); aes_inv_round(plaintext, &exp_key->round[12]); diff --git a/libs/srtp/crypto/cipher/aes_gcm_ossl.c b/libs/srtp/crypto/cipher/aes_gcm_ossl.c index 416582aacc..ef13a78240 100644 --- a/libs/srtp/crypto/cipher/aes_gcm_ossl.c +++ b/libs/srtp/crypto/cipher/aes_gcm_ossl.c @@ -45,36 +45,28 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include #include "aes_icm_ossl.h" #include "aes_gcm_ossl.h" #include "alloc.h" -#include "err.h" /* for srtp_debug */ +#include "err.h" /* for srtp_debug */ #include "crypto_types.h" - +#include "cipher_types.h" srtp_debug_module_t srtp_mod_aes_gcm = { - 0, /* debugging is off by default */ - "aes gcm" /* printable module name */ + 0, /* debugging is off by default */ + "aes gcm" /* printable module name */ }; -/* - * The following are the global singleton instances for the - * 128-bit and 256-bit GCM ciphers. - */ -extern const srtp_cipher_type_t srtp_aes_gcm_128_openssl; -extern const srtp_cipher_type_t srtp_aes_gcm_256_openssl; - /* * For now we only support 8 and 16 octet tags. The spec allows for * optional 12 byte tag, which may be supported in the future. */ -#define GCM_AUTH_TAG_LEN 16 -#define GCM_AUTH_TAG_LEN_8 8 - +#define GCM_AUTH_TAG_LEN 16 +#define GCM_AUTH_TAG_LEN_8 8 /* * This function allocates a new instance of this crypto engine. @@ -83,11 +75,14 @@ extern const srtp_cipher_type_t srtp_aes_gcm_256_openssl; * key length includes the 14 byte salt value that is used when * initializing the KDF. */ -static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_len, int tlen) +static srtp_err_status_t srtp_aes_gcm_openssl_alloc(srtp_cipher_t **c, + int key_len, + int tlen) { srtp_aes_gcm_ctx_t *gcm; - debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d", key_len); + debug_print(srtp_mod_aes_gcm, "allocating cipher with key length %d", + key_len); debug_print(srtp_mod_aes_gcm, "allocating cipher with tag length %d", tlen); /* @@ -98,8 +93,7 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_ return (srtp_err_status_bad_param); } - if (tlen != GCM_AUTH_TAG_LEN && - tlen != GCM_AUTH_TAG_LEN_8) { + if (tlen != GCM_AUTH_TAG_LEN && tlen != GCM_AUTH_TAG_LEN_8) { return (srtp_err_status_bad_param); } @@ -108,15 +102,13 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_ if (*c == NULL) { return (srtp_err_status_alloc_fail); } - memset(*c, 0x0, sizeof(srtp_cipher_t)); gcm = (srtp_aes_gcm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_gcm_ctx_t)); if (gcm == NULL) { - srtp_crypto_free(*c); - *c = NULL; + srtp_crypto_free(*c); + *c = NULL; return (srtp_err_status_alloc_fail); } - memset(gcm, 0x0, sizeof(srtp_aes_gcm_ctx_t)); gcm->ctx = EVP_CIPHER_CTX_new(); if (gcm->ctx == NULL) { @@ -151,15 +143,14 @@ static srtp_err_status_t srtp_aes_gcm_openssl_alloc (srtp_cipher_t **c, int key_ return (srtp_err_status_ok); } - /* * This function deallocates a GCM session */ -static srtp_err_status_t srtp_aes_gcm_openssl_dealloc (srtp_cipher_t *c) +static srtp_err_status_t srtp_aes_gcm_openssl_dealloc(srtp_cipher_t *c) { srtp_aes_gcm_ctx_t *ctx; - ctx = (srtp_aes_gcm_ctx_t*)c->state; + ctx = (srtp_aes_gcm_ctx_t *)c->state; if (ctx) { EVP_CIPHER_CTX_free(ctx->ctx); /* zeroize the key material */ @@ -179,14 +170,16 @@ static srtp_err_status_t srtp_aes_gcm_openssl_dealloc (srtp_cipher_t *c) * * the key is the secret key */ -static srtp_err_status_t srtp_aes_gcm_openssl_context_init (void* cv, const uint8_t *key) +static srtp_err_status_t srtp_aes_gcm_openssl_context_init(void *cv, + const uint8_t *key) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; const EVP_CIPHER *evp; c->dir = srtp_direction_any; - debug_print(srtp_mod_aes_gcm, "key: %s", srtp_octet_string_hex_string(key, c->key_size)); + debug_print(srtp_mod_aes_gcm, "key: %s", + srtp_octet_string_hex_string(key, c->key_size)); switch (c->key_size) { case SRTP_AES_256_KEY_LEN: @@ -207,35 +200,32 @@ static srtp_err_status_t srtp_aes_gcm_openssl_context_init (void* cv, const uint return (srtp_err_status_ok); } - /* * aes_gcm_openssl_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ -static srtp_err_status_t srtp_aes_gcm_openssl_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t direction) +static srtp_err_status_t srtp_aes_gcm_openssl_set_iv( + void *cv, + uint8_t *iv, + srtp_cipher_direction_t direction) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; - if (direction != srtp_direction_encrypt && direction != srtp_direction_decrypt) { + if (direction != srtp_direction_encrypt && + direction != srtp_direction_decrypt) { return (srtp_err_status_bad_param); } c->dir = direction; - debug_print(srtp_mod_aes_gcm, "setting iv: %s", v128_hex_string((v128_t*)iv)); + debug_print(srtp_mod_aes_gcm, "setting iv: %s", + v128_hex_string((v128_t *)iv)); - if (!EVP_CipherInit_ex(c->ctx, NULL, NULL, NULL, - NULL, (c->dir == srtp_direction_encrypt ? 1 : 0))) { - return (srtp_err_status_init_fail); - } - - /* set IV len and the IV value, the followiong 3 calls are required */ if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0)) { return (srtp_err_status_init_fail); } - if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, (void*)iv)) { - return (srtp_err_status_init_fail); - } - if (!EVP_CIPHER_CTX_ctrl(c->ctx, EVP_CTRL_GCM_IV_GEN, 0, (void*)iv)) { + + if (!EVP_CipherInit_ex(c->ctx, NULL, NULL, NULL, iv, + (c->dir == srtp_direction_encrypt ? 1 : 0))) { return (srtp_err_status_init_fail); } @@ -250,7 +240,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_iv (void *cv, uint8_t *iv, srt * aad Additional data to process for AEAD cipher suites * aad_len length of aad buffer */ -static srtp_err_status_t srtp_aes_gcm_openssl_set_aad (void *cv, const uint8_t *aad, uint32_t aad_len) +static srtp_err_status_t srtp_aes_gcm_openssl_set_aad(void *cv, + const uint8_t *aad, + uint32_t aad_len) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; int rv; @@ -262,8 +254,8 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_aad (void *cv, const uint8_t * /* * OpenSSL never write to address pointed by the last parameter of - * EVP_CIPHER_CTX_ctrl while EVP_CTRL_GCM_SET_TAG (in reality, - * OpenSSL copy its content to the context), so we can make + * EVP_CIPHER_CTX_ctrl while EVP_CTRL_GCM_SET_TAG (in reality, + * OpenSSL copy its content to the context), so we can make * aad read-only in this function and all its wrappers. */ unsigned char dummy_tag[GCM_AUTH_TAG_LEN]; @@ -286,7 +278,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_set_aad (void *cv, const uint8_t * * buf data to encrypt * enc_len length of encrypt buffer */ -static srtp_err_status_t srtp_aes_gcm_openssl_encrypt (void *cv, unsigned char *buf, unsigned int *enc_len) +static srtp_err_status_t srtp_aes_gcm_openssl_encrypt(void *cv, + unsigned char *buf, + unsigned int *enc_len) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) { @@ -312,7 +306,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_encrypt (void *cv, unsigned char * * buf data to encrypt * len length of encrypt buffer */ -static srtp_err_status_t srtp_aes_gcm_openssl_get_tag (void *cv, uint8_t *buf, uint32_t *len) +static srtp_err_status_t srtp_aes_gcm_openssl_get_tag(void *cv, + uint8_t *buf, + uint32_t *len) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; /* @@ -333,7 +329,6 @@ static srtp_err_status_t srtp_aes_gcm_openssl_get_tag (void *cv, uint8_t *buf, u return (srtp_err_status_ok); } - /* * This function decrypts a buffer using AES GCM mode * @@ -342,7 +337,9 @@ static srtp_err_status_t srtp_aes_gcm_openssl_get_tag (void *cv, uint8_t *buf, u * buf data to encrypt * enc_len length of encrypt buffer */ -static srtp_err_status_t srtp_aes_gcm_openssl_decrypt (void *cv, unsigned char *buf, unsigned int *enc_len) +static srtp_err_status_t srtp_aes_gcm_openssl_decrypt(void *cv, + unsigned char *buf, + unsigned int *enc_len) { srtp_aes_gcm_ctx_t *c = (srtp_aes_gcm_ctx_t *)cv; if (c->dir != srtp_direction_encrypt && c->dir != srtp_direction_decrypt) { @@ -372,32 +369,36 @@ static srtp_err_status_t srtp_aes_gcm_openssl_decrypt (void *cv, unsigned char * return (srtp_err_status_ok); } - - /* * Name of this crypto engine */ -static const char srtp_aes_gcm_128_openssl_description[] = "AES-128 GCM using openssl"; -static const char srtp_aes_gcm_256_openssl_description[] = "AES-256 GCM using openssl"; - +static const char srtp_aes_gcm_128_openssl_description[] = + "AES-128 GCM using openssl"; +static const char srtp_aes_gcm_256_openssl_description[] = + "AES-256 GCM using openssl"; /* * KAT values for AES self-test. These * values we're derived from independent test code * using OpenSSL. */ +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_0_key[SRTP_AES_GCM_128_KEY_LEN_WSALT] = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, }; +/* clang-format on */ +/* clang-format off */ static uint8_t srtp_aes_gcm_test_case_0_iv[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_0_plaintext[60] = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, @@ -409,12 +410,15 @@ static const uint8_t srtp_aes_gcm_test_case_0_plaintext[60] = { 0xba, 0x63, 0x7b, 0x39 }; +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_0_aad[20] = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_0_ciphertext[76] = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, @@ -428,6 +432,7 @@ static const uint8_t srtp_aes_gcm_test_case_0_ciphertext[76] = { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, }; +/* clang-format on */ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_0a = { SRTP_AES_GCM_128_KEY_LEN_WSALT, /* octets in key */ @@ -439,7 +444,7 @@ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_0a = { srtp_aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */ 20, /* octets in AAD */ srtp_aes_gcm_test_case_0_aad, /* AAD */ - GCM_AUTH_TAG_LEN_8, + GCM_AUTH_TAG_LEN_8, /* */ NULL /* pointer to next testcase */ }; @@ -453,10 +458,11 @@ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_0 = { srtp_aes_gcm_test_case_0_ciphertext, /* ciphertext + tag */ 20, /* octets in AAD */ srtp_aes_gcm_test_case_0_aad, /* AAD */ - GCM_AUTH_TAG_LEN, + GCM_AUTH_TAG_LEN, /* */ &srtp_aes_gcm_test_case_0a /* pointer to next testcase */ }; +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_1_key[SRTP_AES_GCM_256_KEY_LEN_WSALT] = { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0xa5, 0x59, 0x09, 0xc5, 0x54, 0x66, 0x93, 0x1c, @@ -464,14 +470,17 @@ static const uint8_t srtp_aes_gcm_test_case_1_key[SRTP_AES_GCM_256_KEY_LEN_WSALT 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, - }; +/* clang-format on */ +/* clang-format off */ static uint8_t srtp_aes_gcm_test_case_1_iv[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_1_plaintext[60] = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, @@ -482,13 +491,17 @@ static const uint8_t srtp_aes_gcm_test_case_1_plaintext[60] = { 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_1_aad[20] = { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_gcm_test_case_1_ciphertext[76] = { 0x0b, 0x11, 0xcf, 0xaf, 0x68, 0x4d, 0xae, 0x46, 0xc7, 0x90, 0xb8, 0x8e, 0xb7, 0x6a, 0x76, 0x2a, @@ -502,6 +515,7 @@ static const uint8_t srtp_aes_gcm_test_case_1_ciphertext[76] = { 0x45, 0xbc, 0x03, 0xe6, 0xe1, 0xac, 0x0a, 0x9f, 0x81, 0xcb, 0x8e, 0x5b, 0x46, 0x65, 0x63, 0x1d, }; +/* clang-format on */ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1a = { SRTP_AES_GCM_256_KEY_LEN_WSALT, /* octets in key */ @@ -513,7 +527,7 @@ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1a = { srtp_aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */ 20, /* octets in AAD */ srtp_aes_gcm_test_case_1_aad, /* AAD */ - GCM_AUTH_TAG_LEN_8, + GCM_AUTH_TAG_LEN_8, /* */ NULL /* pointer to next testcase */ }; @@ -527,7 +541,7 @@ static const srtp_cipher_test_case_t srtp_aes_gcm_test_case_1 = { srtp_aes_gcm_test_case_1_ciphertext, /* ciphertext + tag */ 20, /* octets in AAD */ srtp_aes_gcm_test_case_1_aad, /* AAD */ - GCM_AUTH_TAG_LEN, + GCM_AUTH_TAG_LEN, /* */ &srtp_aes_gcm_test_case_1a /* pointer to next testcase */ }; @@ -564,4 +578,3 @@ const srtp_cipher_type_t srtp_aes_gcm_256_openssl = { &srtp_aes_gcm_test_case_1, SRTP_AES_GCM_256 }; - diff --git a/libs/srtp/crypto/cipher/aes_icm.c b/libs/srtp/crypto/cipher/aes_icm.c index 6901213bad..7551c75148 100644 --- a/libs/srtp/crypto/cipher/aes_icm.c +++ b/libs/srtp/crypto/cipher/aes_icm.c @@ -44,21 +44,19 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #define ALIGN_32 0 #include "aes_icm.h" #include "alloc.h" - +#include "cipher_types.h" srtp_debug_module_t srtp_mod_aes_icm = { - 0, /* debugging is off by default */ - "aes icm" /* printable module name */ + 0, /* debugging is off by default */ + "aes icm" /* printable module name */ }; -extern const srtp_cipher_type_t srtp_aes_icm_128; -extern const srtp_cipher_type_t srtp_aes_icm_256; /* * integer counter mode works as follows: @@ -94,12 +92,14 @@ extern const srtp_cipher_type_t srtp_aes_icm_256; * */ -static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int tlen) +static srtp_err_status_t srtp_aes_icm_alloc(srtp_cipher_t **c, + int key_len, + int tlen) { srtp_aes_icm_ctx_t *icm; - debug_print(srtp_mod_aes_icm, - "allocating cipher with key length %d", key_len); + debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", + key_len); /* * The check for key_len = 30/46 does not apply. Our usage @@ -107,7 +107,8 @@ static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int * has not broken anything. Don't know what would be the * effect of skipping this check for srtp in general. */ - if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT && key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) { + if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT && + key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) { return srtp_err_status_bad_param; } @@ -116,14 +117,13 @@ static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int if (*c == NULL) { return srtp_err_status_alloc_fail; } - memset(*c, 0x0, sizeof(srtp_cipher_t)); icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t)); if (icm == NULL) { - srtp_crypto_free(*c); + srtp_crypto_free(*c); + *c = NULL; return srtp_err_status_alloc_fail; } - memset(icm, 0x0, sizeof(srtp_aes_icm_ctx_t)); /* set pointers */ (*c)->state = icm; @@ -146,7 +146,7 @@ static srtp_err_status_t srtp_aes_icm_alloc (srtp_cipher_t **c, int key_len, int return srtp_err_status_ok; } -static srtp_err_status_t srtp_aes_icm_dealloc (srtp_cipher_t *c) +static srtp_err_status_t srtp_aes_icm_dealloc(srtp_cipher_t *c) { srtp_aes_icm_ctx_t *ctx; @@ -167,7 +167,6 @@ static srtp_err_status_t srtp_aes_icm_dealloc (srtp_cipher_t *c) return srtp_err_status_ok; } - /* * aes_icm_context_init(...) initializes the aes_icm_context * using the value in key[]. @@ -178,15 +177,16 @@ static srtp_err_status_t srtp_aes_icm_dealloc (srtp_cipher_t *c) * randomizes the starting point in the keystream */ -static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key) +static srtp_err_status_t srtp_aes_icm_context_init(void *cv, const uint8_t *key) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; srtp_err_status_t status; int base_key_len, copy_len; - if (c->key_size == SRTP_AES_ICM_128_KEY_LEN_WSALT || c->key_size == SRTP_AES_ICM_256_KEY_LEN_WSALT) { + if (c->key_size == SRTP_AES_ICM_128_KEY_LEN_WSALT || + c->key_size == SRTP_AES_ICM_256_KEY_LEN_WSALT) { base_key_len = c->key_size - SRTP_SALT_LEN; - } else{ + } else { return srtp_err_status_bad_param; } @@ -198,7 +198,8 @@ static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key v128_set_to_zero(&c->offset); copy_len = c->key_size - base_key_len; - /* force last two octets of the offset to be left zero (for srtp compatibility) */ + /* force last two octets of the offset to be left zero (for srtp + * compatibility) */ if (copy_len > SRTP_SALT_LEN) { copy_len = SRTP_SALT_LEN; } @@ -206,13 +207,13 @@ static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key memcpy(&c->counter, key + base_key_len, copy_len); memcpy(&c->offset, key + base_key_len, copy_len); - debug_print(srtp_mod_aes_icm, - "key: %s", srtp_octet_string_hex_string(key, base_key_len)); - debug_print(srtp_mod_aes_icm, - "offset: %s", v128_hex_string(&c->offset)); + debug_print(srtp_mod_aes_icm, "key: %s", + srtp_octet_string_hex_string(key, base_key_len)); + debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); /* expand key */ - status = srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key); + status = + srtp_aes_expand_encryption_key(key, base_key_len, &c->expanded_key); if (status) { v128_set_to_zero(&c->counter); v128_set_to_zero(&c->offset); @@ -230,7 +231,9 @@ static srtp_err_status_t srtp_aes_icm_context_init (void *cv, const uint8_t *key * the offset */ -static srtp_err_status_t srtp_aes_icm_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t direction) +static srtp_err_status_t srtp_aes_icm_set_iv(void *cv, + uint8_t *iv, + srtp_cipher_direction_t direction) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; v128_t nonce; @@ -238,13 +241,12 @@ static srtp_err_status_t srtp_aes_icm_set_iv (void *cv, uint8_t *iv, srtp_cipher /* set nonce (for alignment) */ v128_copy_octet_string(&nonce, iv); - debug_print(srtp_mod_aes_icm, - "setting iv: %s", v128_hex_string(&nonce)); + debug_print(srtp_mod_aes_icm, "setting iv: %s", v128_hex_string(&nonce)); v128_xor(&c->counter, &c->offset, &nonce); - debug_print(srtp_mod_aes_icm, - "set_counter: %s", v128_hex_string(&c->counter)); + debug_print(srtp_mod_aes_icm, "set_counter: %s", + v128_hex_string(&c->counter)); /* indicate that the keystream_buffer is empty */ c->bytes_in_buffer = 0; @@ -252,15 +254,13 @@ static srtp_err_status_t srtp_aes_icm_set_iv (void *cv, uint8_t *iv, srtp_cipher return srtp_err_status_ok; } - - /* * aes_icm_advance(...) refills the keystream_buffer and * advances the block index of the sicm_context forward by one * * this is an internal, hopefully inlined function */ -static void srtp_aes_icm_advance (srtp_aes_icm_ctx_t *c) +static void srtp_aes_icm_advance(srtp_aes_icm_ctx_t *c) { /* fill buffer with new keystream */ v128_copy(&c->keystream_buffer, &c->counter); @@ -278,7 +278,7 @@ static void srtp_aes_icm_advance (srtp_aes_icm_ctx_t *c) } } -/*e +/* * icm_encrypt deals with the following cases: * * bytes_to_encr < bytes_in_buffer @@ -291,10 +291,11 @@ static void srtp_aes_icm_advance (srtp_aes_icm_ctx_t *c) * - fill buffer then add in remaining (< 16) bytes of keystream */ -static srtp_err_status_t srtp_aes_icm_encrypt (void *cv, - unsigned char *buf, unsigned int *enc_len) +static srtp_err_status_t srtp_aes_icm_encrypt(void *cv, + unsigned char *buf, + unsigned int *enc_len) { - srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t*)cv; + srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; unsigned int bytes_to_encr = *enc_len; unsigned int i; uint32_t *b; @@ -304,10 +305,8 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv, return srtp_err_status_terminus; } - debug_print(srtp_mod_aes_icm, "block index: %d", - htons(c->counter.v16[7])); + debug_print(srtp_mod_aes_icm, "block index: %d", htons(c->counter.v16[7])); if (bytes_to_encr <= (unsigned int)c->bytes_in_buffer) { - /* deal with odd case of small bytes_to_encr */ for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < (sizeof(v128_t) - c->bytes_in_buffer + bytes_to_encr); i++) { @@ -320,37 +319,35 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv, return srtp_err_status_ok; } else { - /* encrypt bytes until the remaining data is 16-byte aligned */ - for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); i++) { + for (i = (sizeof(v128_t) - c->bytes_in_buffer); i < sizeof(v128_t); + i++) { *buf++ ^= c->keystream_buffer.v8[i]; } bytes_to_encr -= c->bytes_in_buffer; c->bytes_in_buffer = 0; - } /* now loop over entire 16-byte blocks of keystream */ for (i = 0; i < (bytes_to_encr / sizeof(v128_t)); i++) { - /* fill buffer with new keystream */ srtp_aes_icm_advance(c); - /* - * add keystream into the data buffer (this would be a lot faster - * if we could assume 32-bit alignment!) - */ +/* + * add keystream into the data buffer (this would be a lot faster + * if we could assume 32-bit alignment!) + */ #if ALIGN_32 - b = (uint32_t*)buf; + b = (uint32_t *)buf; *b++ ^= c->keystream_buffer.v32[0]; *b++ ^= c->keystream_buffer.v32[1]; *b++ ^= c->keystream_buffer.v32[2]; *b++ ^= c->keystream_buffer.v32[3]; - buf = (uint8_t*)b; + buf = (uint8_t *)b; #else - if ((((unsigned long)buf) & 0x03) != 0) { + if ((((uintptr_t)buf) & 0x03) != 0) { *buf++ ^= c->keystream_buffer.v8[0]; *buf++ ^= c->keystream_buffer.v8[1]; *buf++ ^= c->keystream_buffer.v8[2]; @@ -368,20 +365,18 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv, *buf++ ^= c->keystream_buffer.v8[14]; *buf++ ^= c->keystream_buffer.v8[15]; } else { - b = (uint32_t*)buf; + b = (uint32_t *)buf; *b++ ^= c->keystream_buffer.v32[0]; *b++ ^= c->keystream_buffer.v32[1]; *b++ ^= c->keystream_buffer.v32[2]; *b++ ^= c->keystream_buffer.v32[3]; - buf = (uint8_t*)b; + buf = (uint8_t *)b; } -#endif /* #if ALIGN_32 */ - +#endif /* #if ALIGN_32 */ } /* if there is a tail end of the data, process it */ if ((bytes_to_encr & 0xf) != 0) { - /* fill buffer with new keystream */ srtp_aes_icm_advance(c); @@ -392,58 +387,67 @@ static srtp_err_status_t srtp_aes_icm_encrypt (void *cv, /* reset the keystream buffer size to right value */ c->bytes_in_buffer = sizeof(v128_t) - i; } else { - /* no tail, so just reset the keystream buffer size to zero */ c->bytes_in_buffer = 0; - } return srtp_err_status_ok; } -static const char srtp_aes_icm_128_description[] = "AES-128 integer counter mode"; -static const char srtp_aes_icm_256_description[] = "AES-256 integer counter mode"; +static const char srtp_aes_icm_128_description[] = + "AES-128 integer counter mode"; +static const char srtp_aes_icm_256_description[] = + "AES-256 integer counter mode"; +/* clang-format off */ static const uint8_t srtp_aes_icm_128_test_case_0_key[SRTP_AES_ICM_128_KEY_LEN_WSALT] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd }; +/* clang-format on */ +/* clang-format off */ static uint8_t srtp_aes_icm_128_test_case_0_nonce[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_128_test_case_0_plaintext[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_128_test_case_0_ciphertext[32] = { 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80, 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4, 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7, 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab }; +/* clang-format on */ static const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0 = { - SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */ + SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */ srtp_aes_icm_128_test_case_0_key, /* key */ srtp_aes_icm_128_test_case_0_nonce, /* packet index */ - 32, /* octets in plaintext */ + 32, /* octets in plaintext */ srtp_aes_icm_128_test_case_0_plaintext, /* plaintext */ - 32, /* octets in ciphertext */ + 32, /* octets in ciphertext */ srtp_aes_icm_128_test_case_0_ciphertext, /* ciphertext */ - 0, - NULL, - 0, - NULL /* pointer to next testcase */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ }; +/* clang-format off */ static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_WSALT] = { 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70, 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92, @@ -452,70 +456,75 @@ static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_W 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd }; +/* clang-format on */ +/* clang-format off */ static uint8_t srtp_aes_icm_256_test_case_0_nonce[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_256_test_case_0_plaintext[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_256_test_case_0_ciphertext[32] = { 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25, 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4, 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6, 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac }; +/* clang-format on */ static const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0 = { - SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */ + SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */ srtp_aes_icm_256_test_case_0_key, /* key */ srtp_aes_icm_256_test_case_0_nonce, /* packet index */ - 32, /* octets in plaintext */ + 32, /* octets in plaintext */ srtp_aes_icm_256_test_case_0_plaintext, /* plaintext */ - 32, /* octets in ciphertext */ + 32, /* octets in ciphertext */ srtp_aes_icm_256_test_case_0_ciphertext, /* ciphertext */ - 0, - NULL, - 0, - NULL, /* pointer to next testcase */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL, /* pointer to next testcase */ }; - - /* * note: the encrypt function is identical to the decrypt function */ const srtp_cipher_type_t srtp_aes_icm_128 = { - srtp_aes_icm_alloc, - srtp_aes_icm_dealloc, - srtp_aes_icm_context_init, - 0, /* set_aad */ - srtp_aes_icm_encrypt, - srtp_aes_icm_encrypt, - srtp_aes_icm_set_iv, - 0, /* get_tag */ - srtp_aes_icm_128_description, - &srtp_aes_icm_128_test_case_0, - SRTP_AES_ICM_128 + srtp_aes_icm_alloc, /* */ + srtp_aes_icm_dealloc, /* */ + srtp_aes_icm_context_init, /* */ + 0, /* set_aad */ + srtp_aes_icm_encrypt, /* */ + srtp_aes_icm_encrypt, /* */ + srtp_aes_icm_set_iv, /* */ + 0, /* get_tag */ + srtp_aes_icm_128_description, /* */ + &srtp_aes_icm_128_test_case_0, /* */ + SRTP_AES_ICM_128 /* */ }; const srtp_cipher_type_t srtp_aes_icm_256 = { - srtp_aes_icm_alloc, - srtp_aes_icm_dealloc, - srtp_aes_icm_context_init, - 0, /* set_aad */ - srtp_aes_icm_encrypt, - srtp_aes_icm_encrypt, - srtp_aes_icm_set_iv, - 0, /* get_tag */ - srtp_aes_icm_256_description, - &srtp_aes_icm_256_test_case_0, - SRTP_AES_ICM_256 + srtp_aes_icm_alloc, /* */ + srtp_aes_icm_dealloc, /* */ + srtp_aes_icm_context_init, /* */ + 0, /* set_aad */ + srtp_aes_icm_encrypt, /* */ + srtp_aes_icm_encrypt, /* */ + srtp_aes_icm_set_iv, /* */ + 0, /* get_tag */ + srtp_aes_icm_256_description, /* */ + &srtp_aes_icm_256_test_case_0, /* */ + SRTP_AES_ICM_256 /* */ }; diff --git a/libs/srtp/crypto/cipher/aes_icm_ossl.c b/libs/srtp/crypto/cipher/aes_icm_ossl.c index 25b431fadd..b591897623 100644 --- a/libs/srtp/crypto/cipher/aes_icm_ossl.c +++ b/libs/srtp/crypto/cipher/aes_icm_ossl.c @@ -49,23 +49,20 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include #include "aes_icm_ossl.h" #include "crypto_types.h" -#include "err.h" /* for srtp_debug */ +#include "err.h" /* for srtp_debug */ #include "alloc.h" - +#include "cipher_types.h" srtp_debug_module_t srtp_mod_aes_icm = { - 0, /* debugging is off by default */ - "aes icm ossl" /* printable module name */ + 0, /* debugging is off by default */ + "aes icm ossl" /* printable module name */ }; -extern const srtp_cipher_type_t srtp_aes_icm_128; -extern const srtp_cipher_type_t srtp_aes_icm_192; -extern const srtp_cipher_type_t srtp_aes_icm_256; /* * integer counter mode works as follows: @@ -109,16 +106,20 @@ extern const srtp_cipher_type_t srtp_aes_icm_256; * value. The tlen argument is for the AEAD tag length, which * isn't used in counter mode. */ -static srtp_err_status_t srtp_aes_icm_openssl_alloc (srtp_cipher_t **c, int key_len, int tlen) +static srtp_err_status_t srtp_aes_icm_openssl_alloc(srtp_cipher_t **c, + int key_len, + int tlen) { srtp_aes_icm_ctx_t *icm; - debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", key_len); + debug_print(srtp_mod_aes_icm, "allocating cipher with key length %d", + key_len); /* * Verify the key_len is valid for one of: AES-128/192/256 */ - if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT && key_len != SRTP_AES_ICM_192_KEY_LEN_WSALT && + if (key_len != SRTP_AES_ICM_128_KEY_LEN_WSALT && + key_len != SRTP_AES_ICM_192_KEY_LEN_WSALT && key_len != SRTP_AES_ICM_256_KEY_LEN_WSALT) { return srtp_err_status_bad_param; } @@ -128,15 +129,13 @@ static srtp_err_status_t srtp_aes_icm_openssl_alloc (srtp_cipher_t **c, int key_ if (*c == NULL) { return srtp_err_status_alloc_fail; } - memset(*c, 0x0, sizeof(srtp_cipher_t)); icm = (srtp_aes_icm_ctx_t *)srtp_crypto_alloc(sizeof(srtp_aes_icm_ctx_t)); if (icm == NULL) { - srtp_crypto_free(*c); - *c = NULL; + srtp_crypto_free(*c); + *c = NULL; return srtp_err_status_alloc_fail; } - memset(icm, 0x0, sizeof(srtp_aes_icm_ctx_t)); icm->ctx = EVP_CIPHER_CTX_new(); if (icm->ctx == NULL) { @@ -174,11 +173,10 @@ static srtp_err_status_t srtp_aes_icm_openssl_alloc (srtp_cipher_t **c, int key_ return srtp_err_status_ok; } - /* * This function deallocates an instance of this engine */ -static srtp_err_status_t srtp_aes_icm_openssl_dealloc (srtp_cipher_t *c) +static srtp_err_status_t srtp_aes_icm_openssl_dealloc(srtp_cipher_t *c) { srtp_aes_icm_ctx_t *ctx; @@ -189,7 +187,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_dealloc (srtp_cipher_t *c) /* * Free the EVP context */ - ctx = (srtp_aes_icm_ctx_t*)c->state; + ctx = (srtp_aes_icm_ctx_t *)c->state; if (ctx != NULL) { EVP_CIPHER_CTX_free(ctx->ctx); /* zeroize the key material */ @@ -212,7 +210,8 @@ static srtp_err_status_t srtp_aes_icm_openssl_dealloc (srtp_cipher_t *c) * the salt is unpredictable (but not necessarily secret) data which * randomizes the starting point in the keystream */ -static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint8_t *key) +static srtp_err_status_t srtp_aes_icm_openssl_context_init(void *cv, + const uint8_t *key) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; const EVP_CIPHER *evp; @@ -230,7 +229,8 @@ static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint c->offset.v8[SRTP_SALT_LEN] = c->offset.v8[SRTP_SALT_LEN + 1] = 0; c->counter.v8[SRTP_SALT_LEN] = c->counter.v8[SRTP_SALT_LEN + 1] = 0; - debug_print(srtp_mod_aes_icm, "key: %s", srtp_octet_string_hex_string(key, c->key_size)); + debug_print(srtp_mod_aes_icm, "key: %s", + srtp_octet_string_hex_string(key, c->key_size)); debug_print(srtp_mod_aes_icm, "offset: %s", v128_hex_string(&c->offset)); switch (c->key_size) { @@ -248,8 +248,7 @@ static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint break; } - if (!EVP_EncryptInit_ex(c->ctx, evp, - NULL, key, NULL)) { + if (!EVP_EncryptInit_ex(c->ctx, evp, NULL, key, NULL)) { return srtp_err_status_fail; } else { return srtp_err_status_ok; @@ -258,12 +257,14 @@ static srtp_err_status_t srtp_aes_icm_openssl_context_init (void* cv, const uint return srtp_err_status_ok; } - /* * aes_icm_set_iv(c, iv) sets the counter value to the exor of iv with * the offset */ -static srtp_err_status_t srtp_aes_icm_openssl_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t dir) +static srtp_err_status_t srtp_aes_icm_openssl_set_iv( + void *cv, + uint8_t *iv, + srtp_cipher_direction_t dir) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; v128_t nonce; @@ -275,10 +276,10 @@ static srtp_err_status_t srtp_aes_icm_openssl_set_iv (void *cv, uint8_t *iv, srt v128_xor(&c->counter, &c->offset, &nonce); - debug_print(srtp_mod_aes_icm, "set_counter: %s", v128_hex_string(&c->counter)); + debug_print(srtp_mod_aes_icm, "set_counter: %s", + v128_hex_string(&c->counter)); - if (!EVP_EncryptInit_ex(c->ctx, NULL, - NULL, NULL, c->counter.v8)) { + if (!EVP_EncryptInit_ex(c->ctx, NULL, NULL, NULL, c->counter.v8)) { return srtp_err_status_fail; } else { return srtp_err_status_ok; @@ -293,7 +294,9 @@ static srtp_err_status_t srtp_aes_icm_openssl_set_iv (void *cv, uint8_t *iv, srt * buf data to encrypt * enc_len length of encrypt buffer */ -static srtp_err_status_t srtp_aes_icm_openssl_encrypt (void *cv, unsigned char *buf, unsigned int *enc_len) +static srtp_err_status_t srtp_aes_icm_openssl_encrypt(void *cv, + unsigned char *buf, + unsigned int *enc_len) { srtp_aes_icm_ctx_t *c = (srtp_aes_icm_ctx_t *)cv; int len = 0; @@ -316,59 +319,70 @@ static srtp_err_status_t srtp_aes_icm_openssl_encrypt (void *cv, unsigned char * /* * Name of this crypto engine */ -static const char srtp_aes_icm_128_openssl_description[] = "AES-128 counter mode using openssl"; -static const char srtp_aes_icm_192_openssl_description[] = "AES-192 counter mode using openssl"; -static const char srtp_aes_icm_256_openssl_description[] = "AES-256 counter mode using openssl"; - +static const char srtp_aes_icm_128_openssl_description[] = + "AES-128 counter mode using openssl"; +static const char srtp_aes_icm_192_openssl_description[] = + "AES-192 counter mode using openssl"; +static const char srtp_aes_icm_256_openssl_description[] = + "AES-256 counter mode using openssl"; /* * KAT values for AES self-test. These * values came from the legacy libsrtp code. */ +/* clang-format off */ static const uint8_t srtp_aes_icm_128_test_case_0_key[SRTP_AES_ICM_128_KEY_LEN_WSALT] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd }; +/* clang-format on */ +/* clang-format off */ static uint8_t srtp_aes_icm_128_test_case_0_nonce[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_128_test_case_0_plaintext[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_128_test_case_0_ciphertext[32] = { 0xe0, 0x3e, 0xad, 0x09, 0x35, 0xc9, 0x5e, 0x80, 0xe1, 0x66, 0xb1, 0x6d, 0xd9, 0x2b, 0x4e, 0xb4, 0xd2, 0x35, 0x13, 0x16, 0x2b, 0x02, 0xd0, 0xf7, 0x2a, 0x43, 0xa2, 0xfe, 0x4a, 0x5f, 0x97, 0xab }; +/* clang-format on */ static const srtp_cipher_test_case_t srtp_aes_icm_128_test_case_0 = { - SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */ - srtp_aes_icm_128_test_case_0_key, /* key */ - srtp_aes_icm_128_test_case_0_nonce, /* packet index */ - 32, /* octets in plaintext */ - srtp_aes_icm_128_test_case_0_plaintext, /* plaintext */ - 32, /* octets in ciphertext */ - srtp_aes_icm_128_test_case_0_ciphertext, /* ciphertext */ - 0, - NULL, - 0, - NULL /* pointer to next testcase */ + SRTP_AES_ICM_128_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_icm_128_test_case_0_key, /* key */ + srtp_aes_icm_128_test_case_0_nonce, /* packet index */ + 32, /* octets in plaintext */ + srtp_aes_icm_128_test_case_0_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + srtp_aes_icm_128_test_case_0_ciphertext, /* ciphertext */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ }; /* * KAT values for AES-192-CTR self-test. These * values came from section 7 of RFC 6188. */ +/* clang-format off */ static const uint8_t srtp_aes_icm_192_test_case_0_key[SRTP_AES_ICM_192_KEY_LEN_WSALT] = { 0xea, 0xb2, 0x34, 0x76, 0x4e, 0x51, 0x7b, 0x2d, 0x3d, 0x16, 0x0d, 0x58, 0x7d, 0x8c, 0x86, 0x21, @@ -376,44 +390,52 @@ static const uint8_t srtp_aes_icm_192_test_case_0_key[SRTP_AES_ICM_192_KEY_LEN_W 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd }; +/* clang-format on */ +/* clang-format off */ static uint8_t srtp_aes_icm_192_test_case_0_nonce[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_192_test_case_0_plaintext[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_192_test_case_0_ciphertext[32] = { 0x35, 0x09, 0x6c, 0xba, 0x46, 0x10, 0x02, 0x8d, 0xc1, 0xb5, 0x75, 0x03, 0x80, 0x4c, 0xe3, 0x7c, 0x5d, 0xe9, 0x86, 0x29, 0x1d, 0xcc, 0xe1, 0x61, 0xd5, 0x16, 0x5e, 0xc4, 0x56, 0x8f, 0x5c, 0x9a }; +/* clang-format on */ static const srtp_cipher_test_case_t srtp_aes_icm_192_test_case_0 = { - SRTP_AES_ICM_192_KEY_LEN_WSALT, /* octets in key */ - srtp_aes_icm_192_test_case_0_key, /* key */ - srtp_aes_icm_192_test_case_0_nonce, /* packet index */ - 32, /* octets in plaintext */ - srtp_aes_icm_192_test_case_0_plaintext, /* plaintext */ - 32, /* octets in ciphertext */ - srtp_aes_icm_192_test_case_0_ciphertext, /* ciphertext */ - 0, - NULL, - 0, - NULL /* pointer to next testcase */ + SRTP_AES_ICM_192_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_icm_192_test_case_0_key, /* key */ + srtp_aes_icm_192_test_case_0_nonce, /* packet index */ + 32, /* octets in plaintext */ + srtp_aes_icm_192_test_case_0_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + srtp_aes_icm_192_test_case_0_ciphertext, /* ciphertext */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ }; /* * KAT values for AES-256-CTR self-test. These * values came from section 7 of RFC 6188. */ +/* clang-format off */ static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_WSALT] = { 0x57, 0xf8, 0x2f, 0xe3, 0x61, 0x3f, 0xd1, 0x70, 0xa8, 0x5e, 0xc9, 0x3c, 0x40, 0xb1, 0xf0, 0x92, @@ -422,38 +444,45 @@ static const uint8_t srtp_aes_icm_256_test_case_0_key[SRTP_AES_ICM_256_KEY_LEN_W 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd }; +/* clang-format on */ +/* clang-format off */ static uint8_t srtp_aes_icm_256_test_case_0_nonce[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_256_test_case_0_plaintext[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_aes_icm_256_test_case_0_ciphertext[32] = { 0x92, 0xbd, 0xd2, 0x8a, 0x93, 0xc3, 0xf5, 0x25, 0x11, 0xc6, 0x77, 0xd0, 0x8b, 0x55, 0x15, 0xa4, 0x9d, 0xa7, 0x1b, 0x23, 0x78, 0xa8, 0x54, 0xf6, 0x70, 0x50, 0x75, 0x6d, 0xed, 0x16, 0x5b, 0xac }; +/* clang-format on */ static const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0 = { - SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */ - srtp_aes_icm_256_test_case_0_key, /* key */ - srtp_aes_icm_256_test_case_0_nonce, /* packet index */ - 32, /* octets in plaintext */ - srtp_aes_icm_256_test_case_0_plaintext, /* plaintext */ - 32, /* octets in ciphertext */ - srtp_aes_icm_256_test_case_0_ciphertext, /* ciphertext */ - 0, - NULL, - 0, - NULL /* pointer to next testcase */ + SRTP_AES_ICM_256_KEY_LEN_WSALT, /* octets in key */ + srtp_aes_icm_256_test_case_0_key, /* key */ + srtp_aes_icm_256_test_case_0_nonce, /* packet index */ + 32, /* octets in plaintext */ + srtp_aes_icm_256_test_case_0_plaintext, /* plaintext */ + 32, /* octets in ciphertext */ + srtp_aes_icm_256_test_case_0_ciphertext, /* ciphertext */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ }; /* @@ -461,17 +490,17 @@ static const srtp_cipher_test_case_t srtp_aes_icm_256_test_case_0 = { * note: the encrypt function is identical to the decrypt function */ const srtp_cipher_type_t srtp_aes_icm_128 = { - srtp_aes_icm_openssl_alloc, - srtp_aes_icm_openssl_dealloc, - srtp_aes_icm_openssl_context_init, - 0, /* set_aad */ - srtp_aes_icm_openssl_encrypt, - srtp_aes_icm_openssl_encrypt, - srtp_aes_icm_openssl_set_iv, - 0, /* get_tag */ - srtp_aes_icm_128_openssl_description, - &srtp_aes_icm_128_test_case_0, - SRTP_AES_ICM_128 + srtp_aes_icm_openssl_alloc, /* */ + srtp_aes_icm_openssl_dealloc, /* */ + srtp_aes_icm_openssl_context_init, /* */ + 0, /* set_aad */ + srtp_aes_icm_openssl_encrypt, /* */ + srtp_aes_icm_openssl_encrypt, /* */ + srtp_aes_icm_openssl_set_iv, /* */ + 0, /* get_tag */ + srtp_aes_icm_128_openssl_description, /* */ + &srtp_aes_icm_128_test_case_0, /* */ + SRTP_AES_ICM_128 /* */ }; /* @@ -479,17 +508,17 @@ const srtp_cipher_type_t srtp_aes_icm_128 = { * note: the encrypt function is identical to the decrypt function */ const srtp_cipher_type_t srtp_aes_icm_192 = { - srtp_aes_icm_openssl_alloc, - srtp_aes_icm_openssl_dealloc, - srtp_aes_icm_openssl_context_init, - 0, /* set_aad */ - srtp_aes_icm_openssl_encrypt, - srtp_aes_icm_openssl_encrypt, - srtp_aes_icm_openssl_set_iv, - 0, /* get_tag */ - srtp_aes_icm_192_openssl_description, - &srtp_aes_icm_192_test_case_0, - SRTP_AES_ICM_192 + srtp_aes_icm_openssl_alloc, /* */ + srtp_aes_icm_openssl_dealloc, /* */ + srtp_aes_icm_openssl_context_init, /* */ + 0, /* set_aad */ + srtp_aes_icm_openssl_encrypt, /* */ + srtp_aes_icm_openssl_encrypt, /* */ + srtp_aes_icm_openssl_set_iv, /* */ + 0, /* get_tag */ + srtp_aes_icm_192_openssl_description, /* */ + &srtp_aes_icm_192_test_case_0, /* */ + SRTP_AES_ICM_192 /* */ }; /* @@ -497,16 +526,15 @@ const srtp_cipher_type_t srtp_aes_icm_192 = { * note: the encrypt function is identical to the decrypt function */ const srtp_cipher_type_t srtp_aes_icm_256 = { - srtp_aes_icm_openssl_alloc, - srtp_aes_icm_openssl_dealloc, - srtp_aes_icm_openssl_context_init, - 0, /* set_aad */ - srtp_aes_icm_openssl_encrypt, - srtp_aes_icm_openssl_encrypt, - srtp_aes_icm_openssl_set_iv, - 0, /* get_tag */ - srtp_aes_icm_256_openssl_description, - &srtp_aes_icm_256_test_case_0, - SRTP_AES_ICM_256 + srtp_aes_icm_openssl_alloc, /* */ + srtp_aes_icm_openssl_dealloc, /* */ + srtp_aes_icm_openssl_context_init, /* */ + 0, /* set_aad */ + srtp_aes_icm_openssl_encrypt, /* */ + srtp_aes_icm_openssl_encrypt, /* */ + srtp_aes_icm_openssl_set_iv, /* */ + 0, /* get_tag */ + srtp_aes_icm_256_openssl_description, /* */ + &srtp_aes_icm_256_test_case_0, /* */ + SRTP_AES_ICM_256 /* */ }; - diff --git a/libs/srtp/crypto/cipher/cipher.c b/libs/srtp/crypto/cipher/cipher.c index 3c67790888..19f00abc55 100644 --- a/libs/srtp/crypto/cipher/cipher.c +++ b/libs/srtp/crypto/cipher/cipher.c @@ -45,56 +45,61 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "cipher.h" #include "crypto_types.h" -#include "err.h" /* for srtp_debug */ -#include "alloc.h" /* for crypto_alloc(), crypto_free() */ +#include "err.h" /* for srtp_debug */ +#include "alloc.h" /* for crypto_alloc(), crypto_free() */ srtp_debug_module_t srtp_mod_cipher = { - 0, /* debugging is off by default */ - "cipher" /* printable module name */ + 0, /* debugging is off by default */ + "cipher" /* printable module name */ }; -srtp_err_status_t srtp_cipher_type_alloc (const srtp_cipher_type_t *ct, srtp_cipher_t **c, int key_len, int tlen) +srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct, + srtp_cipher_t **c, + int key_len, + int tlen) { if (!ct || !ct->alloc) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } return ((ct)->alloc((c), (key_len), (tlen))); } -srtp_err_status_t srtp_cipher_dealloc (srtp_cipher_t *c) +srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c) { if (!c || !c->type) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } return (((c)->type)->dealloc(c)); } -srtp_err_status_t srtp_cipher_init (srtp_cipher_t *c, const uint8_t *key) +srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key) { if (!c || !c->type || !c->state) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } return (((c)->type)->init(((c)->state), (key))); } - -srtp_err_status_t srtp_cipher_set_iv (srtp_cipher_t *c, uint8_t *iv, int direction) +srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c, + uint8_t *iv, + int direction) { if (!c || !c->type || !c->state) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } - return (((c)->type)->set_iv(((c)->state), iv, direction)); + return (((c)->type)->set_iv(((c)->state), iv, direction)); } -srtp_err_status_t srtp_cipher_output (srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output) +srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output) { - /* zeroize the buffer */ octet_string_set_to_zero(buffer, *num_octets_to_output); @@ -102,43 +107,51 @@ srtp_err_status_t srtp_cipher_output (srtp_cipher_t *c, uint8_t *buffer, uint32_ return (((c)->type)->encrypt(((c)->state), buffer, num_octets_to_output)); } -srtp_err_status_t srtp_cipher_encrypt (srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output) +srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output) { if (!c || !c->type || !c->state) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } return (((c)->type)->encrypt(((c)->state), buffer, num_octets_to_output)); } -srtp_err_status_t srtp_cipher_decrypt (srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output) +srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output) { if (!c || !c->type || !c->state) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } return (((c)->type)->decrypt(((c)->state), buffer, num_octets_to_output)); } -srtp_err_status_t srtp_cipher_get_tag (srtp_cipher_t *c, uint8_t *buffer, uint32_t *tag_len) +srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *tag_len) { if (!c || !c->type || !c->state) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } if (!((c)->type)->get_tag) { - return (srtp_err_status_no_such_op); + return (srtp_err_status_no_such_op); } return (((c)->type)->get_tag(((c)->state), buffer, tag_len)); } -srtp_err_status_t srtp_cipher_set_aad (srtp_cipher_t *c, const uint8_t *aad, uint32_t aad_len) +srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c, + const uint8_t *aad, + uint32_t aad_len) { if (!c || !c->type || !c->state) { - return (srtp_err_status_bad_param); + return (srtp_err_status_bad_param); } if (!((c)->type)->set_aad) { - return (srtp_err_status_no_such_op); + return (srtp_err_status_no_such_op); } return (((c)->type)->set_aad(((c)->state), aad, aad_len)); @@ -146,57 +159,56 @@ srtp_err_status_t srtp_cipher_set_aad (srtp_cipher_t *c, const uint8_t *aad, uin /* some bookkeeping functions */ -int srtp_cipher_get_key_length (const srtp_cipher_t *c) +int srtp_cipher_get_key_length(const srtp_cipher_t *c) { return c->key_len; } - /* * A trivial platform independent random source. The random * data is used for some of the cipher self-tests. */ -static srtp_err_status_t srtp_cipher_rand (void *dest, uint32_t len) +static srtp_err_status_t srtp_cipher_rand(void *dest, uint32_t len) { #if defined(HAVE_RAND_S) - uint8_t *dst = (uint8_t *)dest; - while (len) - { - unsigned int val; - errno_t err = rand_s(&val); + uint8_t *dst = (uint8_t *)dest; + while (len) { + unsigned int val; + errno_t err = rand_s(&val); - if (err != 0) - return srtp_err_status_fail; - - *dst++ = val & 0xff; - len--; - } + if (err != 0) + return srtp_err_status_fail; + + *dst++ = val & 0xff; + len--; + } #else - /* Generic C-library (rand()) version */ - /* This is a random source of last resort */ - uint8_t *dst = (uint8_t *)dest; - while (len) - { - int val = rand(); - /* rand() returns 0-32767 (ugh) */ - /* Is this a good enough way to get random bytes? - It is if it passes FIPS-140... */ - *dst++ = val & 0xff; - len--; - } + /* Generic C-library (rand()) version */ + /* This is a random source of last resort */ + uint8_t *dst = (uint8_t *)dest; + while (len) { + int val = rand(); + /* rand() returns 0-32767 (ugh) */ + /* Is this a good enough way to get random bytes? + It is if it passes FIPS-140... */ + *dst++ = val & 0xff; + len--; + } #endif - return srtp_err_status_ok; + return srtp_err_status_ok; } - + #define SELF_TEST_BUF_OCTETS 128 -#define NUM_RAND_TESTS 128 -#define MAX_KEY_LEN 64 +#define NUM_RAND_TESTS 128 +#define MAX_KEY_LEN 64 /* * srtp_cipher_type_test(ct, test_data) tests a cipher of type ct against * test cases provided in a list test_data of values of key, salt, iv, * plaintext, and ciphertext that is known to be good */ -srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srtp_cipher_test_case_t *test_data) +srtp_err_status_t srtp_cipher_type_test( + const srtp_cipher_type_t *ct, + const srtp_cipher_test_case_t *test_data) { const srtp_cipher_test_case_t *test_case = test_data; srtp_cipher_t *c; @@ -206,6 +218,7 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt uint32_t tag_len; unsigned int len; int i, j, case_num = 0; + unsigned k = 0; debug_print(srtp_mod_cipher, "running self-test for cipher %s", ct->description); @@ -224,7 +237,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt */ while (test_case != NULL) { /* allocate cipher */ - status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets); + status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets, + test_case->tag_length_octets); if (status) { return status; } @@ -246,36 +260,39 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt srtp_cipher_dealloc(c); return srtp_err_status_bad_param; } - for (i = 0; i < test_case->plaintext_length_octets; i++) { - buffer[i] = test_case->plaintext[i]; + for (k = 0; k < test_case->plaintext_length_octets; k++) { + buffer[k] = test_case->plaintext[k]; } debug_print(srtp_mod_cipher, "plaintext: %s", - srtp_octet_string_hex_string(buffer, - test_case->plaintext_length_octets)); + srtp_octet_string_hex_string( + buffer, test_case->plaintext_length_octets)); /* set the initialization vector */ - status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_encrypt); + status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx, + srtp_direction_encrypt); if (status) { srtp_cipher_dealloc(c); return status; } - if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) { + if (c->algorithm == SRTP_AES_GCM_128 || + c->algorithm == SRTP_AES_GCM_256) { debug_print(srtp_mod_cipher, "IV: %s", srtp_octet_string_hex_string(test_case->idx, 12)); /* * Set the AAD */ - status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets); + status = srtp_cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); if (status) { srtp_cipher_dealloc(c); return status; } debug_print(srtp_mod_cipher, "AAD: %s", - srtp_octet_string_hex_string(test_case->aad, - test_case->aad_length_octets)); + srtp_octet_string_hex_string( + test_case->aad, test_case->aad_length_octets)); } /* encrypt */ @@ -286,7 +303,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt return status; } - if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) { + if (c->algorithm == SRTP_AES_GCM_128 || + c->algorithm == SRTP_AES_GCM_256) { /* * Get the GCM tag */ @@ -299,8 +317,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt } debug_print(srtp_mod_cipher, "ciphertext: %s", - srtp_octet_string_hex_string(buffer, - test_case->ciphertext_length_octets)); + srtp_octet_string_hex_string( + buffer, test_case->ciphertext_length_octets)); /* compare the resulting ciphertext with that in the test case */ if (len != test_case->ciphertext_length_octets) { @@ -308,22 +326,22 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt return srtp_err_status_algo_fail; } status = srtp_err_status_ok; - for (i = 0; i < test_case->ciphertext_length_octets; i++) { - if (buffer[i] != test_case->ciphertext[i]) { + for (k = 0; k < test_case->ciphertext_length_octets; k++) { + if (buffer[k] != test_case->ciphertext[k]) { status = srtp_err_status_algo_fail; debug_print(srtp_mod_cipher, "test case %d failed", case_num); - debug_print(srtp_mod_cipher, "(failure at byte %d)", i); + debug_print(srtp_mod_cipher, "(failure at byte %u)", k); break; } } if (status) { - debug_print(srtp_mod_cipher, "c computed: %s", - srtp_octet_string_hex_string(buffer, - 2 * test_case->plaintext_length_octets)); + srtp_octet_string_hex_string( + buffer, 2 * test_case->plaintext_length_octets)); debug_print(srtp_mod_cipher, "c expected: %s", - srtp_octet_string_hex_string(test_case->ciphertext, - 2 * test_case->plaintext_length_octets)); + srtp_octet_string_hex_string( + test_case->ciphertext, + 2 * test_case->plaintext_length_octets)); srtp_cipher_dealloc(c); return srtp_err_status_algo_fail; @@ -346,33 +364,36 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt srtp_cipher_dealloc(c); return srtp_err_status_bad_param; } - for (i = 0; i < test_case->ciphertext_length_octets; i++) { - buffer[i] = test_case->ciphertext[i]; + for (k = 0; k < test_case->ciphertext_length_octets; k++) { + buffer[k] = test_case->ciphertext[k]; } debug_print(srtp_mod_cipher, "ciphertext: %s", - srtp_octet_string_hex_string(buffer, - test_case->plaintext_length_octets)); + srtp_octet_string_hex_string( + buffer, test_case->plaintext_length_octets)); /* set the initialization vector */ - status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_decrypt); + status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx, + srtp_direction_decrypt); if (status) { srtp_cipher_dealloc(c); return status; } - if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) { + if (c->algorithm == SRTP_AES_GCM_128 || + c->algorithm == SRTP_AES_GCM_256) { /* * Set the AAD */ - status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets); + status = srtp_cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); if (status) { srtp_cipher_dealloc(c); return status; } debug_print(srtp_mod_cipher, "AAD: %s", - srtp_octet_string_hex_string(test_case->aad, - test_case->aad_length_octets)); + srtp_octet_string_hex_string( + test_case->aad, test_case->aad_length_octets)); } /* decrypt */ @@ -384,8 +405,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt } debug_print(srtp_mod_cipher, "plaintext: %s", - srtp_octet_string_hex_string(buffer, - test_case->plaintext_length_octets)); + srtp_octet_string_hex_string( + buffer, test_case->plaintext_length_octets)); /* compare the resulting plaintext with that in the test case */ if (len != test_case->plaintext_length_octets) { @@ -393,21 +414,21 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt return srtp_err_status_algo_fail; } status = srtp_err_status_ok; - for (i = 0; i < test_case->plaintext_length_octets; i++) { - if (buffer[i] != test_case->plaintext[i]) { + for (k = 0; k < test_case->plaintext_length_octets; k++) { + if (buffer[k] != test_case->plaintext[k]) { status = srtp_err_status_algo_fail; debug_print(srtp_mod_cipher, "test case %d failed", case_num); - debug_print(srtp_mod_cipher, "(failure at byte %d)", i); + debug_print(srtp_mod_cipher, "(failure at byte %u)", k); } } if (status) { - debug_print(srtp_mod_cipher, "p computed: %s", - srtp_octet_string_hex_string(buffer, - 2 * test_case->plaintext_length_octets)); + srtp_octet_string_hex_string( + buffer, 2 * test_case->plaintext_length_octets)); debug_print(srtp_mod_cipher, "p expected: %s", - srtp_octet_string_hex_string(test_case->plaintext, - 2 * test_case->plaintext_length_octets)); + srtp_octet_string_hex_string( + test_case->plaintext, + 2 * test_case->plaintext_length_octets)); srtp_cipher_dealloc(c); return srtp_err_status_algo_fail; @@ -431,14 +452,15 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt /* allocate cipher, using paramaters from the first test case */ test_case = test_data; - status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets, test_case->tag_length_octets); + status = srtp_cipher_type_alloc(ct, &c, test_case->key_length_octets, + test_case->tag_length_octets); if (status) { return status; } for (j = 0; j < NUM_RAND_TESTS; j++) { - unsigned length; - int plaintext_len; + unsigned int length; + unsigned int plaintext_len; uint8_t key[MAX_KEY_LEN]; uint8_t iv[MAX_KEY_LEN]; @@ -485,24 +507,27 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt } /* set initialization vector */ - status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_encrypt); + status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx, + srtp_direction_encrypt); if (status) { srtp_cipher_dealloc(c); return status; } - if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) { + if (c->algorithm == SRTP_AES_GCM_128 || + c->algorithm == SRTP_AES_GCM_256) { /* * Set the AAD */ - status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets); + status = srtp_cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); if (status) { srtp_cipher_dealloc(c); return status; } debug_print(srtp_mod_cipher, "AAD: %s", - srtp_octet_string_hex_string(test_case->aad, - test_case->aad_length_octets)); + srtp_octet_string_hex_string( + test_case->aad, test_case->aad_length_octets)); } /* encrypt buffer with cipher */ @@ -512,7 +537,8 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt srtp_cipher_dealloc(c); return status; } - if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) { + if (c->algorithm == SRTP_AES_GCM_128 || + c->algorithm == SRTP_AES_GCM_256) { /* * Get the GCM tag */ @@ -535,23 +561,26 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt srtp_cipher_dealloc(c); return status; } - status = srtp_cipher_set_iv(c, (uint8_t*)test_case->idx, srtp_direction_decrypt); + status = srtp_cipher_set_iv(c, (uint8_t *)test_case->idx, + srtp_direction_decrypt); if (status) { srtp_cipher_dealloc(c); return status; } - if (c->algorithm == SRTP_AES_GCM_128 || c->algorithm == SRTP_AES_GCM_256) { + if (c->algorithm == SRTP_AES_GCM_128 || + c->algorithm == SRTP_AES_GCM_256) { /* * Set the AAD */ - status = srtp_cipher_set_aad(c, test_case->aad, test_case->aad_length_octets); + status = srtp_cipher_set_aad(c, test_case->aad, + test_case->aad_length_octets); if (status) { srtp_cipher_dealloc(c); return status; } debug_print(srtp_mod_cipher, "AAD: %s", - srtp_octet_string_hex_string(test_case->aad, - test_case->aad_length_octets)); + srtp_octet_string_hex_string( + test_case->aad, test_case->aad_length_octets)); } status = srtp_cipher_decrypt(c, buffer, &length); if (status) { @@ -568,18 +597,18 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt return srtp_err_status_algo_fail; } status = srtp_err_status_ok; - for (i = 0; i < plaintext_len; i++) { - if (buffer[i] != buffer2[i]) { + for (k = 0; k < plaintext_len; k++) { + if (buffer[k] != buffer2[k]) { status = srtp_err_status_algo_fail; - debug_print(srtp_mod_cipher, "random test case %d failed", case_num); - debug_print(srtp_mod_cipher, "(failure at byte %d)", i); + debug_print(srtp_mod_cipher, "random test case %d failed", + case_num); + debug_print(srtp_mod_cipher, "(failure at byte %u)", k); } } if (status) { srtp_cipher_dealloc(c); return srtp_err_status_algo_fail; } - } status = srtp_cipher_dealloc(c); @@ -590,12 +619,11 @@ srtp_err_status_t srtp_cipher_type_test (const srtp_cipher_type_t *ct, const srt return srtp_err_status_ok; } - /* - * srtp_cipher_type_self_test(ct) performs srtp_cipher_type_test on ct's internal - * list of test data. + * srtp_cipher_type_self_test(ct) performs srtp_cipher_type_test on ct's + * internal list of test data. */ -srtp_err_status_t srtp_cipher_type_self_test (const srtp_cipher_type_t *ct) +srtp_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct) { return srtp_cipher_type_test(ct, ct->test_data); } @@ -610,7 +638,9 @@ srtp_err_status_t srtp_cipher_type_self_test (const srtp_cipher_type_t *ct) * * if an error is encountered, the value 0 is returned */ -uint64_t srtp_cipher_bits_per_second (srtp_cipher_t *c, int octets_in_buffer, int num_trials) +uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c, + int octets_in_buffer, + int num_trials) { int i; v128_t nonce; @@ -618,16 +648,16 @@ uint64_t srtp_cipher_bits_per_second (srtp_cipher_t *c, int octets_in_buffer, in unsigned char *enc_buf; unsigned int len = octets_in_buffer; - enc_buf = (unsigned char*)srtp_crypto_alloc(octets_in_buffer); + enc_buf = (unsigned char *)srtp_crypto_alloc(octets_in_buffer); if (enc_buf == NULL) { return 0; /* indicate bad parameters by returning null */ - } /* time repeated trials */ v128_set_to_zero(&nonce); timer = clock(); for (i = 0; i < num_trials; i++, nonce.v32[3] = i) { - if (srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt) != srtp_err_status_ok) { + if (srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt) != + srtp_err_status_ok) { srtp_crypto_free(enc_buf); return 0; } diff --git a/libs/srtp/crypto/cipher/null_cipher.c b/libs/srtp/crypto/cipher/null_cipher.c index 46bf1126da..659add0d47 100644 --- a/libs/srtp/crypto/cipher/null_cipher.c +++ b/libs/srtp/crypto/cipher/null_cipher.c @@ -45,45 +45,42 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "datatypes.h" #include "null_cipher.h" -#include "err.h" /* for srtp_debug */ +#include "err.h" /* for srtp_debug */ #include "alloc.h" +#include "cipher_types.h" -/* the null_cipher uses the cipher debug module */ - -extern srtp_debug_module_t srtp_mod_cipher; - -static srtp_err_status_t srtp_null_cipher_alloc (srtp_cipher_t **c, int key_len, int tlen) +static srtp_err_status_t srtp_null_cipher_alloc(srtp_cipher_t **c, + int key_len, + int tlen) { extern const srtp_cipher_type_t srtp_null_cipher; - debug_print(srtp_mod_cipher, - "allocating cipher with key length %d", key_len); + debug_print(srtp_mod_cipher, "allocating cipher with key length %d", + key_len); /* allocate memory a cipher of type null_cipher */ *c = (srtp_cipher_t *)srtp_crypto_alloc(sizeof(srtp_cipher_t)); if (*c == NULL) { return srtp_err_status_alloc_fail; } - memset(*c, 0x0, sizeof(srtp_cipher_t)); /* set pointers */ (*c)->algorithm = SRTP_NULL_CIPHER; (*c)->type = &srtp_null_cipher; - (*c)->state = (void *) 0x1; /* The null cipher does not maintain state */ + (*c)->state = (void *)0x1; /* The null cipher does not maintain state */ /* set key size */ (*c)->key_len = key_len; return srtp_err_status_ok; - } -static srtp_err_status_t srtp_null_cipher_dealloc (srtp_cipher_t *c) +static srtp_err_status_t srtp_null_cipher_dealloc(srtp_cipher_t *c) { extern const srtp_cipher_type_t srtp_null_cipher; @@ -94,28 +91,30 @@ static srtp_err_status_t srtp_null_cipher_dealloc (srtp_cipher_t *c) srtp_crypto_free(c); return srtp_err_status_ok; - } -static srtp_err_status_t srtp_null_cipher_init (void *cv, const uint8_t *key) +static srtp_err_status_t srtp_null_cipher_init(void *cv, const uint8_t *key) { - /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ + /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ debug_print(srtp_mod_cipher, "initializing null cipher", NULL); return srtp_err_status_ok; } -static srtp_err_status_t srtp_null_cipher_set_iv (void *cv, uint8_t *iv, srtp_cipher_direction_t dir) +static srtp_err_status_t srtp_null_cipher_set_iv(void *cv, + uint8_t *iv, + srtp_cipher_direction_t dir) { - /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ + /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ return srtp_err_status_ok; } -static srtp_err_status_t srtp_null_cipher_encrypt (void *cv, - unsigned char *buf, unsigned int *bytes_to_encr) +static srtp_err_status_t srtp_null_cipher_encrypt(void *cv, + unsigned char *buf, + unsigned int *bytes_to_encr) { - /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ + /* srtp_null_cipher_ctx_t *c = (srtp_null_cipher_ctx_t *)cv; */ return srtp_err_status_ok; } @@ -129,28 +128,26 @@ static const srtp_cipher_test_case_t srtp_null_cipher_test_0 = { NULL, /* plaintext */ 0, /* octets in plaintext */ NULL, /* ciphertext */ - 0, - NULL, - 0, - NULL /* pointer to next testcase */ + 0, /* */ + NULL, /* */ + 0, /* */ + NULL /* pointer to next testcase */ }; - /* * note: the decrypt function is idential to the encrypt function */ const srtp_cipher_type_t srtp_null_cipher = { - srtp_null_cipher_alloc, - srtp_null_cipher_dealloc, - srtp_null_cipher_init, - 0, /* set_aad */ - srtp_null_cipher_encrypt, - srtp_null_cipher_encrypt, - srtp_null_cipher_set_iv, - 0, /* get_tag */ - srtp_null_cipher_description, - &srtp_null_cipher_test_0, - SRTP_NULL_CIPHER + srtp_null_cipher_alloc, /* */ + srtp_null_cipher_dealloc, /* */ + srtp_null_cipher_init, /* */ + 0, /* set_aad */ + srtp_null_cipher_encrypt, /* */ + srtp_null_cipher_encrypt, /* */ + srtp_null_cipher_set_iv, /* */ + 0, /* get_tag */ + srtp_null_cipher_description, /* */ + &srtp_null_cipher_test_0, /* */ + SRTP_NULL_CIPHER /* */ }; - diff --git a/libs/srtp/crypto/hash/auth.c b/libs/srtp/crypto/hash/auth.c index c6ce3576f7..f19327dc8e 100644 --- a/libs/srtp/crypto/hash/auth.c +++ b/libs/srtp/crypto/hash/auth.c @@ -44,32 +44,31 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "auth.h" -#include "err.h" /* for srtp_debug */ -#include "datatypes.h" /* for octet_string */ +#include "err.h" /* for srtp_debug */ +#include "datatypes.h" /* for octet_string */ /* the debug module for authentiation */ srtp_debug_module_t srtp_mod_auth = { - 0, /* debugging is off by default */ - "auth func" /* printable name for module */ + 0, /* debugging is off by default */ + "auth func" /* printable name for module */ }; - -int srtp_auth_get_key_length (const srtp_auth_t *a) +int srtp_auth_get_key_length(const srtp_auth_t *a) { return a->key_len; } -int srtp_auth_get_tag_length (const srtp_auth_t *a) +int srtp_auth_get_tag_length(const srtp_auth_t *a) { return a->out_len; } -int srtp_auth_get_prefix_length (const srtp_auth_t *a) +int srtp_auth_get_prefix_length(const srtp_auth_t *a) { return a->prefix_len; } @@ -83,8 +82,8 @@ int srtp_auth_get_prefix_length (const srtp_auth_t *a) /* should be big enough for most occasions */ #define SELF_TEST_TAG_BUF_OCTETS 32 -srtp_err_status_t -srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *test_data) +srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at, + const srtp_auth_test_case_t *test_data) { const srtp_auth_test_case_t *test_case = test_data; srtp_auth_t *a; @@ -105,7 +104,6 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te /* loop over all test cases */ while (test_case != NULL) { - /* check test case parameters */ if (test_case->tag_length_octets > SELF_TEST_TAG_BUF_OCTETS) { return srtp_err_status_bad_param; @@ -113,7 +111,7 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te /* allocate auth */ status = srtp_auth_type_alloc(at, &a, test_case->key_length_octets, - test_case->tag_length_octets); + test_case->tag_length_octets); if (status) { return status; } @@ -128,7 +126,7 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te /* zeroize tag then compute */ octet_string_set_to_zero(tag, test_case->tag_length_octets); status = srtp_auth_compute(a, test_case->data, - test_case->data_length_octets, tag); + test_case->data_length_octets, tag); if (status) { srtp_auth_dealloc(a); return status; @@ -138,10 +136,11 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te srtp_octet_string_hex_string(test_case->key, test_case->key_length_octets)); debug_print(srtp_mod_auth, "data: %s", - srtp_octet_string_hex_string(test_case->data, - test_case->data_length_octets)); - debug_print(srtp_mod_auth, "tag computed: %s", - srtp_octet_string_hex_string(tag, test_case->tag_length_octets)); + srtp_octet_string_hex_string( + test_case->data, test_case->data_length_octets)); + debug_print( + srtp_mod_auth, "tag computed: %s", + srtp_octet_string_hex_string(tag, test_case->tag_length_octets)); debug_print(srtp_mod_auth, "tag expected: %s", srtp_octet_string_hex_string(test_case->tag, test_case->tag_length_octets)); @@ -177,14 +176,12 @@ srtp_auth_type_test (const srtp_auth_type_t *at, const srtp_auth_test_case_t *te return srtp_err_status_ok; } - /* - * auth_type_self_test(at) performs srtp_auth_type_test on at's internal + * srtp_auth_type_self_test(at) performs srtp_auth_type_test on at's internal * list of test data. */ -srtp_err_status_t srtp_auth_type_self_test (const srtp_auth_type_t *at) +srtp_err_status_t srtp_auth_type_self_test(const srtp_auth_type_t *at) { return srtp_auth_type_test(at, at->test_data); } - diff --git a/libs/srtp/crypto/hash/hmac.c b/libs/srtp/crypto/hash/hmac.c index 416f17be26..6e91468f36 100644 --- a/libs/srtp/crypto/hash/hmac.c +++ b/libs/srtp/crypto/hash/hmac.c @@ -43,27 +43,31 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "hmac.h" #include "alloc.h" +#include "cipher_types.h" /* the debug module for authentiation */ srtp_debug_module_t srtp_mod_hmac = { - 0, /* debugging is off by default */ - "hmac sha-1" /* printable name for module */ + 0, /* debugging is off by default */ + "hmac sha-1" /* printable name for module */ }; - -static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_len) +static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a, + int key_len, + int out_len) { extern const srtp_auth_type_t srtp_hmac; uint8_t *pointer; - debug_print(srtp_mod_hmac, "allocating auth func with key length %d", key_len); - debug_print(srtp_mod_hmac, " tag length %d", out_len); + debug_print(srtp_mod_hmac, "allocating auth func with key length %d", + key_len); + debug_print(srtp_mod_hmac, " tag length %d", + out_len); /* * check key length - note that we don't support keys larger @@ -79,13 +83,14 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_ } /* allocate memory for auth and srtp_hmac_ctx_t structures */ - pointer = (uint8_t*)srtp_crypto_alloc(sizeof(srtp_hmac_ctx_t) + sizeof(srtp_auth_t)); + pointer = (uint8_t *)srtp_crypto_alloc(sizeof(srtp_hmac_ctx_t) + + sizeof(srtp_auth_t)); if (pointer == NULL) { return srtp_err_status_alloc_fail; } /* set pointers */ - *a = (srtp_auth_t*)pointer; + *a = (srtp_auth_t *)pointer; (*a)->type = &srtp_hmac; (*a)->state = pointer + sizeof(srtp_auth_t); (*a)->out_len = out_len; @@ -95,7 +100,7 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_ return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a) +static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a) { /* zeroize entire state*/ octet_string_set_to_zero(a, sizeof(srtp_hmac_ctx_t) + sizeof(srtp_auth_t)); @@ -106,7 +111,9 @@ static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a) return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int key_len) +static srtp_err_status_t srtp_hmac_init(void *statev, + const uint8_t *key, + int key_len) { srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; int i; @@ -131,10 +138,11 @@ static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int k /* set the rest of ipad, opad to constant values */ for (; i < 64; i++) { ipad[i] = 0x36; - ((uint8_t*)state->opad)[i] = 0x5c; + ((uint8_t *)state->opad)[i] = 0x5c; } - debug_print(srtp_mod_hmac, "ipad: %s", srtp_octet_string_hex_string(ipad, 64)); + debug_print(srtp_mod_hmac, "ipad: %s", + srtp_octet_string_hex_string(ipad, 64)); /* initialize sha1 context */ srtp_sha1_init(&state->init_ctx); @@ -146,7 +154,7 @@ static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int k return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_start (void *statev) +static srtp_err_status_t srtp_hmac_start(void *statev) { srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; @@ -155,7 +163,9 @@ static srtp_err_status_t srtp_hmac_start (void *statev) return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message, int msg_octets) +static srtp_err_status_t srtp_hmac_update(void *statev, + const uint8_t *message, + int msg_octets) { srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; @@ -168,8 +178,11 @@ static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message, return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message, - int msg_octets, int tag_len, uint8_t *result) +static srtp_err_status_t srtp_hmac_compute(void *statev, + const uint8_t *message, + int msg_octets, + int tag_len, + uint8_t *result) { srtp_hmac_ctx_t *state = (srtp_hmac_ctx_t *)statev; uint32_t hash_value[5]; @@ -190,49 +203,53 @@ static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message * function hmac_update() already did that for us */ debug_print(srtp_mod_hmac, "intermediate state: %s", - srtp_octet_string_hex_string((uint8_t*)H, 20)); + srtp_octet_string_hex_string((uint8_t *)H, 20)); /* re-initialize hash context */ srtp_sha1_init(&state->ctx); /* hash opad ^ key */ - srtp_sha1_update(&state->ctx, (uint8_t*)state->opad, 64); + srtp_sha1_update(&state->ctx, (uint8_t *)state->opad, 64); /* hash the result of the inner hash */ - srtp_sha1_update(&state->ctx, (uint8_t*)H, 20); + srtp_sha1_update(&state->ctx, (uint8_t *)H, 20); /* the result is returned in the array hash_value[] */ srtp_sha1_final(&state->ctx, hash_value); /* copy hash_value to *result */ for (i = 0; i < tag_len; i++) { - result[i] = ((uint8_t*)hash_value)[i]; + result[i] = ((uint8_t *)hash_value)[i]; } debug_print(srtp_mod_hmac, "output: %s", - srtp_octet_string_hex_string((uint8_t*)hash_value, tag_len)); + srtp_octet_string_hex_string((uint8_t *)hash_value, tag_len)); return srtp_err_status_ok; } - /* begin test case 0 */ - +/* clang-format off */ static const uint8_t srtp_hmac_test_case_0_key[20] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_hmac_test_case_0_data[8] = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */ }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_hmac_test_case_0_tag[20] = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 }; +/* clang-format on */ static const srtp_auth_test_case_t srtp_hmac_test_case_0 = { 20, /* octets in key */ @@ -246,21 +263,21 @@ static const srtp_auth_test_case_t srtp_hmac_test_case_0 = { /* end test case 0 */ -static const char srtp_hmac_description[] = "hmac sha-1 authentication function"; +static const char srtp_hmac_description[] = + "hmac sha-1 authentication function"; /* * srtp_auth_type_t hmac is the hmac metaobject */ -const srtp_auth_type_t srtp_hmac = { - srtp_hmac_alloc, - srtp_hmac_dealloc, - srtp_hmac_init, - srtp_hmac_compute, - srtp_hmac_update, - srtp_hmac_start, - srtp_hmac_description, - &srtp_hmac_test_case_0, - SRTP_HMAC_SHA1 +const srtp_auth_type_t srtp_hmac = { + srtp_hmac_alloc, /* */ + srtp_hmac_dealloc, /* */ + srtp_hmac_init, /* */ + srtp_hmac_compute, /* */ + srtp_hmac_update, /* */ + srtp_hmac_start, /* */ + srtp_hmac_description, /* */ + &srtp_hmac_test_case_0, /* */ + SRTP_HMAC_SHA1 /* */ }; - diff --git a/libs/srtp/crypto/hash/hmac_ossl.c b/libs/srtp/crypto/hash/hmac_ossl.c index f99646b58f..8146438b05 100644 --- a/libs/srtp/crypto/hash/hmac_ossl.c +++ b/libs/srtp/crypto/hash/hmac_ossl.c @@ -43,31 +43,34 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "auth.h" #include "alloc.h" -#include "err.h" /* for srtp_debug */ +#include "err.h" /* for srtp_debug */ #include #include -#define SHA1_DIGEST_SIZE 20 +#define SHA1_DIGEST_SIZE 20 /* the debug module for authentiation */ srtp_debug_module_t srtp_mod_hmac = { - 0, /* debugging is off by default */ - "hmac sha-1 openssl" /* printable name for module */ + 0, /* debugging is off by default */ + "hmac sha-1 openssl" /* printable name for module */ }; - -static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_len) +static srtp_err_status_t srtp_hmac_alloc(srtp_auth_t **a, + int key_len, + int out_len) { extern const srtp_auth_type_t srtp_hmac; - debug_print(srtp_mod_hmac, "allocating auth func with key length %d", key_len); - debug_print(srtp_mod_hmac, " tag length %d", out_len); + debug_print(srtp_mod_hmac, "allocating auth func with key length %d", + key_len); + debug_print(srtp_mod_hmac, " tag length %d", + out_len); /* check output length - should be less than 20 bytes */ if (out_len > SHA1_DIGEST_SIZE) { @@ -76,24 +79,25 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_ /* OpenSSL 1.1.0 made HMAC_CTX an opaque structure, which must be allocated using HMAC_CTX_new. But this function doesn't exist in OpenSSL 1.0.x. */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER { /* allocate memory for auth and HMAC_CTX structures */ - uint8_t* pointer; + uint8_t *pointer; HMAC_CTX *new_hmac_ctx; - pointer = (uint8_t*)srtp_crypto_alloc(sizeof(HMAC_CTX) + sizeof(srtp_auth_t)); + pointer = (uint8_t *)srtp_crypto_alloc(sizeof(HMAC_CTX) + + sizeof(srtp_auth_t)); if (pointer == NULL) { return srtp_err_status_alloc_fail; } - *a = (srtp_auth_t*)pointer; + *a = (srtp_auth_t *)pointer; (*a)->state = pointer + sizeof(srtp_auth_t); - new_hmac_ctx = (HMAC_CTX*)((*a)->state); + new_hmac_ctx = (HMAC_CTX *)((*a)->state); HMAC_CTX_init(new_hmac_ctx); } #else - *a = (srtp_auth_t*)srtp_crypto_alloc(sizeof(srtp_auth_t)); + *a = (srtp_auth_t *)srtp_crypto_alloc(sizeof(srtp_auth_t)); if (*a == NULL) { return srtp_err_status_alloc_fail; } @@ -115,13 +119,13 @@ static srtp_err_status_t srtp_hmac_alloc (srtp_auth_t **a, int key_len, int out_ return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a) +static srtp_err_status_t srtp_hmac_dealloc(srtp_auth_t *a) { HMAC_CTX *hmac_ctx; - hmac_ctx = (HMAC_CTX*)a->state; + hmac_ctx = (HMAC_CTX *)a->state; -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER HMAC_CTX_cleanup(hmac_ctx); /* zeroize entire state*/ @@ -140,7 +144,7 @@ static srtp_err_status_t srtp_hmac_dealloc (srtp_auth_t *a) return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_start (void *statev) +static srtp_err_status_t srtp_hmac_start(void *statev) { HMAC_CTX *state = (HMAC_CTX *)statev; @@ -150,7 +154,9 @@ static srtp_err_status_t srtp_hmac_start (void *statev) return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int key_len) +static srtp_err_status_t srtp_hmac_init(void *statev, + const uint8_t *key, + int key_len) { HMAC_CTX *state = (HMAC_CTX *)statev; @@ -160,7 +166,9 @@ static srtp_err_status_t srtp_hmac_init (void *statev, const uint8_t *key, int k return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message, int msg_octets) +static srtp_err_status_t srtp_hmac_update(void *statev, + const uint8_t *message, + int msg_octets) { HMAC_CTX *state = (HMAC_CTX *)statev; @@ -173,8 +181,11 @@ static srtp_err_status_t srtp_hmac_update (void *statev, const uint8_t *message, return srtp_err_status_ok; } -static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message, - int msg_octets, int tag_len, uint8_t *result) +static srtp_err_status_t srtp_hmac_compute(void *statev, + const uint8_t *message, + int msg_octets, + int tag_len, + uint8_t *result) { HMAC_CTX *state = (HMAC_CTX *)statev; uint8_t hash_value[SHA1_DIGEST_SIZE]; @@ -207,52 +218,56 @@ static srtp_err_status_t srtp_hmac_compute (void *statev, const uint8_t *message return srtp_err_status_ok; } - /* begin test case 0 */ - +/* clang-format off */ static const uint8_t srtp_hmac_test_case_0_key[SHA1_DIGEST_SIZE] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_hmac_test_case_0_data[8] = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 /* "Hi There" */ }; +/* clang-format on */ +/* clang-format off */ static const uint8_t srtp_hmac_test_case_0_tag[SHA1_DIGEST_SIZE] = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 }; +/* clang-format on */ static const srtp_auth_test_case_t srtp_hmac_test_case_0 = { - sizeof(srtp_hmac_test_case_0_key), /* octets in key */ - srtp_hmac_test_case_0_key, /* key */ - sizeof(srtp_hmac_test_case_0_data), /* octets in data */ - srtp_hmac_test_case_0_data, /* data */ - sizeof(srtp_hmac_test_case_0_tag), /* octets in tag */ - srtp_hmac_test_case_0_tag, /* tag */ - NULL /* pointer to next testcase */ + sizeof(srtp_hmac_test_case_0_key), /* octets in key */ + srtp_hmac_test_case_0_key, /* key */ + sizeof(srtp_hmac_test_case_0_data), /* octets in data */ + srtp_hmac_test_case_0_data, /* data */ + sizeof(srtp_hmac_test_case_0_tag), /* octets in tag */ + srtp_hmac_test_case_0_tag, /* tag */ + NULL /* pointer to next testcase */ }; /* end test case 0 */ -static const char srtp_hmac_description[] = "hmac sha-1 authentication function"; +static const char srtp_hmac_description[] = + "hmac sha-1 authentication function"; /* * srtp_auth_type_t hmac is the hmac metaobject */ -const srtp_auth_type_t srtp_hmac = { - srtp_hmac_alloc, - srtp_hmac_dealloc, - srtp_hmac_init, - srtp_hmac_compute, - srtp_hmac_update, - srtp_hmac_start, - srtp_hmac_description, - &srtp_hmac_test_case_0, - SRTP_HMAC_SHA1 +const srtp_auth_type_t srtp_hmac = { + srtp_hmac_alloc, /* */ + srtp_hmac_dealloc, /* */ + srtp_hmac_init, /* */ + srtp_hmac_compute, /* */ + srtp_hmac_update, /* */ + srtp_hmac_start, /* */ + srtp_hmac_description, /* */ + &srtp_hmac_test_case_0, /* */ + SRTP_HMAC_SHA1 /* */ }; - diff --git a/libs/srtp/crypto/hash/null_auth.c b/libs/srtp/crypto/hash/null_auth.c index 2d99027caa..5194417caf 100644 --- a/libs/srtp/crypto/hash/null_auth.c +++ b/libs/srtp/crypto/hash/null_auth.c @@ -45,33 +45,35 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "null_auth.h" -#include "err.h" /* for srtp_debug */ +#include "err.h" /* for srtp_debug */ #include "alloc.h" +#include "cipher_types.h" -/* null_auth uses the auth debug module */ - -extern srtp_debug_module_t srtp_mod_auth; - -static srtp_err_status_t srtp_null_auth_alloc (srtp_auth_t **a, int key_len, int out_len) +static srtp_err_status_t srtp_null_auth_alloc(srtp_auth_t **a, + int key_len, + int out_len) { extern const srtp_auth_type_t srtp_null_auth; uint8_t *pointer; - debug_print(srtp_mod_auth, "allocating auth func with key length %d", key_len); - debug_print(srtp_mod_auth, " tag length %d", out_len); + debug_print(srtp_mod_auth, "allocating auth func with key length %d", + key_len); + debug_print(srtp_mod_auth, " tag length %d", + out_len); /* allocate memory for auth and srtp_null_auth_ctx_t structures */ - pointer = (uint8_t*)srtp_crypto_alloc(sizeof(srtp_null_auth_ctx_t) + sizeof(srtp_auth_t)); + pointer = (uint8_t *)srtp_crypto_alloc(sizeof(srtp_null_auth_ctx_t) + + sizeof(srtp_auth_t)); if (pointer == NULL) { return srtp_err_status_alloc_fail; } /* set pointers */ - *a = (srtp_auth_t*)pointer; + *a = (srtp_auth_t *)pointer; (*a)->type = &srtp_null_auth; (*a)->state = pointer + sizeof(srtp_auth_t); (*a)->out_len = out_len; @@ -81,12 +83,13 @@ static srtp_err_status_t srtp_null_auth_alloc (srtp_auth_t **a, int key_len, int return srtp_err_status_ok; } -static srtp_err_status_t srtp_null_auth_dealloc (srtp_auth_t *a) +static srtp_err_status_t srtp_null_auth_dealloc(srtp_auth_t *a) { extern const srtp_auth_type_t srtp_null_auth; /* zeroize entire state*/ - octet_string_set_to_zero(a, sizeof(srtp_null_auth_ctx_t) + sizeof(srtp_auth_t)); + octet_string_set_to_zero(a, sizeof(srtp_null_auth_ctx_t) + + sizeof(srtp_auth_t)); /* free memory */ srtp_crypto_free(a); @@ -94,7 +97,9 @@ static srtp_err_status_t srtp_null_auth_dealloc (srtp_auth_t *a) return srtp_err_status_ok; } -static srtp_err_status_t srtp_null_auth_init (void *statev, const uint8_t *key, int key_len) +static srtp_err_status_t srtp_null_auth_init(void *statev, + const uint8_t *key, + int key_len) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ /* accept any length of key, and do nothing */ @@ -102,23 +107,27 @@ static srtp_err_status_t srtp_null_auth_init (void *statev, const uint8_t *key, return srtp_err_status_ok; } -static srtp_err_status_t srtp_null_auth_compute (void *statev, const uint8_t *message, - int msg_octets, int tag_len, uint8_t *result) +static srtp_err_status_t srtp_null_auth_compute(void *statev, + const uint8_t *message, + int msg_octets, + int tag_len, + uint8_t *result) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ return srtp_err_status_ok; } -static srtp_err_status_t srtp_null_auth_update (void *statev, const uint8_t *message, - int msg_octets) +static srtp_err_status_t srtp_null_auth_update(void *statev, + const uint8_t *message, + int msg_octets) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ return srtp_err_status_ok; } -static srtp_err_status_t srtp_null_auth_start (void *statev) +static srtp_err_status_t srtp_null_auth_start(void *statev) { /* srtp_null_auth_ctx_t *state = (srtp_null_auth_ctx_t *)statev; */ @@ -133,28 +142,27 @@ static srtp_err_status_t srtp_null_auth_start (void *statev) /* begin test case 0 */ static const srtp_auth_test_case_t srtp_null_auth_test_case_0 = { - 0, /* octets in key */ - NULL, /* key */ - 0, /* octets in data */ - NULL, /* data */ - 0, /* octets in tag */ - NULL, /* tag */ - NULL /* pointer to next testcase */ + 0, /* octets in key */ + NULL, /* key */ + 0, /* octets in data */ + NULL, /* data */ + 0, /* octets in tag */ + NULL, /* tag */ + NULL /* pointer to next testcase */ }; /* end test case 0 */ static const char srtp_null_auth_description[] = "null authentication function"; -const srtp_auth_type_t srtp_null_auth = { - srtp_null_auth_alloc, - srtp_null_auth_dealloc, - srtp_null_auth_init, - srtp_null_auth_compute, - srtp_null_auth_update, - srtp_null_auth_start, - srtp_null_auth_description, - &srtp_null_auth_test_case_0, - SRTP_NULL_AUTH +const srtp_auth_type_t srtp_null_auth = { + srtp_null_auth_alloc, /* */ + srtp_null_auth_dealloc, /* */ + srtp_null_auth_init, /* */ + srtp_null_auth_compute, /* */ + srtp_null_auth_update, /* */ + srtp_null_auth_start, /* */ + srtp_null_auth_description, /* */ + &srtp_null_auth_test_case_0, /* */ + SRTP_NULL_AUTH /* */ }; - diff --git a/libs/srtp/crypto/hash/sha1.c b/libs/srtp/crypto/hash/sha1.c index 94528899c6..afd6381542 100644 --- a/libs/srtp/crypto/hash/sha1.c +++ b/libs/srtp/crypto/hash/sha1.c @@ -45,19 +45,19 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "sha1.h" srtp_debug_module_t srtp_mod_sha1 = { - 0, /* debugging is off by default */ - "sha-1" /* printable module name */ + 0, /* debugging is off by default */ + "sha-1" /* printable module name */ }; /* SN == Rotate left N bits */ -#define S1(X) ((X << 1) | (X >> 31)) -#define S5(X) ((X << 5) | (X >> 27)) +#define S1(X) ((X << 1) | (X >> 31)) +#define S5(X) ((X << 5) | (X >> 27)) #define S30(X) ((X << 30) | (X >> 2)) #define f0(B, C, D) ((B & C) | (~B & D)) @@ -71,19 +71,18 @@ srtp_debug_module_t srtp_mod_sha1 = { * on systems that uses curses */ -uint32_t SHA_K0 = 0x5A827999; /* Kt for 0 <= t <= 19 */ -uint32_t SHA_K1 = 0x6ED9EBA1; /* Kt for 20 <= t <= 39 */ -uint32_t SHA_K2 = 0x8F1BBCDC; /* Kt for 40 <= t <= 59 */ -uint32_t SHA_K3 = 0xCA62C1D6; /* Kt for 60 <= t <= 79 */ +uint32_t SHA_K0 = 0x5A827999; /* Kt for 0 <= t <= 19 */ +uint32_t SHA_K1 = 0x6ED9EBA1; /* Kt for 20 <= t <= 39 */ +uint32_t SHA_K2 = 0x8F1BBCDC; /* Kt for 40 <= t <= 59 */ +uint32_t SHA_K3 = 0xCA62C1D6; /* Kt for 60 <= t <= 79 */ -void srtp_sha1 (const uint8_t *msg, int octets_in_msg, uint32_t hash_value[5]) +void srtp_sha1(const uint8_t *msg, int octets_in_msg, uint32_t hash_value[5]) { srtp_sha1_ctx_t ctx; srtp_sha1_init(&ctx); srtp_sha1_update(&ctx, msg, octets_in_msg); srtp_sha1_final(&ctx, hash_value); - } /* @@ -98,7 +97,7 @@ void srtp_sha1 (const uint8_t *msg, int octets_in_msg, uint32_t hash_value[5]) * (crypto/cipher/seal.c) */ -void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5]) +void srtp_sha1_core(const uint32_t M[16], uint32_t hash_value[5]) { uint32_t H0; uint32_t H1; @@ -118,38 +117,54 @@ void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5]) /* copy/xor message into array */ - W[0] = be32_to_cpu(M[0]); - W[1] = be32_to_cpu(M[1]); - W[2] = be32_to_cpu(M[2]); - W[3] = be32_to_cpu(M[3]); - W[4] = be32_to_cpu(M[4]); - W[5] = be32_to_cpu(M[5]); - W[6] = be32_to_cpu(M[6]); - W[7] = be32_to_cpu(M[7]); - W[8] = be32_to_cpu(M[8]); - W[9] = be32_to_cpu(M[9]); + W[0] = be32_to_cpu(M[0]); + W[1] = be32_to_cpu(M[1]); + W[2] = be32_to_cpu(M[2]); + W[3] = be32_to_cpu(M[3]); + W[4] = be32_to_cpu(M[4]); + W[5] = be32_to_cpu(M[5]); + W[6] = be32_to_cpu(M[6]); + W[7] = be32_to_cpu(M[7]); + W[8] = be32_to_cpu(M[8]); + W[9] = be32_to_cpu(M[9]); W[10] = be32_to_cpu(M[10]); W[11] = be32_to_cpu(M[11]); W[12] = be32_to_cpu(M[12]); W[13] = be32_to_cpu(M[13]); W[14] = be32_to_cpu(M[14]); W[15] = be32_to_cpu(M[15]); - TEMP = W[13] ^ W[8] ^ W[2] ^ W[0]; W[16] = S1(TEMP); - TEMP = W[14] ^ W[9] ^ W[3] ^ W[1]; W[17] = S1(TEMP); - TEMP = W[15] ^ W[10] ^ W[4] ^ W[2]; W[18] = S1(TEMP); - TEMP = W[16] ^ W[11] ^ W[5] ^ W[3]; W[19] = S1(TEMP); - TEMP = W[17] ^ W[12] ^ W[6] ^ W[4]; W[20] = S1(TEMP); - TEMP = W[18] ^ W[13] ^ W[7] ^ W[5]; W[21] = S1(TEMP); - TEMP = W[19] ^ W[14] ^ W[8] ^ W[6]; W[22] = S1(TEMP); - TEMP = W[20] ^ W[15] ^ W[9] ^ W[7]; W[23] = S1(TEMP); - TEMP = W[21] ^ W[16] ^ W[10] ^ W[8]; W[24] = S1(TEMP); - TEMP = W[22] ^ W[17] ^ W[11] ^ W[9]; W[25] = S1(TEMP); - TEMP = W[23] ^ W[18] ^ W[12] ^ W[10]; W[26] = S1(TEMP); - TEMP = W[24] ^ W[19] ^ W[13] ^ W[11]; W[27] = S1(TEMP); - TEMP = W[25] ^ W[20] ^ W[14] ^ W[12]; W[28] = S1(TEMP); - TEMP = W[26] ^ W[21] ^ W[15] ^ W[13]; W[29] = S1(TEMP); - TEMP = W[27] ^ W[22] ^ W[16] ^ W[14]; W[30] = S1(TEMP); - TEMP = W[28] ^ W[23] ^ W[17] ^ W[15]; W[31] = S1(TEMP); + TEMP = W[13] ^ W[8] ^ W[2] ^ W[0]; + W[16] = S1(TEMP); + TEMP = W[14] ^ W[9] ^ W[3] ^ W[1]; + W[17] = S1(TEMP); + TEMP = W[15] ^ W[10] ^ W[4] ^ W[2]; + W[18] = S1(TEMP); + TEMP = W[16] ^ W[11] ^ W[5] ^ W[3]; + W[19] = S1(TEMP); + TEMP = W[17] ^ W[12] ^ W[6] ^ W[4]; + W[20] = S1(TEMP); + TEMP = W[18] ^ W[13] ^ W[7] ^ W[5]; + W[21] = S1(TEMP); + TEMP = W[19] ^ W[14] ^ W[8] ^ W[6]; + W[22] = S1(TEMP); + TEMP = W[20] ^ W[15] ^ W[9] ^ W[7]; + W[23] = S1(TEMP); + TEMP = W[21] ^ W[16] ^ W[10] ^ W[8]; + W[24] = S1(TEMP); + TEMP = W[22] ^ W[17] ^ W[11] ^ W[9]; + W[25] = S1(TEMP); + TEMP = W[23] ^ W[18] ^ W[12] ^ W[10]; + W[26] = S1(TEMP); + TEMP = W[24] ^ W[19] ^ W[13] ^ W[11]; + W[27] = S1(TEMP); + TEMP = W[25] ^ W[20] ^ W[14] ^ W[12]; + W[28] = S1(TEMP); + TEMP = W[26] ^ W[21] ^ W[15] ^ W[13]; + W[29] = S1(TEMP); + TEMP = W[27] ^ W[22] ^ W[16] ^ W[14]; + W[30] = S1(TEMP); + TEMP = W[28] ^ W[23] ^ W[17] ^ W[15]; + W[31] = S1(TEMP); /* process the remainder of the array */ for (t = 32; t < 80; t++) { @@ -157,23 +172,43 @@ void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5]) W[t] = S1(TEMP); } - A = H0; B = H1; C = H2; D = H3; E = H4; + A = H0; + B = H1; + C = H2; + D = H3; + E = H4; for (t = 0; t < 20; t++) { TEMP = S5(A) + f0(B, C, D) + E + W[t] + SHA_K0; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 40; t++) { TEMP = S5(A) + f1(B, C, D) + E + W[t] + SHA_K1; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 60; t++) { TEMP = S5(A) + f2(B, C, D) + E + W[t] + SHA_K2; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 80; t++) { TEMP = S5(A) + f3(B, C, D) + E + W[t] + SHA_K3; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } hash_value[0] = H0 + A; @@ -185,9 +220,8 @@ void srtp_sha1_core (const uint32_t M[16], uint32_t hash_value[5]) return; } -void srtp_sha1_init (srtp_sha1_ctx_t *ctx) +void srtp_sha1_init(srtp_sha1_ctx_t *ctx) { - /* initialize state vector */ ctx->H[0] = 0x67452301; ctx->H[1] = 0xefcdab89; @@ -200,22 +234,21 @@ void srtp_sha1_init (srtp_sha1_ctx_t *ctx) /* reset message bit-count to zero */ ctx->num_bits_in_msg = 0; - } -void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_msg) +void srtp_sha1_update(srtp_sha1_ctx_t *ctx, + const uint8_t *msg, + int octets_in_msg) { int i; - uint8_t *buf = (uint8_t*)ctx->M; + uint8_t *buf = (uint8_t *)ctx->M; /* update message bit-count */ ctx->num_bits_in_msg += octets_in_msg * 8; /* loop over 16-word blocks of M */ while (octets_in_msg > 0) { - if (octets_in_msg + ctx->octets_in_buffer >= 64) { - /* * copy words of M into msg buffer until that buffer is full, * converting them into host byte order as needed @@ -228,13 +261,14 @@ void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_m /* process a whole block */ - debug_print(srtp_mod_sha1, "(update) running srtp_sha1_core()", NULL); + debug_print(srtp_mod_sha1, "(update) running srtp_sha1_core()", + NULL); srtp_sha1_core(ctx->M, ctx->H); } else { - - debug_print(srtp_mod_sha1, "(update) not running srtp_sha1_core()", NULL); + debug_print(srtp_mod_sha1, "(update) not running srtp_sha1_core()", + NULL); for (i = ctx->octets_in_buffer; i < (ctx->octets_in_buffer + octets_in_msg); i++) { @@ -243,9 +277,7 @@ void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_m ctx->octets_in_buffer += octets_in_msg; octets_in_msg = 0; } - } - } /* @@ -253,7 +285,7 @@ void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *msg, int octets_in_m * into the twenty octets located at *output */ -void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) +void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t *output) { uint32_t A, B, C, D, E, TEMP; uint32_t W[80]; @@ -268,7 +300,7 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) /* copy/xor message into array */ for (i = 0; i < (ctx->octets_in_buffer + 3) / 4; i++) { - W[i] = be32_to_cpu(ctx->M[i]); + W[i] = be32_to_cpu(ctx->M[i]); } /* set the high bit of the octet immediately following the message */ @@ -321,19 +353,35 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) for (t = 0; t < 20; t++) { TEMP = S5(A) + f0(B, C, D) + E + W[t] + SHA_K0; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 40; t++) { TEMP = S5(A) + f1(B, C, D) + E + W[t] + SHA_K1; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 60; t++) { TEMP = S5(A) + f2(B, C, D) + E + W[t] + SHA_K2; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 80; t++) { TEMP = S5(A) + f3(B, C, D) + E + W[t] + SHA_K3; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } ctx->H[0] += A; @@ -341,14 +389,13 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) ctx->H[2] += C; ctx->H[3] += D; ctx->H[4] += E; - } debug_print(srtp_mod_sha1, "(final) running srtp_sha1_core()", NULL); if (ctx->octets_in_buffer >= 56) { - - debug_print(srtp_mod_sha1, "(final) running srtp_sha1_core() again", NULL); + debug_print(srtp_mod_sha1, "(final) running srtp_sha1_core() again", + NULL); /* we need to do one final run of the compression algo */ @@ -375,19 +422,35 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) for (t = 0; t < 20; t++) { TEMP = S5(A) + f0(B, C, D) + E + W[t] + SHA_K0; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 40; t++) { TEMP = S5(A) + f1(B, C, D) + E + W[t] + SHA_K1; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 60; t++) { TEMP = S5(A) + f2(B, C, D) + E + W[t] + SHA_K2; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } for (; t < 80; t++) { TEMP = S5(A) + f3(B, C, D) + E + W[t] + SHA_K3; - E = D; D = C; C = S30(B); B = A; A = TEMP; + E = D; + D = C; + C = S30(B); + B = A; + A = TEMP; } ctx->H[0] += A; @@ -409,6 +472,3 @@ void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) return; } - - - diff --git a/libs/srtp/crypto/include/aes.h b/libs/srtp/crypto/include/aes.h index 007163c534..779c3ac744 100644 --- a/libs/srtp/crypto/include/aes.h +++ b/libs/srtp/crypto/include/aes.h @@ -70,9 +70,11 @@ srtp_err_status_t srtp_aes_expand_decryption_key( int key_len, srtp_aes_expanded_key_t *expanded_key); -void srtp_aes_encrypt(v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key); +void srtp_aes_encrypt(v128_t *plaintext, + const srtp_aes_expanded_key_t *exp_key); -void srtp_aes_decrypt(v128_t *plaintext, const srtp_aes_expanded_key_t *exp_key); +void srtp_aes_decrypt(v128_t *plaintext, + const srtp_aes_expanded_key_t *exp_key); #ifdef __cplusplus } diff --git a/libs/srtp/crypto/include/aes_gcm_ossl.h b/libs/srtp/crypto/include/aes_gcm_ossl.h index 8b0d7a0264..d5b83eeeb0 100644 --- a/libs/srtp/crypto/include/aes_gcm_ossl.h +++ b/libs/srtp/crypto/include/aes_gcm_ossl.h @@ -55,9 +55,8 @@ typedef struct { int key_size; int tag_len; - EVP_CIPHER_CTX* ctx; + EVP_CIPHER_CTX *ctx; srtp_cipher_direction_t dir; } srtp_aes_gcm_ctx_t; #endif /* AES_GCM_OSSL_H */ - diff --git a/libs/srtp/crypto/include/aes_icm.h b/libs/srtp/crypto/include/aes_icm.h index 90fbd5e35d..8ded156a29 100644 --- a/libs/srtp/crypto/include/aes_icm.h +++ b/libs/srtp/crypto/include/aes_icm.h @@ -9,26 +9,26 @@ */ /* - * + * * 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 @@ -60,4 +60,3 @@ typedef struct { } srtp_aes_icm_ctx_t; #endif /* AES_ICM_H */ - diff --git a/libs/srtp/crypto/include/aes_icm_ossl.h b/libs/srtp/crypto/include/aes_icm_ossl.h index 1dddd755fc..c4aae376e6 100644 --- a/libs/srtp/crypto/include/aes_icm_ossl.h +++ b/libs/srtp/crypto/include/aes_icm_ossl.h @@ -52,11 +52,10 @@ #include typedef struct { - v128_t counter; /* holds the counter value */ - v128_t offset; /* initial offset value */ + v128_t counter; /* holds the counter value */ + v128_t offset; /* initial offset value */ int key_size; - EVP_CIPHER_CTX* ctx; + EVP_CIPHER_CTX *ctx; } srtp_aes_icm_ctx_t; #endif /* AES_ICM_H */ - diff --git a/libs/srtp/crypto/include/alloc.h b/libs/srtp/crypto/include/alloc.h index 0bd2a90820..1fc041014d 100644 --- a/libs/srtp/crypto/include/alloc.h +++ b/libs/srtp/crypto/include/alloc.h @@ -1,32 +1,32 @@ /* * alloc.h * - * interface to memory allocation and deallocation, with optional debugging + * interface to memory allocation and deallocation, with optional debugging * * 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 @@ -42,7 +42,6 @@ * */ - #ifndef CRYPTO_ALLOC_H #define CRYPTO_ALLOC_H @@ -52,8 +51,22 @@ extern "C" { #endif -void * srtp_crypto_alloc(size_t size); +/* + * srtp_crypto_alloc + * + * Allocates a block of memory of given size. The memory will be + * initialized to zero's. Free the memory with a call to srtp_crypto_free. + * + * returns pointer to memory on success or else NULL + */ +void *srtp_crypto_alloc(size_t size); +/* + * srtp_crypto_free + * + * Frees the block of memory ptr previously allocated with + * srtp_crypto_alloc + */ void srtp_crypto_free(void *ptr); #ifdef __cplusplus diff --git a/libs/srtp/crypto/include/auth.h b/libs/srtp/crypto/include/auth.h index 7870b29450..774ea1687b 100644 --- a/libs/srtp/crypto/include/auth.h +++ b/libs/srtp/crypto/include/auth.h @@ -47,46 +47,51 @@ #define SRTP_AUTH_H #include "srtp.h" -#include "crypto_types.h" /* for values of auth_type_id_t */ +#include "crypto_types.h" /* for values of auth_type_id_t */ #ifdef __cplusplus extern "C" { #endif typedef const struct srtp_auth_type_t *srtp_auth_type_pointer; -typedef struct srtp_auth_t *srtp_auth_pointer_t; +typedef struct srtp_auth_t *srtp_auth_pointer_t; -typedef srtp_err_status_t (*srtp_auth_alloc_func) - (srtp_auth_pointer_t *ap, int key_len, int out_len); +typedef srtp_err_status_t (*srtp_auth_alloc_func)(srtp_auth_pointer_t *ap, + int key_len, + int out_len); -typedef srtp_err_status_t (*srtp_auth_init_func) - (void *state, const uint8_t *key, int key_len); +typedef srtp_err_status_t (*srtp_auth_init_func)(void *state, + const uint8_t *key, + int key_len); typedef srtp_err_status_t (*srtp_auth_dealloc_func)(srtp_auth_pointer_t ap); -typedef srtp_err_status_t (*srtp_auth_compute_func) - (void *state, const uint8_t *buffer, int octets_to_auth, - int tag_len, uint8_t *tag); +typedef srtp_err_status_t (*srtp_auth_compute_func)(void *state, + const uint8_t *buffer, + int octets_to_auth, + int tag_len, + uint8_t *tag); -typedef srtp_err_status_t (*srtp_auth_update_func) - (void *state, const uint8_t *buffer, int octets_to_auth); +typedef srtp_err_status_t (*srtp_auth_update_func)(void *state, + const uint8_t *buffer, + int octets_to_auth); typedef srtp_err_status_t (*srtp_auth_start_func)(void *state); /* some syntactic sugar on these function types */ -#define srtp_auth_type_alloc(at, a, klen, outlen) \ +#define srtp_auth_type_alloc(at, a, klen, outlen) \ ((at)->alloc((a), (klen), (outlen))) -#define srtp_auth_init(a, key) \ +#define srtp_auth_init(a, key) \ (((a)->type)->init((a)->state, (key), ((a)->key_len))) -#define srtp_auth_compute(a, buf, len, res) \ +#define srtp_auth_compute(a, buf, len, res) \ (((a)->type)->compute((a)->state, (buf), (len), (a)->out_len, (res))) -#define srtp_auth_update(a, buf, len) \ +#define srtp_auth_update(a, buf, len) \ (((a)->type)->update((a)->state, (buf), (len))) -#define srtp_auth_start(a)(((a)->type)->start((a)->state)) +#define srtp_auth_start(a) (((a)->type)->start((a)->state)) #define srtp_auth_dealloc(c) (((c)->type)->dealloc(c)) @@ -105,13 +110,14 @@ int srtp_auth_get_prefix_length(const struct srtp_auth_t *a); * function below) */ typedef struct srtp_auth_test_case_t { - int key_length_octets; /* octets in key */ - const uint8_t *key; /* key */ - int data_length_octets; /* octets in data */ - const uint8_t *data; /* data */ - int tag_length_octets; /* octets in tag */ - const uint8_t *tag; /* tag */ - const struct srtp_auth_test_case_t *next_test_case; /* pointer to next testcase */ + int key_length_octets; /* octets in key */ + const uint8_t *key; /* key */ + int data_length_octets; /* octets in data */ + const uint8_t *data; /* data */ + int tag_length_octets; /* octets in tag */ + const uint8_t *tag; /* tag */ + const struct srtp_auth_test_case_t + *next_test_case; /* pointer to next testcase */ } srtp_auth_test_case_t; /* srtp_auth_type_t */ @@ -122,17 +128,17 @@ typedef struct srtp_auth_type_t { srtp_auth_compute_func compute; srtp_auth_update_func update; srtp_auth_start_func start; - const char *description; - const srtp_auth_test_case_t *test_data; + const char *description; + const srtp_auth_test_case_t *test_data; srtp_auth_type_id_t id; } srtp_auth_type_t; typedef struct srtp_auth_t { const srtp_auth_type_t *type; - void *state; - int out_len; /* length of output tag in octets */ - int key_len; /* length of key in octets */ - int prefix_len; /* length of keystream prefix */ + void *state; + int out_len; /* length of output tag in octets */ + int key_len; /* length of key in octets */ + int prefix_len; /* length of keystream prefix */ } srtp_auth_t; /* @@ -147,8 +153,8 @@ srtp_err_status_t srtp_auth_type_self_test(const srtp_auth_type_t *at); * provided in an array of values of key/message/tag that is known to * be good */ -srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at, - const srtp_auth_test_case_t *test_data); +srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at, + const srtp_auth_test_case_t *test_data); /* * srtp_replace_auth_type(ct, id) @@ -157,7 +163,8 @@ srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at, * with a new one passed in externally. The new auth type must pass all the * existing auth_type's self tests as well as its own. */ -srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *ct, srtp_auth_type_id_t id); +srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *ct, + srtp_auth_type_id_t id); #ifdef __cplusplus } diff --git a/libs/srtp/crypto/include/cipher.h b/libs/srtp/crypto/include/cipher.h index d544b12045..4f14e3560f 100644 --- a/libs/srtp/crypto/include/cipher.h +++ b/libs/srtp/crypto/include/cipher.h @@ -42,13 +42,11 @@ * */ - #ifndef SRTP_CIPHER_H #define SRTP_CIPHER_H #include "srtp.h" -#include "crypto_types.h" /* for values of cipher_type_id_t */ - +#include "crypto_types.h" /* for values of cipher_type_id_t */ #ifdef __cplusplus extern "C" { @@ -71,51 +69,60 @@ typedef enum { * the srtp_cipher_pointer_t definition is needed * as srtp_cipher_t is not yet defined */ -typedef struct srtp_cipher_t *srtp_cipher_pointer_t; +typedef struct srtp_cipher_t *srtp_cipher_pointer_t; /* - * a srtp_cipher_alloc_func_t allocates (but does not initialize) a srtp_cipher_t + * a srtp_cipher_alloc_func_t allocates (but does not initialize) a + * srtp_cipher_t */ -typedef srtp_err_status_t (*srtp_cipher_alloc_func_t) - (srtp_cipher_pointer_t *cp, int key_len, int tag_len); +typedef srtp_err_status_t (*srtp_cipher_alloc_func_t)(srtp_cipher_pointer_t *cp, + int key_len, + int tag_len); /* * a srtp_cipher_init_func_t [re-]initializes a cipher_t with a given key */ -typedef srtp_err_status_t (*srtp_cipher_init_func_t) - (void *state, const uint8_t *key); +typedef srtp_err_status_t (*srtp_cipher_init_func_t)(void *state, + const uint8_t *key); /* a srtp_cipher_dealloc_func_t de-allocates a cipher_t */ -typedef srtp_err_status_t (*srtp_cipher_dealloc_func_t)(srtp_cipher_pointer_t cp); +typedef srtp_err_status_t (*srtp_cipher_dealloc_func_t)( + srtp_cipher_pointer_t cp); /* * a srtp_cipher_set_aad_func_t processes the AAD data for AEAD ciphers */ -typedef srtp_err_status_t (*srtp_cipher_set_aad_func_t) - (void *state, const uint8_t *aad, uint32_t aad_len); - +typedef srtp_err_status_t (*srtp_cipher_set_aad_func_t)(void *state, + const uint8_t *aad, + uint32_t aad_len); /* a srtp_cipher_encrypt_func_t encrypts data in-place */ -typedef srtp_err_status_t (*srtp_cipher_encrypt_func_t) - (void *state, uint8_t *buffer, unsigned int *octets_to_encrypt); +typedef srtp_err_status_t (*srtp_cipher_encrypt_func_t)( + void *state, + uint8_t *buffer, + unsigned int *octets_to_encrypt); /* a srtp_cipher_decrypt_func_t decrypts data in-place */ -typedef srtp_err_status_t (*srtp_cipher_decrypt_func_t) - (void *state, uint8_t *buffer, unsigned int *octets_to_decrypt); +typedef srtp_err_status_t (*srtp_cipher_decrypt_func_t)( + void *state, + uint8_t *buffer, + unsigned int *octets_to_decrypt); /* * a srtp_cipher_set_iv_func_t function sets the current initialization vector */ -typedef srtp_err_status_t (*srtp_cipher_set_iv_func_t) - (void *state, uint8_t *iv, srtp_cipher_direction_t direction); +typedef srtp_err_status_t (*srtp_cipher_set_iv_func_t)( + void *state, + uint8_t *iv, + srtp_cipher_direction_t direction); /* * a cipher_get_tag_func_t function is used to get the authentication * tag that was calculated by an AEAD cipher. */ -typedef srtp_err_status_t (*srtp_cipher_get_tag_func_t) - (void *state, uint8_t *tag, uint32_t *len); - +typedef srtp_err_status_t (*srtp_cipher_get_tag_func_t)(void *state, + uint8_t *tag, + uint32_t *len); /* * srtp_cipher_test_case_t is a (list of) key, salt, plaintext, ciphertext, @@ -125,17 +132,18 @@ typedef srtp_err_status_t (*srtp_cipher_get_tag_func_t) * (see the srtp_cipher_type_self_test() function below) */ typedef struct srtp_cipher_test_case_t { - int key_length_octets; /* octets in key */ - const uint8_t *key; /* key */ - uint8_t *idx; /* packet index */ - int plaintext_length_octets; /* octets in plaintext */ - const uint8_t *plaintext; /* plaintext */ - int ciphertext_length_octets; /* octets in plaintext */ - const uint8_t *ciphertext; /* ciphertext */ - int aad_length_octets; /* octets in AAD */ - const uint8_t *aad; /* AAD */ - int tag_length_octets; /* Length of AEAD tag */ - const struct srtp_cipher_test_case_t *next_test_case; /* pointer to next testcase */ + int key_length_octets; /* octets in key */ + const uint8_t *key; /* key */ + uint8_t *idx; /* packet index */ + unsigned int plaintext_length_octets; /* octets in plaintext */ + const uint8_t *plaintext; /* plaintext */ + unsigned int ciphertext_length_octets; /* octets in plaintext */ + const uint8_t *ciphertext; /* ciphertext */ + int aad_length_octets; /* octets in AAD */ + const uint8_t *aad; /* AAD */ + int tag_length_octets; /* Length of AEAD tag */ + const struct srtp_cipher_test_case_t + *next_test_case; /* pointer to next testcase */ } srtp_cipher_test_case_t; /* srtp_cipher_type_t defines the 'metadata' for a particular cipher type */ @@ -148,8 +156,8 @@ typedef struct srtp_cipher_type_t { srtp_cipher_encrypt_func_t decrypt; srtp_cipher_set_iv_func_t set_iv; srtp_cipher_get_tag_func_t get_tag; - const char *description; - const srtp_cipher_test_case_t *test_data; + const char *description; + const srtp_cipher_test_case_t *test_data; srtp_cipher_type_id_t id; } srtp_cipher_type_t; @@ -159,7 +167,7 @@ typedef struct srtp_cipher_type_t { */ typedef struct srtp_cipher_t { const srtp_cipher_type_t *type; - void *state; + void *state; int key_len; int algorithm; } srtp_cipher_t; @@ -167,7 +175,6 @@ typedef struct srtp_cipher_t { /* some bookkeeping functions */ int srtp_cipher_get_key_length(const srtp_cipher_t *c); - /* * srtp_cipher_type_self_test() tests a cipher against test cases provided in * an array of values of key/srtp_xtd_seq_num_t/plaintext/ciphertext @@ -175,14 +182,15 @@ int srtp_cipher_get_key_length(const srtp_cipher_t *c); */ srtp_err_status_t srtp_cipher_type_self_test(const srtp_cipher_type_t *ct); - /* - * srtp_cipher_type_test() tests a cipher against external test cases provided in + * srtp_cipher_type_test() tests a cipher against external test cases provided + * in * an array of values of key/srtp_xtd_seq_num_t/plaintext/ciphertext * that is known to be good */ -srtp_err_status_t srtp_cipher_type_test(const srtp_cipher_type_t *ct, const srtp_cipher_test_case_t *test_data); - +srtp_err_status_t srtp_cipher_type_test( + const srtp_cipher_type_t *ct, + const srtp_cipher_test_case_t *test_data); /* * srtp_cipher_bits_per_second(c, l, t) computes (an estimate of) the @@ -194,17 +202,34 @@ srtp_err_status_t srtp_cipher_type_test(const srtp_cipher_type_t *ct, const srtp * * if an error is encountered, then the value 0 is returned */ -uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c, int octets_in_buffer, int num_trials); +uint64_t srtp_cipher_bits_per_second(srtp_cipher_t *c, + int octets_in_buffer, + int num_trials); -srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct, srtp_cipher_t **c, int key_len, int tlen); +srtp_err_status_t srtp_cipher_type_alloc(const srtp_cipher_type_t *ct, + srtp_cipher_t **c, + int key_len, + int tlen); srtp_err_status_t srtp_cipher_dealloc(srtp_cipher_t *c); srtp_err_status_t srtp_cipher_init(srtp_cipher_t *c, const uint8_t *key); -srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c, uint8_t *iv, int direction); -srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output); -srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output); -srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c, uint8_t *buffer, uint32_t *num_octets_to_output); -srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c, uint8_t *buffer, uint32_t *tag_len); -srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c, const uint8_t *aad, uint32_t aad_len); +srtp_err_status_t srtp_cipher_set_iv(srtp_cipher_t *c, + uint8_t *iv, + int direction); +srtp_err_status_t srtp_cipher_output(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output); +srtp_err_status_t srtp_cipher_encrypt(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output); +srtp_err_status_t srtp_cipher_decrypt(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *num_octets_to_output); +srtp_err_status_t srtp_cipher_get_tag(srtp_cipher_t *c, + uint8_t *buffer, + uint32_t *tag_len); +srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c, + const uint8_t *aad, + uint32_t aad_len); /* * srtp_replace_cipher_type(ct, id) @@ -213,7 +238,8 @@ srtp_err_status_t srtp_cipher_set_aad(srtp_cipher_t *c, const uint8_t *aad, uint * with a new one passed in externally. The new cipher must pass all the * existing cipher_type's self tests as well as its own. */ -srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *ct, srtp_cipher_type_id_t id); +srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *ct, + srtp_cipher_type_id_t id); #ifdef __cplusplus } diff --git a/libs/srtp/include/rtp_priv.h b/libs/srtp/crypto/include/cipher_types.h similarity index 57% rename from libs/srtp/include/rtp_priv.h rename to libs/srtp/crypto/include/cipher_types.h index 1421386673..a543b5478b 100644 --- a/libs/srtp/include/rtp_priv.h +++ b/libs/srtp/crypto/include/cipher_types.h @@ -1,32 +1,24 @@ /* - * rtp_priv.h * - * private, internal header file for RTP - * - * David A. McGrew - * Cisco Systems, Inc. - */ -/* - * - * Copyright (c) 2001-2006 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 @@ -42,33 +34,48 @@ * */ +#ifndef CIHPER_TYPES_H +#define CIHPER_TYPES_H -#ifndef RTP_PRIV_H -#define RTP_PRIV_H +#include "cipher.h" +#include "auth.h" -#include "srtp_priv.h" -#include "rtp.h" +/* + * cipher types that can be included in the kernel + */ -typedef srtp_hdr_t rtp_hdr_t; +extern const srtp_cipher_type_t srtp_null_cipher; +extern const srtp_cipher_type_t srtp_aes_icm_128; +extern const srtp_cipher_type_t srtp_aes_icm_256; +#ifdef OPENSSL +extern const srtp_cipher_type_t srtp_aes_icm_192; +extern const srtp_cipher_type_t srtp_aes_gcm_128_openssl; +extern const srtp_cipher_type_t srtp_aes_gcm_256_openssl; +#endif -typedef struct { - srtp_hdr_t header; - char body[RTP_MAX_BUF_LEN]; -} rtp_msg_t; +/* + * auth func types that can be included in the kernel + */ -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; +extern const srtp_auth_type_t srtp_null_auth; +extern const srtp_auth_type_t srtp_hmac; -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; +/* + * other generic debug modules that can be included in the kernel + */ +extern srtp_debug_module_t srtp_mod_auth; +extern srtp_debug_module_t srtp_mod_cipher; +extern srtp_debug_module_t srtp_mod_stat; +extern srtp_debug_module_t srtp_mod_alloc; -#endif /* RTP_PRIV_H */ +/* debug modules for cipher types */ +extern srtp_debug_module_t srtp_mod_aes_icm; +#ifdef OPENSSL +extern srtp_debug_module_t srtp_mod_aes_gcm; +#endif + +/* debug modules for auth types */ +extern srtp_debug_module_t srtp_mod_hmac; + +#endif diff --git a/libs/srtp/crypto/include/crypto_kernel.h b/libs/srtp/crypto/include/crypto_kernel.h index 1abf383f5a..1f8dfa7712 100644 --- a/libs/srtp/crypto/include/crypto_kernel.h +++ b/libs/srtp/crypto/include/crypto_kernel.h @@ -42,7 +42,6 @@ * */ - #ifndef CRYPTO_KERNEL #define CRYPTO_KERNEL @@ -72,7 +71,7 @@ typedef enum { */ typedef struct srtp_kernel_cipher_type { srtp_cipher_type_id_t id; - const srtp_cipher_type_t *cipher_type; + const srtp_cipher_type_t *cipher_type; struct srtp_kernel_cipher_type *next; } srtp_kernel_cipher_type_t; @@ -81,7 +80,7 @@ typedef struct srtp_kernel_cipher_type { */ typedef struct srtp_kernel_auth_type { srtp_auth_type_id_t id; - const srtp_auth_type_t *auth_type; + const srtp_auth_type_t *auth_type; struct srtp_kernel_auth_type *next; } srtp_kernel_auth_type_t; @@ -93,7 +92,6 @@ typedef struct srtp_kernel_debug_module { struct srtp_kernel_debug_module *next; } srtp_kernel_debug_module_t; - /* * crypto_kernel_t is the data structure for the crypto kernel * @@ -101,18 +99,17 @@ typedef struct srtp_kernel_debug_module { * a global variable defined in crypto_kernel.c */ typedef struct { - srtp_crypto_kernel_state_t state; /* current state of kernel */ - srtp_kernel_cipher_type_t *cipher_type_list; /* list of all cipher types */ - srtp_kernel_auth_type_t *auth_type_list; /* list of all auth func types */ - srtp_kernel_debug_module_t *debug_module_list; /* list of all debug modules */ + srtp_crypto_kernel_state_t state; /* current state of kernel */ + srtp_kernel_cipher_type_t *cipher_type_list; /* list of all cipher types */ + srtp_kernel_auth_type_t *auth_type_list; /* list of all auth func types */ + srtp_kernel_debug_module_t + *debug_module_list; /* list of all debug modules */ } srtp_crypto_kernel_t; - /* * srtp_crypto_kernel_t external api */ - /* * The function srtp_crypto_kernel_init() initialized the crypto kernel and * runs the self-test operations on the random number generators and @@ -126,7 +123,6 @@ typedef struct { */ srtp_err_status_t srtp_crypto_kernel_init(void); - /* * The function srtp_crypto_kernel_shutdown() de-initializes the * crypto_kernel, zeroizes keys and other cryptographic material, and @@ -150,7 +146,6 @@ srtp_err_status_t srtp_crypto_kernel_shutdown(void); */ srtp_err_status_t srtp_crypto_kernel_status(void); - /* * srtp_crypto_kernel_list_debug_modules() outputs a list of debugging modules * @@ -161,11 +156,15 @@ srtp_err_status_t srtp_crypto_kernel_list_debug_modules(void); * srtp_crypto_kernel_load_cipher_type() * */ -srtp_err_status_t srtp_crypto_kernel_load_cipher_type(const srtp_cipher_type_t *ct, srtp_cipher_type_id_t id); +srtp_err_status_t srtp_crypto_kernel_load_cipher_type( + const srtp_cipher_type_t *ct, + srtp_cipher_type_id_t id); -srtp_err_status_t srtp_crypto_kernel_load_auth_type(const srtp_auth_type_t *ct, srtp_auth_type_id_t id); +srtp_err_status_t srtp_crypto_kernel_load_auth_type(const srtp_auth_type_t *ct, + srtp_auth_type_id_t id); -srtp_err_status_t srtp_crypto_kernel_load_debug_module(srtp_debug_module_t *new_dm); +srtp_err_status_t srtp_crypto_kernel_load_debug_module( + srtp_debug_module_t *new_dm); /* * srtp_crypto_kernel_alloc_cipher(id, cp, key_len); @@ -177,7 +176,10 @@ srtp_err_status_t srtp_crypto_kernel_load_debug_module(srtp_debug_module_t *new_ * srtp_err_status_alloc_fail an allocation failure occured * srtp_err_status_fail couldn't find cipher with identifier 'id' */ -srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id, srtp_cipher_pointer_t *cp, int key_len, int tag_len); +srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id, + srtp_cipher_pointer_t *cp, + int key_len, + int tag_len); /* * srtp_crypto_kernel_alloc_auth(id, ap, key_len, tag_len); @@ -190,8 +192,10 @@ srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id, srtp * srtp_err_status_alloc_fail an allocation failure occured * srtp_err_status_fail couldn't find auth with identifier 'id' */ -srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id, srtp_auth_pointer_t *ap, int key_len, int tag_len); - +srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id, + srtp_auth_pointer_t *ap, + int key_len, + int tag_len); /* * srtp_crypto_kernel_set_debug_module(mod_name, v) @@ -201,7 +205,8 @@ srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id, srtp_aut * * returns srtp_err_status_ok on success, srtp_err_status_fail otherwise */ -srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *mod_name, int v); +srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *mod_name, + int v); #ifdef __cplusplus } diff --git a/libs/srtp/crypto/include/crypto_types.h b/libs/srtp/crypto/include/crypto_types.h index 329d60dbd1..7fd3178b0b 100644 --- a/libs/srtp/crypto/include/crypto_types.h +++ b/libs/srtp/crypto/include/crypto_types.h @@ -7,26 +7,26 @@ * 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 @@ -48,62 +48,62 @@ /* * The null cipher performs no encryption. * - * The SRTP_NULL_CIPHER leaves its inputs unaltered, during both the + * The SRTP_NULL_CIPHER leaves its inputs unaltered, during both the * encryption and decryption operations. This cipher can be chosen * to indicate that no encryption is to be performed. */ -#define SRTP_NULL_CIPHER 0 +#define SRTP_NULL_CIPHER 0 -/* +/* * AES-128 Integer Counter Mode (AES ICM) * * AES-128 ICM is the variant of counter mode that is used by * Secure RTP. This cipher uses a 16-octet key concatenated with a * 14-octet offset (or salt) value. */ -#define SRTP_AES_ICM_128 1 +#define SRTP_AES_ICM_128 1 -/* +/* * AES-192 Integer Counter Mode (AES ICM) * * AES-128 ICM is the variant of counter mode that is used by * Secure RTP. This cipher uses a 24-octet key concatenated with a * 14-octet offset (or salt) value. */ -#define SRTP_AES_ICM_192 4 +#define SRTP_AES_ICM_192 4 -/* +/* * AES-256 Integer Counter Mode (AES ICM) * * AES-128 ICM is the variant of counter mode that is used by * Secure RTP. This cipher uses a 32-octet key concatenated with a * 14-octet offset (or salt) value. */ -#define SRTP_AES_ICM_256 5 +#define SRTP_AES_ICM_256 5 -/* - * AES-128_GCM Galois Counter Mode (AES GCM) +/* + * AES-128_GCM Galois Counter Mode (AES GCM) * - * AES-128 GCM is the variant of galois counter mode that is used by + * AES-128 GCM is the variant of galois counter mode that is used by * Secure RTP. This cipher uses a 16-octet key. */ -#define SRTP_AES_GCM_128 6 +#define SRTP_AES_GCM_128 6 -/* - * AES-256_GCM Galois Counter Mode (AES GCM) +/* + * AES-256_GCM Galois Counter Mode (AES GCM) * - * AES-256 GCM is the variant of galois counter mode that is used by + * AES-256 GCM is the variant of galois counter mode that is used by * Secure RTP. This cipher uses a 32-octet key. */ -#define SRTP_AES_GCM_256 7 +#define SRTP_AES_GCM_256 7 /* * The null authentication function performs no authentication. * * The NULL_AUTH function does nothing, and can be selected to indicate * that authentication should not be performed. - */ -#define SRTP_NULL_AUTH 0 + */ +#define SRTP_NULL_AUTH 0 /* * HMAC-SHA1 @@ -111,6 +111,6 @@ * SRTP_HMAC_SHA1 implements the Hash-based MAC using the NIST Secure * Hash Algorithm version 1 (SHA1). */ -#define SRTP_HMAC_SHA1 3 +#define SRTP_HMAC_SHA1 3 -#endif /* SRTP_CRYPTO_TYPES_H */ +#endif /* SRTP_CRYPTO_TYPES_H */ diff --git a/libs/srtp/crypto/include/datatypes.h b/libs/srtp/crypto/include/datatypes.h index 8440376824..182cca25b9 100644 --- a/libs/srtp/crypto/include/datatypes.h +++ b/libs/srtp/crypto/include/datatypes.h @@ -1,6 +1,6 @@ /* * datatypes.h - * + * * data types for bit vectors and finite fields * * David A. McGrew @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -43,11 +43,10 @@ * */ - #ifndef DATATYPES_H #define DATATYPES_H -#include "integers.h" /* definitions of uint32_t, et cetera */ +#include "integers.h" /* definitions of uint32_t, et cetera */ #include "alloc.h" #include @@ -56,42 +55,43 @@ #include #include #ifdef HAVE_NETINET_IN_H -# include +#include #elif defined HAVE_WINSOCK2_H -# include +#include +#else +#error "Platform not recognized" #endif #ifdef __cplusplus extern "C" { #endif - /* if DATATYPES_USE_MACROS is defined, then little functions are macros */ -#define DATATYPES_USE_MACROS +#define DATATYPES_USE_MACROS typedef union { - uint8_t v8[2]; - uint16_t value; + uint8_t v8[2]; + uint16_t value; } v16_t; typedef union { - uint8_t v8[4]; - uint16_t v16[2]; - uint32_t value; + uint8_t v8[4]; + uint16_t v16[2]; + uint32_t value; } v32_t; typedef union { - uint8_t v8[8]; - uint16_t v16[4]; - uint32_t v32[2]; - uint64_t value; + uint8_t v8[8]; + uint16_t v16[4]; + uint32_t v32[2]; + uint64_t value; } v64_t; typedef union { - uint8_t v8[16]; - uint16_t v16[8]; - uint32_t v32[4]; - uint64_t v64[2]; + uint8_t v8[16]; + uint16_t v16[8]; + uint32_t v32[4]; + uint64_t v64[2]; } v128_t; typedef union { @@ -101,118 +101,82 @@ typedef union { uint64_t v64[4]; } v256_t; - /* some useful and simple math functions */ -#define pow_2(X) ( (unsigned int)1 << (X) ) /* 2^X */ - -#define pow_minus_one(X) ( (X) ? -1 : 1 ) /* (-1)^X */ +#define pow_2(X) ((unsigned int)1 << (X)) /* 2^X */ +#define pow_minus_one(X) ((X) ? -1 : 1) /* (-1)^X */ /* * octet_get_weight(x) returns the hamming weight (number of bits equal to * one) in the octet x */ -int -octet_get_weight(uint8_t octet); +int octet_get_weight(uint8_t octet); #define MAX_PRINT_STRING_LEN 1024 -char * -srtp_octet_string_hex_string(const void *str, int length); +char *srtp_octet_string_hex_string(const void *str, int length); -char * -v128_bit_string(v128_t *x); +char *v128_bit_string(v128_t *x); -char * -v128_hex_string(v128_t *x); +char *v128_hex_string(v128_t *x); -void -v128_copy_octet_string(v128_t *x, const uint8_t s[16]); +void v128_copy_octet_string(v128_t *x, const uint8_t s[16]); -void -v128_left_shift(v128_t *x, int shift_index); +void v128_left_shift(v128_t *x, int shift_index); -void -v128_right_shift(v128_t *x, int shift_index); +void v128_right_shift(v128_t *x, int shift_index); /* * the following macros define the data manipulation functions - * + * * If DATATYPES_USE_MACROS is defined, then these macros are used * directly (and function call overhead is avoided). Otherwise, * the macros are used through the functions defined in datatypes.c * (and the compiler provides better warnings). */ -#define _v128_set_to_zero(x) \ -( \ - (x)->v32[0] = 0, \ - (x)->v32[1] = 0, \ - (x)->v32[2] = 0, \ - (x)->v32[3] = 0 \ -) +#define _v128_set_to_zero(x) \ + ((x)->v32[0] = 0, (x)->v32[1] = 0, (x)->v32[2] = 0, (x)->v32[3] = 0) -#define _v128_copy(x, y) \ -( \ - (x)->v32[0] = (y)->v32[0], \ - (x)->v32[1] = (y)->v32[1], \ - (x)->v32[2] = (y)->v32[2], \ - (x)->v32[3] = (y)->v32[3] \ -) +#define _v128_copy(x, y) \ + ((x)->v32[0] = (y)->v32[0], (x)->v32[1] = (y)->v32[1], \ + (x)->v32[2] = (y)->v32[2], (x)->v32[3] = (y)->v32[3]) -#define _v128_xor(z, x, y) \ -( \ - (z)->v32[0] = (x)->v32[0] ^ (y)->v32[0], \ - (z)->v32[1] = (x)->v32[1] ^ (y)->v32[1], \ - (z)->v32[2] = (x)->v32[2] ^ (y)->v32[2], \ - (z)->v32[3] = (x)->v32[3] ^ (y)->v32[3] \ -) +#define _v128_xor(z, x, y) \ + ((z)->v32[0] = (x)->v32[0] ^ (y)->v32[0], \ + (z)->v32[1] = (x)->v32[1] ^ (y)->v32[1], \ + (z)->v32[2] = (x)->v32[2] ^ (y)->v32[2], \ + (z)->v32[3] = (x)->v32[3] ^ (y)->v32[3]) -#define _v128_and(z, x, y) \ -( \ - (z)->v32[0] = (x)->v32[0] & (y)->v32[0], \ - (z)->v32[1] = (x)->v32[1] & (y)->v32[1], \ - (z)->v32[2] = (x)->v32[2] & (y)->v32[2], \ - (z)->v32[3] = (x)->v32[3] & (y)->v32[3] \ -) +#define _v128_and(z, x, y) \ + ((z)->v32[0] = (x)->v32[0] & (y)->v32[0], \ + (z)->v32[1] = (x)->v32[1] & (y)->v32[1], \ + (z)->v32[2] = (x)->v32[2] & (y)->v32[2], \ + (z)->v32[3] = (x)->v32[3] & (y)->v32[3]) -#define _v128_or(z, x, y) \ -( \ - (z)->v32[0] = (x)->v32[0] | (y)->v32[0], \ - (z)->v32[1] = (x)->v32[1] | (y)->v32[1], \ - (z)->v32[2] = (x)->v32[2] | (y)->v32[2], \ - (z)->v32[3] = (x)->v32[3] | (y)->v32[3] \ -) +#define _v128_or(z, x, y) \ + ((z)->v32[0] = (x)->v32[0] | (y)->v32[0], \ + (z)->v32[1] = (x)->v32[1] | (y)->v32[1], \ + (z)->v32[2] = (x)->v32[2] | (y)->v32[2], \ + (z)->v32[3] = (x)->v32[3] | (y)->v32[3]) -#define _v128_complement(x) \ -( \ - (x)->v32[0] = ~(x)->v32[0], \ - (x)->v32[1] = ~(x)->v32[1], \ - (x)->v32[2] = ~(x)->v32[2], \ - (x)->v32[3] = ~(x)->v32[3] \ -) +#define _v128_complement(x) \ + ((x)->v32[0] = ~(x)->v32[0], (x)->v32[1] = ~(x)->v32[1], \ + (x)->v32[2] = ~(x)->v32[2], (x)->v32[3] = ~(x)->v32[3]) /* ok for NO_64BIT_MATH if it can compare uint64_t's (even as structures) */ -#define _v128_is_eq(x, y) \ - (((x)->v64[0] == (y)->v64[0]) && ((x)->v64[1] == (y)->v64[1])) - +#define _v128_is_eq(x, y) \ + (((x)->v64[0] == (y)->v64[0]) && ((x)->v64[1] == (y)->v64[1])) #ifdef NO_64BIT_MATH -#define _v128_xor_eq(z, x) \ -( \ - (z)->v32[0] ^= (x)->v32[0], \ - (z)->v32[1] ^= (x)->v32[1], \ - (z)->v32[2] ^= (x)->v32[2], \ - (z)->v32[3] ^= (x)->v32[3] \ -) +#define _v128_xor_eq(z, x) \ + ((z)->v32[0] ^= (x)->v32[0], (z)->v32[1] ^= (x)->v32[1], \ + (z)->v32[2] ^= (x)->v32[2], (z)->v32[3] ^= (x)->v32[3]) #else -#define _v128_xor_eq(z, x) \ -( \ - (z)->v64[0] ^= (x)->v64[0], \ - (z)->v64[1] ^= (x)->v64[1] \ -) +#define _v128_xor_eq(z, x) \ + ((z)->v64[0] ^= (x)->v64[0], (z)->v64[1] ^= (x)->v64[1]) #endif /* NOTE! This assumes an odd ordering! */ @@ -224,76 +188,55 @@ v128_right_shift(v128_t *x, int shift_index); really care which bit is which. AES does care which bit is which, but doesn't use the 128-bit get/set or 128-bit shifts */ -#define _v128_get_bit(x, bit) \ -( \ - ((((x)->v32[(bit) >> 5]) >> ((bit) & 31)) & 1) \ -) +#define _v128_get_bit(x, bit) (((((x)->v32[(bit) >> 5]) >> ((bit)&31)) & 1)) -#define _v128_set_bit(x, bit) \ -( \ - (((x)->v32[(bit) >> 5]) |= ((uint32_t)1 << ((bit) & 31))) \ -) +#define _v128_set_bit(x, bit) \ + ((((x)->v32[(bit) >> 5]) |= ((uint32_t)1 << ((bit)&31)))) -#define _v128_clear_bit(x, bit) \ -( \ - (((x)->v32[(bit) >> 5]) &= ~((uint32_t)1 << ((bit) & 31))) \ -) +#define _v128_clear_bit(x, bit) \ + ((((x)->v32[(bit) >> 5]) &= ~((uint32_t)1 << ((bit)&31)))) -#define _v128_set_bit_to(x, bit, value) \ -( \ - (value) ? _v128_set_bit(x, bit) : \ - _v128_clear_bit(x, bit) \ -) +#define _v128_set_bit_to(x, bit, value) \ + ((value) ? _v128_set_bit(x, bit) : _v128_clear_bit(x, bit)) -#ifdef DATATYPES_USE_MACROS /* little functions are really macros */ - -#define v128_set_to_zero(z) _v128_set_to_zero(z) -#define v128_copy(z, x) _v128_copy(z, x) -#define v128_xor(z, x, y) _v128_xor(z, x, y) -#define v128_and(z, x, y) _v128_and(z, x, y) -#define v128_or(z, x, y) _v128_or(z, x, y) -#define v128_complement(x) _v128_complement(x) -#define v128_is_eq(x, y) _v128_is_eq(x, y) -#define v128_xor_eq(x, y) _v128_xor_eq(x, y) -#define v128_get_bit(x, i) _v128_get_bit(x, i) -#define v128_set_bit(x, i) _v128_set_bit(x, i) -#define v128_clear_bit(x, i) _v128_clear_bit(x, i) -#define v128_set_bit_to(x, i, y) _v128_set_bit_to(x, i, y) +#ifdef DATATYPES_USE_MACROS /* little functions are really macros */ + +#define v128_set_to_zero(z) _v128_set_to_zero(z) +#define v128_copy(z, x) _v128_copy(z, x) +#define v128_xor(z, x, y) _v128_xor(z, x, y) +#define v128_and(z, x, y) _v128_and(z, x, y) +#define v128_or(z, x, y) _v128_or(z, x, y) +#define v128_complement(x) _v128_complement(x) +#define v128_is_eq(x, y) _v128_is_eq(x, y) +#define v128_xor_eq(x, y) _v128_xor_eq(x, y) +#define v128_get_bit(x, i) _v128_get_bit(x, i) +#define v128_set_bit(x, i) _v128_set_bit(x, i) +#define v128_clear_bit(x, i) _v128_clear_bit(x, i) +#define v128_set_bit_to(x, i, y) _v128_set_bit_to(x, i, y) #else -void -v128_set_to_zero(v128_t *x); +void v128_set_to_zero(v128_t *x); -int -v128_is_eq(const v128_t *x, const v128_t *y); +int v128_is_eq(const v128_t *x, const v128_t *y); -void -v128_copy(v128_t *x, const v128_t *y); +void v128_copy(v128_t *x, const v128_t *y); -void -v128_xor(v128_t *z, v128_t *x, v128_t *y); +void v128_xor(v128_t *z, v128_t *x, v128_t *y); -void -v128_and(v128_t *z, v128_t *x, v128_t *y); +void v128_and(v128_t *z, v128_t *x, v128_t *y); -void -v128_or(v128_t *z, v128_t *x, v128_t *y); +void v128_or(v128_t *z, v128_t *x, v128_t *y); -void -v128_complement(v128_t *x); +void v128_complement(v128_t *x); -int -v128_get_bit(const v128_t *x, int i); +int v128_get_bit(const v128_t *x, int i); -void -v128_set_bit(v128_t *x, int i) ; +void v128_set_bit(v128_t *x, int i); -void -v128_clear_bit(v128_t *x, int i); +void v128_clear_bit(v128_t *x, int i); -void -v128_set_bit_to(v128_t *x, int i, int y); +void v128_set_bit_to(v128_t *x, int i, int y); #endif /* DATATYPES_USE_MACROS */ @@ -304,113 +247,102 @@ v128_set_bit_to(v128_t *x, int i, int y); * verifying authentication tags. */ -int -octet_string_is_eq(uint8_t *a, uint8_t *b, int len); +int octet_string_is_eq(uint8_t *a, uint8_t *b, int len); /* * A portable way to zero out memory as recommended by * https://cryptocoding.net/index.php/Coding_rules#Clean_memory_of_secret_data * This is used to zero memory when OPENSSL_cleanse() is not available. */ -void -srtp_cleanse(void *s, size_t len); +void srtp_cleanse(void *s, size_t len); /* * Functions as a wrapper that delegates to either srtp_cleanse() or * OPENSSL_cleanse() if available to zero memory. */ -void -octet_string_set_to_zero(void *s, size_t len); +void octet_string_set_to_zero(void *s, size_t len); -#if defined(HAVE_CONFIG_H) +#if defined(HAVE_CONFIG_H) -/* +/* * Convert big endian integers to CPU byte order. */ #ifdef WORDS_BIGENDIAN /* Nothing to do. */ -# define be32_to_cpu(x) (x) -# define be64_to_cpu(x) (x) +#define be32_to_cpu(x) (x) +#define be64_to_cpu(x) (x) #elif defined(HAVE_BYTESWAP_H) /* We have (hopefully) optimized versions in byteswap.h */ -# include -# define be32_to_cpu(x) bswap_32((x)) -# define be64_to_cpu(x) bswap_64((x)) -#else +#include +#define be32_to_cpu(x) bswap_32((x)) +#define be64_to_cpu(x) bswap_64((x)) +#else /* WORDS_BIGENDIAN */ #if defined(__GNUC__) && defined(HAVE_X86) /* Fall back. */ -static inline uint32_t be32_to_cpu(uint32_t v) { - /* optimized for x86. */ - __asm__("bswap %0" : "=r" (v) : "0" (v)); - return v; +static inline uint32_t be32_to_cpu(uint32_t v) +{ + /* optimized for x86. */ + asm("bswap %0" : "=r"(v) : "0"(v)); + return v; } -# else /* HAVE_X86 */ -# ifdef HAVE_NETINET_IN_H -# include -# elif defined HAVE_WINSOCK2_H -# include -# endif -# define be32_to_cpu(x) ntohl((x)) -# endif /* HAVE_X86 */ +#else /* HAVE_X86 */ +#ifdef HAVE_NETINET_IN_H +#include +#elif defined HAVE_WINSOCK2_H +#include +#endif /* HAVE_NETINET_IN_H */ +#define be32_to_cpu(x) ntohl((x)) +#endif /* HAVE_X86 */ -static inline uint64_t be64_to_cpu(uint64_t v) { -# ifdef NO_64BIT_MATH - /* use the make64 functions to do 64-bit math */ - v = make64(htonl(low32(v)),htonl(high32(v))); -# else - /* use the native 64-bit math */ - v= (uint64_t)((be32_to_cpu((uint32_t)(v >> 32))) | (((uint64_t)be32_to_cpu((uint32_t)v)) << 32)); -# endif - return v; +static inline uint64_t be64_to_cpu(uint64_t v) +{ +#ifdef NO_64BIT_MATH + /* use the make64 functions to do 64-bit math */ + v = make64(htonl(low32(v)), htonl(high32(v))); +#else /* NO_64BIT_MATH */ + /* use the native 64-bit math */ + v = (uint64_t)((be32_to_cpu((uint32_t)(v >> 32))) | + (((uint64_t)be32_to_cpu((uint32_t)v)) << 32)); +#endif /* NO_64BIT_MATH */ + return v; } -#endif - #endif /* WORDS_BIGENDIAN */ +#endif /* HAVE_CONFIG_H */ + /* - * functions manipulating bitvector_t + * functions manipulating bitvector_t * * A bitvector_t consists of an array of words and an integer * representing the number of significant bits stored in the array. * The bits are packed as follows: the least significant bit is that * of word[0], while the most significant bit is the nth most * significant bit of word[m], where length = bits_per_word * m + n. - * + * */ -#define bits_per_word 32 +#define bits_per_word 32 #define bytes_per_word 4 typedef struct { - uint32_t length; - uint32_t *word; + uint32_t length; + uint32_t *word; } bitvector_t; +#define _bitvector_get_bit(v, bit_index) \ + (((((v)->word[((bit_index) >> 5)]) >> ((bit_index)&31)) & 1)) -#define _bitvector_get_bit(v, bit_index) \ -( \ - ((((v)->word[((bit_index) >> 5)]) >> ((bit_index) & 31)) & 1) \ -) +#define _bitvector_set_bit(v, bit_index) \ + ((((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index)&31))))) +#define _bitvector_clear_bit(v, bit_index) \ + ((((v)->word[((bit_index) >> 5)] &= ~((uint32_t)1 << ((bit_index)&31))))) -#define _bitvector_set_bit(v, bit_index) \ -( \ - (((v)->word[((bit_index) >> 5)] |= ((uint32_t)1 << ((bit_index) & 31)))) \ -) +#define _bitvector_get_length(v) (((v)->length)) -#define _bitvector_clear_bit(v, bit_index) \ -( \ - (((v)->word[((bit_index) >> 5)] &= ~((uint32_t)1 << ((bit_index) & 31)))) \ -) - -#define _bitvector_get_length(v) \ -( \ - ((v)->length) \ -) - -#ifdef DATATYPES_USE_MACROS /* little functions are really macros */ +#ifdef DATATYPES_USE_MACROS /* little functions are really macros */ #define bitvector_get_bit(v, bit_index) _bitvector_get_bit(v, bit_index) #define bitvector_set_bit(v, bit_index) _bitvector_set_bit(v, bit_index) @@ -419,34 +351,25 @@ typedef struct { #else -int -bitvector_get_bit(const bitvector_t *v, int bit_index); +int bitvector_get_bit(const bitvector_t *v, int bit_index); -void -bitvector_set_bit(bitvector_t *v, int bit_index); +void bitvector_set_bit(bitvector_t *v, int bit_index); -void -bitvector_clear_bit(bitvector_t *v, int bit_index); +void bitvector_clear_bit(bitvector_t *v, int bit_index); -unsigned long -bitvector_get_length(const bitvector_t *v); +unsigned long bitvector_get_length(const bitvector_t *v); #endif -int -bitvector_alloc(bitvector_t *v, unsigned long length); +int bitvector_alloc(bitvector_t *v, unsigned long length); -void -bitvector_dealloc(bitvector_t *v); +void bitvector_dealloc(bitvector_t *v); -void -bitvector_set_to_zero(bitvector_t *x); +void bitvector_set_to_zero(bitvector_t *x); -void -bitvector_left_shift(bitvector_t *x, int index); +void bitvector_left_shift(bitvector_t *x, int index); -char * -bitvector_bit_string(bitvector_t *x, char* buf, int len); +char *bitvector_bit_string(bitvector_t *x, char *buf, int len); #ifdef __cplusplus } diff --git a/libs/srtp/crypto/include/err.h b/libs/srtp/crypto/include/err.h index b6f196da84..66a1023ec8 100644 --- a/libs/srtp/crypto/include/err.h +++ b/libs/srtp/crypto/include/err.h @@ -42,7 +42,6 @@ * */ - #ifndef ERR_H #define ERR_H @@ -62,7 +61,6 @@ extern "C" { * @{ */ - /** * @} */ @@ -82,9 +80,11 @@ typedef enum { srtp_err_status_t srtp_err_reporting_init(void); -typedef void (srtp_err_report_handler_func_t)(srtp_err_reporting_level_t level, const char * msg); +typedef void(srtp_err_report_handler_func_t)(srtp_err_reporting_level_t level, + const char *msg); -srtp_err_status_t srtp_install_err_report_handler(srtp_err_report_handler_func_t func); +srtp_err_status_t srtp_install_err_report_handler( + srtp_err_report_handler_func_t func); /* * srtp_err_report reports a 'printf' formatted error @@ -96,9 +96,7 @@ srtp_err_status_t srtp_install_err_report_handler(srtp_err_report_handler_func_t * */ -void -srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...); - +void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...); /* * debug_module_t defines a debug module @@ -111,17 +109,21 @@ typedef struct { #ifdef ENABLE_DEBUG_LOGGING -#define debug_print(mod, format, arg) \ +#define debug_print(mod, format, arg) \ srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg) -#define debug_print2(mod, format, arg1, arg2) \ - srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg1, arg2) +#define debug_print2(mod, format, arg1, arg2) \ + srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, \ + arg1, arg2) #else -#define debug_print(mod, format, arg) \ - if (mod.on) srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg) -#define debug_print2(mod, format, arg1, arg2) \ - if (mod.on) srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg1, arg2) +#define debug_print(mod, format, arg) \ + if (mod.on) \ + srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, arg) +#define debug_print2(mod, format, arg1, arg2) \ + if (mod.on) \ + srtp_err_report(srtp_err_level_debug, ("%s: " format "\n"), mod.name, \ + arg1, arg2) #endif diff --git a/libs/srtp/crypto/include/integers.h b/libs/srtp/crypto/include/integers.h index 4a871c7085..f2cd7c064d 100644 --- a/libs/srtp/crypto/include/integers.h +++ b/libs/srtp/crypto/include/integers.h @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -43,29 +43,27 @@ * */ - #ifndef INTEGERS_H #define INTEGERS_H - /* use standard integer definitions, if they're available */ #ifdef HAVE_STDLIB_H -# include +#include #endif #ifdef HAVE_STDINT_H -# include +#include #endif #ifdef HAVE_INTTYPES_H -# include +#include #endif #ifdef HAVE_SYS_TYPES_H -# include +#include #endif #ifdef HAVE_SYS_INT_TYPES_H -# include /* this exists on Sun OS */ +#include /* this exists on Sun OS */ #endif #ifdef HAVE_MACHINE_TYPES_H -# include +#include #endif #ifdef __cplusplus @@ -74,31 +72,30 @@ extern "C" { /* Can we do 64 bit integers? */ #if !defined(HAVE_UINT64_T) -# if SIZEOF_UNSIGNED_LONG == 8 -typedef unsigned long uint64_t; -# elif SIZEOF_UNSIGNED_LONG_LONG == 8 -typedef unsigned long long uint64_t; -# else -# define NO_64BIT_MATH 1 -# endif +#if SIZEOF_UNSIGNED_LONG == 8 +typedef unsigned long uint64_t; +#elif SIZEOF_UNSIGNED_LONG_LONG == 8 +typedef unsigned long long uint64_t; +#else +#define NO_64BIT_MATH 1 +#endif #endif /* Reasonable defaults for 32 bit machines - you may need to * edit these definitions for your own machine. */ #ifndef HAVE_UINT8_T -typedef unsigned char uint8_t; +typedef unsigned char uint8_t; #endif #ifndef HAVE_UINT16_T -typedef unsigned short int uint16_t; +typedef unsigned short int uint16_t; #endif #ifndef HAVE_UINT32_T -typedef unsigned int uint32_t; +typedef unsigned int uint32_t; #endif #ifndef HAVE_INT32_T typedef int int32_t; #endif - #if defined(NO_64BIT_MATH) && defined(HAVE_CONFIG_H) typedef double uint64_t; /* assert that sizeof(double) == 8 */ @@ -107,39 +104,38 @@ extern uint32_t high32(uint64_t value); extern uint32_t low32(uint64_t value); #endif - /* These macros are to load and store 32-bit values from un-aligned addresses. This is required for processors that do not allow unaligned loads. */ #ifdef ALIGNMENT_32BIT_REQUIRED /* Note that if it's in a variable, you can memcpy it */ #ifdef WORDS_BIGENDIAN -#define PUT_32(addr,value) \ - { \ - ((unsigned char *) (addr))[0] = (value >> 24); \ - ((unsigned char *) (addr))[1] = (value >> 16) & 0xff; \ - ((unsigned char *) (addr))[2] = (value >> 8) & 0xff; \ - ((unsigned char *) (addr))[3] = (value) & 0xff; \ +#define PUT_32(addr, value) \ + { \ + ((unsigned char *)(addr))[0] = (value >> 24); \ + ((unsigned char *)(addr))[1] = (value >> 16) & 0xff; \ + ((unsigned char *)(addr))[2] = (value >> 8) & 0xff; \ + ((unsigned char *)(addr))[3] = (value)&0xff; \ } -#define GET_32(addr) ((((unsigned char *) (addr))[0] << 24) | \ - (((unsigned char *) (addr))[1] << 16) | \ - (((unsigned char *) (addr))[2] << 8) | \ - (((unsigned char *) (addr))[3])) +#define GET_32(addr) \ + ((((unsigned char *)(addr))[0] << 24) | \ + (((unsigned char *)(addr))[1] << 16) | \ + (((unsigned char *)(addr))[2] << 8) | (((unsigned char *)(addr))[3])) #else -#define PUT_32(addr,value) \ - { \ - ((unsigned char *) (addr))[3] = (value >> 24); \ - ((unsigned char *) (addr))[2] = (value >> 16) & 0xff; \ - ((unsigned char *) (addr))[1] = (value >> 8) & 0xff; \ - ((unsigned char *) (addr))[0] = (value) & 0xff; \ +#define PUT_32(addr, value) \ + { \ + ((unsigned char *)(addr))[3] = (value >> 24); \ + ((unsigned char *)(addr))[2] = (value >> 16) & 0xff; \ + ((unsigned char *)(addr))[1] = (value >> 8) & 0xff; \ + ((unsigned char *)(addr))[0] = (value)&0xff; \ } -#define GET_32(addr) ((((unsigned char *) (addr))[3] << 24) | \ - (((unsigned char *) (addr))[2] << 16) | \ - (((unsigned char *) (addr))[1] << 8) | \ - (((unsigned char *) (addr))[0])) +#define GET_32(addr) \ + ((((unsigned char *)(addr))[3] << 24) | \ + (((unsigned char *)(addr))[2] << 16) | \ + (((unsigned char *)(addr))[1] << 8) | (((unsigned char *)(addr))[0])) #endif // WORDS_BIGENDIAN #else -#define PUT_32(addr,value) *(((uint32_t *) (addr)) = (value) +#define PUT_32(addr, value) *(((uint32_t *) (addr)) = (value) #define GET_32(addr) (*(((uint32_t *) (addr))) #endif diff --git a/libs/srtp/crypto/include/key.h b/libs/srtp/crypto/include/key.h index 55ba126435..3498114b05 100644 --- a/libs/srtp/crypto/include/key.h +++ b/libs/srtp/crypto/include/key.h @@ -45,7 +45,7 @@ #ifndef KEY_H #define KEY_H -#include "rdbx.h" /* for srtp_xtd_seq_num_t */ +#include "rdbx.h" /* for srtp_xtd_seq_num_t */ #include "err.h" #ifdef __cplusplus @@ -60,9 +60,11 @@ typedef enum { srtp_key_event_hard_limit } srtp_key_event_t; -srtp_err_status_t srtp_key_limit_set(srtp_key_limit_t key, const srtp_xtd_seq_num_t s); +srtp_err_status_t srtp_key_limit_set(srtp_key_limit_t key, + const srtp_xtd_seq_num_t s); -srtp_err_status_t srtp_key_limit_clone(srtp_key_limit_t original, srtp_key_limit_t *new_key); +srtp_err_status_t srtp_key_limit_clone(srtp_key_limit_t original, + srtp_key_limit_t *new_key); srtp_err_status_t srtp_key_limit_check(const srtp_key_limit_t key); diff --git a/libs/srtp/crypto/include/null_cipher.h b/libs/srtp/crypto/include/null_cipher.h index 4e168f1a77..5e8c91c134 100644 --- a/libs/srtp/crypto/include/null_cipher.h +++ b/libs/srtp/crypto/include/null_cipher.h @@ -44,7 +44,6 @@ * */ - #ifndef NULL_CIPHER_H #define NULL_CIPHER_H diff --git a/libs/srtp/crypto/include/rdb.h b/libs/srtp/crypto/include/rdb.h index 4671a0a0d9..98314c1f3e 100644 --- a/libs/srtp/crypto/include/rdb.h +++ b/libs/srtp/crypto/include/rdb.h @@ -7,28 +7,27 @@ * 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 @@ -47,9 +46,9 @@ #ifndef REPLAY_DB_H #define REPLAY_DB_H -#include "integers.h" /* for uint32_t */ -#include "datatypes.h" /* for v128_t */ -#include "err.h" /* for srtp_err_status_t */ +#include "integers.h" /* for uint32_t */ +#include "datatypes.h" /* for v128_t */ +#include "err.h" /* for srtp_err_status_t */ #ifdef __cplusplus extern "C" { @@ -76,7 +75,6 @@ typedef struct { */ srtp_err_status_t srtp_rdb_init(srtp_rdb_t *rdb); - /* * srtp_rdb_check * @@ -103,7 +101,6 @@ srtp_err_status_t srtp_rdb_add_index(srtp_rdb_t *rdb, uint32_t rdb_index); * srtp_rdb_t upon which srtp_rdb_add_index is used! */ - /* * srtp_rdb_increment(db) increments the sequence number in db, if it is * not too high @@ -121,7 +118,6 @@ srtp_err_status_t srtp_rdb_increment(srtp_rdb_t *rdb); */ uint32_t srtp_rdb_get_value(const srtp_rdb_t *rdb); - #ifdef __cplusplus } #endif diff --git a/libs/srtp/crypto/include/rdbx.h b/libs/srtp/crypto/include/rdbx.h index 010eb012d7..2194178ee2 100644 --- a/libs/srtp/crypto/include/rdbx.h +++ b/libs/srtp/crypto/include/rdbx.h @@ -9,26 +9,26 @@ */ /* - * + * * 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 @@ -58,10 +58,10 @@ extern "C" { #ifndef ROC_TEST -typedef uint16_t srtp_sequence_number_t; /* 16 bit sequence number */ -typedef uint32_t srtp_rollover_counter_t; /* 32 bit rollover counter */ +typedef uint16_t srtp_sequence_number_t; /* 16 bit sequence number */ +typedef uint32_t srtp_rollover_counter_t; /* 32 bit rollover counter */ -#else /* use small seq_num and roc datatypes for testing purposes */ +#else /* use small seq_num and roc datatypes for testing purposes */ typedef unsigned char srtp_sequence_number_t; /* 8 bit sequence number */ typedef uint16_t srtp_rollover_counter_t; /* 16 bit rollover counter */ @@ -69,7 +69,7 @@ typedef uint16_t srtp_rollover_counter_t; /* 16 bit rollover counter */ #endif #define seq_num_median (1 << (8 * sizeof(srtp_sequence_number_t) - 1)) -#define seq_num_max (1 << (8 * sizeof(srtp_sequence_number_t))) +#define seq_num_max (1 << (8 * sizeof(srtp_sequence_number_t))) /* * An rtp_xtd_seq_num_t is a 64-bit unsigned integer used as an 'extended' @@ -77,7 +77,6 @@ typedef uint16_t srtp_rollover_counter_t; /* 16 bit rollover counter */ */ typedef uint64_t srtp_xtd_seq_num_t; - /* * An srtp_rdbx_t is a replay database with extended range; it uses an * xtd_seq_num_t and a bitmask of recently received indices. @@ -87,7 +86,6 @@ typedef struct { bitvector_t bitmask; } srtp_rdbx_t; - /* * srtp_rdbx_init(rdbx_ptr, ws) * @@ -96,7 +94,6 @@ typedef struct { */ srtp_err_status_t srtp_rdbx_init(srtp_rdbx_t *rdbx, unsigned long ws); - /* * srtp_rdbx_dealloc(rdbx_ptr) * @@ -104,7 +101,6 @@ srtp_err_status_t srtp_rdbx_init(srtp_rdbx_t *rdbx, unsigned long ws); */ srtp_err_status_t srtp_rdbx_dealloc(srtp_rdbx_t *rdbx); - /* * srtp_rdbx_estimate_index(rdbx, guess, s) * @@ -113,7 +109,9 @@ srtp_err_status_t srtp_rdbx_dealloc(srtp_rdbx_t *rdbx); * index to which s corresponds, and returns the difference between * *guess and the locally stored synch info */ -int32_t srtp_rdbx_estimate_index(const srtp_rdbx_t *rdbx, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s); +int32_t srtp_rdbx_estimate_index(const srtp_rdbx_t *rdbx, + srtp_xtd_seq_num_t *guess, + srtp_sequence_number_t s); /* * srtp_rdbx_check(rdbx, delta); @@ -136,7 +134,6 @@ srtp_err_status_t srtp_rdbx_check(const srtp_rdbx_t *rdbx, int difference); */ srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, int delta); - /* * srtp_rdbx_set_roc(rdbx, roc) initalizes the srtp_rdbx_t at the location rdbx * to have the rollover counter value roc. If that value is less than @@ -147,7 +144,8 @@ srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, int delta); srtp_err_status_t srtp_rdbx_set_roc(srtp_rdbx_t *rdbx, uint32_t roc); /* - * srtp_rdbx_get_packet_index(rdbx) returns the value of the rollover counter for + * srtp_rdbx_get_packet_index(rdbx) returns the value of the rollover counter + * for * the srtp_rdbx_t pointed to by rdbx * */ @@ -166,14 +164,12 @@ srtp_xtd_seq_num_t srtp_rdbx_get_packet_index(const srtp_rdbx_t *rdbx); */ unsigned long srtp_rdbx_get_window_size(const srtp_rdbx_t *rdbx); - /* index_init(&pi) initializes a packet index pi (sets it to zero) */ void srtp_index_init(srtp_xtd_seq_num_t *pi); /* index_advance(&pi, s) advances a xtd_seq_num_t forward by s */ void srtp_index_advance(srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s); - /* * srtp_index_guess(local, guess, s) * @@ -183,7 +179,9 @@ void srtp_index_advance(srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s); * guess of the packet index to which s corresponds, and returns the * difference between *guess and *local */ -int32_t srtp_index_guess(const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s); +int32_t srtp_index_guess(const srtp_xtd_seq_num_t *local, + srtp_xtd_seq_num_t *guess, + srtp_sequence_number_t s); /* * srtp_rdbx_get_roc(rdbx) @@ -200,9 +198,9 @@ uint32_t srtp_rdbx_get_roc(const srtp_rdbx_t *rdbx); * rollover counter value, then the function returns * srtp_err_status_replay_old, otherwise, srtp_err_status_ok is returned. */ -srtp_err_status_t srtp_rdbx_set_roc_seq (srtp_rdbx_t *rdbx, - uint32_t roc, - uint16_t seq); +srtp_err_status_t srtp_rdbx_set_roc_seq(srtp_rdbx_t *rdbx, + uint32_t roc, + uint16_t seq); #ifdef __cplusplus } diff --git a/libs/srtp/crypto/include/sha1.h b/libs/srtp/crypto/include/sha1.h index 3dc8d91039..933c1466a3 100644 --- a/libs/srtp/crypto/include/sha1.h +++ b/libs/srtp/crypto/include/sha1.h @@ -48,7 +48,7 @@ #define SHA1_H #ifdef HAVE_CONFIG_H - #include +#include #endif #include "err.h" @@ -81,49 +81,53 @@ extern "C" { /* OpenSSL 1.1.0 made EVP_MD_CTX an opaque structure, which must be allocated using EVP_MD_CTX_new. But this function doesn't exist in OpenSSL 1.0.x. */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER typedef EVP_MD_CTX srtp_sha1_ctx_t; -static inline void srtp_sha1_init (srtp_sha1_ctx_t *ctx) +static inline void srtp_sha1_init(srtp_sha1_ctx_t *ctx) { EVP_MD_CTX_init(ctx); EVP_DigestInit(ctx, EVP_sha1()); } -static inline void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg) +static inline void srtp_sha1_update(srtp_sha1_ctx_t *ctx, + const uint8_t *M, + int octets_in_msg) { EVP_DigestUpdate(ctx, M, octets_in_msg); } -static inline void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) +static inline void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t *output) { unsigned int len = 0; - EVP_DigestFinal(ctx, (unsigned char*)output, &len); + EVP_DigestFinal(ctx, (unsigned char *)output, &len); EVP_MD_CTX_cleanup(ctx); } #else -typedef EVP_MD_CTX* srtp_sha1_ctx_t; +typedef EVP_MD_CTX *srtp_sha1_ctx_t; -static inline void srtp_sha1_init (srtp_sha1_ctx_t *ctx) +static inline void srtp_sha1_init(srtp_sha1_ctx_t *ctx) { *ctx = EVP_MD_CTX_new(); EVP_DigestInit(*ctx, EVP_sha1()); } -static inline void srtp_sha1_update (srtp_sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg) +static inline void srtp_sha1_update(srtp_sha1_ctx_t *ctx, + const uint8_t *M, + int octets_in_msg) { EVP_DigestUpdate(*ctx, M, octets_in_msg); } -static inline void srtp_sha1_final (srtp_sha1_ctx_t *ctx, uint32_t *output) +static inline void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t *output) { unsigned int len = 0; - EVP_DigestFinal(*ctx, (unsigned char*)output, &len); + EVP_DigestFinal(*ctx, (unsigned char *)output, &len); EVP_MD_CTX_free(*ctx); } #endif @@ -137,7 +141,6 @@ typedef struct { uint32_t num_bits_in_msg; /* total number of bits in message */ } srtp_sha1_ctx_t; - /* * srtp_sha1_init(&ctx) initializes the SHA1 context ctx * @@ -150,9 +153,11 @@ typedef struct { */ void srtp_sha1_init(srtp_sha1_ctx_t *ctx); -void srtp_sha1_update(srtp_sha1_ctx_t *ctx, const uint8_t *M, int octets_in_msg); +void srtp_sha1_update(srtp_sha1_ctx_t *ctx, + const uint8_t *M, + int octets_in_msg); -void srtp_sha1_final(srtp_sha1_ctx_t * ctx, uint32_t output[5]); +void srtp_sha1_final(srtp_sha1_ctx_t *ctx, uint32_t output[5]); /* * The srtp_sha1_core function is INTERNAL to SHA-1, but it is declared diff --git a/libs/srtp/crypto/include/stat.h b/libs/srtp/crypto/include/stat.h index e8cf3605a8..1894e041aa 100644 --- a/libs/srtp/crypto/include/stat.h +++ b/libs/srtp/crypto/include/stat.h @@ -1,6 +1,6 @@ /* * stats.h - * + * * interface to statistical test functions * * David A. McGrew @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -43,12 +43,11 @@ * */ - #ifndef STAT_H #define STAT_H -#include "datatypes.h" /* for uint8_t */ -#include "err.h" /* for srtp_err_status_t */ +#include "datatypes.h" /* for uint8_t */ +#include "err.h" /* for srtp_err_status_t */ #ifdef __cplusplus extern "C" { diff --git a/libs/srtp/crypto/kernel/alloc.c b/libs/srtp/crypto/kernel/alloc.c index cbd8877c87..dbe58266f4 100644 --- a/libs/srtp/crypto/kernel/alloc.c +++ b/libs/srtp/crypto/kernel/alloc.c @@ -1,32 +1,32 @@ /* * alloc.c * - * memory allocation and deallocation + * memory allocation and deallocation * * 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 @@ -43,7 +43,7 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "alloc.h" @@ -51,9 +51,9 @@ /* the debug module for memory allocation */ -srtp_debug_module_t mod_alloc = { - 0, /* debugging is off by default */ - "alloc" /* printable name for module */ +srtp_debug_module_t srtp_mod_alloc = { + 0, /* debugging is off by default */ + "alloc" /* printable name for module */ }; /* @@ -67,29 +67,35 @@ srtp_debug_module_t mod_alloc = { #if defined(HAVE_STDLIB_H) -void * srtp_crypto_alloc(size_t size) { - void *ptr; +void *srtp_crypto_alloc(size_t size) +{ + void *ptr; - ptr = malloc(size); - - if (ptr) { - debug_print(mod_alloc, "(location: %p) allocated", ptr); - } else { - debug_print(mod_alloc, "allocation failed (asked for %d bytes)\n", size); - } + if (!size) { + return NULL; + } - return ptr; + ptr = calloc(1, size); + + if (ptr) { + debug_print(srtp_mod_alloc, "(location: %p) allocated", ptr); + } else { + debug_print(srtp_mod_alloc, "allocation failed (asked for %d bytes)\n", + size); + } + + return ptr; } -void srtp_crypto_free(void *ptr) { +void srtp_crypto_free(void *ptr) +{ + debug_print(srtp_mod_alloc, "(location: %p) freed", ptr); - debug_print(mod_alloc, "(location: %p) freed", ptr); - - free(ptr); + free(ptr); } -#else /* we need to define our own memory allocation routines */ +#else /* we need to define our own memory allocation routines */ -#error no memory allocation defined yet +#error no memory allocation defined yet #endif diff --git a/libs/srtp/crypto/kernel/crypto_kernel.c b/libs/srtp/crypto/kernel/crypto_kernel.c index 3caff0e123..ab4492e8a6 100644 --- a/libs/srtp/crypto/kernel/crypto_kernel.c +++ b/libs/srtp/crypto/kernel/crypto_kernel.c @@ -42,60 +42,22 @@ * */ - #ifdef HAVE_CONFIG_H - #include +#include #endif #include "alloc.h" #include "crypto_kernel.h" +#include "cipher_types.h" /* the debug module for the crypto_kernel */ srtp_debug_module_t srtp_mod_crypto_kernel = { - 0, /* debugging is off by default */ - "crypto kernel" /* printable name for module */ + 0, /* debugging is off by default */ + "crypto kernel" /* printable name for module */ }; -/* - * other generic debug modules that can be included in the kernel - */ - -extern srtp_debug_module_t srtp_mod_auth; -extern srtp_debug_module_t srtp_mod_cipher; -extern srtp_debug_module_t mod_stat; -extern srtp_debug_module_t mod_alloc; - -/* - * cipher types that can be included in the kernel - */ - -extern srtp_cipher_type_t srtp_null_cipher; -extern srtp_cipher_type_t srtp_aes_icm_128; -extern srtp_cipher_type_t srtp_aes_icm_256; -#ifdef OPENSSL -extern srtp_cipher_type_t srtp_aes_icm_192; -extern srtp_cipher_type_t srtp_aes_gcm_128_openssl; -extern srtp_cipher_type_t srtp_aes_gcm_256_openssl; -#endif - -/* debug modules for cipher types */ -extern srtp_debug_module_t srtp_mod_aes_icm; -#ifdef OPENSSL -extern srtp_debug_module_t srtp_mod_aes_gcm; -#endif - -/* - * auth func types that can be included in the kernel - */ - -extern srtp_auth_type_t srtp_null_auth; -extern srtp_auth_type_t srtp_hmac; - -/* debug modules for auth types */ -extern srtp_debug_module_t srtp_mod_hmac; - /* crypto_kernel is a global variable, the only one of its datatype */ srtp_crypto_kernel_t crypto_kernel = { @@ -107,13 +69,12 @@ srtp_crypto_kernel_t crypto_kernel = { #define MAX_RNG_TRIALS 25 -srtp_err_status_t srtp_crypto_kernel_init () +srtp_err_status_t srtp_crypto_kernel_init() { srtp_err_status_t status; /* check the security state */ if (crypto_kernel.state == srtp_crypto_kernel_state_secure) { - /* * we're already in the secure state, but we've been asked to * re-initialize, so we just re-run the self-tests and then return @@ -140,25 +101,28 @@ srtp_err_status_t srtp_crypto_kernel_init () if (status) { return status; } - status = srtp_crypto_kernel_load_debug_module(&mod_stat); + status = srtp_crypto_kernel_load_debug_module(&srtp_mod_stat); if (status) { return status; } - status = srtp_crypto_kernel_load_debug_module(&mod_alloc); + status = srtp_crypto_kernel_load_debug_module(&srtp_mod_alloc); if (status) { return status; } /* load cipher types */ - status = srtp_crypto_kernel_load_cipher_type(&srtp_null_cipher, SRTP_NULL_CIPHER); + status = srtp_crypto_kernel_load_cipher_type(&srtp_null_cipher, + SRTP_NULL_CIPHER); if (status) { return status; } - status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_128, SRTP_AES_ICM_128); + status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_128, + SRTP_AES_ICM_128); if (status) { return status; } - status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_256, SRTP_AES_ICM_256); + status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_256, + SRTP_AES_ICM_256); if (status) { return status; } @@ -167,15 +131,18 @@ srtp_err_status_t srtp_crypto_kernel_init () return status; } #ifdef OPENSSL - status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192, SRTP_AES_ICM_192); + status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192, + SRTP_AES_ICM_192); if (status) { return status; } - status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_128_openssl, SRTP_AES_GCM_128); + status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_128_openssl, + SRTP_AES_GCM_128); if (status) { return status; } - status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_256_openssl, SRTP_AES_GCM_256); + status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_256_openssl, + SRTP_AES_GCM_256); if (status) { return status; } @@ -205,19 +172,21 @@ srtp_err_status_t srtp_crypto_kernel_init () return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_status () +srtp_err_status_t srtp_crypto_kernel_status() { srtp_err_status_t status; - srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; - srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list; + srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; + srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list; /* for each cipher type, describe and test */ while (ctype != NULL) { - srtp_err_report(srtp_err_level_info, "cipher: %s\n", ctype->cipher_type->description); + srtp_err_report(srtp_err_level_info, "cipher: %s\n", + ctype->cipher_type->description); srtp_err_report(srtp_err_level_info, " self-test: "); status = srtp_cipher_type_self_test(ctype->cipher_type); if (status) { - srtp_err_report(srtp_err_level_error, "failed with error code %d\n", status); + srtp_err_report(srtp_err_level_error, "failed with error code %d\n", + status); exit(status); } srtp_err_report(srtp_err_level_info, "passed\n"); @@ -226,11 +195,13 @@ srtp_err_status_t srtp_crypto_kernel_status () /* for each auth type, describe and test */ while (atype != NULL) { - srtp_err_report(srtp_err_level_info, "auth func: %s\n", atype->auth_type->description); + srtp_err_report(srtp_err_level_info, "auth func: %s\n", + atype->auth_type->description); srtp_err_report(srtp_err_level_info, " self-test: "); status = srtp_auth_type_self_test(atype->auth_type); if (status) { - srtp_err_report(srtp_err_level_error, "failed with error code %d\n", status); + srtp_err_report(srtp_err_level_error, "failed with error code %d\n", + status); exit(status); } srtp_err_report(srtp_err_level_info, "passed\n"); @@ -242,7 +213,7 @@ srtp_err_status_t srtp_crypto_kernel_status () return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_list_debug_modules () +srtp_err_status_t srtp_crypto_kernel_list_debug_modules() { srtp_kernel_debug_module_t *dm = crypto_kernel.debug_module_list; @@ -252,7 +223,7 @@ srtp_err_status_t srtp_crypto_kernel_list_debug_modules () srtp_err_report(srtp_err_level_info, " %s ", dm->mod->name); if (dm->mod->on) { srtp_err_report(srtp_err_level_info, "(on)\n"); - } else{ + } else { srtp_err_report(srtp_err_level_info, "(off)\n"); } dm = dm->next; @@ -261,7 +232,7 @@ srtp_err_status_t srtp_crypto_kernel_list_debug_modules () return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_shutdown () +srtp_err_status_t srtp_crypto_kernel_shutdown() { /* * free dynamic memory used in crypto_kernel at present @@ -271,8 +242,7 @@ srtp_err_status_t srtp_crypto_kernel_shutdown () while (crypto_kernel.cipher_type_list != NULL) { srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list; crypto_kernel.cipher_type_list = ctype->next; - debug_print(srtp_mod_crypto_kernel, - "freeing memory for cipher %s", + debug_print(srtp_mod_crypto_kernel, "freeing memory for cipher %s", ctype->cipher_type->description); srtp_crypto_free(ctype); } @@ -292,8 +262,7 @@ srtp_err_status_t srtp_crypto_kernel_shutdown () srtp_kernel_debug_module_t *kdm = crypto_kernel.debug_module_list; crypto_kernel.debug_module_list = kdm->next; debug_print(srtp_mod_crypto_kernel, - "freeing memory for debug module %s", - kdm->mod->name); + "freeing memory for debug module %s", kdm->mod->name); srtp_crypto_free(kdm); } @@ -303,7 +272,10 @@ srtp_err_status_t srtp_crypto_kernel_shutdown () return srtp_err_status_ok; } -static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const srtp_cipher_type_t *new_ct, srtp_cipher_type_id_t id, int replace) +static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type( + const srtp_cipher_type_t *new_ct, + srtp_cipher_type_id_t id, + int replace) { srtp_kernel_cipher_type_t *ctype, *new_ctype; srtp_err_status_t status; @@ -330,13 +302,14 @@ static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const sr if (!replace) { return srtp_err_status_bad_param; } - status = srtp_cipher_type_test(new_ct, ctype->cipher_type->test_data); + status = + srtp_cipher_type_test(new_ct, ctype->cipher_type->test_data); if (status) { return status; } new_ctype = ctype; break; - }else if (new_ct == ctype->cipher_type) { + } else if (new_ct == ctype->cipher_type) { return srtp_err_status_bad_param; } ctype = ctype->next; @@ -345,7 +318,8 @@ static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const sr /* if not found, put new_ct at the head of the list */ if (ctype == NULL) { /* allocate memory */ - new_ctype = (srtp_kernel_cipher_type_t*)srtp_crypto_alloc(sizeof(srtp_kernel_cipher_type_t)); + new_ctype = (srtp_kernel_cipher_type_t *)srtp_crypto_alloc( + sizeof(srtp_kernel_cipher_type_t)); if (new_ctype == NULL) { return srtp_err_status_alloc_fail; } @@ -362,17 +336,23 @@ static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type (const sr return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_load_cipher_type (const srtp_cipher_type_t *new_ct, srtp_cipher_type_id_t id) +srtp_err_status_t srtp_crypto_kernel_load_cipher_type( + const srtp_cipher_type_t *new_ct, + srtp_cipher_type_id_t id) { return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, 0); } -srtp_err_status_t srtp_replace_cipher_type (const srtp_cipher_type_t *new_ct, srtp_cipher_type_id_t id) +srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *new_ct, + srtp_cipher_type_id_t id) { return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, 1); } -srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t *new_at, srtp_auth_type_id_t id, int replace) +srtp_err_status_t srtp_crypto_kernel_do_load_auth_type( + const srtp_auth_type_t *new_at, + srtp_auth_type_id_t id, + int replace) { srtp_kernel_auth_type_t *atype, *new_atype; srtp_err_status_t status; @@ -405,7 +385,7 @@ srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t * } new_atype = atype; break; - }else if (new_at == atype->auth_type) { + } else if (new_at == atype->auth_type) { return srtp_err_status_bad_param; } atype = atype->next; @@ -414,7 +394,8 @@ srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t * /* if not found, put new_at at the head of the list */ if (atype == NULL) { /* allocate memory */ - new_atype = (srtp_kernel_auth_type_t*)srtp_crypto_alloc(sizeof(srtp_kernel_auth_type_t)); + new_atype = (srtp_kernel_auth_type_t *)srtp_crypto_alloc( + sizeof(srtp_kernel_auth_type_t)); if (new_atype == NULL) { return srtp_err_status_alloc_fail; } @@ -429,21 +410,23 @@ srtp_err_status_t srtp_crypto_kernel_do_load_auth_type (const srtp_auth_type_t * new_atype->id = id; return srtp_err_status_ok; - } -srtp_err_status_t srtp_crypto_kernel_load_auth_type (const srtp_auth_type_t *new_at, srtp_auth_type_id_t id) +srtp_err_status_t srtp_crypto_kernel_load_auth_type( + const srtp_auth_type_t *new_at, + srtp_auth_type_id_t id) { return srtp_crypto_kernel_do_load_auth_type(new_at, id, 0); } -srtp_err_status_t srtp_replace_auth_type (const srtp_auth_type_t *new_at, srtp_auth_type_id_t id) +srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *new_at, + srtp_auth_type_id_t id) { return srtp_crypto_kernel_do_load_auth_type(new_at, id, 1); } - -const srtp_cipher_type_t * srtp_crypto_kernel_get_cipher_type (srtp_cipher_type_id_t id) +const srtp_cipher_type_t *srtp_crypto_kernel_get_cipher_type( + srtp_cipher_type_id_t id) { srtp_kernel_cipher_type_t *ctype; @@ -460,8 +443,10 @@ const srtp_cipher_type_t * srtp_crypto_kernel_get_cipher_type (srtp_cipher_type_ return NULL; } - -srtp_err_status_t srtp_crypto_kernel_alloc_cipher (srtp_cipher_type_id_t id, srtp_cipher_pointer_t *cp, int key_len, int tag_len) +srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id, + srtp_cipher_pointer_t *cp, + int key_len, + int tag_len) { const srtp_cipher_type_t *ct; @@ -481,9 +466,7 @@ srtp_err_status_t srtp_crypto_kernel_alloc_cipher (srtp_cipher_type_id_t id, srt return ((ct)->alloc(cp, key_len, tag_len)); } - - -const srtp_auth_type_t * srtp_crypto_kernel_get_auth_type (srtp_auth_type_id_t id) +const srtp_auth_type_t *srtp_crypto_kernel_get_auth_type(srtp_auth_type_id_t id) { srtp_kernel_auth_type_t *atype; @@ -500,7 +483,10 @@ const srtp_auth_type_t * srtp_crypto_kernel_get_auth_type (srtp_auth_type_id_t i return NULL; } -srtp_err_status_t srtp_crypto_kernel_alloc_auth (srtp_auth_type_id_t id, srtp_auth_pointer_t *ap, int key_len, int tag_len) +srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id, + srtp_auth_pointer_t *ap, + int key_len, + int tag_len) { const srtp_auth_type_t *at; @@ -520,12 +506,13 @@ srtp_err_status_t srtp_crypto_kernel_alloc_auth (srtp_auth_type_id_t id, srtp_au return ((at)->alloc(ap, key_len, tag_len)); } -srtp_err_status_t srtp_crypto_kernel_load_debug_module (srtp_debug_module_t *new_dm) +srtp_err_status_t srtp_crypto_kernel_load_debug_module( + srtp_debug_module_t *new_dm) { srtp_kernel_debug_module_t *kdm, *new; /* defensive coding */ - if (new_dm == NULL) { + if (new_dm == NULL || new_dm->name == NULL) { return srtp_err_status_bad_param; } @@ -540,7 +527,8 @@ srtp_err_status_t srtp_crypto_kernel_load_debug_module (srtp_debug_module_t *new /* put new_dm at the head of the list */ /* allocate memory */ - new = (srtp_kernel_debug_module_t*)srtp_crypto_alloc(sizeof(srtp_kernel_debug_module_t)); + new = (srtp_kernel_debug_module_t *)srtp_crypto_alloc( + sizeof(srtp_kernel_debug_module_t)); if (new == NULL) { return srtp_err_status_alloc_fail; } @@ -555,7 +543,7 @@ srtp_err_status_t srtp_crypto_kernel_load_debug_module (srtp_debug_module_t *new return srtp_err_status_ok; } -srtp_err_status_t srtp_crypto_kernel_set_debug_module (const char *name, int on) +srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *name, int on) { srtp_kernel_debug_module_t *kdm; diff --git a/libs/srtp/crypto/kernel/err.c b/libs/srtp/crypto/kernel/err.c index 9dcecbadd5..f443549e5a 100644 --- a/libs/srtp/crypto/kernel/err.c +++ b/libs/srtp/crypto/kernel/err.c @@ -43,7 +43,7 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "err.h" @@ -54,7 +54,7 @@ static FILE *srtp_err_file = NULL; -srtp_err_status_t srtp_err_reporting_init () +srtp_err_status_t srtp_err_reporting_init() { #ifdef ERR_REPORTING_STDOUT srtp_err_file = stdout; @@ -69,15 +69,16 @@ srtp_err_status_t srtp_err_reporting_init () return srtp_err_status_ok; } -static srtp_err_report_handler_func_t * srtp_err_report_handler = NULL; +static srtp_err_report_handler_func_t *srtp_err_report_handler = NULL; -srtp_err_status_t srtp_install_err_report_handler(srtp_err_report_handler_func_t func) +srtp_err_status_t srtp_install_err_report_handler( + srtp_err_report_handler_func_t func) { srtp_err_report_handler = func; return srtp_err_status_ok; } -void srtp_err_report (srtp_err_reporting_level_t level, const char *format, ...) +void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...) { va_list args; if (srtp_err_file != NULL) { @@ -91,12 +92,13 @@ void srtp_err_report (srtp_err_reporting_level_t level, const char *format, ...) if (vsnprintf(msg, sizeof(msg), format, args) > 0) { /* strip trailing \n, callback should not have one */ size_t l = strlen(msg); - if (l && msg[l-1] == '\n') { - msg[l-1] = '\0'; + if (l && msg[l - 1] == '\n') { + msg[l - 1] = '\0'; } srtp_err_report_handler(level, msg); /* - * NOTE, need to be carefull, there is a potential that octet_string_set_to_zero() could + * NOTE, need to be carefull, there is a potential that + * octet_string_set_to_zero() could * call srtp_err_report() in the future, leading to recursion */ octet_string_set_to_zero(msg, sizeof(msg)); diff --git a/libs/srtp/crypto/kernel/key.c b/libs/srtp/crypto/kernel/key.c index 1430f0df67..0466195046 100644 --- a/libs/srtp/crypto/kernel/key.c +++ b/libs/srtp/crypto/kernel/key.c @@ -43,14 +43,15 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "key.h" #define soft_limit 0x10000 -srtp_err_status_t srtp_key_limit_set (srtp_key_limit_t key, const srtp_xtd_seq_num_t s) +srtp_err_status_t srtp_key_limit_set(srtp_key_limit_t key, + const srtp_xtd_seq_num_t s) { #ifdef NO_64BIT_MATH if (high32(s) == 0 && low32(s) < soft_limit) { @@ -66,7 +67,8 @@ srtp_err_status_t srtp_key_limit_set (srtp_key_limit_t key, const srtp_xtd_seq_n return srtp_err_status_ok; } -srtp_err_status_t srtp_key_limit_clone (srtp_key_limit_t original, srtp_key_limit_t *new_key) +srtp_err_status_t srtp_key_limit_clone(srtp_key_limit_t original, + srtp_key_limit_t *new_key) { if (original == NULL) { return srtp_err_status_bad_param; @@ -75,7 +77,7 @@ srtp_err_status_t srtp_key_limit_clone (srtp_key_limit_t original, srtp_key_limi return srtp_err_status_ok; } -srtp_err_status_t srtp_key_limit_check (const srtp_key_limit_t key) +srtp_err_status_t srtp_key_limit_check(const srtp_key_limit_t key) { if (key->state == srtp_key_state_expired) { return srtp_err_status_key_expired; @@ -83,13 +85,14 @@ srtp_err_status_t srtp_key_limit_check (const srtp_key_limit_t key) return srtp_err_status_ok; } -srtp_key_event_t srtp_key_limit_update (srtp_key_limit_t key) +srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key) { #ifdef NO_64BIT_MATH if (low32(key->num_left) == 0) { // carry - key->num_left = make64(high32(key->num_left) - 1, low32(key->num_left) - 1); - }else { + key->num_left = + make64(high32(key->num_left) - 1, low32(key->num_left) - 1); + } else { // no carry key->num_left = make64(high32(key->num_left), low32(key->num_left) - 1); } @@ -111,10 +114,9 @@ srtp_key_event_t srtp_key_limit_update (srtp_key_limit_t key) #else if (key->num_left < 1) #endif - { /* we just hit the hard limit */ + { /* we just hit the hard limit */ key->state = srtp_key_state_expired; return srtp_key_event_hard_limit; } return srtp_key_event_soft_limit; } - diff --git a/libs/srtp/crypto/math/datatypes.c b/libs/srtp/crypto/math/datatypes.c index bb4b56e307..c0dfece659 100644 --- a/libs/srtp/crypto/math/datatypes.c +++ b/libs/srtp/crypto/math/datatypes.c @@ -8,26 +8,26 @@ * 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 @@ -44,7 +44,7 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #ifdef OPENSSL @@ -53,48 +53,24 @@ #include "datatypes.h" -int -octet_weight[256] = { - 0, 1, 1, 2, 1, 2, 2, 3, - 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, - 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, - 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, - 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, - 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, - 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, - 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, - 4, 5, 5, 6, 5, 6, 6, 7, - 1, 2, 2, 3, 2, 3, 3, 4, - 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, - 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, - 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, - 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, - 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, - 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, - 4, 5, 5, 6, 5, 6, 6, 7, - 4, 5, 5, 6, 5, 6, 6, 7, - 5, 6, 6, 7, 6, 7, 7, 8 +static const int8_t octet_weight[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; -int -octet_get_weight(uint8_t octet) { - extern int octet_weight[256]; - - return octet_weight[octet]; -} +int octet_get_weight(uint8_t octet) +{ + return (int)octet_weight[octet]; +} /* * bit_string is a buffer that is used to hold output strings, e.g. @@ -105,414 +81,410 @@ octet_get_weight(uint8_t octet) { char bit_string[MAX_PRINT_STRING_LEN]; -uint8_t -srtp_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]; +uint8_t srtp_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]; } -char * srtp_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; +char *srtp_octet_string_hex_string(const void *s, int length) +{ + const uint8_t *str = (const uint8_t *)s; + int i; - /* truncate string if it would be too long */ - if (length > MAX_PRINT_STRING_LEN) - length = MAX_PRINT_STRING_LEN-2; - - for (i=0; i < length; i+=2) { - bit_string[i] = srtp_nibble_to_hex_char(*str >> 4); - bit_string[i+1] = srtp_nibble_to_hex_char(*str++ & 0xF); - } - bit_string[i] = 0; /* null terminate string */ - return bit_string; -} + /* double length, since one octet takes two hex characters */ + length *= 2; -char * -v128_hex_string(v128_t *x) { - int i, j; + /* truncate string if it would be too long */ + if (length > MAX_PRINT_STRING_LEN) + length = MAX_PRINT_STRING_LEN - 2; - for (i=j=0; i < 16; i++) { - bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] >> 4); - bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] & 0xF); - } - - bit_string[j] = 0; /* null terminate string */ - return bit_string; -} - -char * -v128_bit_string(v128_t *x) { - int j, i; - uint32_t mask; - - for (j=i=0; j < 4; j++) { - for (mask=0x80000000; mask > 0; mask >>= 1) { - if (x->v32[j] & mask) - bit_string[i] = '1'; - else - bit_string[i] = '0'; - ++i; + for (i = 0; i < length; i += 2) { + bit_string[i] = srtp_nibble_to_hex_char(*str >> 4); + bit_string[i + 1] = srtp_nibble_to_hex_char(*str++ & 0xF); } - } - bit_string[128] = 0; /* null terminate string */ - - return bit_string; + bit_string[i] = 0; /* null terminate string */ + return bit_string; } -void -v128_copy_octet_string(v128_t *x, const uint8_t s[16]) { -#ifdef ALIGNMENT_32BIT_REQUIRED - if ((((uint32_t) &s[0]) & 0x3) != 0) -#endif - { - x->v8[0] = s[0]; - x->v8[1] = s[1]; - x->v8[2] = s[2]; - x->v8[3] = s[3]; - x->v8[4] = s[4]; - x->v8[5] = s[5]; - x->v8[6] = s[6]; - x->v8[7] = s[7]; - x->v8[8] = s[8]; - x->v8[9] = s[9]; - x->v8[10] = s[10]; - x->v8[11] = s[11]; - x->v8[12] = s[12]; - x->v8[13] = s[13]; - x->v8[14] = s[14]; - x->v8[15] = s[15]; - } -#ifdef ALIGNMENT_32BIT_REQUIRED - else - { - v128_t *v = (v128_t *) &s[0]; +char *v128_hex_string(v128_t *x) +{ + int i, j; - v128_copy(x,v); - } + for (i = j = 0; i < 16; i++) { + bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] >> 4); + bit_string[j++] = srtp_nibble_to_hex_char(x->v8[i] & 0xF); + } + + bit_string[j] = 0; /* null terminate string */ + return bit_string; +} + +char *v128_bit_string(v128_t *x) +{ + int j, i; + uint32_t mask; + + for (j = i = 0; j < 4; j++) { + for (mask = 0x80000000; mask > 0; mask >>= 1) { + if (x->v32[j] & mask) + bit_string[i] = '1'; + else + bit_string[i] = '0'; + ++i; + } + } + bit_string[128] = 0; /* null terminate string */ + + return bit_string; +} + +void v128_copy_octet_string(v128_t *x, const uint8_t s[16]) +{ +#ifdef ALIGNMENT_32BIT_REQUIRED + if ((((uint32_t)&s[0]) & 0x3) != 0) +#endif + { + x->v8[0] = s[0]; + x->v8[1] = s[1]; + x->v8[2] = s[2]; + x->v8[3] = s[3]; + x->v8[4] = s[4]; + x->v8[5] = s[5]; + x->v8[6] = s[6]; + x->v8[7] = s[7]; + x->v8[8] = s[8]; + x->v8[9] = s[9]; + x->v8[10] = s[10]; + x->v8[11] = s[11]; + x->v8[12] = s[12]; + x->v8[13] = s[13]; + x->v8[14] = s[14]; + x->v8[15] = s[15]; + } +#ifdef ALIGNMENT_32BIT_REQUIRED + else { + v128_t *v = (v128_t *)&s[0]; + + v128_copy(x, v); + } #endif } #ifndef DATATYPES_USE_MACROS /* little functions are not macros */ -void -v128_set_to_zero(v128_t *x) { - _v128_set_to_zero(x); +void v128_set_to_zero(v128_t *x) +{ + _v128_set_to_zero(x); } -void -v128_copy(v128_t *x, const v128_t *y) { - _v128_copy(x, y); +void v128_copy(v128_t *x, const v128_t *y) +{ + _v128_copy(x, y); } -void -v128_xor(v128_t *z, v128_t *x, v128_t *y) { - _v128_xor(z, x, y); -} - -void -v128_and(v128_t *z, v128_t *x, v128_t *y) { - _v128_and(z, x, y); +void v128_xor(v128_t *z, v128_t *x, v128_t *y) +{ + _v128_xor(z, x, y); } -void -v128_or(v128_t *z, v128_t *x, v128_t *y) { - _v128_or(z, x, y); +void v128_and(v128_t *z, v128_t *x, v128_t *y) +{ + _v128_and(z, x, y); } -void -v128_complement(v128_t *x) { - _v128_complement(x); +void v128_or(v128_t *z, v128_t *x, v128_t *y) +{ + _v128_or(z, x, y); } -int -v128_is_eq(const v128_t *x, const v128_t *y) { - return _v128_is_eq(x, y); +void v128_complement(v128_t *x) +{ + _v128_complement(x); } -int -v128_xor_eq(v128_t *x, const v128_t *y) { - return _v128_xor_eq(x, y); +int v128_is_eq(const v128_t *x, const v128_t *y) +{ + return _v128_is_eq(x, y); } -int -v128_get_bit(const v128_t *x, int i) { - return _v128_get_bit(x, i); +int v128_xor_eq(v128_t *x, const v128_t *y) +{ + return _v128_xor_eq(x, y); } -void -v128_set_bit(v128_t *x, int i) { - _v128_set_bit(x, i); -} - -void -v128_clear_bit(v128_t *x, int i){ - _v128_clear_bit(x, i); -} - -void -v128_set_bit_to(v128_t *x, int i, int y){ - _v128_set_bit_to(x, i, y); +int v128_get_bit(const v128_t *x, int i) +{ + return _v128_get_bit(x, i); } +void v128_set_bit(v128_t *x, int i) +{ + _v128_set_bit(x, i); +} + +void v128_clear_bit(v128_t *x, int i) +{ + _v128_clear_bit(x, i); +} + +void v128_set_bit_to(v128_t *x, int i, int y) +{ + _v128_set_bit_to(x, i, y); +} #endif /* DATATYPES_USE_MACROS */ -void -v128_right_shift(v128_t *x, int shift) { - const int base_index = shift >> 5; - const int bit_index = shift & 31; - int i, from; - uint32_t b; - - if (shift > 127) { - v128_set_to_zero(x); - return; - } +void v128_right_shift(v128_t *x, int shift) +{ + const int base_index = shift >> 5; + const int bit_index = shift & 31; + int i, from; + uint32_t b; - if (bit_index == 0) { - - /* copy each word from left size to right side */ - x->v32[4-1] = x->v32[4-1-base_index]; - for (i=4-1; i > base_index; i--) - x->v32[i-1] = x->v32[i-1-base_index]; - - } else { - - /* set each word to the "or" of the two bit-shifted words */ - for (i = 4; i > base_index; i--) { - from = i-1 - base_index; - b = x->v32[from] << bit_index; - if (from > 0) - b |= x->v32[from-1] >> (32-bit_index); - x->v32[i-1] = b; + if (shift > 127) { + v128_set_to_zero(x); + return; } - - } - /* now wrap up the final portion */ - for (i=0; i < base_index; i++) - x->v32[i] = 0; - + if (bit_index == 0) { + /* copy each word from left size to right side */ + x->v32[4 - 1] = x->v32[4 - 1 - base_index]; + for (i = 4 - 1; i > base_index; i--) + x->v32[i - 1] = x->v32[i - 1 - base_index]; + + } else { + /* set each word to the "or" of the two bit-shifted words */ + for (i = 4; i > base_index; i--) { + from = i - 1 - base_index; + b = x->v32[from] << bit_index; + if (from > 0) + b |= x->v32[from - 1] >> (32 - bit_index); + x->v32[i - 1] = b; + } + } + + /* now wrap up the final portion */ + for (i = 0; i < base_index; i++) + x->v32[i] = 0; } -void -v128_left_shift(v128_t *x, int shift) { - int i; - const int base_index = shift >> 5; - const int bit_index = shift & 31; +void v128_left_shift(v128_t *x, int shift) +{ + int i; + const int base_index = shift >> 5; + const int bit_index = shift & 31; - if (shift > 127) { - v128_set_to_zero(x); - return; - } - - if (bit_index == 0) { - for (i=0; i < 4 - base_index; i++) - x->v32[i] = x->v32[i+base_index]; - } else { - for (i=0; i < 4 - base_index - 1; i++) - x->v32[i] = (x->v32[i+base_index] >> bit_index) ^ - (x->v32[i+base_index+1] << (32 - bit_index)); - x->v32[4 - base_index-1] = x->v32[4-1] >> bit_index; - } + if (shift > 127) { + v128_set_to_zero(x); + return; + } - /* now wrap up the final portion */ - for (i = 4 - base_index; i < 4; i++) - x->v32[i] = 0; + if (bit_index == 0) { + for (i = 0; i < 4 - base_index; i++) + x->v32[i] = x->v32[i + base_index]; + } else { + for (i = 0; i < 4 - base_index - 1; i++) + x->v32[i] = (x->v32[i + base_index] >> bit_index) ^ + (x->v32[i + base_index + 1] << (32 - bit_index)); + x->v32[4 - base_index - 1] = x->v32[4 - 1] >> bit_index; + } + /* now wrap up the final portion */ + for (i = 4 - base_index; i < 4; i++) + x->v32[i] = 0; } /* functions manipulating bitvector_t */ #ifndef DATATYPES_USE_MACROS /* little functions are not macros */ -int -bitvector_get_bit(const bitvector_t *v, int bit_index) +int bitvector_get_bit(const bitvector_t *v, int bit_index) { - return _bitvector_get_bit(v, bit_index); + return _bitvector_get_bit(v, bit_index); } -void -bitvector_set_bit(bitvector_t *v, int bit_index) +void bitvector_set_bit(bitvector_t *v, int bit_index) { - _bitvector_set_bit(v, bit_index); + _bitvector_set_bit(v, bit_index); } -void -bitvector_clear_bit(bitvector_t *v, int bit_index) +void bitvector_clear_bit(bitvector_t *v, int bit_index) { - _bitvector_clear_bit(v, bit_index); + _bitvector_clear_bit(v, bit_index); } - #endif /* DATATYPES_USE_MACROS */ -int -bitvector_alloc(bitvector_t *v, unsigned long length) { - unsigned long l; +int bitvector_alloc(bitvector_t *v, unsigned long length) +{ + unsigned long l; - /* Round length up to a multiple of bits_per_word */ - length = (length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1)); + /* Round length up to a multiple of bits_per_word */ + length = + (length + bits_per_word - 1) & ~(unsigned long)((bits_per_word - 1)); - l = length / bits_per_word * bytes_per_word; + l = length / bits_per_word * bytes_per_word; - /* allocate memory, then set parameters */ - if (l == 0) + /* allocate memory, then set parameters */ + if (l == 0) { + v->word = NULL; + v->length = 0; + return -1; + } else { + v->word = (uint32_t *)srtp_crypto_alloc(l); + if (v->word == NULL) { + v->length = 0; + return -1; + } + } + v->length = length; + + /* initialize bitvector to zero */ + bitvector_set_to_zero(v); + + return 0; +} + +void bitvector_dealloc(bitvector_t *v) +{ + if (v->word != NULL) + srtp_crypto_free(v->word); v->word = NULL; - else { - v->word = (uint32_t*)srtp_crypto_alloc(l); - if (v->word == NULL) { - v->word = NULL; - v->length = 0; - return -1; - } - } - v->length = length; - - /* initialize bitvector to zero */ - bitvector_set_to_zero(v); - - return 0; + v->length = 0; } - -void -bitvector_dealloc(bitvector_t *v) { - if (v->word != NULL) - srtp_crypto_free(v->word); - v->word = NULL; - v->length = 0; -} - -void -bitvector_set_to_zero(bitvector_t *x) +void bitvector_set_to_zero(bitvector_t *x) { - /* C99 guarantees that memset(0) will set the value 0 for uint32_t */ - memset(x->word, 0, x->length >> 3); + /* C99 guarantees that memset(0) will set the value 0 for uint32_t */ + memset(x->word, 0, x->length >> 3); } -char * -bitvector_bit_string(bitvector_t *x, char* buf, int len) { - int j, i; - uint32_t mask; - - for (j=i=0; j < (int)(x->length>>5) && i < len-1; j++) { - for (mask=0x80000000; mask > 0; mask >>= 1) { - if (x->word[j] & mask) - buf[i] = '1'; - else - buf[i] = '0'; - ++i; - if (i >= len-1) - break; - } - } - buf[i] = 0; /* null terminate string */ - - return buf; -} - -void -bitvector_left_shift(bitvector_t *x, int shift) { - int i; - const int base_index = shift >> 5; - const int bit_index = shift & 31; - const int word_length = x->length >> 5; - - if (shift >= (int)x->length) { - bitvector_set_to_zero(x); - return; - } - - if (bit_index == 0) { - for (i=0; i < word_length - base_index; i++) - x->word[i] = x->word[i+base_index]; - } else { - for (i=0; i < word_length - base_index - 1; i++) - x->word[i] = (x->word[i+base_index] >> bit_index) ^ - (x->word[i+base_index+1] << (32 - bit_index)); - x->word[word_length - base_index-1] = x->word[word_length-1] >> bit_index; - } - - /* now wrap up the final portion */ - for (i = word_length - base_index; i < word_length; i++) - x->word[i] = 0; - -} - -int -octet_string_is_eq(uint8_t *a, uint8_t *b, int len) { - uint8_t *end = b + len; - uint8_t accumulator = 0; - - /* - * We use this somewhat obscure implementation to try to ensure the running - * time only depends on len, even accounting for compiler optimizations. - * The accumulator ends up zero iff the strings are equal. - */ - while (b < end) - accumulator |= (*a++ ^ *b++); - - /* Return 1 if *not* equal. */ - return accumulator != 0; -} - -void -srtp_cleanse(void *s, size_t len) +char *bitvector_bit_string(bitvector_t *x, char *buf, int len) { - volatile unsigned char *p = (volatile unsigned char *)s; - while(len--) *p++ = 0; + int j, i; + uint32_t mask; + + for (j = i = 0; j < (int)(x->length >> 5) && i < len - 1; j++) { + for (mask = 0x80000000; mask > 0; mask >>= 1) { + if (x->word[j] & mask) + buf[i] = '1'; + else + buf[i] = '0'; + ++i; + if (i >= len - 1) + break; + } + } + buf[i] = 0; /* null terminate string */ + + return buf; } -void -octet_string_set_to_zero(void *s, size_t len) +void bitvector_left_shift(bitvector_t *x, int shift) +{ + int i; + const int base_index = shift >> 5; + const int bit_index = shift & 31; + const int word_length = x->length >> 5; + + if (shift >= (int)x->length) { + bitvector_set_to_zero(x); + return; + } + + if (bit_index == 0) { + for (i = 0; i < word_length - base_index; i++) + x->word[i] = x->word[i + base_index]; + } else { + for (i = 0; i < word_length - base_index - 1; i++) + x->word[i] = (x->word[i + base_index] >> bit_index) ^ + (x->word[i + base_index + 1] << (32 - bit_index)); + x->word[word_length - base_index - 1] = + x->word[word_length - 1] >> bit_index; + } + + /* now wrap up the final portion */ + for (i = word_length - base_index; i < word_length; i++) + x->word[i] = 0; +} + +int octet_string_is_eq(uint8_t *a, uint8_t *b, int len) +{ + uint8_t *end = b + len; + uint8_t accumulator = 0; + + /* + * We use this somewhat obscure implementation to try to ensure the running + * time only depends on len, even accounting for compiler optimizations. + * The accumulator ends up zero iff the strings are equal. + */ + while (b < end) + accumulator |= (*a++ ^ *b++); + + /* Return 1 if *not* equal. */ + return accumulator != 0; +} + +void srtp_cleanse(void *s, size_t len) +{ + volatile unsigned char *p = (volatile unsigned char *)s; + while (len--) + *p++ = 0; +} + +void octet_string_set_to_zero(void *s, size_t len) { #ifdef OPENSSL - OPENSSL_cleanse(s, len); + OPENSSL_cleanse(s, len); #else - srtp_cleanse(s, len); + srtp_cleanse(s, len); #endif } #ifdef TESTAPP_SOURCE static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789+/"; + "abcdefghijklmnopqrstuvwxyz0123456789+/"; -static int base64_block_to_octet_triple(char *out, char *in) { - unsigned char sextets[4] = {0}; - int j = 0; - int i; +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++; - } + 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; + 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; +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; + while (i < len && j == 0) { + j = base64_block_to_octet_triple(out + k, in + i); + k += 3; + i += 4; + } + *pad = j; + return i; } #endif diff --git a/libs/srtp/crypto/math/stat.c b/libs/srtp/crypto/math/stat.c index 0b4aec3764..6dd332b0cf 100644 --- a/libs/srtp/crypto/math/stat.c +++ b/libs/srtp/crypto/math/stat.c @@ -1,33 +1,33 @@ /* * stats.c * - * statistical tests - * + * statistical tests + * * 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 @@ -44,14 +44,14 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "stat.h" -srtp_debug_module_t mod_stat = { - 0, /* debugging is off by default */ - (char *)"stat test" /* printable module name */ +srtp_debug_module_t srtp_mod_stat = { + 0, /* debugging is off by default */ + (char *)"stat test" /* printable module name */ }; /* @@ -61,166 +61,153 @@ srtp_debug_module_t mod_stat = { #define STAT_TEST_DATA_LEN 2500 -srtp_err_status_t -stat_test_monobit(uint8_t *data) { - uint8_t *data_end = data + STAT_TEST_DATA_LEN; - uint16_t ones_count; +srtp_err_status_t stat_test_monobit(uint8_t *data) +{ + uint8_t *data_end = data + STAT_TEST_DATA_LEN; + uint16_t ones_count; - ones_count = 0; - while (data < data_end) { - ones_count += octet_get_weight(*data); - data++; - } + ones_count = 0; + while (data < data_end) { + ones_count += octet_get_weight(*data); + data++; + } - debug_print(mod_stat, "bit count: %d", ones_count); - - if ((ones_count < 9725) || (ones_count > 10275)) - return srtp_err_status_algo_fail; + debug_print(srtp_mod_stat, "bit count: %d", ones_count); - return srtp_err_status_ok; + if ((ones_count < 9725) || (ones_count > 10275)) + return srtp_err_status_algo_fail; + + return srtp_err_status_ok; } -srtp_err_status_t -stat_test_poker(uint8_t *data) { - int i; - uint8_t *data_end = data + STAT_TEST_DATA_LEN; - double poker; - uint16_t f[16] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 - }; - - while (data < data_end) { - f[*data & 0x0f]++; /* increment freq. count for low nibble */ - f[(*data) >> 4]++; /* increment freq. count for high nibble */ - data++; - } +srtp_err_status_t stat_test_poker(uint8_t *data) +{ + int i; + uint8_t *data_end = data + STAT_TEST_DATA_LEN; + double poker; + uint16_t f[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - poker = 0.0; - for (i=0; i < 16; i++) - poker += (double) f[i] * f[i]; + while (data < data_end) { + f[*data & 0x0f]++; /* increment freq. count for low nibble */ + f[(*data) >> 4]++; /* increment freq. count for high nibble */ + data++; + } - poker *= (16.0 / 5000.0); - poker -= 5000.0; + poker = 0.0; + for (i = 0; i < 16; i++) + poker += (double)f[i] * f[i]; - debug_print(mod_stat, "poker test: %f\n", poker); - - if ((poker < 2.16) || (poker > 46.17)) - return srtp_err_status_algo_fail; - - return srtp_err_status_ok; + poker *= (16.0 / 5000.0); + poker -= 5000.0; + + debug_print(srtp_mod_stat, "poker test: %f\n", poker); + + if ((poker < 2.16) || (poker > 46.17)) + return srtp_err_status_algo_fail; + + return srtp_err_status_ok; } - /* * runs[i] holds the number of runs of size (i-1) */ -srtp_err_status_t -stat_test_runs(uint8_t *data) { - uint8_t *data_end = data + STAT_TEST_DATA_LEN; - uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; - uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 }; - uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 }; - uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 }; - int state = 0; - uint16_t mask; - int i; - - /* - * the state variable holds the number of bits in the - * current run (or gap, if negative) - */ - - while (data < data_end) { +srtp_err_status_t stat_test_runs(uint8_t *data) +{ + uint8_t *data_end = data + STAT_TEST_DATA_LEN; + uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; + uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 }; + uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 }; + uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 }; + int state = 0; + uint16_t mask; + int i; - /* loop over the bits of this byte */ - for (mask = 1; mask < 256; mask <<= 1) { - if (*data & mask) { + /* + * the state variable holds the number of bits in the + * current run (or gap, if negative) + */ - /* next bit is a one */ - if (state > 0) { + while (data < data_end) { + /* loop over the bits of this byte */ + for (mask = 1; mask < 256; mask <<= 1) { + if (*data & mask) { + /* next bit is a one */ + if (state > 0) { + /* prefix is a run, so increment the run-count */ + state++; - /* prefix is a run, so increment the run-count */ - state++; + /* check for long runs */ + if (state > 25) { + debug_print(srtp_mod_stat, ">25 runs: %d", state); + return srtp_err_status_algo_fail; + } - /* check for long runs */ - if (state > 25) { - debug_print(mod_stat, ">25 runs: %d", state); - return srtp_err_status_algo_fail; - } + } else if (state < 0) { + /* prefix is a gap */ + if (state < -25) { + debug_print(srtp_mod_stat, ">25 gaps: %d", state); + return srtp_err_status_algo_fail; /* long-runs test + failed */ + } + if (state < -6) { + state = -6; /* group together gaps > 5 */ + } + gaps[-1 - state]++; /* increment gap count */ + state = 1; /* set state at one set bit */ + } else { + /* state is zero; this happens only at initialization */ + state = 1; + } + } else { + /* next bit is a zero */ + if (state > 0) { + /* prefix is a run */ + if (state > 25) { + debug_print(srtp_mod_stat, ">25 runs (2): %d", state); + return srtp_err_status_algo_fail; /* long-runs test + failed */ + } + if (state > 6) { + state = 6; /* group together runs > 5 */ + } + runs[state - 1]++; /* increment run count */ + state = -1; /* set state at one zero bit */ + } else if (state < 0) { + /* prefix is a gap, so increment gap-count (decrement state) + */ + state--; - } else if (state < 0) { + /* check for long gaps */ + if (state < -25) { + debug_print(srtp_mod_stat, ">25 gaps (2): %d", state); + return srtp_err_status_algo_fail; + } - /* prefix is a gap */ - if (state < -25) { - debug_print(mod_stat, ">25 gaps: %d", state); - return srtp_err_status_algo_fail; /* long-runs test failed */ - } - if (state < -6) { - state = -6; /* group together gaps > 5 */ - } - gaps[-1-state]++; /* increment gap count */ - state = 1; /* set state at one set bit */ - } else { + } else { + /* state is zero; this happens only at initialization */ + state = -1; + } + } + } - /* state is zero; this happens only at initialization */ - state = 1; - } - } else { - - /* next bit is a zero */ - if (state > 0) { - - /* prefix is a run */ - if (state > 25) { - debug_print(mod_stat, ">25 runs (2): %d", state); - return srtp_err_status_algo_fail; /* long-runs test failed */ - } - if (state > 6) { - state = 6; /* group together runs > 5 */ - } - runs[state-1]++; /* increment run count */ - state = -1; /* set state at one zero bit */ - } else if (state < 0) { - - /* prefix is a gap, so increment gap-count (decrement state) */ - state--; - - /* check for long gaps */ - if (state < -25) { - debug_print(mod_stat, ">25 gaps (2): %d", state); - return srtp_err_status_algo_fail; - } - - } else { - - /* state is zero; this happens only at initialization */ - state = -1; - } - } + /* move along to next octet */ + data++; } - /* move along to next octet */ - data++; - } + if (srtp_mod_stat.on) { + debug_print(srtp_mod_stat, "runs test", NULL); + for (i = 0; i < 6; i++) + debug_print(srtp_mod_stat, " runs[]: %d", runs[i]); + for (i = 0; i < 6; i++) + debug_print(srtp_mod_stat, " gaps[]: %d", gaps[i]); + } - if (mod_stat.on) { - debug_print(mod_stat, "runs test", NULL); - for (i=0; i < 6; i++) - debug_print(mod_stat, " runs[]: %d", runs[i]); - for (i=0; i < 6; i++) - debug_print(mod_stat, " gaps[]: %d", gaps[i]); - } + /* check run and gap counts against the fixed limits */ + for (i = 0; i < 6; i++) + if ((runs[i] < lo_value[i]) || (runs[i] > hi_value[i]) || + (gaps[i] < lo_value[i]) || (gaps[i] > hi_value[i])) + return srtp_err_status_algo_fail; - /* check run and gap counts against the fixed limits */ - for (i=0; i < 6; i++) - if ( (runs[i] < lo_value[i] ) || (runs[i] > hi_value[i]) - || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i])) - return srtp_err_status_algo_fail; - - - return srtp_err_status_ok; + return srtp_err_status_ok; } - - diff --git a/libs/srtp/crypto/replay/rdb.c b/libs/srtp/crypto/replay/rdb.c index 3741367f68..ab1c7b55b6 100644 --- a/libs/srtp/crypto/replay/rdb.c +++ b/libs/srtp/crypto/replay/rdb.c @@ -43,14 +43,12 @@ * */ - #ifdef HAVE_CONFIG_H - #include +#include #endif #include "rdb.h" - /* * this implementation of a replay database works as follows: * @@ -61,7 +59,7 @@ */ /* srtp_rdb_init initalizes rdb */ -srtp_err_status_t srtp_rdb_init (srtp_rdb_t *rdb) +srtp_err_status_t srtp_rdb_init(srtp_rdb_t *rdb) { v128_set_to_zero(&rdb->bitmask); rdb->window_start = 0; @@ -71,9 +69,8 @@ srtp_err_status_t srtp_rdb_init (srtp_rdb_t *rdb) /* * srtp_rdb_check checks to see if index appears in rdb */ -srtp_err_status_t srtp_rdb_check (const srtp_rdb_t *rdb, uint32_t p_index) +srtp_err_status_t srtp_rdb_check(const srtp_rdb_t *rdb, uint32_t p_index) { - /* if the index appears after (or at very end of) the window, its good */ if (p_index >= rdb->window_start + rdb_bits_in_bitmask) { return srtp_err_status_ok; @@ -101,35 +98,32 @@ srtp_err_status_t srtp_rdb_check (const srtp_rdb_t *rdb, uint32_t p_index) * indicated that the index does not appear in the rdb, e.g., a mutex * should protect the rdb between these calls */ -srtp_err_status_t srtp_rdb_add_index (srtp_rdb_t *rdb, uint32_t p_index) +srtp_err_status_t srtp_rdb_add_index(srtp_rdb_t *rdb, uint32_t p_index) { - int delta; + unsigned int delta; - /* here we *assume* that p_index > rdb->window_start */ + if (p_index < rdb->window_start) + return srtp_err_status_replay_fail; delta = (p_index - rdb->window_start); if (delta < rdb_bits_in_bitmask) { - /* if the p_index is within the window, set the appropriate bit */ v128_set_bit(&rdb->bitmask, delta); } else { - delta -= rdb_bits_in_bitmask - 1; /* shift the window forward by delta bits*/ v128_left_shift(&rdb->bitmask, delta); v128_set_bit(&rdb->bitmask, rdb_bits_in_bitmask - 1); rdb->window_start += delta; - } return srtp_err_status_ok; } -srtp_err_status_t srtp_rdb_increment (srtp_rdb_t *rdb) +srtp_err_status_t srtp_rdb_increment(srtp_rdb_t *rdb) { - if (rdb->window_start >= 0x7fffffff) { return srtp_err_status_key_expired; } @@ -137,7 +131,7 @@ srtp_err_status_t srtp_rdb_increment (srtp_rdb_t *rdb) return srtp_err_status_ok; } -uint32_t srtp_rdb_get_value (const srtp_rdb_t *rdb) +uint32_t srtp_rdb_get_value(const srtp_rdb_t *rdb) { return rdb->window_start; } diff --git a/libs/srtp/crypto/replay/rdbx.c b/libs/srtp/crypto/replay/rdbx.c index 63f66ff024..40cba01a1f 100644 --- a/libs/srtp/crypto/replay/rdbx.c +++ b/libs/srtp/crypto/replay/rdbx.c @@ -44,12 +44,11 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "rdbx.h" - /* * from RFC 3711: * @@ -64,8 +63,6 @@ * incremented by one (if the packet containing s is authentic). */ - - /* * rdbx implementation notes * @@ -83,14 +80,13 @@ * srtp_index_advance(&guess, delta), where delta is the difference. * * - * A srtp_rdbx_t consists of a srtp_xtd_seq_num_t and a bitmask. The index is highest - * sequence number that has been received, and the bitmask indicates + * A srtp_rdbx_t consists of a srtp_xtd_seq_num_t and a bitmask. The index is + * highest sequence number that has been received, and the bitmask indicates * which of the recent indicies have been received as well. The * highest bit in the bitmask corresponds to the index in the bitmask. */ - -void srtp_index_init (srtp_xtd_seq_num_t *pi) +void srtp_index_init(srtp_xtd_seq_num_t *pi) { #ifdef NO_64BIT_MATH *pi = make64(0, 0); @@ -99,7 +95,7 @@ void srtp_index_init (srtp_xtd_seq_num_t *pi) #endif } -void srtp_index_advance (srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s) +void srtp_index_advance(srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s) { #ifdef NO_64BIT_MATH /* a > ~b means a+b will generate a carry */ @@ -110,7 +106,6 @@ void srtp_index_advance (srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s) #endif } - /* * srtp_index_guess(local, guess, s) * @@ -124,24 +119,19 @@ void srtp_index_advance (srtp_xtd_seq_num_t *pi, srtp_sequence_number_t s) * unsigned integer! */ -int32_t srtp_index_guess (const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s) +int32_t srtp_index_guess(const srtp_xtd_seq_num_t *local, + srtp_xtd_seq_num_t *guess, + srtp_sequence_number_t s) { #ifdef NO_64BIT_MATH - uint32_t local_roc = ((high32(*local) << 16) | - (low32(*local) >> 16)); + uint32_t local_roc = ((high32(*local) << 16) | (low32(*local) >> 16)); uint16_t local_seq = (uint16_t)(low32(*local)); #else uint32_t local_roc = (uint32_t)(*local >> 16); uint16_t local_seq = (uint16_t)*local; #endif -#ifdef NO_64BIT_MATH - uint32_t guess_roc = ((high32(*guess) << 16) | - (low32(*guess) >> 16)); - uint16_t guess_seq = (uint16_t)(low32(*guess)); -#else - uint32_t guess_roc = (uint32_t)(*guess >> 16); - uint16_t guess_seq = (uint16_t)*guess; -#endif + uint32_t guess_roc; + uint16_t guess_seq; int32_t difference; if (local_seq < seq_num_median) { @@ -163,10 +153,9 @@ int32_t srtp_index_guess (const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *g } guess_seq = s; - /* Note: guess_roc is 32 bits, so this generates a 48-bit result! */ +/* Note: guess_roc is 32 bits, so this generates a 48-bit result! */ #ifdef NO_64BIT_MATH - *guess = make64(guess_roc >> 16, - (guess_roc << 16) | guess_seq); + *guess = make64(guess_roc >> 16, (guess_roc << 16) | guess_seq); #else *guess = (((uint64_t)guess_roc) << 16) | guess_seq; #endif @@ -179,11 +168,11 @@ int32_t srtp_index_guess (const srtp_xtd_seq_num_t *local, srtp_xtd_seq_num_t *g * */ - /* - * srtp_rdbx_init(&r, ws) initializes the srtp_rdbx_t pointed to by r with window size ws + * srtp_rdbx_init(&r, ws) initializes the srtp_rdbx_t pointed to by r with + * window size ws */ -srtp_err_status_t srtp_rdbx_init (srtp_rdbx_t *rdbx, unsigned long ws) +srtp_err_status_t srtp_rdbx_init(srtp_rdbx_t *rdbx, unsigned long ws) { if (ws == 0) { return srtp_err_status_bad_param; @@ -201,7 +190,7 @@ srtp_err_status_t srtp_rdbx_init (srtp_rdbx_t *rdbx, unsigned long ws) /* * srtp_rdbx_dealloc(&r) frees memory for the srtp_rdbx_t pointed to by r */ -srtp_err_status_t srtp_rdbx_dealloc (srtp_rdbx_t *rdbx) +srtp_err_status_t srtp_rdbx_dealloc(srtp_rdbx_t *rdbx) { bitvector_dealloc(&rdbx->bitmask); @@ -215,12 +204,12 @@ srtp_err_status_t srtp_rdbx_dealloc (srtp_rdbx_t *rdbx) * srtp_err_status_replay_old; otherwise, srtp_err_status_ok is returned. * */ -srtp_err_status_t srtp_rdbx_set_roc (srtp_rdbx_t *rdbx, uint32_t roc) +srtp_err_status_t srtp_rdbx_set_roc(srtp_rdbx_t *rdbx, uint32_t roc) { bitvector_set_to_zero(&rdbx->bitmask); #ifdef NO_64BIT_MATH - #error not yet implemented +#error not yet implemented #else /* make sure that we're not moving backwards */ @@ -240,7 +229,7 @@ srtp_err_status_t srtp_rdbx_set_roc (srtp_rdbx_t *rdbx, uint32_t roc) * for the srtp_rdbx_t pointed to by rdbx * */ -srtp_xtd_seq_num_t srtp_rdbx_get_packet_index (const srtp_rdbx_t *rdbx) +srtp_xtd_seq_num_t srtp_rdbx_get_packet_index(const srtp_rdbx_t *rdbx) { return rdbx->index; } @@ -250,7 +239,7 @@ srtp_xtd_seq_num_t srtp_rdbx_get_packet_index (const srtp_rdbx_t *rdbx) * for the srtp_rdbx_t pointed to by rdbx * */ -unsigned long srtp_rdbx_get_window_size (const srtp_rdbx_t *rdbx) +unsigned long srtp_rdbx_get_window_size(const srtp_rdbx_t *rdbx) { return bitvector_get_length(&rdbx->bitmask); } @@ -259,16 +248,17 @@ unsigned long srtp_rdbx_get_window_size (const srtp_rdbx_t *rdbx) * srtp_rdbx_check(&r, delta) checks to see if the srtp_xtd_seq_num_t * which is at rdbx->index + delta is in the rdb */ -srtp_err_status_t srtp_rdbx_check (const srtp_rdbx_t *rdbx, int delta) +srtp_err_status_t srtp_rdbx_check(const srtp_rdbx_t *rdbx, int delta) { - - if (delta > 0) { /* if delta is positive, it's good */ + if (delta > 0) { /* if delta is positive, it's good */ return srtp_err_status_ok; } else if ((int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta < 0) { /* if delta is lower than the bitmask, it's bad */ return srtp_err_status_replay_old; - } else if (bitvector_get_bit(&rdbx->bitmask, - (int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) == 1) { + } else if (bitvector_get_bit( + &rdbx->bitmask, + (int)(bitvector_get_length(&rdbx->bitmask) - 1) + delta) == + 1) { /* delta is within the window, so check the bitmask */ return srtp_err_status_replay_fail; } @@ -285,17 +275,18 @@ srtp_err_status_t srtp_rdbx_check (const srtp_rdbx_t *rdbx, int delta) * indicated that the index does not appear in the rdbx, e.g., a mutex * should protect the rdbx between these calls if need be */ -srtp_err_status_t srtp_rdbx_add_index (srtp_rdbx_t *rdbx, int delta) +srtp_err_status_t srtp_rdbx_add_index(srtp_rdbx_t *rdbx, int delta) { - if (delta > 0) { /* shift forward by delta */ srtp_index_advance(&rdbx->index, delta); bitvector_left_shift(&rdbx->bitmask, delta); - bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1); + bitvector_set_bit(&rdbx->bitmask, + bitvector_get_length(&rdbx->bitmask) - 1); } else { /* delta is in window */ - bitvector_set_bit(&rdbx->bitmask, bitvector_get_length(&rdbx->bitmask) - 1 + delta); + bitvector_set_bit(&rdbx->bitmask, + bitvector_get_length(&rdbx->bitmask) - 1 + delta); } /* note that we need not consider the case that delta == 0 */ @@ -303,8 +294,6 @@ srtp_err_status_t srtp_rdbx_add_index (srtp_rdbx_t *rdbx, int delta) return srtp_err_status_ok; } - - /* * srtp_rdbx_estimate_index(rdbx, guess, s) * @@ -313,25 +302,27 @@ srtp_err_status_t srtp_rdbx_add_index (srtp_rdbx_t *rdbx, int delta) * index to which s corresponds, and returns the difference between * *guess and the locally stored synch info */ -int32_t srtp_rdbx_estimate_index (const srtp_rdbx_t *rdbx, srtp_xtd_seq_num_t *guess, srtp_sequence_number_t s) +int32_t srtp_rdbx_estimate_index(const srtp_rdbx_t *rdbx, + srtp_xtd_seq_num_t *guess, + srtp_sequence_number_t s) { - - /* - * if the sequence number and rollover counter in the rdbx are - * non-zero, then use the srtp_index_guess(...) function, otherwise, just - * set the rollover counter to zero (since the srtp_index_guess(...) - * function might incorrectly guess that the rollover counter is - * 0xffffffff) - */ +/* + * if the sequence number and rollover counter in the rdbx are + * non-zero, then use the srtp_index_guess(...) function, otherwise, just + * set the rollover counter to zero (since the srtp_index_guess(...) + * function might incorrectly guess that the rollover counter is + * 0xffffffff) + */ #ifdef NO_64BIT_MATH /* seq_num_median = 0x8000 */ - if (high32(rdbx->index) > 0 || - low32(rdbx->index) > seq_num_median) + if (high32(rdbx->index) > 0 || low32(rdbx->index) > seq_num_median) #else if (rdbx->index > seq_num_median) #endif - { return srtp_index_guess(&rdbx->index, guess, s); } + { + return srtp_index_guess(&rdbx->index, guess, s); + } #ifdef NO_64BIT_MATH *guess = make64(0, (uint32_t)s); @@ -372,12 +363,12 @@ uint32_t srtp_rdbx_get_roc(const srtp_rdbx_t *rdbx) * rollover counter value, then the function returns * srtp_err_status_replay_old, otherwise, srtp_err_status_ok is returned. */ -srtp_err_status_t srtp_rdbx_set_roc_seq (srtp_rdbx_t *rdbx, - uint32_t roc, - uint16_t seq) +srtp_err_status_t srtp_rdbx_set_roc_seq(srtp_rdbx_t *rdbx, + uint32_t roc, + uint16_t seq) { #ifdef NO_64BIT_MATH - #error not yet implemented +#error not yet implemented #else /* make sure that we're not moving backwards */ @@ -393,4 +384,3 @@ srtp_err_status_t srtp_rdbx_set_roc_seq (srtp_rdbx_t *rdbx, return srtp_err_status_ok; } - diff --git a/libs/srtp/crypto/replay/ut_sim.c b/libs/srtp/crypto/replay/ut_sim.c index b50164ced1..c621c0e9f2 100644 --- a/libs/srtp/crypto/replay/ut_sim.c +++ b/libs/srtp/crypto/replay/ut_sim.c @@ -3,32 +3,32 @@ * * an unreliable transport simulator * (for testing replay databases and suchlike) - * + * * 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 @@ -44,66 +44,61 @@ * */ - #ifdef HAVE_CONFIG_H - #include +#include #endif #include "ut_sim.h" - -int -ut_compar(const void *a, const void *b) { - return rand() > (RAND_MAX/2) ? -1 : 1; +int ut_compar(const void *a, const void *b) +{ + return rand() > (RAND_MAX / 2) ? -1 : 1; } -void -ut_init(ut_connection *utc) { - int i; - utc->index = 0; +void ut_init(ut_connection *utc) +{ + int i; + utc->index = 0; - for (i=0; i < UT_BUF; i++) - utc->buffer[i] = i; - - qsort(utc->buffer, UT_BUF, sizeof(uint32_t), ut_compar); + for (i = 0; i < UT_BUF; i++) + utc->buffer[i] = i; - utc->index = UT_BUF - 1; + qsort(utc->buffer, UT_BUF, sizeof(uint32_t), ut_compar); + + utc->index = UT_BUF - 1; } -uint32_t -ut_next_index(ut_connection *utc) { - uint32_t tmp; +uint32_t ut_next_index(ut_connection *utc) +{ + uint32_t tmp; - tmp = utc->buffer[0]; - utc->index++; - utc->buffer[0] = utc->index; + tmp = utc->buffer[0]; + utc->index++; + utc->buffer[0] = utc->index; - qsort(utc->buffer, UT_BUF, sizeof(uint32_t), ut_compar); - - return tmp; + qsort(utc->buffer, UT_BUF, sizeof(uint32_t), ut_compar); + + return tmp; } - - #ifdef UT_TEST #include -int -main() { - uint32_t i, irecvd, idiff; - ut_connection utc; +int main() +{ + uint32_t i, irecvd, idiff; + ut_connection utc; - ut_init(&utc); + ut_init(&utc); - for (i=0; i < 1000; i++) { - irecvd = ut_next_index(&utc); - idiff = i - irecvd; - printf("%lu\t%lu\t%d\n", i, irecvd, idiff); - } - - return 0; + for (i = 0; i < 1000; i++) { + irecvd = ut_next_index(&utc); + idiff = i - irecvd; + printf("%lu\t%lu\t%d\n", i, irecvd, idiff); + } + + return 0; } - #endif diff --git a/libs/srtp/crypto/test/aes_calc.c b/libs/srtp/crypto/test/aes_calc.c index 08a0541a1b..b362fd57fc 100644 --- a/libs/srtp/crypto/test/aes_calc.c +++ b/libs/srtp/crypto/test/aes_calc.c @@ -1,6 +1,6 @@ /* * aes_calc.c - * + * * A simple AES calculator for generating AES encryption values * * David A. McGrew @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -44,10 +44,12 @@ */ /* - + Example usage (with first NIST FIPS 197 test case): - -[sh]$ test/aes_calc 000102030405060708090a0b0c0d0e0f 00112233445566778899aabbccddeeff -v + + [sh]$ test/aes_calc 000102030405060708090a0b0c0d0e0f \ + 00112233445566778899aabbccddeeff -v + plaintext: 00112233445566778899aabbccddeeff key: 000102030405060708090a0b0c0d0e0f ciphertext: 69c4e0d86a7b0430d8cdb78070b4c55a @@ -55,7 +57,7 @@ */ #ifdef HAVE_CONFIG_H - #include +#include #endif #include "aes.h" @@ -63,98 +65,93 @@ #include #include "util.h" -void -usage(char *prog_name) { - printf("usage: %s [-v]\n", prog_name); - exit(255); +void usage(char *prog_name) +{ + printf("usage: %s <key> <plaintext> [-v]\n", prog_name); + exit(255); } #define AES_MAX_KEY_LEN 32 -int -main (int argc, char *argv[]) { - v128_t data; - uint8_t key[AES_MAX_KEY_LEN]; - srtp_aes_expanded_key_t exp_key; - int key_len, len; - int verbose = 0; - srtp_err_status_t status; +int main(int argc, char *argv[]) +{ + v128_t data; + uint8_t key[AES_MAX_KEY_LEN]; + srtp_aes_expanded_key_t exp_key; + int key_len, len; + int verbose = 0; + srtp_err_status_t status; - if (argc == 3) { - /* we're not in verbose mode */ - verbose = 0; - } else if (argc == 4) { - if (strncmp(argv[3], "-v", 2) == 0) { - /* we're in verbose mode */ - verbose = 1; + if (argc == 3) { + /* we're not in verbose mode */ + verbose = 0; + } else if (argc == 4) { + if (strncmp(argv[3], "-v", 2) == 0) { + /* we're in verbose mode */ + verbose = 1; + } else { + /* unrecognized flag, complain and exit */ + usage(argv[0]); + } } else { - /* unrecognized flag, complain and exit */ - usage(argv[0]); + /* we've been fed the wrong number of arguments - compain and exit */ + usage(argv[0]); } - } else { - /* we've been fed the wrong number of arguments - compain and exit */ - usage(argv[0]); - } - - /* read in key, checking length */ - if (strlen(argv[1]) > AES_MAX_KEY_LEN*2) { - fprintf(stderr, - "error: too many digits in key " - "(should be at most %d hexadecimal digits, found %u)\n", - AES_MAX_KEY_LEN*2, (unsigned)strlen(argv[1])); - exit(1); - } - len = hex_string_to_octet_string((char*)key, argv[1], AES_MAX_KEY_LEN*2); - /* check that hex string is the right length */ - if (len != 32 && len != 48 && len != 64) { - fprintf(stderr, - "error: bad number of digits in key " - "(should be 32/48/64 hexadecimal digits, found %d)\n", - len); - exit(1); - } - key_len = len/2; - - /* read in plaintext, checking length */ - if (strlen(argv[2]) > 16*2) { - fprintf(stderr, - "error: too many digits in plaintext " - "(should be %d hexadecimal digits, found %u)\n", - 16*2, (unsigned)strlen(argv[2])); - exit(1); - } - len = hex_string_to_octet_string((char *)(&data), argv[2], 16*2); - /* check that hex string is the right length */ - if (len < 16*2) { - fprintf(stderr, - "error: too few digits in plaintext " - "(should be %d hexadecimal digits, found %d)\n", - 16*2, len); - exit(1); - } - if (verbose) { - /* print out plaintext */ - printf("plaintext:\t%s\n", octet_string_hex_string((uint8_t *)&data, 16)); - } + /* read in key, checking length */ + if (strlen(argv[1]) > AES_MAX_KEY_LEN * 2) { + fprintf(stderr, "error: too many digits in key " + "(should be at most %d hexadecimal digits, found %u)\n", + AES_MAX_KEY_LEN * 2, (unsigned)strlen(argv[1])); + exit(1); + } + len = hex_string_to_octet_string((char *)key, argv[1], AES_MAX_KEY_LEN * 2); + /* check that hex string is the right length */ + if (len != 32 && len != 48 && len != 64) { + fprintf(stderr, "error: bad number of digits in key " + "(should be 32/48/64 hexadecimal digits, found %d)\n", + len); + exit(1); + } + key_len = len / 2; - /* encrypt plaintext */ - status = srtp_aes_expand_encryption_key(key, key_len, &exp_key); - if (status) { - fprintf(stderr, - "error: AES key expansion failed.\n"); - exit(1); - } + /* read in plaintext, checking length */ + if (strlen(argv[2]) > 16 * 2) { + fprintf(stderr, "error: too many digits in plaintext " + "(should be %d hexadecimal digits, found %u)\n", + 16 * 2, (unsigned)strlen(argv[2])); + exit(1); + } + len = hex_string_to_octet_string((char *)(&data), argv[2], 16 * 2); + /* check that hex string is the right length */ + if (len < 16 * 2) { + fprintf(stderr, "error: too few digits in plaintext " + "(should be %d hexadecimal digits, found %d)\n", + 16 * 2, len); + exit(1); + } - srtp_aes_encrypt(&data, &exp_key); + if (verbose) { + /* print out plaintext */ + printf("plaintext:\t%s\n", + octet_string_hex_string((uint8_t *)&data, 16)); + } - /* write ciphertext to output */ - if (verbose) { - printf("key:\t\t%s\n", octet_string_hex_string(key, key_len)); - printf("ciphertext:\t"); - } - printf("%s\n", v128_hex_string(&data)); + /* encrypt plaintext */ + status = srtp_aes_expand_encryption_key(key, key_len, &exp_key); + if (status) { + fprintf(stderr, "error: AES key expansion failed.\n"); + exit(1); + } - return 0; + srtp_aes_encrypt(&data, &exp_key); + + /* write ciphertext to output */ + if (verbose) { + printf("key:\t\t%s\n", octet_string_hex_string(key, key_len)); + printf("ciphertext:\t"); + } + printf("%s\n", v128_hex_string(&data)); + + return 0; } - diff --git a/libs/srtp/crypto/test/cipher_driver.c b/libs/srtp/crypto/test/cipher_driver.c index b63cd5ba0a..e28f5f264f 100644 --- a/libs/srtp/crypto/test/cipher_driver.c +++ b/libs/srtp/crypto/test/cipher_driver.c @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -44,12 +44,11 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif -#include <stdio.h> /* for printf() */ -#include <stdlib.h> /* for rand() */ -#include <string.h> /* for memset() */ +#include <stdio.h> /* for printf() */ +#include <stdlib.h> /* for rand() */ #include "getopt_s.h" #include "cipher.h" #ifdef OPENSSL @@ -61,12 +60,9 @@ #define PRINT_DEBUG 0 -void -cipher_driver_test_throughput(srtp_cipher_t *c); - -srtp_err_status_t -cipher_driver_self_test(srtp_cipher_type_t *ct); +void cipher_driver_test_throughput(srtp_cipher_t *c); +srtp_err_status_t cipher_driver_self_test(srtp_cipher_type_t *ct); /* * cipher_driver_test_buffering(ct) tests the cipher's output @@ -74,44 +70,43 @@ cipher_driver_self_test(srtp_cipher_type_t *ct); * calls */ -srtp_err_status_t -cipher_driver_test_buffering(srtp_cipher_t *c); - +srtp_err_status_t cipher_driver_test_buffering(srtp_cipher_t *c); /* * functions for testing cipher cache thrash */ -srtp_err_status_t -cipher_driver_test_array_throughput(srtp_cipher_type_t *ct, - int klen, int num_cipher); +srtp_err_status_t cipher_driver_test_array_throughput(srtp_cipher_type_t *ct, + int klen, + int num_cipher); -void -cipher_array_test_throughput(srtp_cipher_t *ca[], int num_cipher); +void cipher_array_test_throughput(srtp_cipher_t *ca[], int num_cipher); -uint64_t -cipher_array_bits_per_second(srtp_cipher_t *cipher_array[], int num_cipher, - unsigned octets_in_buffer, int num_trials); +uint64_t cipher_array_bits_per_second(srtp_cipher_t *cipher_array[], + int num_cipher, + unsigned octets_in_buffer, + int num_trials); -srtp_err_status_t -cipher_array_delete(srtp_cipher_t *cipher_array[], int num_cipher); +srtp_err_status_t cipher_array_delete(srtp_cipher_t *cipher_array[], + int num_cipher); -srtp_err_status_t -cipher_array_alloc_init(srtp_cipher_t ***cipher_array, int num_ciphers, - srtp_cipher_type_t *ctype, int klen); +srtp_err_status_t cipher_array_alloc_init(srtp_cipher_t ***cipher_array, + int num_ciphers, + srtp_cipher_type_t *ctype, + int klen); -void -usage(char *prog_name) { - printf("usage: %s [ -t | -v | -a ]\n", prog_name); - exit(255); +void usage(char *prog_name) +{ + printf("usage: %s [ -t | -v | -a ]\n", prog_name); + exit(255); } -void -check_status(srtp_err_status_t s) { - if (s) { - printf("error (code %d)\n", s); - exit(s); - } - return; +void check_status(srtp_err_status_t s) +{ + if (s) { + printf("error (code %d)\n", s); + exit(s); + } + return; } /* @@ -129,151 +124,163 @@ extern srtp_cipher_type_t srtp_aes_gcm_128_openssl; extern srtp_cipher_type_t srtp_aes_gcm_256_openssl; #endif -int -main(int argc, char *argv[]) { - srtp_cipher_t *c = NULL; - srtp_err_status_t status; - unsigned char test_key[48] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - }; - int q; - unsigned do_timing_test = 0; - unsigned do_validation = 0; - unsigned do_array_timing_test = 0; +int main(int argc, char *argv[]) +{ + srtp_cipher_t *c = NULL; + srtp_err_status_t status; + /* clang-format off */ + unsigned char test_key[48] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }; + /* clang-format on */ + int q; + unsigned do_timing_test = 0; + unsigned do_validation = 0; + unsigned do_array_timing_test = 0; - /* process input arguments */ - while (1) { - q = getopt_s(argc, argv, "tva"); - if (q == -1) - break; - switch (q) { - case 't': - do_timing_test = 1; - break; - case 'v': - do_validation = 1; - break; - case 'a': - do_array_timing_test = 1; - break; - default: - usage(argv[0]); - } - } - - printf("cipher test driver\n" - "David A. McGrew\n" - "Cisco Systems, Inc.\n"); - - if (!do_validation && !do_timing_test && !do_array_timing_test) - usage(argv[0]); - - /* arry timing (cache thrash) test */ - if (do_array_timing_test) { - int max_num_cipher = 1 << 16; /* number of ciphers in cipher_array */ - int num_cipher; - - for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) - cipher_driver_test_array_throughput(&srtp_null_cipher, 0, num_cipher); - - for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) - cipher_driver_test_array_throughput(&srtp_aes_icm_128, SRTP_AES_ICM_128_KEY_LEN_WSALT, num_cipher); - - for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) - cipher_driver_test_array_throughput(&srtp_aes_icm_256, SRTP_AES_ICM_256_KEY_LEN_WSALT, num_cipher); - -#ifdef OPENSSL - for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) - cipher_driver_test_array_throughput(&srtp_aes_icm_192, SRTP_AES_ICM_192_KEY_LEN_WSALT, num_cipher); - - for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { - cipher_driver_test_array_throughput(&srtp_aes_gcm_128_openssl, SRTP_AES_GCM_128_KEY_LEN_WSALT, num_cipher); + /* process input arguments */ + while (1) { + q = getopt_s(argc, argv, "tva"); + if (q == -1) + break; + switch (q) { + case 't': + do_timing_test = 1; + break; + case 'v': + do_validation = 1; + break; + case 'a': + do_array_timing_test = 1; + break; + default: + usage(argv[0]); + } } - for (num_cipher=1; num_cipher < max_num_cipher; num_cipher *=8) { - cipher_driver_test_array_throughput(&srtp_aes_gcm_256_openssl, SRTP_AES_GCM_256_KEY_LEN_WSALT, num_cipher); - } -#endif - } + printf("cipher test driver\n" + "David A. McGrew\n" + "Cisco Systems, Inc.\n"); + + if (!do_validation && !do_timing_test && !do_array_timing_test) + usage(argv[0]); + + /* arry timing (cache thrash) test */ + if (do_array_timing_test) { + int max_num_cipher = 1 << 16; /* number of ciphers in cipher_array */ + int num_cipher; + + for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) + cipher_driver_test_array_throughput(&srtp_null_cipher, 0, + num_cipher); + + for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) + cipher_driver_test_array_throughput( + &srtp_aes_icm_128, SRTP_AES_ICM_128_KEY_LEN_WSALT, num_cipher); + + for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) + cipher_driver_test_array_throughput( + &srtp_aes_icm_256, SRTP_AES_ICM_256_KEY_LEN_WSALT, num_cipher); - if (do_validation) { - cipher_driver_self_test(&srtp_null_cipher); - cipher_driver_self_test(&srtp_aes_icm_128); - cipher_driver_self_test(&srtp_aes_icm_256); #ifdef OPENSSL - cipher_driver_self_test(&srtp_aes_icm_192); - cipher_driver_self_test(&srtp_aes_gcm_128_openssl); - cipher_driver_self_test(&srtp_aes_gcm_256_openssl); + for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) + cipher_driver_test_array_throughput( + &srtp_aes_icm_192, SRTP_AES_ICM_192_KEY_LEN_WSALT, num_cipher); + + for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { + cipher_driver_test_array_throughput(&srtp_aes_gcm_128_openssl, + SRTP_AES_GCM_128_KEY_LEN_WSALT, + num_cipher); + } + + for (num_cipher = 1; num_cipher < max_num_cipher; num_cipher *= 8) { + cipher_driver_test_array_throughput(&srtp_aes_gcm_256_openssl, + SRTP_AES_GCM_256_KEY_LEN_WSALT, + num_cipher); + } #endif - } + } - /* do timing and/or buffer_test on srtp_null_cipher */ - status = srtp_cipher_type_alloc(&srtp_null_cipher, &c, 0, 0); - check_status(status); + if (do_validation) { + cipher_driver_self_test(&srtp_null_cipher); + cipher_driver_self_test(&srtp_aes_icm_128); + cipher_driver_self_test(&srtp_aes_icm_256); +#ifdef OPENSSL + cipher_driver_self_test(&srtp_aes_icm_192); + cipher_driver_self_test(&srtp_aes_gcm_128_openssl); + cipher_driver_self_test(&srtp_aes_gcm_256_openssl); +#endif + } - status = srtp_cipher_init(c, NULL); - check_status(status); - - if (do_timing_test) - cipher_driver_test_throughput(c); - if (do_validation) { - status = cipher_driver_test_buffering(c); + /* do timing and/or buffer_test on srtp_null_cipher */ + status = srtp_cipher_type_alloc(&srtp_null_cipher, &c, 0, 0); check_status(status); - } - status = srtp_cipher_dealloc(c); - check_status(status); - - /* run the throughput test on the aes_icm cipher (128-bit key) */ - status = srtp_cipher_type_alloc(&srtp_aes_icm_128, &c, SRTP_AES_ICM_128_KEY_LEN_WSALT, 0); - if (status) { - fprintf(stderr, "error: can't allocate cipher\n"); - exit(status); - } - - status = srtp_cipher_init(c, test_key); + status = srtp_cipher_init(c, NULL); check_status(status); if (do_timing_test) - cipher_driver_test_throughput(c); - + cipher_driver_test_throughput(c); if (do_validation) { - status = cipher_driver_test_buffering(c); - check_status(status); + status = cipher_driver_test_buffering(c); + check_status(status); } - status = srtp_cipher_dealloc(c); check_status(status); - /* repeat the tests with 256-bit keys */ - status = srtp_cipher_type_alloc(&srtp_aes_icm_256, &c, SRTP_AES_ICM_256_KEY_LEN_WSALT, 0); + /* run the throughput test on the aes_icm cipher (128-bit key) */ + status = srtp_cipher_type_alloc(&srtp_aes_icm_128, &c, + SRTP_AES_ICM_128_KEY_LEN_WSALT, 0); if (status) { - fprintf(stderr, "error: can't allocate cipher\n"); - exit(status); + fprintf(stderr, "error: can't allocate cipher\n"); + exit(status); } status = srtp_cipher_init(c, test_key); check_status(status); if (do_timing_test) - cipher_driver_test_throughput(c); - + cipher_driver_test_throughput(c); + if (do_validation) { - status = cipher_driver_test_buffering(c); - check_status(status); + status = cipher_driver_test_buffering(c); + check_status(status); } - + + status = srtp_cipher_dealloc(c); + check_status(status); + + /* repeat the tests with 256-bit keys */ + status = srtp_cipher_type_alloc(&srtp_aes_icm_256, &c, + SRTP_AES_ICM_256_KEY_LEN_WSALT, 0); + if (status) { + fprintf(stderr, "error: can't allocate cipher\n"); + exit(status); + } + + status = srtp_cipher_init(c, test_key); + check_status(status); + + if (do_timing_test) + cipher_driver_test_throughput(c); + + if (do_validation) { + status = cipher_driver_test_buffering(c); + check_status(status); + } + status = srtp_cipher_dealloc(c); check_status(status); #ifdef OPENSSL /* run the throughput test on the aes_gcm_128_openssl cipher */ - status = srtp_cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, SRTP_AES_GCM_128_KEY_LEN_WSALT, 8); + status = srtp_cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, + SRTP_AES_GCM_128_KEY_LEN_WSALT, 8); if (status) { fprintf(stderr, "error: can't allocate GCM 128 cipher\n"); exit(status); @@ -292,7 +299,8 @@ main(int argc, char *argv[]) { check_status(status); /* run the throughput test on the aes_gcm_256_openssl cipher */ - status = srtp_cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, SRTP_AES_GCM_256_KEY_LEN_WSALT, 16); + status = srtp_cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, + SRTP_AES_GCM_256_KEY_LEN_WSALT, 16); if (status) { fprintf(stderr, "error: can't allocate GCM 256 cipher\n"); exit(status); @@ -309,39 +317,39 @@ main(int argc, char *argv[]) { } status = srtp_cipher_dealloc(c); check_status(status); -#endif +#endif return 0; } -void -cipher_driver_test_throughput(srtp_cipher_t *c) { - int i; - int min_enc_len = 32; - int max_enc_len = 2048; /* should be a power of two */ - int num_trials = 1000000; - - printf("timing %s throughput, key length %d:\n", c->type->description, c->key_len); - fflush(stdout); - for (i=min_enc_len; i <= max_enc_len; i = i * 2) - printf("msg len: %d\tgigabits per second: %f\n", - i, srtp_cipher_bits_per_second(c, i, num_trials) / 1e9); +void cipher_driver_test_throughput(srtp_cipher_t *c) +{ + int i; + int min_enc_len = 32; + int max_enc_len = 2048; /* should be a power of two */ + int num_trials = 1000000; + printf("timing %s throughput, key length %d:\n", c->type->description, + c->key_len); + fflush(stdout); + for (i = min_enc_len; i <= max_enc_len; i = i * 2) + printf("msg len: %d\tgigabits per second: %f\n", i, + srtp_cipher_bits_per_second(c, i, num_trials) / 1e9); } -srtp_err_status_t -cipher_driver_self_test(srtp_cipher_type_t *ct) { - srtp_err_status_t status; - - printf("running cipher self-test for %s...", ct->description); - status = srtp_cipher_type_self_test(ct); - if (status) { - printf("failed with error code %d\n", status); - exit(status); - } - printf("passed\n"); - - return srtp_err_status_ok; +srtp_err_status_t cipher_driver_self_test(srtp_cipher_type_t *ct) +{ + srtp_err_status_t status; + + printf("running cipher self-test for %s...", ct->description); + status = srtp_cipher_type_self_test(ct); + if (status) { + printf("failed with error code %d\n", status); + exit(status); + } + printf("passed\n"); + + return srtp_err_status_ok; } /* @@ -351,168 +359,166 @@ cipher_driver_self_test(srtp_cipher_type_t *ct) { */ #define INITIAL_BUFLEN 1024 -srtp_err_status_t -cipher_driver_test_buffering(srtp_cipher_t *c) { - int i, j, num_trials = 1000; - unsigned len, buflen = INITIAL_BUFLEN; - uint8_t buffer0[INITIAL_BUFLEN], buffer1[INITIAL_BUFLEN], *current, *end; - uint8_t idx[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34 - }; - srtp_err_status_t status; - - printf("testing output buffering for cipher %s...", - c->type->description); +srtp_err_status_t cipher_driver_test_buffering(srtp_cipher_t *c) +{ + int i, j, num_trials = 1000; + unsigned len, buflen = INITIAL_BUFLEN; + uint8_t buffer0[INITIAL_BUFLEN], buffer1[INITIAL_BUFLEN], *current, *end; + uint8_t idx[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34 }; + srtp_err_status_t status; - for (i=0; i < num_trials; i++) { + printf("testing output buffering for cipher %s...", c->type->description); - /* set buffers to zero */ - for (j=0; j < (int) buflen; j++) { - buffer0[j] = buffer1[j] = 0; - } - - /* initialize cipher */ - status = srtp_cipher_set_iv(c, (uint8_t*)idx, srtp_direction_encrypt); - if (status) - return status; + for (i = 0; i < num_trials; i++) { + /* set buffers to zero */ + for (j = 0; j < (int)buflen; j++) { + buffer0[j] = buffer1[j] = 0; + } - /* generate 'reference' value by encrypting all at once */ - status = srtp_cipher_encrypt(c, buffer0, &buflen); - if (status) - return status; + /* initialize cipher */ + status = srtp_cipher_set_iv(c, (uint8_t *)idx, srtp_direction_encrypt); + if (status) + return status; - /* re-initialize cipher */ - status = srtp_cipher_set_iv(c, (uint8_t*)idx, srtp_direction_encrypt); - if (status) - return status; - - /* now loop over short lengths until buffer1 is encrypted */ - current = buffer1; - end = buffer1 + buflen; - while (current < end) { + /* generate 'reference' value by encrypting all at once */ + status = srtp_cipher_encrypt(c, buffer0, &buflen); + if (status) + return status; - /* choose a short length */ - len = rand() & 0x01f; + /* re-initialize cipher */ + status = srtp_cipher_set_iv(c, (uint8_t *)idx, srtp_direction_encrypt); + if (status) + return status; - /* make sure that len doesn't cause us to overreach the buffer */ - if (current + len > end) - len = end - current; + /* now loop over short lengths until buffer1 is encrypted */ + current = buffer1; + end = buffer1 + buflen; + while (current < end) { + /* choose a short length */ + len = rand() & 0x01f; - status = srtp_cipher_encrypt(c, current, &len); - if (status) - return status; - - /* advance pointer into buffer1 to reflect encryption */ - current += len; - - /* if buffer1 is all encrypted, break out of loop */ - if (current == end) - break; - } + /* make sure that len doesn't cause us to overreach the buffer */ + if (current + len > end) + len = end - current; - /* compare buffers */ - for (j=0; j < (int) buflen; j++) { - if (buffer0[j] != buffer1[j]) { + status = srtp_cipher_encrypt(c, current, &len); + if (status) + return status; + + /* advance pointer into buffer1 to reflect encryption */ + current += len; + + /* if buffer1 is all encrypted, break out of loop */ + if (current == end) + break; + } + + /* compare buffers */ + for (j = 0; j < (int)buflen; j++) { + if (buffer0[j] != buffer1[j]) { #if PRINT_DEBUG - printf("test case %d failed at byte %d\n", i, j); - printf("computed: %s\n", octet_string_hex_string(buffer1, buflen)); - printf("expected: %s\n", octet_string_hex_string(buffer0, buflen)); -#endif - return srtp_err_status_algo_fail; - } + printf("test case %d failed at byte %d\n", i, j); + printf("computed: %s\n", + octet_string_hex_string(buffer1, buflen)); + printf("expected: %s\n", + octet_string_hex_string(buffer0, buflen)); +#endif + return srtp_err_status_algo_fail; + } + } } - } - - printf("passed\n"); - return srtp_err_status_ok; + printf("passed\n"); + + return srtp_err_status_ok; } - /* * The function cipher_test_throughput_array() tests the effect of CPU - * cache thrash on cipher throughput. + * cache thrash on cipher throughput. * * cipher_array_alloc_init(ctype, array, num_ciphers) creates an array * of srtp_cipher_t of type ctype */ -srtp_err_status_t -cipher_array_alloc_init(srtp_cipher_t ***ca, int num_ciphers, - srtp_cipher_type_t *ctype, int klen) { - int i, j; - srtp_err_status_t status; - uint8_t *key; - srtp_cipher_t **cipher_array; - /* pad klen allocation, to handle aes_icm reading 16 bytes for the - 14-byte salt */ - int klen_pad = ((klen + 15) >> 4) << 4; +srtp_err_status_t cipher_array_alloc_init(srtp_cipher_t ***ca, + int num_ciphers, + srtp_cipher_type_t *ctype, + int klen) +{ + int i, j; + srtp_err_status_t status; + uint8_t *key; + srtp_cipher_t **cipher_array; + /* pad klen allocation, to handle aes_icm reading 16 bytes for the + 14-byte salt */ + int klen_pad = ((klen + 15) >> 4) << 4; - /* allocate array of pointers to ciphers */ - cipher_array = (srtp_cipher_t **) malloc(sizeof(srtp_cipher_t *) * num_ciphers); - if (cipher_array == NULL) - return srtp_err_status_alloc_fail; + /* allocate array of pointers to ciphers */ + cipher_array = (srtp_cipher_t **)srtp_crypto_alloc(sizeof(srtp_cipher_t *) * + num_ciphers); + if (cipher_array == NULL) + return srtp_err_status_alloc_fail; - /* set ca to location of cipher_array */ - *ca = cipher_array; + /* set ca to location of cipher_array */ + *ca = cipher_array; - /* allocate key */ - key = srtp_crypto_alloc(klen_pad); - if (key == NULL) { - free(cipher_array); - return srtp_err_status_alloc_fail; - } - - /* allocate and initialize an array of ciphers */ - for (i=0; i < num_ciphers; i++) { + /* allocate key */ + key = srtp_crypto_alloc(klen_pad); + if (key == NULL) { + srtp_crypto_free(cipher_array); + return srtp_err_status_alloc_fail; + } - /* allocate cipher */ - status = srtp_cipher_type_alloc(ctype, cipher_array, klen, 16); - if (status) - return status; - - /* generate random key and initialize cipher */ - for (j=0; j < klen; j++) - key[j] = (uint8_t) rand(); - for (; j < klen_pad; j++) - key[j] = 0; - status = srtp_cipher_init(*cipher_array, key); - if (status) - return status; + /* allocate and initialize an array of ciphers */ + for (i = 0; i < num_ciphers; i++) { + /* allocate cipher */ + status = srtp_cipher_type_alloc(ctype, cipher_array, klen, 16); + if (status) + return status; -/* printf("%dth cipher is at %p\n", i, *cipher_array); */ -/* printf("%dth cipher description: %s\n", i, */ -/* (*cipher_array)->type->description); */ - - /* advance cipher array pointer */ - cipher_array++; - } + /* generate random key and initialize cipher */ + for (j = 0; j < klen; j++) + key[j] = (uint8_t)rand(); + for (; j < klen_pad; j++) + key[j] = 0; + status = srtp_cipher_init(*cipher_array, key); + if (status) + return status; - srtp_crypto_free(key); + /* printf("%dth cipher is at %p\n", i, *cipher_array); */ + /* printf("%dth cipher description: %s\n", i, */ + /* (*cipher_array)->type->description); */ - return srtp_err_status_ok; + /* advance cipher array pointer */ + cipher_array++; + } + + srtp_crypto_free(key); + + return srtp_err_status_ok; } -srtp_err_status_t -cipher_array_delete(srtp_cipher_t *cipher_array[], int num_cipher) { - int i; - - for (i=0; i < num_cipher; i++) { - srtp_cipher_dealloc(cipher_array[i]); - } +srtp_err_status_t cipher_array_delete(srtp_cipher_t *cipher_array[], + int num_cipher) +{ + int i; - free(cipher_array); - - return srtp_err_status_ok; + for (i = 0; i < num_cipher; i++) { + srtp_cipher_dealloc(cipher_array[i]); + } + + srtp_crypto_free(cipher_array); + + return srtp_err_status_ok; } - /* * cipher_array_bits_per_second(c, l, t) computes (an estimate of) the * number of bits that a cipher implementation can encrypt in a second * when distinct keys are used to encrypt distinct messages - * + * * c is a cipher (which MUST be allocated an initialized already), l * is the length in octets of the test data to be encrypted, and t is * the number of trials @@ -520,80 +526,85 @@ cipher_array_delete(srtp_cipher_t *cipher_array[], int num_cipher) { * if an error is encountered, the value 0 is returned */ -uint64_t -cipher_array_bits_per_second(srtp_cipher_t *cipher_array[], int num_cipher, - unsigned octets_in_buffer, int num_trials) { - int i; - v128_t nonce; - clock_t timer; - unsigned char *enc_buf; - int cipher_index = rand() % num_cipher; +uint64_t cipher_array_bits_per_second(srtp_cipher_t *cipher_array[], + int num_cipher, + unsigned octets_in_buffer, + int num_trials) +{ + int i; + v128_t nonce; + clock_t timer; + unsigned char *enc_buf; + int cipher_index = rand() % num_cipher; - /* Over-alloc, for NIST CBC padding */ - enc_buf = srtp_crypto_alloc(octets_in_buffer+17); - if (enc_buf == NULL) - return 0; /* indicate bad parameters by returning null */ - memset(enc_buf, 0, octets_in_buffer); - - /* time repeated trials */ - v128_set_to_zero(&nonce); - timer = clock(); - for(i=0; i < num_trials; i++, nonce.v32[3] = i) { - /* length parameter to srtp_cipher_encrypt is in/out -- out is total, padded - * length -- so reset it each time. */ - unsigned octets_to_encrypt = octets_in_buffer; + /* Over-alloc, for NIST CBC padding */ + enc_buf = srtp_crypto_alloc(octets_in_buffer + 17); + if (enc_buf == NULL) + return 0; /* indicate bad parameters by returning null */ - /* encrypt buffer with cipher */ - srtp_cipher_set_iv(cipher_array[cipher_index], (uint8_t*)&nonce, srtp_direction_encrypt); - srtp_cipher_encrypt(cipher_array[cipher_index], enc_buf, &octets_to_encrypt); + /* time repeated trials */ + v128_set_to_zero(&nonce); + timer = clock(); + for (i = 0; i < num_trials; i++, nonce.v32[3] = i) { + /* length parameter to srtp_cipher_encrypt is in/out -- out is total, + * padded + * length -- so reset it each time. */ + unsigned octets_to_encrypt = octets_in_buffer; - /* choose a cipher at random from the array*/ - cipher_index = (*((uint32_t *)enc_buf)) % num_cipher; - } - timer = clock() - timer; + /* encrypt buffer with cipher */ + srtp_cipher_set_iv(cipher_array[cipher_index], (uint8_t *)&nonce, + srtp_direction_encrypt); + srtp_cipher_encrypt(cipher_array[cipher_index], enc_buf, + &octets_to_encrypt); - free(enc_buf); + /* choose a cipher at random from the array*/ + cipher_index = (*((uint32_t *)enc_buf)) % num_cipher; + } + timer = clock() - timer; - if (timer == 0) { - /* Too fast! */ - return 0; - } + srtp_crypto_free(enc_buf); - return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; + if (timer == 0) { + /* Too fast! */ + return 0; + } + + return (uint64_t)CLOCKS_PER_SEC * num_trials * 8 * octets_in_buffer / timer; } -void -cipher_array_test_throughput(srtp_cipher_t *ca[], int num_cipher) { - int i; - int min_enc_len = 16; - int max_enc_len = 2048; /* should be a power of two */ - int num_trials = 1000000; - - printf("timing %s throughput with key length %d, array size %d:\n", - (ca[0])->type->description, (ca[0])->key_len, num_cipher); - fflush(stdout); - for (i=min_enc_len; i <= max_enc_len; i = i * 4) - printf("msg len: %d\tgigabits per second: %f\n", i, - cipher_array_bits_per_second(ca, num_cipher, i, num_trials) / 1e9); +void cipher_array_test_throughput(srtp_cipher_t *ca[], int num_cipher) +{ + int i; + int min_enc_len = 16; + int max_enc_len = 2048; /* should be a power of two */ + int num_trials = 1000000; + printf("timing %s throughput with key length %d, array size %d:\n", + (ca[0])->type->description, (ca[0])->key_len, num_cipher); + fflush(stdout); + for (i = min_enc_len; i <= max_enc_len; i = i * 4) + printf("msg len: %d\tgigabits per second: %f\n", i, + cipher_array_bits_per_second(ca, num_cipher, i, num_trials) / + 1e9); } -srtp_err_status_t -cipher_driver_test_array_throughput(srtp_cipher_type_t *ct, - int klen, int num_cipher) { - srtp_cipher_t **ca = NULL; - srtp_err_status_t status; +srtp_err_status_t cipher_driver_test_array_throughput(srtp_cipher_type_t *ct, + int klen, + int num_cipher) +{ + srtp_cipher_t **ca = NULL; + srtp_err_status_t status; - status = cipher_array_alloc_init(&ca, num_cipher, ct, klen); - if (status) { - printf("error: cipher_array_alloc_init() failed with error code %d\n", - status); - return status; - } - - cipher_array_test_throughput(ca, num_cipher); - - cipher_array_delete(ca, num_cipher); - - return srtp_err_status_ok; + status = cipher_array_alloc_init(&ca, num_cipher, ct, klen); + if (status) { + printf("error: cipher_array_alloc_init() failed with error code %d\n", + status); + return status; + } + + cipher_array_test_throughput(ca, num_cipher); + + cipher_array_delete(ca, num_cipher); + + return srtp_err_status_ok; } diff --git a/libs/srtp/crypto/test/datatypes_driver.c b/libs/srtp/crypto/test/datatypes_driver.c index d847c2f802..2f78903eb8 100644 --- a/libs/srtp/crypto/test/datatypes_driver.c +++ b/libs/srtp/crypto/test/datatypes_driver.c @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -43,117 +43,108 @@ * */ - #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif -#include <stdio.h> /* for printf() */ -#include <string.h> /* for strlen() */ +#include <stdio.h> /* for printf() */ +#include <string.h> /* for strlen() */ #include "datatypes.h" #include "util.h" -void -byte_order(void); +void byte_order(void); -void -test_hex_string_funcs(void); +void test_hex_string_funcs(void); -void -print_string(char *s); +void print_string(char *s); -void -test_bswap(void); +void test_bswap(void); -int -main (void) { - - /* - * this program includes various and sundry tests for fundamental - * datatypes. it's a grab-bag of throwaway code, retained only in - * case of future problems - */ +int main(void) +{ + /* + * this program includes various and sundry tests for fundamental + * datatypes. it's a grab-bag of throwaway code, retained only in + * case of future problems + */ - int i, j; - v128_t x; - char *r = - "The Moving Finger writes; and, having writ,\n" - "Moves on: nor all thy Piety nor Wit\n" - "Shall lure it back to cancel half a Line,\n" - "Nor all thy Tears wash out a Word of it."; - char *s = "incomplet"; - - print_string(r); - print_string(s); - - byte_order(); - test_hex_string_funcs(); + int i, j; + v128_t x; + char *r = "The Moving Finger writes; and, having writ,\n" + "Moves on: nor all thy Piety nor Wit\n" + "Shall lure it back to cancel half a Line,\n" + "Nor all thy Tears wash out a Word of it."; + char *s = "incomplet"; - for (j=0; j < 128; j++) { + print_string(r); + print_string(s); + + byte_order(); + test_hex_string_funcs(); + + for (j = 0; j < 128; j++) { + v128_set_to_zero(&x); + /* x.v32[0] = (1 << j); */ + v128_set_bit(&x, j); + printf("%s\n", v128_bit_string(&x)); + v128_clear_bit(&x, j); + printf("%s\n", v128_bit_string(&x)); + } + + printf("----------------------------------------------\n"); v128_set_to_zero(&x); - /* x.v32[0] = (1 << j); */ - v128_set_bit(&x, j); - printf("%s\n", v128_bit_string(&x)); - v128_clear_bit(&x, j); - printf("%s\n", v128_bit_string(&x)); - - } + for (i = 0; i < 128; i++) { + v128_set_bit(&x, i); + } + printf("%s\n", v128_bit_string(&x)); - printf("----------------------------------------------\n"); - v128_set_to_zero(&x); - for (i=0; i < 128; i++) { - v128_set_bit(&x, i); - } - printf("%s\n", v128_bit_string(&x)); - - printf("----------------------------------------------\n"); - v128_set_to_zero(&x); - v128_set_bit(&x, 0); - for (i=0; i < 128; i++) { - printf("%s\n", v128_bit_string(&x)); - v128_right_shift(&x, 1); - } - printf("----------------------------------------------\n"); - v128_set_to_zero(&x); - v128_set_bit(&x, 127); - for (i=0; i < 128; i++) { - printf("%s\n", v128_bit_string(&x)); - v128_left_shift(&x, 1); - } - printf("----------------------------------------------\n"); - for (i=0; i < 128; i++) { + printf("----------------------------------------------\n"); + v128_set_to_zero(&x); + v128_set_bit(&x, 0); + for (i = 0; i < 128; i++) { + printf("%s\n", v128_bit_string(&x)); + v128_right_shift(&x, 1); + } + printf("----------------------------------------------\n"); v128_set_to_zero(&x); v128_set_bit(&x, 127); - v128_left_shift(&x, i); - printf("%s\n", v128_bit_string(&x)); - } - printf("----------------------------------------------\n"); - v128_set_to_zero(&x); - for (i=0; i < 128; i+=2) { - v128_set_bit(&x, i); - } - printf("bit_string: { %s }\n", v128_bit_string(&x)); - printf("get_bit: { "); - for (i=0; i < 128; i++) { - if (v128_get_bit(&x, i) == 1) - printf("1"); - else - printf("0"); - } - printf(" } \n"); + for (i = 0; i < 128; i++) { + printf("%s\n", v128_bit_string(&x)); + v128_left_shift(&x, 1); + } + printf("----------------------------------------------\n"); + for (i = 0; i < 128; i++) { + v128_set_to_zero(&x); + v128_set_bit(&x, 127); + v128_left_shift(&x, i); + printf("%s\n", v128_bit_string(&x)); + } + printf("----------------------------------------------\n"); + v128_set_to_zero(&x); + for (i = 0; i < 128; i += 2) { + v128_set_bit(&x, i); + } + printf("bit_string: { %s }\n", v128_bit_string(&x)); + printf("get_bit: { "); + for (i = 0; i < 128; i++) { + if (v128_get_bit(&x, i) == 1) + printf("1"); + else + printf("0"); + } + printf(" } \n"); - test_bswap(); + test_bswap(); - return 0; + return 0; } - /* byte_order() prints out byte ordering of datatypes */ -void -byte_order(void) { - int i; - v128_t e; +void byte_order(void) +{ + int i; + v128_t e; #if 0 v16_t b; v32_t c; @@ -180,63 +171,60 @@ byte_order(void) { c.value = 0x00010002; printf("v32_t:\t%x%x\n", c.v16[0], c.v16[1]); -#endif +#endif - printf("byte ordering of crypto/math datatypes:\n"); - for (i=0; i < sizeof(e); i++) - e.v8[i] = i; - printf("v128_t: %s\n", v128_hex_string(&e)); - + printf("byte ordering of crypto/math datatypes:\n"); + for (i = 0; i < sizeof(e); i++) + e.v8[i] = i; + printf("v128_t: %s\n", v128_hex_string(&e)); } -void -test_hex_string_funcs(void) { - char hex1[] = "abadcafe"; - char hex2[] = "0123456789abcdefqqqqq"; - char raw[10]; - int len; +void test_hex_string_funcs(void) +{ + char hex1[] = "abadcafe"; + char hex2[] = "0123456789abcdefqqqqq"; + char raw[10]; + int len; - len = hex_string_to_octet_string(raw, hex1, strlen(hex1)); - printf("computed length: %d\tstring: %s\n", len, - octet_string_hex_string(raw, len/2)); - printf("expected length: %u\tstring: %s\n", (unsigned)strlen(hex1), hex1); - - len = hex_string_to_octet_string(raw, hex2, strlen(hex2)); - printf("computed length: %d\tstring: %s\n", len, - octet_string_hex_string(raw, len/2)); - printf("expected length: %d\tstring: %s\n", 16, "0123456789abcdef"); + len = hex_string_to_octet_string(raw, hex1, strlen(hex1)); + printf("computed length: %d\tstring: %s\n", len, + octet_string_hex_string(raw, len / 2)); + printf("expected length: %u\tstring: %s\n", (unsigned)strlen(hex1), hex1); + len = hex_string_to_octet_string(raw, hex2, strlen(hex2)); + printf("computed length: %d\tstring: %s\n", len, + octet_string_hex_string(raw, len / 2)); + printf("expected length: %d\tstring: %s\n", 16, "0123456789abcdef"); } -void -print_string(char *s) { - size_t i; - printf("%s\n", s); - printf("strlen(s) = %u\n", (unsigned)strlen(s)); - printf("{ "); - for (i=0; i < strlen(s); i++) { - printf("0x%x, ", s[i]); - if (((i+1) % 8) == 0) - printf("\n "); - } - printf("}\n"); +void print_string(char *s) +{ + size_t i; + printf("%s\n", s); + printf("strlen(s) = %u\n", (unsigned)strlen(s)); + printf("{ "); + for (i = 0; i < strlen(s); i++) { + printf("0x%x, ", s[i]); + if (((i + 1) % 8) == 0) + printf("\n "); + } + printf("}\n"); } -void -test_bswap(void) { - uint32_t x = 0x11223344; - uint64_t y = 0x1122334455667788LL; +void test_bswap(void) +{ + uint32_t x = 0x11223344; + uint64_t y = 0x1122334455667788LL; - printf("before: %0x\nafter: %0x\n", x, (unsigned int)be32_to_cpu(x)); - printf("before: %0llx\nafter: %0llx\n", (unsigned long long)y, - (unsigned long long)be64_to_cpu(y)); + printf("before: %0x\nafter: %0x\n", x, (unsigned int)be32_to_cpu(x)); + printf("before: %0llx\nafter: %0llx\n", (unsigned long long)y, + (unsigned long long)be64_to_cpu(y)); - y = 1234; + y = 1234; - printf("1234: %0llx\n", (unsigned long long)y); - printf("as octet string: %s\n", - octet_string_hex_string((uint8_t *) &y, 8)); - y = be64_to_cpu(y); - printf("bswapped octet string: %s\n", - octet_string_hex_string((uint8_t *) &y, 8)); + printf("1234: %0llx\n", (unsigned long long)y); + printf("as octet string: %s\n", octet_string_hex_string((uint8_t *)&y, 8)); + y = be64_to_cpu(y); + printf("bswapped octet string: %s\n", + octet_string_hex_string((uint8_t *)&y, 8)); } diff --git a/libs/srtp/crypto/test/env.c b/libs/srtp/crypto/test/env.c index 669e3d66c1..8c3f4edfac 100644 --- a/libs/srtp/crypto/test/env.c +++ b/libs/srtp/crypto/test/env.c @@ -7,26 +7,26 @@ * 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 @@ -43,45 +43,47 @@ */ #include <stdio.h> -#include <string.h> /* for srtcmp() */ +#include <string.h> /* for srtcmp() */ #include "config.h" -int -main(void) { - int err_count = 0; +int main(void) +{ + int err_count = 0; #ifdef WORDS_BIGENDIAN - printf("CPU set to big-endian\t\t\t(WORDS_BIGENDIAN == 1)\n"); + printf("CPU set to big-endian\t\t\t(WORDS_BIGENDIAN == 1)\n"); #else - printf("CPU set to little-endian\t\t(WORDS_BIGENDIAN == 0)\n"); + printf("CPU set to little-endian\t\t(WORDS_BIGENDIAN == 0)\n"); #endif #ifdef CPU_RISC - printf("CPU set to RISC\t\t\t\t(CPU_RISC == 1)\n"); + printf("CPU set to RISC\t\t\t\t(CPU_RISC == 1)\n"); #elif defined(CPU_CISC) - printf("CPU set to CISC\t\t\t\t(CPU_CISC == 1)\n"); + printf("CPU set to CISC\t\t\t\t(CPU_CISC == 1)\n"); #else - printf("CPU set to an unknown type, probably due to a configuration error\n"); - err_count++; + printf( + "CPU set to an unknown type, probably due to a configuration error\n"); + err_count++; #endif #ifdef CPU_ALTIVEC - printf("CPU set to ALTIVEC\t\t\t\t(CPU_ALTIVEC == 0)\n"); + printf("CPU set to ALTIVEC\t\t\t\t(CPU_ALTIVEC == 0)\n"); #endif #ifndef NO_64BIT_MATH - printf("using native 64-bit type\t\t(NO_64_BIT_MATH == 0)\n"); + printf("using native 64-bit type\t\t(NO_64_BIT_MATH == 0)\n"); #else - printf("using built-in 64-bit math\t\t(NO_64_BIT_MATH == 1)\n"); + printf("using built-in 64-bit math\t\t(NO_64_BIT_MATH == 1)\n"); #endif #ifdef ERR_REPORTING_STDOUT - printf("using stdout for error reporting\t(ERR_REPORTING_STDOUT == 1)\n"); + printf("using stdout for error reporting\t(ERR_REPORTING_STDOUT == 1)\n"); #endif - if (err_count) - printf("warning: configuration is probably in error " - "(found %d problems)\n", err_count); + if (err_count) + printf("warning: configuration is probably in error " + "(found %d problems)\n", + err_count); - return err_count; + return err_count; } diff --git a/libs/srtp/crypto/test/kernel_driver.c b/libs/srtp/crypto/test/kernel_driver.c index 92b7240249..d29405a971 100644 --- a/libs/srtp/crypto/test/kernel_driver.c +++ b/libs/srtp/crypto/test/kernel_driver.c @@ -7,26 +7,26 @@ * 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 @@ -42,77 +42,76 @@ * */ - #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif -#include <stdio.h> /* for printf() */ +#include <stdio.h> /* for printf() */ #include "getopt_s.h" #include "crypto_kernel.h" -void -usage(char *prog_name) { - printf("usage: %s [ -v ][ -d debug_module ]*\n", prog_name); - exit(255); +void usage(char *prog_name) +{ + printf("usage: %s [ -v ][ -d debug_module ]*\n", prog_name); + exit(255); } -int -main (int argc, char *argv[]) { - int q; - int do_validation = 0; - srtp_err_status_t status; +int main(int argc, char *argv[]) +{ + int q; + int do_validation = 0; + srtp_err_status_t status; - if (argc == 1) - usage(argv[0]); + if (argc == 1) + usage(argv[0]); - /* initialize kernel - we need to do this before anything else */ - status = srtp_crypto_kernel_init(); - if (status) { - printf("error: srtp_crypto_kernel init failed\n"); - exit(1); - } - printf("srtp_crypto_kernel successfully initalized\n"); - - /* process input arguments */ - while (1) { - q = getopt_s(argc, argv, "vd:"); - if (q == -1) - break; - switch (q) { - case 'v': - do_validation = 1; - break; - case 'd': - status = srtp_crypto_kernel_set_debug_module(optarg_s, 1); - if (status) { - printf("error: set debug module (%s) failed\n", optarg_s); - exit(1); - } - break; - default: - usage(argv[0]); - } - } - - if (do_validation) { - printf("checking srtp_crypto_kernel status...\n"); - status = srtp_crypto_kernel_status(); + /* initialize kernel - we need to do this before anything else */ + status = srtp_crypto_kernel_init(); if (status) { - printf("failed\n"); - exit(1); + printf("error: srtp_crypto_kernel init failed\n"); + exit(1); } - printf("srtp_crypto_kernel passed self-tests\n"); - } + printf("srtp_crypto_kernel successfully initalized\n"); - status = srtp_crypto_kernel_shutdown(); - if (status) { - printf("error: srtp_crypto_kernel shutdown failed\n"); - exit(1); - } - printf("srtp_crypto_kernel successfully shut down\n"); - - return 0; + /* process input arguments */ + while (1) { + q = getopt_s(argc, argv, "vd:"); + if (q == -1) + break; + switch (q) { + case 'v': + do_validation = 1; + break; + case 'd': + status = srtp_crypto_kernel_set_debug_module(optarg_s, 1); + if (status) { + printf("error: set debug module (%s) failed\n", optarg_s); + exit(1); + } + break; + default: + usage(argv[0]); + } + } + + if (do_validation) { + printf("checking srtp_crypto_kernel status...\n"); + status = srtp_crypto_kernel_status(); + if (status) { + printf("failed\n"); + exit(1); + } + printf("srtp_crypto_kernel passed self-tests\n"); + } + + status = srtp_crypto_kernel_shutdown(); + if (status) { + printf("error: srtp_crypto_kernel shutdown failed\n"); + exit(1); + } + printf("srtp_crypto_kernel successfully shut down\n"); + + return 0; } /* @@ -120,10 +119,9 @@ main (int argc, char *argv[]) { * of the crypto_kernel */ -srtp_err_status_t -crypto_kernel_cipher_test(void) { +srtp_err_status_t crypto_kernel_cipher_test(void) +{ + /* not implemented yet! */ - /* not implemented yet! */ - - return srtp_err_status_ok; + return srtp_err_status_ok; } diff --git a/libs/srtp/crypto/test/sha1_driver.c b/libs/srtp/crypto/test/sha1_driver.c index e22c2b57e5..c64b000f81 100644 --- a/libs/srtp/crypto/test/sha1_driver.c +++ b/libs/srtp/crypto/test/sha1_driver.c @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -44,7 +44,7 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif #include <stdio.h> @@ -56,505 +56,332 @@ #define SHA_FAIL 1 #define MAX_HASH_DATA_LEN 1024 -#define MAX_HASH_OUT_LEN 20 +#define MAX_HASH_OUT_LEN 20 typedef struct hash_test_case_t { - unsigned data_len; /* number of octets in data */ - unsigned hash_len; /* number of octets output by hash */ - uint8_t data[MAX_HASH_DATA_LEN]; /* message data */ - uint8_t hash[MAX_HASH_OUT_LEN]; /* expected hash output */ - struct hash_test_case_t *next_test_case; + unsigned data_len; /* number of octets in data */ + unsigned hash_len; /* number of octets output by hash */ + uint8_t data[MAX_HASH_DATA_LEN]; /* message data */ + uint8_t hash[MAX_HASH_OUT_LEN]; /* expected hash output */ + struct hash_test_case_t *next_test_case; } hash_test_case_t; hash_test_case_t *sha1_test_case_list; -srtp_err_status_t -hash_test_case_add(hash_test_case_t **list_ptr, - char *hex_data, - unsigned data_len, - char *hex_hash, - unsigned hash_len) { - hash_test_case_t *list_head = *list_ptr; - hash_test_case_t *test_case; - unsigned tmp_len; +srtp_err_status_t hash_test_case_add(hash_test_case_t **list_ptr, + char *hex_data, + unsigned data_len, + char *hex_hash, + unsigned hash_len) +{ + hash_test_case_t *list_head = *list_ptr; + hash_test_case_t *test_case; + unsigned tmp_len; - test_case = malloc(sizeof(hash_test_case_t)); - if (test_case == NULL) - return srtp_err_status_alloc_fail; - - tmp_len = hex_string_to_octet_string((char *)test_case->data, hex_data, data_len*2); - if (tmp_len != data_len*2) { - free(test_case); - return srtp_err_status_parse_err; - } + test_case = malloc(sizeof(hash_test_case_t)); + if (test_case == NULL) + return srtp_err_status_alloc_fail; - tmp_len = hex_string_to_octet_string((char *)test_case->hash, hex_hash, hash_len*2); - if (tmp_len != hash_len*2) { - free(test_case); - return srtp_err_status_parse_err; - } + tmp_len = hex_string_to_octet_string((char *)test_case->data, hex_data, + data_len * 2); + if (tmp_len != data_len * 2) { + free(test_case); + return srtp_err_status_parse_err; + } - test_case->data_len = data_len; - test_case->hash_len = hash_len; + tmp_len = hex_string_to_octet_string((char *)test_case->hash, hex_hash, + hash_len * 2); + if (tmp_len != hash_len * 2) { + free(test_case); + return srtp_err_status_parse_err; + } - /* add the new test case to the head of the list */ - test_case->next_test_case = list_head; - *list_ptr = test_case; + test_case->data_len = data_len; + test_case->hash_len = hash_len; - return srtp_err_status_ok; + /* add the new test case to the head of the list */ + test_case->next_test_case = list_head; + *list_ptr = test_case; + + return srtp_err_status_ok; } -srtp_err_status_t -sha1_test_case_validate(const hash_test_case_t *test_case) { - srtp_sha1_ctx_t ctx; - uint32_t hash_value[5]; +srtp_err_status_t sha1_test_case_validate(const hash_test_case_t *test_case) +{ + srtp_sha1_ctx_t ctx; + uint32_t hash_value[5]; - if (test_case == NULL) - return srtp_err_status_bad_param; + if (test_case == NULL) + return srtp_err_status_bad_param; - if (test_case->hash_len != 20) - return srtp_err_status_bad_param; - if (test_case->data_len > MAX_HASH_DATA_LEN) - return srtp_err_status_bad_param; + if (test_case->hash_len != 20) + return srtp_err_status_bad_param; + if (test_case->data_len > MAX_HASH_DATA_LEN) + return srtp_err_status_bad_param; - srtp_sha1_init(&ctx); - srtp_sha1_update(&ctx, test_case->data, test_case->data_len); - srtp_sha1_final(&ctx, hash_value); - if (0 == memcmp(test_case->hash, hash_value, 20)) { + srtp_sha1_init(&ctx); + srtp_sha1_update(&ctx, test_case->data, test_case->data_len); + srtp_sha1_final(&ctx, hash_value); + if (0 == memcmp(test_case->hash, hash_value, 20)) { #if VERBOSE - printf("PASSED: reference value: %s\n", - octet_string_hex_string((const uint8_t *)test_case->hash, 20)); - printf("PASSED: computed value: %s\n", - octet_string_hex_string((const uint8_t *)hash_value, 20)); -#endif - return srtp_err_status_ok; - } + printf("PASSED: reference value: %s\n", + octet_string_hex_string((const uint8_t *)test_case->hash, 20)); + printf("PASSED: computed value: %s\n", + octet_string_hex_string((const uint8_t *)hash_value, 20)); +#endif + return srtp_err_status_ok; + } - printf("reference value: %s\n", - octet_string_hex_string((const uint8_t *)test_case->hash, 20)); - printf("computed value: %s\n", - octet_string_hex_string((const uint8_t *)hash_value, 20)); + printf("reference value: %s\n", + octet_string_hex_string((const uint8_t *)test_case->hash, 20)); + printf("computed value: %s\n", + octet_string_hex_string((const uint8_t *)hash_value, 20)); - return srtp_err_status_algo_fail; - + return srtp_err_status_algo_fail; } struct hex_sha1_test_case_t { - unsigned bit_len; - char hex_data[MAX_HASH_DATA_LEN*2]; - char hex_hash[40]; + unsigned bit_len; + char hex_data[MAX_HASH_DATA_LEN * 2]; + char hex_hash[40]; }; -srtp_err_status_t -sha1_add_test_cases(void) { - int i; - srtp_err_status_t err; +srtp_err_status_t sha1_add_test_cases(void) +{ + int i; + srtp_err_status_t err; - /* - * these test cases are taken from the "SHA-1 Sample Vectors" - * provided by NIST at http://csrc.nist.gov/cryptval/shs.html - */ + /* + * these test cases are taken from the "SHA-1 Sample Vectors" + * provided by NIST at http://csrc.nist.gov/cryptval/shs.html + */ - struct hex_sha1_test_case_t tc[] = { - { - 0, - "", - "da39a3ee5e6b4b0d3255bfef95601890afd80709" - }, - { - 8, - "a8", - "99f2aa95e36f95c2acb0eaf23998f030638f3f15" - }, - { - 16, - "3000", - "f944dcd635f9801f7ac90a407fbc479964dec024" - }, - { - 24, - "42749e", - "a444319e9b6cc1e8464c511ec0969c37d6bb2619" - }, - { - 32, - "9fc3fe08", - "16a0ff84fcc156fd5d3ca3a744f20a232d172253" - }, - { - 40, - "b5c1c6f1af", - "fec9deebfcdedaf66dda525e1be43597a73a1f93" - }, - { - 48, - "e47571e5022e", - "8ce051181f0ed5e9d0c498f6bc4caf448d20deb5" - }, - { - 56, - "3e1b28839fb758", - "67da53837d89e03bf652ef09c369a3415937cfd3" - }, - { - 64, - "a81350cbb224cb90", - "305e4ff9888ad855a78573cddf4c5640cce7e946" - }, - { - 72, "c243d167923dec3ce1", - "5902b77b3265f023f9bbc396ba1a93fa3509bde7" - }, - { - 80, - "50ac18c59d6a37a29bf4", - "fcade5f5d156bf6f9af97bdfa9c19bccfb4ff6ab" - }, - { - 88, - "98e2b611ad3b1cccf634f6", - "1d20fbe00533c10e3cbd6b27088a5de0c632c4b5" - }, - { - 96, - "73fe9afb68e1e8712e5d4eec", - "7e1b7e0f7a8f3455a9c03e9580fd63ae205a2d93" - }, - { - 104, - "9e701ed7d412a9226a2a130e66", - "706f0677146307b20bb0e8d6311e329966884d13" - }, - { - 112, - "6d3ee90413b0a7cbf69e5e6144ca", - "a7241a703aaf0d53fe142f86bf2e849251fa8dff" - }, - { - 120, - "fae24d56514efcb530fd4802f5e71f", - "400f53546916d33ad01a5e6df66822dfbdc4e9e6" - }, - { - 128, - "c5a22dd6eda3fe2bdc4ddb3ce6b35fd1", - "fac8ab93c1ae6c16f0311872b984f729dc928ccd" - }, - { - 136, - "d98cded2adabf08fda356445c781802d95", - "fba6d750c18da58f6e2aab10112b9a5ef3301b3b" - }, - { - 144, - "bcc6d7087a84f00103ccb32e5f5487a751a2", - "29d27c2d44c205c8107f0351b05753ac708226b6" - }, - { - 152, - "36ecacb1055434190dbbc556c48bafcb0feb0d", - "b971bfc1ebd6f359e8d74cb7ecfe7f898d0ba845" - }, - { - 160, - "5ff9edb69e8f6bbd498eb4537580b7fba7ad31d0", - "96d08c430094b9fcc164ad2fb6f72d0a24268f68" - }, - { - 168, "c95b441d8270822a46a798fae5defcf7b26abace36", - "a287ea752a593d5209e287881a09c49fa3f0beb1" - }, - { - 176, - "83104c1d8a55b28f906f1b72cb53f68cbb097b44f860", - "a06c713779cbd88519ed4a585ac0cb8a5e9d612b" - }, - { - 184, - "755175528d55c39c56493d697b790f099a5ce741f7754b", - "bff7d52c13a3688132a1d407b1ab40f5b5ace298" - }, - { - 192, - "088fc38128bbdb9fd7d65228b3184b3faac6c8715f07272f", - "c7566b91d7b6f56bdfcaa9781a7b6841aacb17e9" - }, - { - 200, - "a4a586eb9245a6c87e3adf1009ac8a49f46c07e14185016895", - "ffa30c0b5c550ea4b1e34f8a60ec9295a1e06ac1" - }, - { - 208, - "8e7c555270c006092c2a3189e2a526b873e2e269f0fb28245256", - "29e66ed23e914351e872aa761df6e4f1a07f4b81" - }, - { - 216, - "a5f3bfa6bb0ba3b59f6b9cbdef8a558ec565e8aa3121f405e7f2f0", - "b28cf5e5b806a01491d41f69bd9248765c5dc292" - }, - { - 224, - "589054f0d2bd3c2c85b466bfd8ce18e6ec3e0b87d944cd093ba36469", - "60224fb72c46069652cd78bcd08029ef64da62f3" - }, - { - 232, - "a0abb12083b5bbc78128601bf1cbdbc0fdf4b862b24d899953d8da0ff3", - "b72c4a86f72608f24c05f3b9088ef92fba431df7" - }, - { - 240, - "82143f4cea6fadbf998e128a8811dc75301cf1db4f079501ea568da68eeb", - "73779ad5d6b71b9b8328ef7220ff12eb167076ac" - }, - { - 248, - "9f1231dd6df1ff7bc0b0d4f989d048672683ce35d956d2f57913046267e6f3", - "a09671d4452d7cf50015c914a1e31973d20cc1a0" - }, - { - 256, - "041c512b5eed791f80d3282f3a28df263bb1df95e1239a7650e5670fc2187919", - "e88cdcd233d99184a6fd260b8fca1b7f7687aee0" - }, - { - 264, - "17e81f6ae8c2e5579d69dafa6e070e7111461552d314b691e7a3e7a4feb3fae418", - "010def22850deb1168d525e8c84c28116cb8a269" - }, - { - 272, - "d15976b23a1d712ad28fad04d805f572026b54dd64961fda94d5355a0cc98620cf77", - "aeaa40ba1717ed5439b1e6ea901b294ba500f9ad" - }, - { - 280, - "09fce4d434f6bd32a44e04b848ff50ec9f642a8a85b37a264dc73f130f22838443328f", - "c6433791238795e34f080a5f1f1723f065463ca0" - }, - { - 288, "f17af27d776ec82a257d8d46d2b46b639462c56984cc1be9c1222eadb8b26594a25c709d", - "e21e22b89c1bb944a32932e6b2a2f20d491982c3" - }, - { - 296, - "b13ce635d6f8758143ffb114f2f601cb20b6276951416a2f94fbf4ad081779d79f4f195b22", - "575323a9661f5d28387964d2ba6ab92c17d05a8a" - }, - { - 304, - "5498793f60916ff1c918dde572cdea76da8629ba4ead6d065de3dfb48de94d234cc1c5002910", - "feb44494af72f245bfe68e86c4d7986d57c11db7" - }, - { - 312, - "498a1e0b39fa49582ae688cd715c86fbaf8a81b8b11b4d1594c49c902d197c8ba8a621fd6e3be5", - "cff2290b3648ba2831b98dde436a72f9ebf51eee" - }, - { - 320, - "3a36ae71521f9af628b3e34dcb0d4513f84c78ee49f10416a98857150b8b15cb5c83afb4b570376e", - "9b4efe9d27b965905b0c3dab67b8d7c9ebacd56c" - }, - { - 328, - "dcc76b40ae0ea3ba253e92ac50fcde791662c5b6c948538cffc2d95e9de99cac34dfca38910db2678f", - "afedb0ff156205bcd831cbdbda43db8b0588c113" - }, - { - 336, - "5b5ec6ec4fd3ad9c4906f65c747fd4233c11a1736b6b228b92e90cddabb0c7c2fcf9716d3fad261dff33", - "8deb1e858f88293a5e5e4d521a34b2a4efa70fc4" - }, - { - 344, - "df48a37b29b1d6de4e94717d60cdb4293fcf170bba388bddf7a9035a15d433f20fd697c3e4c8b8c5f590ab", - "95cbdac0f74afa69cebd0e5c7defbc6faf0cbeaf" - }, - { - 352, - "1f179b3b82250a65e1b0aee949e218e2f45c7a8dbfd6ba08de05c55acfc226b48c68d7f7057e5675cd96fcfc", - "f0307bcb92842e5ae0cd4f4f14f3df7f877fbef2" - }, - { - 360, - "ee3d72da3a44d971578972a8e6780ce64941267e0f7d0179b214fa97855e1790e888e09fbe3a70412176cb3b54", - "7b13bb0dbf14964bd63b133ac85e22100542ef55" - }, - { - 368, - "d4d4c7843d312b30f610b3682254c8be96d5f6684503f8fbfbcd15774fc1b084d3741afb8d24aaa8ab9c104f7258", - "c314d2b6cf439be678d2a74e890d96cfac1c02ed" - }, - { - 376, - "32c094944f5936a190a0877fb9178a7bf60ceae36fd530671c5b38c5dbd5e6a6c0d615c2ac8ad04b213cc589541cf6", - "4d0be361e410b47a9d67d8ce0bb6a8e01c53c078" - }, - { - 384, - "e5d3180c14bf27a5409fa12b104a8fd7e9639609bfde6ee82bbf9648be2546d29688a65e2e3f3da47a45ac14343c9c02", - "e5353431ffae097f675cbf498869f6fbb6e1c9f2" - }, - { - 392, - "e7b6e4b69f724327e41e1188a37f4fe38b1dba19cbf5a7311d6e32f1038e97ab506ee05aebebc1eed09fc0e357109818b9", - "b8720a7068a085c018ab18961de2765aa6cd9ac4" - }, - { - 400, - "bc880cb83b8ac68ef2fedc2da95e7677ce2aa18b0e2d8b322701f67af7d5e7a0d96e9e33326ccb7747cfff0852b961bfd475", - "b0732181568543ba85f2b6da602b4b065d9931aa" - }, - { - 408, - "235ea9c2ba7af25400f2e98a47a291b0bccdaad63faa2475721fda5510cc7dad814bce8dabb611790a6abe56030b798b75c944", - "9c22674cf3222c3ba921672694aafee4ce67b96b" - }, - { - 416, - "07e3e29fed63104b8410f323b975fd9fba53f636af8c4e68a53fb202ca35dd9ee07cb169ec5186292e44c27e5696a967f5e67709", - "d128335f4cecca9066cdae08958ce656ff0b4cfc" - }, - { - 424, - "65d2a1dd60a517eb27bfbf530cf6a5458f9d5f4730058bd9814379547f34241822bf67e6335a6d8b5ed06abf8841884c636a25733f", - "0b67c57ac578de88a2ae055caeaec8bb9b0085a0" - }, - { - 432, - "dcc86b3bd461615bab739d8daafac231c0f462e819ad29f9f14058f3ab5b75941d4241ea2f17ebb8a458831b37a9b16dead4a76a9b0e", - "c766f912a89d4ccda88e0cce6a713ef5f178b596" - }, - { - 440, - "4627d54f0568dc126b62a8c35fb46a9ac5024400f2995e51635636e1afc4373dbb848eb32df23914230560b82477e9c3572647a7f2bb92", - "9aa3925a9dcb177b15ccff9b78e70cf344858779" - }, - { - 448, - "ba531affd4381168ef24d8b275a84d9254c7f5cc55fded53aa8024b2c5c5c8aa7146fe1d1b83d62b70467e9a2e2cb67b3361830adbab28d7", - "4811fa30042fc076acf37c8e2274d025307e5943" - }, - { - 456, - "8764dcbcf89dcf4282eb644e3d568bdccb4b13508bfa7bfe0ffc05efd1390be22109969262992d377691eb4f77f3d59ea8466a74abf57b2ef4", - "6743018450c9730761ee2b130df9b91c1e118150" - }, - { - 464, - "497d9df9ddb554f3d17870b1a31986c1be277bc44feff713544217a9f579623d18b5ffae306c25a45521d2759a72c0459b58957255ab592f3be4", - "71ad4a19d37d92a5e6ef3694ddbeb5aa61ada645" - }, - { - 472, - "72c3c2e065aefa8d9f7a65229e818176eef05da83f835107ba90ec2e95472e73e538f783b416c04654ba8909f26a12db6e5c4e376b7615e4a25819", - "a7d9dc68dacefb7d6116186048cb355cc548e11d" - }, - { - 480, - "7cc9894454d0055ab5069a33984e2f712bef7e3124960d33559f5f3b81906bb66fe64da13c153ca7f5cabc89667314c32c01036d12ecaf5f9a78de98", - "142e429f0522ba5abf5131fa81df82d355b96909" - }, - { - 488, - "74e8404d5a453c5f4d306f2cfa338ca65501c840ddab3fb82117933483afd6913c56aaf8a0a0a6b2a342fc3d9dc7599f4a850dfa15d06c61966d74ea59", - "ef72db70dcbcab991e9637976c6faf00d22caae9" - }, - { - 496, - "46fe5ed326c8fe376fcc92dc9e2714e2240d3253b105adfbb256ff7a19bc40975c604ad7c0071c4fd78a7cb64786e1bece548fa4833c04065fe593f6fb10", - "f220a7457f4588d639dc21407c942e9843f8e26b" - }, - { - 504, - "836dfa2524d621cf07c3d2908835de859e549d35030433c796b81272fd8bc0348e8ddbc7705a5ad1fdf2155b6bc48884ac0cd376925f069a37849c089c8645", - "ddd2117b6e309c233ede85f962a0c2fc215e5c69" - }, - { - 512, - "7e3a4c325cb9c52b88387f93d01ae86d42098f5efa7f9457388b5e74b6d28b2438d42d8b64703324d4aa25ab6aad153ae30cd2b2af4d5e5c00a8a2d0220c6116", - "a3054427cdb13f164a610b348702724c808a0dcc" + struct hex_sha1_test_case_t tc[] = { + { 0, "", "da39a3ee5e6b4b0d3255bfef95601890afd80709" }, + { 8, "a8", "99f2aa95e36f95c2acb0eaf23998f030638f3f15" }, + { 16, "3000", "f944dcd635f9801f7ac90a407fbc479964dec024" }, + { 24, "42749e", "a444319e9b6cc1e8464c511ec0969c37d6bb2619" }, + { 32, "9fc3fe08", "16a0ff84fcc156fd5d3ca3a744f20a232d172253" }, + { 40, "b5c1c6f1af", "fec9deebfcdedaf66dda525e1be43597a73a1f93" }, + { 48, "e47571e5022e", "8ce051181f0ed5e9d0c498f6bc4caf448d20deb5" }, + { 56, "3e1b28839fb758", "67da53837d89e03bf652ef09c369a3415937cfd3" }, + { 64, "a81350cbb224cb90", "305e4ff9888ad855a78573cddf4c5640cce7e946" }, + { 72, "c243d167923dec3ce1", + "5902b77b3265f023f9bbc396ba1a93fa3509bde7" }, + { 80, "50ac18c59d6a37a29bf4", + "fcade5f5d156bf6f9af97bdfa9c19bccfb4ff6ab" }, + { 88, "98e2b611ad3b1cccf634f6", + "1d20fbe00533c10e3cbd6b27088a5de0c632c4b5" }, + { 96, "73fe9afb68e1e8712e5d4eec", + "7e1b7e0f7a8f3455a9c03e9580fd63ae205a2d93" }, + { 104, "9e701ed7d412a9226a2a130e66", + "706f0677146307b20bb0e8d6311e329966884d13" }, + { 112, "6d3ee90413b0a7cbf69e5e6144ca", + "a7241a703aaf0d53fe142f86bf2e849251fa8dff" }, + { 120, "fae24d56514efcb530fd4802f5e71f", + "400f53546916d33ad01a5e6df66822dfbdc4e9e6" }, + { 128, "c5a22dd6eda3fe2bdc4ddb3ce6b35fd1", + "fac8ab93c1ae6c16f0311872b984f729dc928ccd" }, + { 136, "d98cded2adabf08fda356445c781802d95", + "fba6d750c18da58f6e2aab10112b9a5ef3301b3b" }, + { 144, "bcc6d7087a84f00103ccb32e5f5487a751a2", + "29d27c2d44c205c8107f0351b05753ac708226b6" }, + { 152, "36ecacb1055434190dbbc556c48bafcb0feb0d", + "b971bfc1ebd6f359e8d74cb7ecfe7f898d0ba845" }, + { 160, "5ff9edb69e8f6bbd498eb4537580b7fba7ad31d0", + "96d08c430094b9fcc164ad2fb6f72d0a24268f68" }, + { 168, "c95b441d8270822a46a798fae5defcf7b26abace36", + "a287ea752a593d5209e287881a09c49fa3f0beb1" }, + { 176, "83104c1d8a55b28f906f1b72cb53f68cbb097b44f860", + "a06c713779cbd88519ed4a585ac0cb8a5e9d612b" }, + { 184, "755175528d55c39c56493d697b790f099a5ce741f7754b", + "bff7d52c13a3688132a1d407b1ab40f5b5ace298" }, + { 192, "088fc38128bbdb9fd7d65228b3184b3faac6c8715f07272f", + "c7566b91d7b6f56bdfcaa9781a7b6841aacb17e9" }, + { 200, "a4a586eb9245a6c87e3adf1009ac8a49f46c07e14185016895", + "ffa30c0b5c550ea4b1e34f8a60ec9295a1e06ac1" }, + { 208, "8e7c555270c006092c2a3189e2a526b873e2e269f0fb28245256", + "29e66ed23e914351e872aa761df6e4f1a07f4b81" }, + { 216, "a5f3bfa6bb0ba3b59f6b9cbdef8a558ec565e8aa3121f405e7f2f0", + "b28cf5e5b806a01491d41f69bd9248765c5dc292" }, + { 224, "589054f0d2bd3c2c85b466bfd8ce18e6ec3e0b87d944cd093ba36469", + "60224fb72c46069652cd78bcd08029ef64da62f3" }, + { 232, "a0abb12083b5bbc78128601bf1cbdbc0fdf4b862b24d899953d8da0ff3", + "b72c4a86f72608f24c05f3b9088ef92fba431df7" }, + { 240, "82143f4cea6fadbf998e128a8811dc75301cf1db4f079501ea568da68eeb", + "73779ad5d6b71b9b8328ef7220ff12eb167076ac" }, + { 248, "9f1231dd6df1ff7bc0b0d4f989d048672683ce35d956d2f57913046267e6f3", + "a09671d4452d7cf50015c914a1e31973d20cc1a0" }, + { 256, + "041c512b5eed791f80d3282f3a28df263bb1df95e1239a7650e5670fc2187919", + "e88cdcd233d99184a6fd260b8fca1b7f7687aee0" }, + { 264, + "17e81f6ae8c2e5579d69dafa6e070e7111461552d314b691e7a3e7a4feb3fae418", + "010def22850deb1168d525e8c84c28116cb8a269" }, + { 272, "d15976b23a1d712ad28fad04d805f572026b54dd64961fda94d5355a0cc9862" + "0cf77", + "aeaa40ba1717ed5439b1e6ea901b294ba500f9ad" }, + { 280, "09fce4d434f6bd32a44e04b848ff50ec9f642a8a85b37a264dc73f130f22838" + "443328f", + "c6433791238795e34f080a5f1f1723f065463ca0" }, + { 288, "f17af27d776ec82a257d8d46d2b46b639462c56984cc1be9c1222eadb8b2659" + "4a25c709d", + "e21e22b89c1bb944a32932e6b2a2f20d491982c3" }, + { 296, "b13ce635d6f8758143ffb114f2f601cb20b6276951416a2f94fbf4ad081779d" + "79f4f195b22", + "575323a9661f5d28387964d2ba6ab92c17d05a8a" }, + { 304, "5498793f60916ff1c918dde572cdea76da8629ba4ead6d065de3dfb48de94d2" + "34cc1c5002910", + "feb44494af72f245bfe68e86c4d7986d57c11db7" }, + { 312, "498a1e0b39fa49582ae688cd715c86fbaf8a81b8b11b4d1594c49c902d197c8" + "ba8a621fd6e3be5", + "cff2290b3648ba2831b98dde436a72f9ebf51eee" }, + { 320, "3a36ae71521f9af628b3e34dcb0d4513f84c78ee49f10416a98857150b8b15c" + "b5c83afb4b570376e", + "9b4efe9d27b965905b0c3dab67b8d7c9ebacd56c" }, + { 328, "dcc76b40ae0ea3ba253e92ac50fcde791662c5b6c948538cffc2d95e9de99ca" + "c34dfca38910db2678f", + "afedb0ff156205bcd831cbdbda43db8b0588c113" }, + { 336, "5b5ec6ec4fd3ad9c4906f65c747fd4233c11a1736b6b228b92e90cddabb0c7c" + "2fcf9716d3fad261dff33", + "8deb1e858f88293a5e5e4d521a34b2a4efa70fc4" }, + { 344, "df48a37b29b1d6de4e94717d60cdb4293fcf170bba388bddf7a9035a15d433f" + "20fd697c3e4c8b8c5f590ab", + "95cbdac0f74afa69cebd0e5c7defbc6faf0cbeaf" }, + { 352, "1f179b3b82250a65e1b0aee949e218e2f45c7a8dbfd6ba08de05c55acfc226b" + "48c68d7f7057e5675cd96fcfc", + "f0307bcb92842e5ae0cd4f4f14f3df7f877fbef2" }, + { 360, "ee3d72da3a44d971578972a8e6780ce64941267e0f7d0179b214fa97855e179" + "0e888e09fbe3a70412176cb3b54", + "7b13bb0dbf14964bd63b133ac85e22100542ef55" }, + { 368, "d4d4c7843d312b30f610b3682254c8be96d5f6684503f8fbfbcd15774fc1b08" + "4d3741afb8d24aaa8ab9c104f7258", + "c314d2b6cf439be678d2a74e890d96cfac1c02ed" }, + { 376, "32c094944f5936a190a0877fb9178a7bf60ceae36fd530671c5b38c5dbd5e6a" + "6c0d615c2ac8ad04b213cc589541cf6", + "4d0be361e410b47a9d67d8ce0bb6a8e01c53c078" }, + { 384, "e5d3180c14bf27a5409fa12b104a8fd7e9639609bfde6ee82bbf9648be2546d" + "29688a65e2e3f3da47a45ac14343c9c02", + "e5353431ffae097f675cbf498869f6fbb6e1c9f2" }, + { 392, "e7b6e4b69f724327e41e1188a37f4fe38b1dba19cbf5a7311d6e32f1038e97a" + "b506ee05aebebc1eed09fc0e357109818b9", + "b8720a7068a085c018ab18961de2765aa6cd9ac4" }, + { 400, "bc880cb83b8ac68ef2fedc2da95e7677ce2aa18b0e2d8b322701f67af7d5e7a" + "0d96e9e33326ccb7747cfff0852b961bfd475", + "b0732181568543ba85f2b6da602b4b065d9931aa" }, + { 408, "235ea9c2ba7af25400f2e98a47a291b0bccdaad63faa2475721fda5510cc7da" + "d814bce8dabb611790a6abe56030b798b75c944", + "9c22674cf3222c3ba921672694aafee4ce67b96b" }, + { 416, "07e3e29fed63104b8410f323b975fd9fba53f636af8c4e68a53fb202ca35dd9" + "ee07cb169ec5186292e44c27e5696a967f5e67709", + "d128335f4cecca9066cdae08958ce656ff0b4cfc" }, + { 424, "65d2a1dd60a517eb27bfbf530cf6a5458f9d5f4730058bd9814379547f34241" + "822bf67e6335a6d8b5ed06abf8841884c636a25733f", + "0b67c57ac578de88a2ae055caeaec8bb9b0085a0" }, + { 432, "dcc86b3bd461615bab739d8daafac231c0f462e819ad29f9f14058f3ab5b759" + "41d4241ea2f17ebb8a458831b37a9b16dead4a76a9b0e", + "c766f912a89d4ccda88e0cce6a713ef5f178b596" }, + { 440, "4627d54f0568dc126b62a8c35fb46a9ac5024400f2995e51635636e1afc4373" + "dbb848eb32df23914230560b82477e9c3572647a7f2bb92", + "9aa3925a9dcb177b15ccff9b78e70cf344858779" }, + { 448, "ba531affd4381168ef24d8b275a84d9254c7f5cc55fded53aa8024b2c5c5c8a" + "a7146fe1d1b83d62b70467e9a2e2cb67b3361830adbab28d7", + "4811fa30042fc076acf37c8e2274d025307e5943" }, + { 456, "8764dcbcf89dcf4282eb644e3d568bdccb4b13508bfa7bfe0ffc05efd1390be" + "22109969262992d377691eb4f77f3d59ea8466a74abf57b2ef4", + "6743018450c9730761ee2b130df9b91c1e118150" }, + { 464, "497d9df9ddb554f3d17870b1a31986c1be277bc44feff713544217a9f579623" + "d18b5ffae306c25a45521d2759a72c0459b58957255ab592f3be4", + "71ad4a19d37d92a5e6ef3694ddbeb5aa61ada645" }, + { 472, "72c3c2e065aefa8d9f7a65229e818176eef05da83f835107ba90ec2e95472e7" + "3e538f783b416c04654ba8909f26a12db6e5c4e376b7615e4a25819", + "a7d9dc68dacefb7d6116186048cb355cc548e11d" }, + { 480, "7cc9894454d0055ab5069a33984e2f712bef7e3124960d33559f5f3b81906bb" + "66fe64da13c153ca7f5cabc89667314c32c01036d12ecaf5f9a78de98", + "142e429f0522ba5abf5131fa81df82d355b96909" }, + { 488, "74e8404d5a453c5f4d306f2cfa338ca65501c840ddab3fb82117933483afd69" + "13c56aaf8a0a0a6b2a342fc3d9dc7599f4a850dfa15d06c61966d74ea59", + "ef72db70dcbcab991e9637976c6faf00d22caae9" }, + { 496, "46fe5ed326c8fe376fcc92dc9e2714e2240d3253b105adfbb256ff7a19bc409" + "75c604ad7c0071c4fd78a7cb64786e1bece548fa4833c04065fe593f6fb10", + "f220a7457f4588d639dc21407c942e9843f8e26b" }, + { 504, "836dfa2524d621cf07c3d2908835de859e549d35030433c796b81272fd8bc03" + "48e8ddbc7705a5ad1fdf2155b6bc48884ac0cd376925f069a37849c089c864" + "5", + "ddd2117b6e309c233ede85f962a0c2fc215e5c69" }, + { 512, "7e3a4c325cb9c52b88387f93d01ae86d42098f5efa7f9457388b5e74b6d28b2" + "438d42d8b64703324d4aa25ab6aad153ae30cd2b2af4d5e5c00a8a2d0220c61" + "16", + "a3054427cdb13f164a610b348702724c808a0dcc" } + }; + + for (i = 0; i < 65; i++) { + err = hash_test_case_add(&sha1_test_case_list, tc[i].hex_data, + tc[i].bit_len / 8, tc[i].hex_hash, 20); + if (err) { + printf("error adding hash test case (code %d)\n", err); + return err; + } } - }; - - for (i=0; i < 65; i++) { - err = hash_test_case_add(&sha1_test_case_list, - tc[i].hex_data, - tc[i].bit_len/8, - tc[i].hex_hash, 20); + return srtp_err_status_ok; +} + +srtp_err_status_t sha1_dealloc_test_cases(void) +{ + hash_test_case_t *t, *next; + + for (t = sha1_test_case_list; t != NULL; t = next) { + next = t->next_test_case; + free(t); + } + + sha1_test_case_list = NULL; + + return srtp_err_status_ok; +} + +srtp_err_status_t sha1_validate(void) +{ + hash_test_case_t *test_case; + srtp_err_status_t err; + + err = sha1_add_test_cases(); if (err) { - printf("error adding hash test case (code %d)\n", err); - return err; + printf("error adding SHA1 test cases (error code %d)\n", err); + return err; } - } - return srtp_err_status_ok; + if (sha1_test_case_list == NULL) + return srtp_err_status_cant_check; + + test_case = sha1_test_case_list; + while (test_case != NULL) { + err = sha1_test_case_validate(test_case); + if (err) { + printf("error validating hash test case (error code %d)\n", err); + return err; + } + test_case = test_case->next_test_case; + } + + sha1_dealloc_test_cases(); + + return srtp_err_status_ok; } -srtp_err_status_t -sha1_dealloc_test_cases(void) { - hash_test_case_t *t, *next; +int main(void) +{ + srtp_err_status_t err; - for (t = sha1_test_case_list; t != NULL; t = next) { - next = t->next_test_case; - free(t); - } + printf("sha1 test driver\n"); - sha1_test_case_list = NULL; - - return srtp_err_status_ok; -} - - - -srtp_err_status_t -sha1_validate(void) { - hash_test_case_t *test_case; - srtp_err_status_t err; - - err = sha1_add_test_cases(); - if (err) { - printf("error adding SHA1 test cases (error code %d)\n", err); - return err; - } - - if (sha1_test_case_list == NULL) - return srtp_err_status_cant_check; - - test_case = sha1_test_case_list; - while (test_case != NULL) { - err = sha1_test_case_validate(test_case); + err = sha1_validate(); if (err) { - printf("error validating hash test case (error code %d)\n", err); - return err; + printf("SHA1 did not pass validation testing\n"); + return 1; } - test_case = test_case->next_test_case; - } - - sha1_dealloc_test_cases(); - - return srtp_err_status_ok; -} - - - -int -main (void) { - srtp_err_status_t err; - - printf("sha1 test driver\n"); - - err = sha1_validate(); - if (err) { - printf("SHA1 did not pass validation testing\n"); - return 1; - } - printf("SHA1 passed validation tests\n"); - - return 0; + printf("SHA1 passed validation tests\n"); + return 0; } diff --git a/libs/srtp/crypto/test/stat_driver.c b/libs/srtp/crypto/test/stat_driver.c index a8939b2830..4149447f74 100644 --- a/libs/srtp/crypto/test/stat_driver.c +++ b/libs/srtp/crypto/test/stat_driver.c @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -44,10 +44,10 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif -#include <stdio.h> /* for printf() */ +#include <stdio.h> /* for printf() */ #include "err.h" #include "stat.h" @@ -56,192 +56,203 @@ #include "cipher.h" typedef struct { - void *state; + void *state; } random_source_t; -srtp_err_status_t -random_source_alloc(void); +srtp_err_status_t random_source_alloc(void); -void -err_check(srtp_err_status_t s) { - if (s) { - printf("error (code %d)\n", s); - exit(1); - } +void err_check(srtp_err_status_t s) +{ + if (s) { + printf("error (code %d)\n", s); + exit(1); + } } -int -main (int argc, char *argv[]) { - uint8_t buffer[2532]; - unsigned int buf_len = 2500; - int i, j; - extern srtp_cipher_type_t srtp_aes_icm_128; - extern srtp_cipher_type_t srtp_aes_icm_256; +int main(int argc, char *argv[]) +{ + uint8_t buffer[2532]; + unsigned int buf_len = 2500; + int i, j; + extern srtp_cipher_type_t srtp_aes_icm_128; + extern srtp_cipher_type_t srtp_aes_icm_256; #ifdef OPENSSL - extern srtp_cipher_type_t srtp_aes_gcm_128_openssl; - extern srtp_cipher_type_t srtp_aes_gcm_256_openssl; + extern srtp_cipher_type_t srtp_aes_gcm_128_openssl; + extern srtp_cipher_type_t srtp_aes_gcm_256_openssl; #endif - srtp_cipher_t *c; - uint8_t key[46] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 + srtp_cipher_t *c; + /* clang-format off */ + uint8_t key[46] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; - v128_t nonce; - int num_trials = 500; - int num_fail; + /* clang-format on */ + v128_t nonce; + int num_trials = 500; + int num_fail; - printf("statistical tests driver\n"); + printf("statistical tests driver\n"); - v128_set_to_zero(&nonce); - for (i=0; i < 2500; i++) - buffer[i] = 0; + v128_set_to_zero(&nonce); + for (i = 0; i < 2500; i++) + buffer[i] = 0; - /* run tests */ - printf("running stat_tests on all-null buffer, expecting failure\n"); - printf("monobit %d\n", stat_test_monobit(buffer)); - printf("poker %d\n", stat_test_poker(buffer)); - printf("runs %d\n", stat_test_runs(buffer)); + /* run tests */ + printf("running stat_tests on all-null buffer, expecting failure\n"); + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); - for (i=0; i < 2500; i++) - buffer[i] = rand(); - printf("running stat_tests on rand(), expecting success\n"); - printf("monobit %d\n", stat_test_monobit(buffer)); - printf("poker %d\n", stat_test_poker(buffer)); - printf("runs %d\n", stat_test_runs(buffer)); + for (i = 0; i < 2500; i++) + buffer[i] = rand(); + printf("running stat_tests on rand(), expecting success\n"); + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); - printf("running stat_tests on AES-128-ICM, expecting success\n"); - /* set buffer to cipher output */ - for (i=0; i < 2500; i++) - buffer[i] = 0; - err_check(srtp_cipher_type_alloc(&srtp_aes_icm_128, &c, SRTP_AES_ICM_128_KEY_LEN_WSALT, 0)); - err_check(srtp_cipher_init(c, key)); - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); - err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - /* run tests on cipher outout */ - printf("monobit %d\n", stat_test_monobit(buffer)); - printf("poker %d\n", stat_test_poker(buffer)); - printf("runs %d\n", stat_test_runs(buffer)); - - printf("runs test (please be patient): "); - fflush(stdout); - num_fail = 0; - v128_set_to_zero(&nonce); - for(j=0; j < num_trials; j++) { - for (i=0; i < 2500; i++) - buffer[i] = 0; - nonce.v32[3] = i; - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); + printf("running stat_tests on AES-128-ICM, expecting success\n"); + /* set buffer to cipher output */ + for (i = 0; i < 2500; i++) + buffer[i] = 0; + err_check(srtp_cipher_type_alloc(&srtp_aes_icm_128, &c, + SRTP_AES_ICM_128_KEY_LEN_WSALT, 0)); + err_check(srtp_cipher_init(c, key)); + err_check(srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt)); err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - if (stat_test_runs(buffer)) { - num_fail++; + /* run tests on cipher outout */ + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); + + printf("runs test (please be patient): "); + fflush(stdout); + num_fail = 0; + v128_set_to_zero(&nonce); + for (j = 0; j < num_trials; j++) { + for (i = 0; i < 2500; i++) + buffer[i] = 0; + nonce.v32[3] = i; + err_check( + srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt)); + err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); + if (stat_test_runs(buffer)) { + num_fail++; + } } - } - printf("%d failures in %d tests\n", num_fail, num_trials); - printf("(nota bene: a small fraction of stat_test failures does not \n" - "indicate that the random source is invalid)\n"); + printf("%d failures in %d tests\n", num_fail, num_trials); + printf("(nota bene: a small fraction of stat_test failures does not \n" + "indicate that the random source is invalid)\n"); - err_check(srtp_cipher_dealloc(c)); + err_check(srtp_cipher_dealloc(c)); - printf("running stat_tests on AES-256-ICM, expecting success\n"); - /* set buffer to cipher output */ - for (i=0; i < 2500; i++) - buffer[i] = 0; - err_check(srtp_cipher_type_alloc(&srtp_aes_icm_256, &c, SRTP_AES_ICM_256_KEY_LEN_WSALT, 0)); - err_check(srtp_cipher_init(c, key)); - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); - err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - /* run tests on cipher outout */ - printf("monobit %d\n", stat_test_monobit(buffer)); - printf("poker %d\n", stat_test_poker(buffer)); - printf("runs %d\n", stat_test_runs(buffer)); - - printf("runs test (please be patient): "); - fflush(stdout); - num_fail = 0; - v128_set_to_zero(&nonce); - for(j=0; j < num_trials; j++) { - for (i=0; i < 2500; i++) - buffer[i] = 0; - nonce.v32[3] = i; - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); + printf("running stat_tests on AES-256-ICM, expecting success\n"); + /* set buffer to cipher output */ + for (i = 0; i < 2500; i++) + buffer[i] = 0; + err_check(srtp_cipher_type_alloc(&srtp_aes_icm_256, &c, + SRTP_AES_ICM_256_KEY_LEN_WSALT, 0)); + err_check(srtp_cipher_init(c, key)); + err_check(srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt)); err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - if (stat_test_runs(buffer)) { - num_fail++; + /* run tests on cipher outout */ + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); + + printf("runs test (please be patient): "); + fflush(stdout); + num_fail = 0; + v128_set_to_zero(&nonce); + for (j = 0; j < num_trials; j++) { + for (i = 0; i < 2500; i++) + buffer[i] = 0; + nonce.v32[3] = i; + err_check( + srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt)); + err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); + if (stat_test_runs(buffer)) { + num_fail++; + } } - } #ifdef OPENSSL - { - printf("running stat_tests on AES-128-GCM, expecting success\n"); - /* set buffer to cipher output */ - for (i=0; i < 2500; i++) { - buffer[i] = 0; - } - err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, SRTP_AES_GCM_128_KEY_LEN_WSALT, 8)); - err_check(srtp_cipher_init(c, key)); - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); - err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - /* run tests on cipher outout */ - printf("monobit %d\n", stat_test_monobit(buffer)); - printf("poker %d\n", stat_test_poker(buffer)); - printf("runs %d\n", stat_test_runs(buffer)); - fflush(stdout); - num_fail = 0; - v128_set_to_zero(&nonce); - for(j=0; j < num_trials; j++) { - for (i=0; i < 2500; i++) { - buffer[i] = 0; - } - nonce.v32[3] = i; - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); - err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - buf_len = 2500; - if (stat_test_runs(buffer)) { - num_fail++; - } - } + { + printf("running stat_tests on AES-128-GCM, expecting success\n"); + /* set buffer to cipher output */ + for (i = 0; i < 2500; i++) { + buffer[i] = 0; + } + err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_128_openssl, &c, + SRTP_AES_GCM_128_KEY_LEN_WSALT, 8)); + err_check(srtp_cipher_init(c, key)); + err_check( + srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt)); + err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); + /* run tests on cipher outout */ + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); + fflush(stdout); + num_fail = 0; + v128_set_to_zero(&nonce); + for (j = 0; j < num_trials; j++) { + for (i = 0; i < 2500; i++) { + buffer[i] = 0; + } + nonce.v32[3] = i; + err_check(srtp_cipher_set_iv(c, (uint8_t *)&nonce, + srtp_direction_encrypt)); + err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); + buf_len = 2500; + if (stat_test_runs(buffer)) { + num_fail++; + } + } - printf("running stat_tests on AES-256-GCM, expecting success\n"); - /* set buffer to cipher output */ - for (i=0; i < 2500; i++) { - buffer[i] = 0; + printf("running stat_tests on AES-256-GCM, expecting success\n"); + /* set buffer to cipher output */ + for (i = 0; i < 2500; i++) { + buffer[i] = 0; + } + err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, + SRTP_AES_GCM_256_KEY_LEN_WSALT, 16)); + err_check(srtp_cipher_init(c, key)); + err_check( + srtp_cipher_set_iv(c, (uint8_t *)&nonce, srtp_direction_encrypt)); + err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); + /* run tests on cipher outout */ + printf("monobit %d\n", stat_test_monobit(buffer)); + printf("poker %d\n", stat_test_poker(buffer)); + printf("runs %d\n", stat_test_runs(buffer)); + fflush(stdout); + num_fail = 0; + v128_set_to_zero(&nonce); + for (j = 0; j < num_trials; j++) { + for (i = 0; i < 2500; i++) { + buffer[i] = 0; + } + nonce.v32[3] = i; + err_check(srtp_cipher_set_iv(c, (uint8_t *)&nonce, + srtp_direction_encrypt)); + err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); + buf_len = 2500; + if (stat_test_runs(buffer)) { + num_fail++; + } + } } - err_check(srtp_cipher_type_alloc(&srtp_aes_gcm_256_openssl, &c, SRTP_AES_GCM_256_KEY_LEN_WSALT, 16)); - err_check(srtp_cipher_init(c, key)); - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); - err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - /* run tests on cipher outout */ - printf("monobit %d\n", stat_test_monobit(buffer)); - printf("poker %d\n", stat_test_poker(buffer)); - printf("runs %d\n", stat_test_runs(buffer)); - fflush(stdout); - num_fail = 0; - v128_set_to_zero(&nonce); - for(j=0; j < num_trials; j++) { - for (i=0; i < 2500; i++) { - buffer[i] = 0; - } - nonce.v32[3] = i; - err_check(srtp_cipher_set_iv(c, (uint8_t*)&nonce, srtp_direction_encrypt)); - err_check(srtp_cipher_encrypt(c, buffer, &buf_len)); - buf_len = 2500; - if (stat_test_runs(buffer)) { - num_fail++; - } - } - } #endif - printf("%d failures in %d tests\n", num_fail, num_trials); - printf("(nota bene: a small fraction of stat_test failures does not \n" - "indicate that the random source is invalid)\n"); + printf("%d failures in %d tests\n", num_fail, num_trials); + printf("(nota bene: a small fraction of stat_test failures does not \n" + "indicate that the random source is invalid)\n"); - err_check(srtp_cipher_dealloc(c)); + err_check(srtp_cipher_dealloc(c)); - return 0; + return 0; } diff --git a/libs/srtp/doc/libsrtp.pdf b/libs/srtp/doc/libsrtp.pdf deleted file mode 100644 index a0a11b7bdc4e3a05397e200890a800599d012c5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234575 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 N3`<Tft|$TfzX06bH%R~h diff --git a/libs/srtp/format.sh b/libs/srtp/format.sh new file mode 100644 index 0000000000..fdf23ef3c6 --- /dev/null +++ b/libs/srtp/format.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# format.sh +# +# run clang-format on each .c & .h file +# +# assumes git tree is clean when reporting status + +if [ -z "${CLANG_FORMAT}" ]; then + CLANG_FORMAT=clang-format +fi + +a=`git ls-files '*.h' '*.c'` +for x in $a; do + if [ $x != "config_in.h" ]; then + $CLANG_FORMAT -i -style=file $x + fi +done + +m=`git ls-files -m` +if [ -n "$m" ]; then + v=`$CLANG_FORMAT -version` + echo "Fromatting required when checking with $v" + echo + echo "The following files required formatting:" + for f in $m; do + echo $f + done + if [ "$1" = "-d" ]; then + echo + git diff + fi + exit 1 +fi +exit 0 diff --git a/libs/srtp/include/ekt.h b/libs/srtp/include/ekt.h index 86bfa17adf..a289a53dab 100644 --- a/libs/srtp/include/ekt.h +++ b/libs/srtp/include/ekt.h @@ -7,26 +7,26 @@ * 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 @@ -42,15 +42,13 @@ * */ - - /* - * EKT implementation strategy - * + * EKT implementation strategy + * * use stream_template approach * * in srtp_unprotect, when a new stream appears, check if template has - * EKT defined, and if it does, then apply EKT processing + * EKT defined, and if it does, then apply EKT processing * * question: will we want to allow key-sharing templates in addition * to EKT templates? could define a new ssrc_type_t that's associated @@ -69,14 +67,13 @@ extern "C" { #endif -#define SRTP_EKT_CIPHER_DEFAULT 1 -#define SRTP_EKT_CIPHER_AES_128_ECB 1 -#define SRTP_EKT_CIPHER_AES_192_KEY_WRAP 2 -#define SRTP_EKT_CIPHER_AES_256_KEY_WRAP 3 +#define SRTP_EKT_CIPHER_DEFAULT 1 +#define SRTP_EKT_CIPHER_AES_128_ECB 1 +#define SRTP_EKT_CIPHER_AES_192_KEY_WRAP 2 +#define SRTP_EKT_CIPHER_AES_256_KEY_WRAP 3 typedef uint16_t srtp_ekt_spi_t; - unsigned srtp_ekt_octets_after_base_tag(srtp_ekt_stream_t ekt); /* @@ -88,24 +85,23 @@ unsigned srtp_ekt_octets_after_base_tag(srtp_ekt_stream_t ekt); */ typedef struct srtp_ekt_policy_ctx_t { - srtp_ekt_spi_t spi; /* security parameter index */ - uint8_t ekt_cipher_type; - uint8_t *ekt_key; - struct srtp_ekt_policy_ctx_t *next_ekt_policy; + srtp_ekt_spi_t spi; /* security parameter index */ + uint8_t ekt_cipher_type; + uint8_t *ekt_key; + struct srtp_ekt_policy_ctx_t *next_ekt_policy; } srtp_ekt_policy_ctx_t; - /* * an srtp_ekt_data_t structure holds the data corresponding to an ekt key, * spi, and so on */ typedef struct srtp_ekt_data_t { - srtp_ekt_spi_t spi; - uint8_t ekt_cipher_type; - srtp_aes_expanded_key_t ekt_enc_key; - srtp_aes_expanded_key_t ekt_dec_key; - struct ekt_data_t *next_ekt_data; + srtp_ekt_spi_t spi; + uint8_t ekt_cipher_type; + srtp_aes_expanded_key_t ekt_enc_key; + srtp_aes_expanded_key_t ekt_dec_key; + struct ekt_data_t *next_ekt_data; } srtp_ekt_data_t; /* @@ -116,25 +112,31 @@ typedef struct srtp_ekt_data_t { */ typedef struct srtp_ekt_stream_ctx_t { - srtp_ekt_data_t *data; - uint16_t isn; /* initial sequence number */ - uint8_t encrypted_master_key[SRTP_MAX_KEY_LEN]; + srtp_ekt_data_t *data; + uint16_t isn; /* initial sequence number */ + uint8_t encrypted_master_key[SRTP_MAX_KEY_LEN]; } srtp_ekt_stream_ctx_t; +srtp_err_status_t srtp_ekt_alloc(srtp_ekt_stream_t *stream_data, + srtp_ekt_policy_t policy); +srtp_err_status_t srtp_ekt_stream_init(srtp_ekt_stream_t e, + srtp_ekt_spi_t spi, + void *ekt_key, + unsigned ekt_cipher_type); -srtp_err_status_t srtp_ekt_alloc(srtp_ekt_stream_t *stream_data, srtp_ekt_policy_t policy); +srtp_err_status_t srtp_ekt_stream_init_from_policy(srtp_ekt_stream_t e, + srtp_ekt_policy_t p); -srtp_err_status_t srtp_ekt_stream_init(srtp_ekt_stream_t e, srtp_ekt_spi_t spi, void *ekt_key, unsigned ekt_cipher_type); +srtp_err_status_t srtp_stream_init_from_ekt(srtp_stream_t stream, + const void *srtcp_hdr, + unsigned pkt_octet_len); -srtp_err_status_t srtp_ekt_stream_init_from_policy(srtp_ekt_stream_t e, srtp_ekt_policy_t p); - - - -srtp_err_status_t srtp_stream_init_from_ekt(srtp_stream_t stream, const void *srtcp_hdr, unsigned pkt_octet_len); - - -void srtp_ekt_write_data(srtp_ekt_stream_t ekt, uint8_t *base_tag, unsigned base_tag_len, int *packet_len, srtp_xtd_seq_num_t pkt_index); +void srtp_ekt_write_data(srtp_ekt_stream_t ekt, + uint8_t *base_tag, + unsigned base_tag_len, + int *packet_len, + srtp_xtd_seq_num_t pkt_index); /* * We handle EKT by performing some additional steps before @@ -144,10 +146,13 @@ void srtp_ekt_write_data(srtp_ekt_stream_t ekt, uint8_t *base_tag, unsigned base * With EKT, the tag_len parameter is actually the base tag * length */ -srtp_err_status_t srtp_ekt_tag_verification_preproces(uint8_t *pkt_tag, uint8_t *pkt_tag_copy, unsigned tag_len); - -srtp_err_status_t srtp_ekt_tag_verification_postproces(uint8_t *pkt_tag, uint8_t *pkt_tag_copy, unsigned tag_len); +srtp_err_status_t srtp_ekt_tag_verification_preproces(uint8_t *pkt_tag, + uint8_t *pkt_tag_copy, + unsigned tag_len); +srtp_err_status_t srtp_ekt_tag_verification_postproces(uint8_t *pkt_tag, + uint8_t *pkt_tag_copy, + unsigned tag_len); /* * @brief EKT pre-processing for srtcp tag generation @@ -157,16 +162,18 @@ srtp_err_status_t srtp_ekt_tag_verification_postproces(uint8_t *pkt_tag, uint8_t * Master Key, the SRTP ROC, the Initial Sequence Number, and SPI * fields. The Base Authentication Tag field is set to the all-zero * value - * + * * When EKT is not used, this function is a no-op. - * + * */ -srtp_err_status_t srtp_stream_srtcp_auth_tag_generation_preprocess(const srtp_stream_t *s, uint8_t *pkt_tag, unsigned pkt_octet_len); +srtp_err_status_t srtp_stream_srtcp_auth_tag_generation_preprocess( + const srtp_stream_t *s, + uint8_t *pkt_tag, + unsigned pkt_octet_len); /* it's not clear that a tag_generation_postprocess function is needed */ srtp_err_status_t srtcp_auth_tag_generation_postprocess(void); - #ifdef __cplusplus } #endif diff --git a/libs/srtp/include/getopt_s.h b/libs/srtp/include/getopt_s.h index 63278e9850..53fb25ba71 100644 --- a/libs/srtp/include/getopt_s.h +++ b/libs/srtp/include/getopt_s.h @@ -7,26 +7,26 @@ * */ /* - * + * * 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 @@ -49,17 +49,16 @@ extern "C" { #endif -/* +/* * getopt_s(), optarg_s, and optind_s are small, locally defined * versions of the POSIX standard getopt() interface. */ - -int -getopt_s(int argc, char * const argv[], const char *optstring); -extern char *optarg_s; /* defined in getopt.c */ +int getopt_s(int argc, char *const argv[], const char *optstring); -extern int optind_s; /* defined in getopt.c */ +extern char *optarg_s; /* defined in getopt.c */ + +extern int optind_s; /* defined in getopt.c */ #ifdef __cplusplus } diff --git a/libs/srtp/include/rtp.h b/libs/srtp/include/rtp.h deleted file mode 100644 index 0e0119cf7b..0000000000 --- a/libs/srtp/include/rtp.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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-2006, 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_H -#define RTP_H - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#elif defined HAVE_WINSOCK2_H -# include <winsock2.h> -#endif - -#include "srtp.h" - -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 */ - 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 */ - 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); - - -/* - * 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 - - -#endif /* RTP_H */ diff --git a/libs/srtp/include/srtp.h b/libs/srtp/include/srtp.h index 6d42f7b52f..1fdd6c3aff 100644 --- a/libs/srtp/include/srtp.h +++ b/libs/srtp/include/srtp.h @@ -7,26 +7,26 @@ * 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 @@ -42,7 +42,6 @@ * */ - #ifndef SRTP_SRTP_H #define SRTP_SRTP_H @@ -70,13 +69,13 @@ extern "C" { /* * SRTP_MAX_KEY_LEN is the maximum key length supported by libSRTP */ -#define SRTP_MAX_KEY_LEN 64 +#define SRTP_MAX_KEY_LEN 64 /* * SRTP_MAX_TAG_LEN is the maximum tag length supported by libSRTP */ -#define SRTP_MAX_TAG_LEN 16 +#define SRTP_MAX_TAG_LEN 16 /** * SRTP_MAX_MKI_LEN is the maximum size the MKI could be which is @@ -84,7 +83,6 @@ extern "C" { */ #define SRTP_MAX_MKI_LEN 128 - /** * SRTP_MAX_TRAILER_LEN is the maximum length of the SRTP trailer * (authentication tag and MKI) supported by libSRTP. This value is @@ -97,32 +95,36 @@ extern "C" { /** * SRTP_MAX_NUM_MASTER_KEYS is the maximum number of Master keys for - * MKI supported by libSRTP. - * + * MKI supported by libSRTP. + * */ #define SRTP_MAX_NUM_MASTER_KEYS 16 -#define SRTP_SALT_LEN 14 +#define SRTP_SALT_LEN 14 + /* * SRTP_AEAD_SALT_LEN is the length of the SALT values used with * GCM mode. GCM mode requires an IV. The SALT value is used * as part of the IV formation logic applied to each RTP packet. */ -#define SRTP_AEAD_SALT_LEN 12 +#define SRTP_AEAD_SALT_LEN 12 -#define SRTP_AES_128_KEY_LEN 16 -#define SRTP_AES_192_KEY_LEN 24 -#define SRTP_AES_256_KEY_LEN 32 +#define SRTP_AES_128_KEY_LEN 16 +#define SRTP_AES_192_KEY_LEN 24 +#define SRTP_AES_256_KEY_LEN 32 -#define SRTP_AES_ICM_128_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_128_KEY_LEN) -#define SRTP_AES_ICM_192_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_192_KEY_LEN) -#define SRTP_AES_ICM_256_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_256_KEY_LEN) +#define SRTP_AES_ICM_128_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_128_KEY_LEN) +#define SRTP_AES_ICM_192_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_192_KEY_LEN) +#define SRTP_AES_ICM_256_KEY_LEN_WSALT (SRTP_SALT_LEN + SRTP_AES_256_KEY_LEN) -#define SRTP_AES_GCM_128_KEY_LEN_WSALT (SRTP_AEAD_SALT_LEN + SRTP_AES_128_KEY_LEN) -#define SRTP_AES_GCM_192_KEY_LEN_WSALT (SRTP_AEAD_SALT_LEN + SRTP_AES_192_KEY_LEN) -#define SRTP_AES_GCM_256_KEY_LEN_WSALT (SRTP_AEAD_SALT_LEN + SRTP_AES_256_KEY_LEN) +#define SRTP_AES_GCM_128_KEY_LEN_WSALT \ + (SRTP_AEAD_SALT_LEN + SRTP_AES_128_KEY_LEN) +#define SRTP_AES_GCM_192_KEY_LEN_WSALT \ + (SRTP_AEAD_SALT_LEN + SRTP_AES_192_KEY_LEN) +#define SRTP_AES_GCM_256_KEY_LEN_WSALT \ + (SRTP_AEAD_SALT_LEN + SRTP_AES_256_KEY_LEN) -/** +/** * @brief A srtp_cipher_type_id_t is an identifier for a particular cipher * type. * @@ -131,13 +133,14 @@ extern "C" { * SRTP_NULL_CIPHER is avaliable; this cipher leaves the data unchanged, * and can be selected to indicate that no encryption is to take * place. - * + * * @ingroup Ciphers */ -typedef uint32_t srtp_cipher_type_id_t; +typedef uint32_t srtp_cipher_type_id_t; /** - * @brief An srtp_auth_type_id_t is an identifier for a particular authentication + * @brief An srtp_auth_type_id_t is an identifier for a particular + * authentication * function. * * An srtp_auth_type_id_t is an integer that represents a particular @@ -145,7 +148,7 @@ typedef uint32_t srtp_cipher_type_id_t; * avaliable; this authentication function performs no computation, * and can be selected to indicate that no authentication is to take * place. - * + * * @ingroup Authentication */ typedef uint32_t srtp_auth_type_id_t; @@ -159,120 +162,119 @@ typedef uint32_t srtp_auth_type_id_t; * */ typedef enum { - srtp_err_status_ok = 0, /**< nothing to report */ - srtp_err_status_fail = 1, /**< unspecified failure */ - srtp_err_status_bad_param = 2, /**< unsupported parameter */ - srtp_err_status_alloc_fail = 3, /**< couldn't allocate memory */ - srtp_err_status_dealloc_fail = 4, /**< couldn't deallocate properly */ - srtp_err_status_init_fail = 5, /**< couldn't initialize */ - srtp_err_status_terminus = 6, /**< can't process as much data as requested */ - srtp_err_status_auth_fail = 7, /**< authentication failure */ - srtp_err_status_cipher_fail = 8, /**< cipher failure */ - srtp_err_status_replay_fail = 9, /**< replay check failed (bad index) */ - srtp_err_status_replay_old = 10, /**< replay check failed (index too old) */ - srtp_err_status_algo_fail = 11, /**< algorithm failed test routine */ - srtp_err_status_no_such_op = 12, /**< unsupported operation */ - srtp_err_status_no_ctx = 13, /**< no appropriate context found */ - srtp_err_status_cant_check = 14, /**< unable to perform desired validation */ - srtp_err_status_key_expired = 15, /**< can't use key any more */ - srtp_err_status_socket_err = 16, /**< error in use of socket */ - srtp_err_status_signal_err = 17, /**< error in use POSIX signals */ - srtp_err_status_nonce_bad = 18, /**< nonce check failed */ - srtp_err_status_read_fail = 19, /**< couldn't read data */ - srtp_err_status_write_fail = 20, /**< couldn't write data */ - srtp_err_status_parse_err = 21, /**< error parsing data */ - srtp_err_status_encode_err = 22, /**< error encoding data */ - srtp_err_status_semaphore_err = 23,/**< error while using semaphores */ - srtp_err_status_pfkey_err = 24, /**< error while using pfkey */ - srtp_err_status_bad_mki = 25, /**< error MKI present in packet is invalid */ - srtp_err_status_pkt_idx_old = 26, /**< packet index is too old to consider */ - srtp_err_status_pkt_idx_adv = 27 /**< packet index advanced, reset needed */ + srtp_err_status_ok = 0, /**< nothing to report */ + srtp_err_status_fail = 1, /**< unspecified failure */ + srtp_err_status_bad_param = 2, /**< unsupported parameter */ + srtp_err_status_alloc_fail = 3, /**< couldn't allocate memory */ + srtp_err_status_dealloc_fail = 4, /**< couldn't deallocate properly */ + srtp_err_status_init_fail = 5, /**< couldn't initialize */ + srtp_err_status_terminus = 6, /**< can't process as much data as */ + /**< requested */ + srtp_err_status_auth_fail = 7, /**< authentication failure */ + srtp_err_status_cipher_fail = 8, /**< cipher failure */ + srtp_err_status_replay_fail = 9, /**< replay check failed (bad index) */ + srtp_err_status_replay_old = 10, /**< replay check failed (index too */ + /**< old) */ + srtp_err_status_algo_fail = 11, /**< algorithm failed test routine */ + srtp_err_status_no_such_op = 12, /**< unsupported operation */ + srtp_err_status_no_ctx = 13, /**< no appropriate context found */ + srtp_err_status_cant_check = 14, /**< unable to perform desired */ + /**< validation */ + srtp_err_status_key_expired = 15, /**< can't use key any more */ + srtp_err_status_socket_err = 16, /**< error in use of socket */ + srtp_err_status_signal_err = 17, /**< error in use POSIX signals */ + srtp_err_status_nonce_bad = 18, /**< nonce check failed */ + srtp_err_status_read_fail = 19, /**< couldn't read data */ + srtp_err_status_write_fail = 20, /**< couldn't write data */ + srtp_err_status_parse_err = 21, /**< error parsing data */ + srtp_err_status_encode_err = 22, /**< error encoding data */ + srtp_err_status_semaphore_err = 23, /**< error while using semaphores */ + srtp_err_status_pfkey_err = 24, /**< error while using pfkey */ + srtp_err_status_bad_mki = 25, /**< error MKI present in packet is */ + /**< invalid */ + srtp_err_status_pkt_idx_old = 26, /**< packet index is too old to */ + /**< consider */ + srtp_err_status_pkt_idx_adv = 27 /**< packet index advanced, reset */ + /**< needed */ } srtp_err_status_t; - typedef struct srtp_ctx_t_ srtp_ctx_t; /** - * @brief srtp_sec_serv_t describes a set of security services. + * @brief srtp_sec_serv_t describes a set of security services. * * A srtp_sec_serv_t enumeration is used to describe the particular * security services that will be applied by a particular crypto - * policy (or other mechanism). + * policy (or other mechanism). */ - typedef enum { - sec_serv_none = 0, /**< no services */ - sec_serv_conf = 1, /**< confidentiality */ - sec_serv_auth = 2, /**< authentication */ - sec_serv_conf_and_auth = 3 /**< confidentiality and authentication */ + sec_serv_none = 0, /**< no services */ + sec_serv_conf = 1, /**< confidentiality */ + sec_serv_auth = 2, /**< authentication */ + sec_serv_conf_and_auth = 3 /**< confidentiality and authentication */ } srtp_sec_serv_t; -/** +/** * @brief srtp_crypto_policy_t describes a particular crypto policy that * can be applied to an SRTP stream. * * A srtp_crypto_policy_t describes a particular cryptographic policy that * can be applied to an SRTP or SRTCP stream. An SRTP session policy - * consists of a list of these policies, one for each SRTP stream + * consists of a list of these policies, one for each SRTP stream * in the session. */ - typedef struct srtp_crypto_policy_t { - srtp_cipher_type_id_t cipher_type; /**< An integer representing - * the type of cipher. */ - int cipher_key_len; /**< The length of the cipher key - * in octets. */ - srtp_auth_type_id_t auth_type; /**< An integer representing the - * authentication function. */ - int auth_key_len; /**< The length of the authentication - * function key in octets. */ - int auth_tag_len; /**< The length of the authentication - * tag in octets. */ - srtp_sec_serv_t sec_serv; /**< The flag indicating the security - * services to be applied. */ + srtp_cipher_type_id_t cipher_type; /**< An integer representing */ + /**< the type of cipher. */ + int cipher_key_len; /**< The length of the cipher key */ + /**< in octets. */ + srtp_auth_type_id_t auth_type; /**< An integer representing the */ + /**< authentication function. */ + int auth_key_len; /**< The length of the authentication */ + /**< function key in octets. */ + int auth_tag_len; /**< The length of the authentication */ + /**< tag in octets. */ + srtp_sec_serv_t sec_serv; /**< The flag indicating the security */ + /**< services to be applied. */ } srtp_crypto_policy_t; - -/** +/** * @brief srtp_ssrc_type_t describes the type of an SSRC. - * + * * An srtp_ssrc_type_t enumeration is used to indicate a type of SSRC. See * @ref srtp_policy_t for more informataion. */ - -typedef enum { - ssrc_undefined = 0, /**< Indicates an undefined SSRC type. */ - ssrc_specific = 1, /**< Indicates a specific SSRC value */ - ssrc_any_inbound = 2, /**< Indicates any inbound SSRC value - (i.e. a value that is used in the - function srtp_unprotect()) */ - ssrc_any_outbound = 3 /**< Indicates any outbound SSRC value - (i.e. a value that is used in the - function srtp_protect()) */ +typedef enum { + ssrc_undefined = 0, /**< Indicates an undefined SSRC type. */ + ssrc_specific = 1, /**< Indicates a specific SSRC value */ + ssrc_any_inbound = 2, /**< Indicates any inbound SSRC value */ + /**< (i.e. a value that is used in the */ + /**< function srtp_unprotect()) */ + ssrc_any_outbound = 3 /**< Indicates any outbound SSRC value */ + /**< (i.e. a value that is used in the */ + /**< function srtp_protect()) */ } srtp_ssrc_type_t; /** - * @brief An srtp_ssrc_t represents a particular SSRC value, or a `wildcard' SSRC. - * + * @brief An srtp_ssrc_t represents a particular SSRC value, or a `wildcard' + * SSRC. + * * An srtp_ssrc_t represents a particular SSRC value (if its type is * ssrc_specific), or a wildcard SSRC value that will match all * outbound SSRCs (if its type is ssrc_any_outbound) or all inbound - * SSRCs (if its type is ssrc_any_inbound). - * + * SSRCs (if its type is ssrc_any_inbound). */ - -typedef struct { - srtp_ssrc_type_t type; /**< The type of this particular SSRC */ - unsigned int value; /**< The value of this SSRC, if it is not a wildcard */ +typedef struct { + srtp_ssrc_type_t type; /**< The type of this particular SSRC */ + unsigned int value; /**< The value of this SSRC, if it is not a */ + /**< wildcard */ } srtp_ssrc_t; - /** * @brief points to an EKT policy */ typedef struct srtp_ekt_policy_ctx_t *srtp_ekt_policy_t; - /** * @brief points to EKT stream data */ @@ -285,13 +287,13 @@ typedef struct srtp_ekt_stream_ctx_t *srtp_ekt_stream_t; * Index Size to correctly read it from a packet. */ typedef struct srtp_master_key_t { - unsigned char *key; - unsigned char *mki_id; - unsigned int mki_size; + unsigned char *key; + unsigned char *mki_id; + unsigned int mki_size; } srtp_master_key_t; -/** - * @brief represents the policy for an SRTP session. +/** + * @brief represents the policy for an SRTP session. * * A single srtp_policy_t struct represents the policy for a single * SRTP stream, and a linked list of these elements represents the @@ -300,7 +302,7 @@ typedef struct srtp_master_key_t { * master key for that stream, the SSRC describing that stream, or a * flag indicating a `wildcard' SSRC value, and a `next' field that * holds a pointer to the next element in the list of policy elements, - * or NULL if it is the last element. + * or NULL if it is the last element. * * The wildcard value SSRC_ANY_INBOUND matches any SSRC from an * inbound stream that for which there is no explicit SSRC entry in @@ -311,47 +313,44 @@ typedef struct srtp_master_key_t { * is intentional, and it allows libSRTP to ensure that no security * lapses result from accidental re-use of SSRC values during key * sharing. - * - * + * * @warning The final element of the list @b must have its `next' pointer * set to NULL. */ typedef struct srtp_policy_t { - srtp_ssrc_t ssrc; /**< The SSRC value of stream, or the - * flags SSRC_ANY_INBOUND or - * SSRC_ANY_OUTBOUND if key sharing - * is used for this policy element. - */ - srtp_crypto_policy_t rtp; /**< SRTP crypto policy. */ - srtp_crypto_policy_t rtcp; /**< SRTCP crypto policy. */ - unsigned char *key; /**< Pointer to the SRTP master key for - * this stream. */ - srtp_master_key_t **keys; /** Array of Master Key structures */ - unsigned long num_master_keys; /** Number of master keys */ - srtp_ekt_policy_t ekt; /**< Pointer to the EKT policy structure - * for this stream (if any) */ - unsigned long window_size; /**< The window size to use for replay - * protection. */ - int allow_repeat_tx; /**< Whether retransmissions of - * packets with the same sequence number - * are allowed. (Note that such repeated - * transmissions must have the same RTP - * payload, or a severe security weakness - * is introduced!) */ - int *enc_xtn_hdr; /**< List of header ids to encrypt. */ - int enc_xtn_hdr_count; /**< Number of entries in list of header ids. */ - struct srtp_policy_t *next; /**< Pointer to next stream policy. */ + srtp_ssrc_t ssrc; /**< The SSRC value of stream, or the */ + /**< flags SSRC_ANY_INBOUND or */ + /**< SSRC_ANY_OUTBOUND if key sharing */ + /**< is used for this policy element. */ + srtp_crypto_policy_t rtp; /**< SRTP crypto policy. */ + srtp_crypto_policy_t rtcp; /**< SRTCP crypto policy. */ + unsigned char *key; /**< Pointer to the SRTP master key for */ + /**< this stream. */ + srtp_master_key_t **keys; /** Array of Master Key structures */ + unsigned long num_master_keys; /** Number of master keys */ + srtp_ekt_policy_t ekt; /**< Pointer to the EKT policy structure */ + /**< for this stream (if any) */ + unsigned long window_size; /**< The window size to use for replay */ + /**< protection. */ + int allow_repeat_tx; /**< Whether retransmissions of */ + /**< packets with the same sequence */ + /**< number are allowed. */ + /**< (Note that such repeated */ + /**< transmissions must have the same */ + /**< RTP payload, or a severe security */ + /**< weakness is introduced!) */ + int *enc_xtn_hdr; /**< List of header ids to encrypt. */ + int enc_xtn_hdr_count; /**< Number of entries in list of header */ + /**< ids. */ + struct srtp_policy_t *next; /**< Pointer to next stream policy. */ } srtp_policy_t; - - - /** * @brief An srtp_t points to an SRTP session structure. * * The typedef srtp_t is a pointer to a structure that represents - * an SRTP session. This datatype is intentially opaque in + * an SRTP session. This datatype is intentially opaque in * order to separate the interface from the implementation. * * An SRTP session consists of all of the traffic sent to the RTP and @@ -359,17 +358,14 @@ typedef struct srtp_policy_t { * Audio/Video Profile). A session can be viewed as a set of SRTP * streams, each of which originates with a different participant. */ - typedef srtp_ctx_t *srtp_t; - /** - * @brief srtp_init() initializes the srtp library. + * @brief srtp_init() initializes the srtp library. * * @warning This function @b must be called before any other srtp * functions. */ - srtp_err_status_t srtp_init(void); /** @@ -377,20 +373,19 @@ srtp_err_status_t srtp_init(void); * * @warning No srtp functions may be called after calling this function. */ - srtp_err_status_t srtp_shutdown(void); /** * @brief srtp_protect() is the Secure RTP sender-side packet processing * function. - * + * * The function call srtp_protect(ctx, rtp_hdr, len_ptr) applies SRTP * protection to the RTP packet rtp_hdr (which has length *len_ptr) using * the SRTP context ctx. If srtp_err_status_ok is returned, then rtp_hdr * points to the resulting SRTP packet and *len_ptr is the number of * octets in that packet; otherwise, no assumptions should be made * about the value of either data elements. - * + * * The sequence numbers of the RTP packets presented to this function * need not be consecutive, but they @b must be out of order by less * than 2^15 = 32,768 packets. @@ -400,11 +395,11 @@ srtp_err_status_t srtp_shutdown(void); * packet, and assumes that the RTP packet is aligned on a 32-bit * boundary. * - * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN - * into the location in memory immediately following the RTP packet. - * Callers MUST ensure that this much writable memory is available in + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN + * into the location in memory immediately following the RTP packet. + * Callers MUST ensure that this much writable memory is available in * the buffer that holds the RTP packet. - * + * * @param ctx is the SRTP context to use in processing the packet. * * @param rtp_hdr is a pointer to the RTP packet (before the call); after @@ -415,25 +410,24 @@ srtp_err_status_t srtp_shutdown(void); * complete SRTP packet after the call, if srtp_err_status_ok was returned. * Otherwise, the value of the data to which it points is undefined. * - * @return + * @return * - srtp_err_status_ok no problems * - srtp_err_status_replay_fail rtp sequence number was non-increasing * - @e other failure in cryptographic mechanisms */ - srtp_err_status_t srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr); /** * @brief srtp_protect_mki() is the Secure RTP sender-side packet processing * function that can utilize MKI. - * + * * The function call srtp_protect(ctx, rtp_hdr, len_ptr) applies SRTP * protection to the RTP packet rtp_hdr (which has length *len_ptr) using * the SRTP context ctx. If srtp_err_status_ok is returned, then rtp_hdr * points to the resulting SRTP packet and *len_ptr is the number of * octets in that packet; otherwise, no assumptions should be made * about the value of either data elements. - * + * * The sequence numbers of the RTP packets presented to this function * need not be consecutive, but they @b must be out of order by less * than 2^15 = 32,768 packets. @@ -443,11 +437,11 @@ srtp_err_status_t srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr); * packet, and assumes that the RTP packet is aligned on a 32-bit * boundary. * - * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN - * into the location in memory immediately following the RTP packet. - * Callers MUST ensure that this much writable memory is available in + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN + * into the location in memory immediately following the RTP packet. + * Callers MUST ensure that this much writable memory is available in * the buffer that holds the RTP packet. - * + * * @param ctx is the SRTP context to use in processing the packet. * * @param rtp_hdr is a pointer to the RTP packet (before the call); after @@ -458,21 +452,23 @@ srtp_err_status_t srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr); * complete SRTP packet after the call, if srtp_err_status_ok was returned. * Otherwise, the value of the data to which it points is undefined. * - * @param use_mki is a boolean to tell the system if mki is being used. If - * set to false then will use the first set of session keys. If set to true will + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true + * will * use the session keys identified by the mki_index * * @param mki_index integer value specifying which set of session keys should be * used if use_mki is set to true. * - * @return + * @return * - srtp_err_status_ok no problems * - srtp_err_status_replay_fail rtp sequence number was non-increasing * - @e other failure in cryptographic mechanisms */ - -srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, - int *pkt_octet_len, unsigned int use_mki, +srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, + void *rtp_hdr, + int *pkt_octet_len, + unsigned int use_mki, unsigned int mki_index); /** @@ -485,12 +481,12 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, * srtp_err_status_ok is returned, then srtp_hdr points to the resulting * RTP packet and *len_ptr is the number of octets in that packet; * otherwise, no assumptions should be made about the value of either - * data elements. - * + * data elements. + * * The sequence numbers of the RTP packets presented to this function * need not be consecutive, but they @b must be out of order by less * than 2^15 = 32,768 packets. - * + * * @warning This function assumes that the SRTP packet is aligned on a * 32-bit boundary. * @@ -506,16 +502,15 @@ srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, * complete rtp packet after the call, if srtp_err_status_ok was returned. * Otherwise, the value of the data to which it points is undefined. * - * @return + * @return * - srtp_err_status_ok if the RTP packet is valid. - * - srtp_err_status_auth_fail if the SRTP packet failed the message - * authentication check. - * - srtp_err_status_replay_fail if the SRTP packet is a replay (e.g. packet has - * already been processed and accepted). + * - srtp_err_status_auth_fail if the SRTP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTP packet is a replay (e.g. packet + * has already been processed and accepted). * - [other] if there has been an error in the cryptographic mechanisms. * */ - srtp_err_status_t srtp_unprotect(srtp_t ctx, void *srtp_hdr, int *len_ptr); /** @@ -528,12 +523,12 @@ srtp_err_status_t srtp_unprotect(srtp_t ctx, void *srtp_hdr, int *len_ptr); * srtp_err_status_ok is returned, then srtp_hdr points to the resulting * RTP packet and *len_ptr is the number of octets in that packet; * otherwise, no assumptions should be made about the value of either - * data elements. - * + * data elements. + * * The sequence numbers of the RTP packets presented to this function * need not be consecutive, but they @b must be out of order by less * than 2^15 = 32,768 packets. - * + * * @warning This function assumes that the SRTP packet is aligned on a * 32-bit boundary. * @@ -550,52 +545,52 @@ srtp_err_status_t srtp_unprotect(srtp_t ctx, void *srtp_hdr, int *len_ptr); * Otherwise, the value of the data to which it points is undefined. * * @param use_mki is a boolean to tell the system if mki is being used. If - * set to false then will use the first set of session keys. If set to true will + * set to false then will use the first set of session keys. If set to true + * will * use the session keys identified by the mki_index * - * @return + * @return * - srtp_err_status_ok if the RTP packet is valid. - * - srtp_err_status_auth_fail if the SRTP packet failed the message - * authentication check. - * - srtp_err_status_replay_fail if the SRTP packet is a replay (e.g. packet has - * already been processed and accepted). + * - srtp_err_status_auth_fail if the SRTP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTP packet is a replay (e.g. packet + * has already been processed and accepted). * - srtp_err_status_bad_mki if the MKI in the packet is not a known MKI id * - [other] if there has been an error in the cryptographic mechanisms. * */ - -srtp_err_status_t srtp_unprotect_mki(srtp_t ctx, void *srtp_hdr, int *len_ptr, +srtp_err_status_t srtp_unprotect_mki(srtp_t ctx, + void *srtp_hdr, + int *len_ptr, unsigned int use_mki); /** * @brief srtp_create() allocates and initializes an SRTP session. * The function call srtp_create(session, policy) allocates and - * initializes an SRTP session context, applying the given policy. + * initializes an SRTP session context, applying the given policy. * * @param session is a pointer to the SRTP session to which the policy is * to be added. - * + * * @param policy is the srtp_policy_t struct that describes the policy * for the session. The struct may be a single element, or it may be * the head of a list, in which case each element of the list is * processed. It may also be NULL, in which case streams should be added * later using srtp_add_stream(). The final element of the list @b must * have its `next' field set to NULL. - * + * * @return * - srtp_err_status_ok if creation succeded. * - srtp_err_status_alloc_fail if allocation failed. * - srtp_err_status_init_fail if initialization failed. */ - srtp_err_status_t srtp_create(srtp_t *session, const srtp_policy_t *policy); - /** * @brief srtp_add_stream() allocates and initializes an SRTP stream * within a given SRTP session. - * + * * The function call srtp_add_stream(session, policy) allocates and * initializes a new SRTP stream within a given, previously created * session, applying the policy given as the other argument to that @@ -606,13 +601,11 @@ srtp_err_status_t srtp_create(srtp_t *session, const srtp_policy_t *policy); * - srtp_err_status_alloc_fail if stream allocation failed * - srtp_err_status_init_fail if stream initialization failed. */ - srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy); - /** * @brief srtp_remove_stream() deallocates an SRTP stream. - * + * * The function call srtp_remove_stream(session, ssrc) removes * the SRTP stream with the SSRC value ssrc from the SRTP session * context given by the argument session. @@ -625,13 +618,12 @@ srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy); * * @warning Wildcard SSRC values cannot be removed from a * session. - * + * * @return * - srtp_err_status_ok if the stream deallocation succeded. * - [other] otherwise. * */ - srtp_err_status_t srtp_remove_stream(srtp_t session, unsigned int ssrc); /** @@ -658,7 +650,6 @@ srtp_err_status_t srtp_remove_stream(srtp_t session, unsigned int ssrc); * - [other] otherwise. * */ - srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy); /** @@ -682,15 +673,15 @@ srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy); * - [other] otherwise. * */ - -srtp_err_status_t srtp_update_stream(srtp_t session, const srtp_policy_t *policy); +srtp_err_status_t srtp_update_stream(srtp_t session, + const srtp_policy_t *policy); /** * @brief srtp_crypto_policy_set_rtp_default() sets a crypto policy * structure to the SRTP default policy for RTP protection. * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call crypto_policy_set_rtp_default(&p) sets the * crypto_policy_t at location p to the SRTP default policy for RTP * protection, as defined in the specification. This function is a @@ -699,19 +690,18 @@ srtp_err_status_t srtp_update_stream(srtp_t session, const srtp_policy_t *policy * with this function call. Doing so may allow your code to be * forward compatible with later versions of libSRTP that include more * elements in the crypto_policy_t datatype. - * + * * @return void. - * + * */ - void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p); /** * @brief srtp_crypto_policy_set_rtcp_default() sets a crypto policy * structure to the SRTP default policy for RTCP protection. * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_rtcp_default(&p) sets the * srtp_crypto_policy_t at location p to the SRTP default policy for RTCP * protection, as defined in the specification. This function is a @@ -720,37 +710,35 @@ void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p); * with this function call. Doing so may allow your code to be * forward compatible with later versions of libSRTP that include more * elements in the srtp_crypto_policy_t datatype. - * + * * @return void. - * + * */ - void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p); /** * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() sets a crypto * policy structure to the SRTP default policy for RTP protection. * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80() is a * synonym for srtp_crypto_policy_set_rtp_default(). It conforms to the * naming convention used in RFC 4568 (SDP Security Descriptions for * Media Streams). - * + * * @return void. - * + * */ - -#define srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(p) srtp_crypto_policy_set_rtp_default(p) - +#define srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(p) \ + srtp_crypto_policy_set_rtp_default(p) /** * @brief srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32() sets a crypto * policy structure to a short-authentication tag policy * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&p) * sets the srtp_crypto_policy_t at location p to use policy * AES_CM_128_HMAC_SHA1_32 as defined in RFC 4568. @@ -760,7 +748,7 @@ void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p); * considered adequate only for protecting audio and video media that * use a stateless playback function. See Section 7.5 of RFC 3711 * (http://www.ietf.org/rfc/rfc3711.txt). - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -773,25 +761,22 @@ void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p); * (http://www.ietf.org/rfc/rfc3711.txt). * * @return void. - * + * */ - void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p); - - /** * @brief srtp_crypto_policy_set_aes_cm_128_null_auth() sets a crypto * policy structure to an encryption-only policy * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_cm_128_null_auth(&p) sets * the srtp_crypto_policy_t at location p to use the SRTP default cipher * (AES-128 Counter Mode), but to use no authentication method. This * policy is NOT RECOMMENDED unless it is unavoidable; see Section 7.5 * of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -803,24 +788,22 @@ void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p); * Section 7.5 of RFC 3711 (http://www.ietf.org/rfc/rfc3711.txt). * * @return void. - * + * */ - void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p); - /** * @brief srtp_crypto_policy_set_null_cipher_hmac_sha1_80() sets a crypto * policy structure to an authentication-only policy * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_null_cipher_hmac_sha1_80(&p) * sets the srtp_crypto_policy_t at location p to use HMAC-SHA1 with an 80 * bit authentication tag to provide message authentication, but to * use no encryption. This policy is NOT RECOMMENDED for SRTP unless - * there is a requirement to forego encryption. - * + * there is a requirement to forego encryption. + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -828,24 +811,24 @@ void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @warning This policy is NOT RECOMMENDED for SRTP unless there is a - * requirement to forego encryption. + * requirement to forego encryption. * * @return void. - * + * */ void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p); /** * @brief srtp_crypto_policy_set_null_cipher_hmac_null() sets a crypto - * policy structure to use no encryption or authentication. + * policy structure to use no encryption or authentication. + * + * @param p is a pointer to the policy structure to be set * - * @param p is a pointer to the policy structure to be set - * * The function call srtp_crypto_policy_set_null_cipher_hmac_null(&p) * sets the srtp_crypto_policy_t at location p to use no encryption and * no authentication. This policy should only be used for testing and - * troubleshootingl. - * + * troubleshootingl. + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -853,27 +836,26 @@ void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @warning This policy is NOT RECOMMENDED for SRTP unless there is a - * requirement to forego encryption and authentication. + * requirement to forego encryption and authentication. * * @return void. - * + * */ void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p); - /** * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80() sets a crypto - * policy structure to a encryption and authentication policy using AES-256 + * policy structure to a encryption and authentication policy using AES-256 * for RTP protection. * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&p) * sets the srtp_crypto_policy_t at location p to use policy * AES_CM_256_HMAC_SHA1_80 as defined in RFC 6188. This policy uses AES-256 * Counter Mode encryption and HMAC-SHA1 authentication, with an 80 bit * authentication tag. - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -881,19 +863,17 @@ void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @return void. - * + * */ - void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p); - /** * @brief srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32() sets a crypto * policy structure to a short-authentication tag policy using AES-256 * encryption. * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(&p) * sets the srtp_crypto_policy_t at location p to use policy * AES_CM_256_HMAC_SHA1_32 as defined in RFC 6188. This policy uses AES-256 @@ -902,7 +882,7 @@ void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p); * considered adequate only for protecting audio and video media that * use a stateless playback function. See Section 7.5 of RFC 3711 * (http://www.ietf.org/rfc/rfc3711.txt). - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -915,9 +895,8 @@ void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p); * (http://www.ietf.org/rfc/rfc3711.txt). * * @return void. - * + * */ - void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p); /** @@ -947,7 +926,6 @@ void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p); */ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p); - /** * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80() sets a crypto * policy structure to a encryption and authentication policy using AES-192 @@ -972,7 +950,6 @@ void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p); */ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p); - /** * @brief srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32() sets a crypto * policy structure to a short-authentication tag policy using AES-192 @@ -1005,7 +982,6 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p); */ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p); - /** * @brief srtp_crypto_policy_set_aes_cm_192_null_auth() sets a crypto * policy structure to an encryption-only policy @@ -1033,19 +1009,18 @@ void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p); */ void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p); - /** * @brief srtp_crypto_policy_set_aes_gcm_128_8_auth() sets a crypto * policy structure to an AEAD encryption policy. * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_gcm_128_8_auth(&p) sets * the srtp_crypto_policy_t at location p to use the SRTP default cipher * (AES-128 Galois Counter Mode) with 8 octet auth tag. This * policy applies confidentiality and authentication to both the * RTP and RTCP packets. - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -1053,7 +1028,7 @@ void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @return void. - * + * */ void srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t *p); @@ -1061,14 +1036,14 @@ void srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t *p); * @brief srtp_crypto_policy_set_aes_gcm_256_8_auth() sets a crypto * policy structure to an AEAD encryption policy * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_gcm_256_8_auth(&p) sets * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-256 Galois Counter Mode) with 8 octet auth tag. This + * (AES-256 Galois Counter Mode) with 8 octet auth tag. This * policy applies confidentiality and authentication to both the * RTP and RTCP packets. - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -1076,7 +1051,7 @@ void srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @return void. - * + * */ void srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t *p); @@ -1084,14 +1059,14 @@ void srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t *p); * @brief srtp_crypto_policy_set_aes_gcm_128_8_only_auth() sets a crypto * policy structure to an AEAD authentication-only policy * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_gcm_128_8_only_auth(&p) sets * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-128 Galois Counter Mode) with 8 octet auth tag. This policy - * applies confidentiality and authentication to the RTP packets, + * (AES-128 Galois Counter Mode) with 8 octet auth tag. This policy + * applies confidentiality and authentication to the RTP packets, * but only authentication to the RTCP packets. - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -1099,7 +1074,7 @@ void srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @return void. - * + * */ void srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t *p); @@ -1107,14 +1082,14 @@ void srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t *p); * @brief srtp_crypto_policy_set_aes_gcm_256_8_only_auth() sets a crypto * policy structure to an AEAD authentication-only policy * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_gcm_256_8_only_auth(&p) sets * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-256 Galois Counter Mode) with 8 octet auth tag. This policy - * applies confidentiality and authentication to the RTP packets, + * (AES-256 Galois Counter Mode) with 8 octet auth tag. This policy + * applies confidentiality and authentication to the RTP packets, * but only authentication to the RTCP packets. - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -1122,7 +1097,7 @@ void srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @return void. - * + * */ void srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t *p); @@ -1130,14 +1105,14 @@ void srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t *p); * @brief srtp_crypto_policy_set_aes_gcm_128_16_auth() sets a crypto * policy structure to an AEAD encryption policy. * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_gcm_128_16_auth(&p) sets * the srtp_crypto_policy_t at location p to use the SRTP default cipher * (AES-128 Galois Counter Mode) with 16 octet auth tag. This * policy applies confidentiality and authentication to both the * RTP and RTCP packets. - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -1145,7 +1120,7 @@ void srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @return void. - * + * */ void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p); @@ -1153,14 +1128,14 @@ void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p); * @brief srtp_crypto_policy_set_aes_gcm_256_16_auth() sets a crypto * policy structure to an AEAD encryption policy * - * @param p is a pointer to the policy structure to be set - * + * @param p is a pointer to the policy structure to be set + * * The function call srtp_crypto_policy_set_aes_gcm_256_16_auth(&p) sets * the srtp_crypto_policy_t at location p to use the SRTP default cipher - * (AES-256 Galois Counter Mode) with 16 octet auth tag. This + * (AES-256 Galois Counter Mode) with 16 octet auth tag. This * policy applies confidentiality and authentication to both the * RTP and RTCP packets. - * + * * This function is a convenience that helps to avoid dealing directly * with the policy data structure. You are encouraged to initialize * policy elements with this function call. Doing so may allow your @@ -1168,15 +1143,14 @@ void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p); * include more elements in the srtp_crypto_policy_t datatype. * * @return void. - * + * */ void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p); - /** * @brief srtp_dealloc() deallocates storage for an SRTP session * context. - * + * * The function call srtp_dealloc(s) deallocates storage for the * SRTP session context s. This function should be called no more * than one time for each of the contexts allocated by the function @@ -1188,30 +1162,26 @@ void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p); * - srtp_err_status_ok if there no problems. * - srtp_err_status_dealloc_fail a memory deallocation failure occured. */ - srtp_err_status_t srtp_dealloc(srtp_t s); - /* - * @brief identifies a particular SRTP profile + * @brief identifies a particular SRTP profile * * An srtp_profile_t enumeration is used to identify a particular SRTP * profile (that is, a set of algorithms and parameters). These profiles * are defined for DTLS-SRTP: * https://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml */ - typedef enum { - srtp_profile_reserved = 0, - srtp_profile_aes128_cm_sha1_80 = 1, - srtp_profile_aes128_cm_sha1_32 = 2, - srtp_profile_null_sha1_80 = 5, - srtp_profile_null_sha1_32 = 6, - srtp_profile_aead_aes_128_gcm = 7, - srtp_profile_aead_aes_256_gcm = 8, + srtp_profile_reserved = 0, + srtp_profile_aes128_cm_sha1_80 = 1, + srtp_profile_aes128_cm_sha1_32 = 2, + srtp_profile_null_sha1_80 = 5, + srtp_profile_null_sha1_32 = 6, + srtp_profile_aead_aes_128_gcm = 7, + srtp_profile_aead_aes_256_gcm = 8, } srtp_profile_t; - /** * @brief srtp_crypto_policy_set_from_profile_for_rtp() sets a crypto policy * structure to the appropriate value for RTP based on an srtp_profile_t @@ -1232,13 +1202,12 @@ typedef enum { * * @return values * - srtp_err_status_ok no problems were encountered - * - srtp_err_status_bad_param the profile is not supported + * - srtp_err_status_bad_param the profile is not supported * */ -srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp(srtp_crypto_policy_t *policy, srtp_profile_t profile); - - - +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile); /** * @brief srtp_crypto_policy_set_from_profile_for_rtcp() sets a crypto policy @@ -1263,48 +1232,43 @@ srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp(srtp_crypto_policy * - srtp_err_status_bad_param the profile is not supported * */ -srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp(srtp_crypto_policy_t *policy, srtp_profile_t profile); +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile); /** * @brief returns the master key length for a given SRTP profile */ -unsigned int -srtp_profile_get_master_key_length(srtp_profile_t profile); - +unsigned int srtp_profile_get_master_key_length(srtp_profile_t profile); /** * @brief returns the master salt length for a given SRTP profile */ -unsigned int -srtp_profile_get_master_salt_length(srtp_profile_t profile); +unsigned int srtp_profile_get_master_salt_length(srtp_profile_t profile); /** * @brief appends the salt to the key * - * The function call srtp_append_salt_to_key(k, klen, s, slen) + * The function call srtp_append_salt_to_key(k, klen, s, slen) * copies the string s to the location at klen bytes following - * the location k. + * the location k. * * @warning There must be at least bytes_in_salt + bytes_in_key bytes * available at the location pointed to by key. - * + * */ - -void -srtp_append_salt_to_key(unsigned char *key, unsigned int bytes_in_key, - unsigned char *salt, unsigned int bytes_in_salt); - - +void srtp_append_salt_to_key(unsigned char *key, + unsigned int bytes_in_key, + unsigned char *salt, + unsigned int bytes_in_salt); /** * @} */ - - /** * @defgroup SRTCP Secure RTCP - * @ingroup SRTP + * @ingroup SRTP * * @brief Secure RTCP functions are used to protect RTCP traffic. * @@ -1312,36 +1276,36 @@ srtp_append_salt_to_key(unsigned char *key, unsigned int bytes_in_key, * traffic in much the same way as it does RTP traffic. The function * srtp_protect_rtcp() applies cryptographic protections to outbound * RTCP packets, and srtp_unprotect_rtcp() verifies the protections on - * inbound RTCP packets. + * inbound RTCP packets. * * A note on the naming convention: srtp_protect_rtcp() has an srtp_t * as its first argument, and thus has `srtp_' as its prefix. The - * trailing `_rtcp' indicates the protocol on which it acts. - * + * trailing `_rtcp' indicates the protocol on which it acts. + * * @{ */ /** * @brief srtp_protect_rtcp() is the Secure RTCP sender-side packet * processing function. - * + * * The function call srtp_protect_rtcp(ctx, rtp_hdr, len_ptr) applies * SRTCP protection to the RTCP packet rtcp_hdr (which has length * *len_ptr) using the SRTP session context ctx. If srtp_err_status_ok is * returned, then rtp_hdr points to the resulting SRTCP packet and * *len_ptr is the number of octets in that packet; otherwise, no * assumptions should be made about the value of either data elements. - * + * * @warning This function assumes that it can write the authentication * tag into the location in memory immediately following the RTCP * packet, and assumes that the RTCP packet is aligned on a 32-bit * boundary. * - * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4 - * into the location in memory immediately following the RTCP packet. - * Callers MUST ensure that this much writable memory is available in + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4 + * into the location in memory immediately following the RTCP packet. + * Callers MUST ensure that this much writable memory is available in * the buffer that holds the RTCP packet. - * + * * @param ctx is the SRTP context to use in processing the packet. * * @param rtcp_hdr is a pointer to the RTCP packet (before the call); after @@ -1353,37 +1317,36 @@ srtp_append_salt_to_key(unsigned char *key, unsigned int bytes_in_key, * was returned. Otherwise, the value of the data to which it points * is undefined. * - * @return + * @return * - srtp_err_status_ok if there were no problems. - * - [other] if there was a failure in + * - [other] if there was a failure in * the cryptographic mechanisms. */ - - -srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len); - +srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, + void *rtcp_hdr, + int *pkt_octet_len); /** * @brief srtp_protect_rtcp_mki() is the Secure RTCP sender-side packet * processing function that can utilize mki. - * + * * The function call srtp_protect_rtcp(ctx, rtp_hdr, len_ptr) applies * SRTCP protection to the RTCP packet rtcp_hdr (which has length * *len_ptr) using the SRTP session context ctx. If srtp_err_status_ok is * returned, then rtp_hdr points to the resulting SRTCP packet and * *len_ptr is the number of octets in that packet; otherwise, no * assumptions should be made about the value of either data elements. - * + * * @warning This function assumes that it can write the authentication * tag into the location in memory immediately following the RTCP * packet, and assumes that the RTCP packet is aligned on a 32-bit * boundary. * - * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4 - * into the location in memory immediately following the RTCP packet. - * Callers MUST ensure that this much writable memory is available in + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4 + * into the location in memory immediately following the RTCP packet. + * Callers MUST ensure that this much writable memory is available in * the buffer that holds the RTCP packet. - * + * * @param ctx is the SRTP context to use in processing the packet. * * @param rtcp_hdr is a pointer to the RTCP packet (before the call); after @@ -1395,21 +1358,24 @@ srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_l * was returned. Otherwise, the value of the data to which it points * is undefined. * - * @param use_mki is a boolean to tell the system if mki is being used. If - * set to false then will use the first set of session keys. If set to true will + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true + * will * use the session keys identified by the mki_index * * @param mki_index integer value specifying which set of session kesy should be * used if use_mki is set to true. * - * @return + * @return * - srtp_err_status_ok if there were no problems. - * - [other] if there was a failure in + * - [other] if there was a failure in * the cryptographic mechanisms. */ - -srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, - unsigned int use_mki, unsigned int mki_index); +srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, + void *rtcp_hdr, + int *pkt_octet_len, + unsigned int use_mki, + unsigned int mki_index); /** * @brief srtp_unprotect_rtcp() is the Secure RTCP receiver-side packet @@ -1422,7 +1388,7 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_oct * to the resulting RTCP packet and *len_ptr is the number of octets * in that packet; otherwise, no assumptions should be made about the * value of either data elements. - * + * * @warning This function assumes that the SRTCP packet is aligned on a * 32-bit boundary. * @@ -1440,17 +1406,18 @@ srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_oct * returned. Otherwise, the value of the data to which it points is * undefined. * - * @return + * @return * - srtp_err_status_ok if the RTCP packet is valid. - * - srtp_err_status_auth_fail if the SRTCP packet failed the message + * - srtp_err_status_auth_fail if the SRTCP packet failed the message * authentication check. * - srtp_err_status_replay_fail if the SRTCP packet is a replay (e.g. has * already been processed and accepted). * - [other] if there has been an error in the cryptographic mechanisms. * */ - -srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len); +srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, + void *srtcp_hdr, + int *pkt_octet_len); /** * @brief srtp_unprotect_rtcp() is the Secure RTCP receiver-side packet @@ -1463,7 +1430,7 @@ srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octe * to the resulting RTCP packet and *len_ptr is the number of octets * in that packet; otherwise, no assumptions should be made about the * value of either data elements. - * + * * @warning This function assumes that the SRTCP packet is aligned on a * 32-bit boundary. * @@ -1482,21 +1449,23 @@ srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octe * undefined. * * @param use_mki is a boolean to tell the system if mki is being used. If - * set to false then will use the first set of session keys. If set to true will - * use the session keys identified by the mki_index + * set to false then will use the first set of session keys. If set to true + * will use the session keys identified by the mki_index * - * @return + * @return * - srtp_err_status_ok if the RTCP packet is valid. - * - srtp_err_status_auth_fail if the SRTCP packet failed the message - * authentication check. + * - srtp_err_status_auth_fail if the SRTCP packet failed the message + * authentication check. * - srtp_err_status_replay_fail if the SRTCP packet is a replay (e.g. has - * already been processed and accepted). - * - srtp_err_status_bad_mki if the MKI in the packet is not a known MKI id - * - [other] if there has been an error in the cryptographic mechanisms. + * already been processed and accepted). + * - srtp_err_status_bad_mki if the MKI in the packet is not a known MKI + * id + * - [other] if there has been an error in the + * cryptographic mechanisms. * */ - -srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, +srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, + void *srtcp_hdr, int *pkt_octet_len, unsigned int use_mki); @@ -1504,7 +1473,6 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, * @} */ - /** * @defgroup User data associated to a SRTP session. * @ingroup SRTP @@ -1527,9 +1495,7 @@ srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, * @return void. * */ - -void -srtp_set_user_data(srtp_t ctx, void *data); +void srtp_set_user_data(srtp_t ctx, void *data); /** * @brief srtp_get_user_data() retrieves the pointer to the custom data @@ -1546,23 +1512,20 @@ srtp_set_user_data(srtp_t ctx, void *data); * @return void* pointer to the user data. * */ - -void* -srtp_get_user_data(srtp_t ctx); +void *srtp_get_user_data(srtp_t ctx); /** * @} */ - /** * @defgroup SRTPevents SRTP events and callbacks * @ingroup SRTP * - * @brief libSRTP can use a user-provided callback function to + * @brief libSRTP can use a user-provided callback function to * handle events. * - * + * * libSRTP allows a user to provide a callback function to handle * events that need to be dealt with outside of the data plane (see * the enum srtp_event_t for a description of these events). Dealing @@ -1583,8 +1546,8 @@ srtp_get_user_data(srtp_t ctx); * @brief srtp_event_t defines events that need to be handled * * The enum srtp_event_t defines events that need to be handled - * outside the `data plane', such as SSRC collisions and - * key expirations. + * outside the `data plane', such as SSRC collisions and + * key expirations. * * When a key expires or the maximum number of packets has been * reached, an SRTP stream will enter an `expired' state in which no @@ -1596,34 +1559,28 @@ srtp_get_user_data(srtp_t ctx); * are unaffected, unless key sharing is used by that stream. In the * latter case, all of the streams in the session will expire. */ - -typedef enum { - event_ssrc_collision, /**< - * An SSRC collision occured. - */ - event_key_soft_limit, /**< An SRTP stream reached the soft key - * usage limit and will expire soon. - */ - event_key_hard_limit, /**< An SRTP stream reached the hard - * key usage limit and has expired. - */ - event_packet_index_limit /**< An SRTP stream reached the hard - * packet limit (2^48 packets). - */ +typedef enum { + event_ssrc_collision, /**< An SSRC collision occured. */ + event_key_soft_limit, /**< An SRTP stream reached the soft key */ + /**< usage limit and will expire soon. */ + event_key_hard_limit, /**< An SRTP stream reached the hard */ + /**< key usage limit and has expired. */ + event_packet_index_limit /**< An SRTP stream reached the hard */ + /**< packet limit (2^48 packets). */ } srtp_event_t; /** - * @brief srtp_event_data_t is the structure passed as a callback to + * @brief srtp_event_data_t is the structure passed as a callback to * the event handler function * * The struct srtp_event_data_t holds the data passed to the event - * handler function. + * handler function. */ - typedef struct srtp_event_data_t { - srtp_t session; /**< The session in which the event happend. */ - uint32_t ssrc; /**< The ssrc in host order of the stream in which the event happend */ - srtp_event_t event; /**< An enum indicating the type of event. */ + srtp_t session; /**< The session in which the event happend. */ + uint32_t ssrc; /**< The ssrc in host order of the stream in which */ + /**< the event happend */ + srtp_event_t event; /**< An enum indicating the type of event. */ } srtp_event_data_t; /** @@ -1636,12 +1593,11 @@ typedef struct srtp_event_data_t { * There can only be a single, global handler for all events in * libSRTP. */ - -typedef void (srtp_event_handler_func_t)(srtp_event_data_t *data); +typedef void(srtp_event_handler_func_t)(srtp_event_data_t *data); /** * @brief sets the event handler to the function supplied by the caller. - * + * * The function call srtp_install_event_handler(func) sets the event * handler function to the value func. The value NULL is acceptable * as an argument; in this case, events will be ignored rather than @@ -1651,24 +1607,23 @@ typedef void (srtp_event_handler_func_t)(srtp_event_data_t *data); * pointer as an argument and returns void. This function * will be used by libSRTP to handle events. */ - srtp_err_status_t srtp_install_event_handler(srtp_event_handler_func_t func); /** - * @brief Returns the version string of the library. - * + * @brief Returns the version string of the library. + * */ const char *srtp_get_version_string(void); /** - * @brief Returns the numeric representation of the library version. - * + * @brief Returns the numeric representation of the library version. + * */ unsigned int srtp_get_version(void); /** * @brief srtp_set_debug_module(mod_name, v) - * + * * sets dynamic debugging to the value v (0 for off, 1 for on) for the * debug module with the name mod_name * @@ -1706,7 +1661,9 @@ typedef enum { * There can only be a single, global handler for all log messages in * libSRTP. */ -typedef void (srtp_log_handler_func_t)(srtp_log_level_t level, const char * msg, void *data); +typedef void(srtp_log_handler_func_t)(srtp_log_level_t level, + const char *msg, + void *data); /** * @brief sets the log handler to the function supplied by the caller. @@ -1719,34 +1676,44 @@ typedef void (srtp_log_handler_func_t)(srtp_log_level_t level, const char * msg, * * @param func is a pointer to a fuction of type srtp_log_handler_func_t. * This function will be used by libSRTP to output log messages. - * @param data is a user pointer that will be returned as the data argument in func. + * @param data is a user pointer that will be returned as the data argument in + * func. */ -srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func, void *data); +srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func, + void *data); /** * @brief srtp_get_protect_trailer_length(session, use_mki, mki_index, length) * - * Determines the length of the amount of data Lib SRTP will add to the - * packet during the protect process. The length is returned in the length parameter + * Determines the length of the amount of data Lib SRTP will add to the + * packet during the protect process. The length is returned in the length + * parameter * - * returns err_status_ok on success, err_status_bad_mki if the MKI index is invalid + * returns err_status_ok on success, err_status_bad_mki if the MKI index is + * invalid * */ -srtp_err_status_t srtp_get_protect_trailer_length(srtp_t session, uint32_t use_mki, - uint32_t mki_index, uint32_t *length); +srtp_err_status_t srtp_get_protect_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length); /** - * @brief srtp_get_protect_rtcp_trailer_length(session, use_mki, mki_index, length) + * @brief srtp_get_protect_rtcp_trailer_length(session, use_mki, mki_index, + * length) * - * Determines the length of the amount of data Lib SRTP will add to the - * packet during the protect process. The length is returned in the length parameter + * Determines the length of the amount of data Lib SRTP will add to the + * packet during the protect process. The length is returned in the length + * parameter * - * returns err_status_ok on success, err_status_bad_mki if the MKI index is invalid + * returns err_status_ok on success, err_status_bad_mki if the MKI index is + * invalid * */ -srtp_err_status_t srtp_get_protect_rtcp_trailer_length(srtp_t session, uint32_t use_mki, - uint32_t mki_index, uint32_t *length); - +srtp_err_status_t srtp_get_protect_rtcp_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length); /** * @brief srtp_set_stream_roc(session, ssrc, roc) @@ -1757,7 +1724,9 @@ srtp_err_status_t srtp_get_protect_rtcp_trailer_length(srtp_t session, uint32_t * stream found * */ -srtp_err_status_t srtp_set_stream_roc(srtp_t session, uint32_t ssrc, uint32_t roc); +srtp_err_status_t srtp_set_stream_roc(srtp_t session, + uint32_t ssrc, + uint32_t roc); /** * @brief srtp_get_stream_roc(session, ssrc, roc) @@ -1768,14 +1737,17 @@ srtp_err_status_t srtp_set_stream_roc(srtp_t session, uint32_t ssrc, uint32_t ro * stream found * */ -srtp_err_status_t srtp_get_stream_roc(srtp_t session, uint32_t ssrc, uint32_t *roc); - +srtp_err_status_t srtp_get_stream_roc(srtp_t session, + uint32_t ssrc, + uint32_t *roc); /** * @} */ + /* in host order, so outside the #if */ -#define SRTCP_E_BIT 0x80000000 +#define SRTCP_E_BIT 0x80000000 + /* for byte-access */ #define SRTCP_E_BYTE_BIT 0x80 #define SRTCP_INDEX_MASK 0x7fffffff diff --git a/libs/srtp/include/srtp_priv.h b/libs/srtp/include/srtp_priv.h index 5d84161407..82116f3b86 100644 --- a/libs/srtp/include/srtp_priv.h +++ b/libs/srtp/include/srtp_priv.h @@ -7,26 +7,26 @@ * 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 @@ -62,14 +62,14 @@ extern "C" { #endif -#define SRTP_VER_STRING PACKAGE_STRING -#define SRTP_VERSION PACKAGE_VERSION +#define SRTP_VER_STRING PACKAGE_STRING +#define SRTP_VERSION PACKAGE_VERSION typedef struct srtp_stream_ctx_t_ srtp_stream_ctx_t; typedef srtp_stream_ctx_t *srtp_stream_t; /* - * the following declarations are libSRTP internal functions + * the following declarations are libSRTP internal functions */ /* @@ -78,7 +78,6 @@ typedef srtp_stream_ctx_t *srtp_stream_t; */ srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc); - /* * srtp_stream_init_keys(s, k) (re)initializes the srtp_stream_t s by * deriving all of the needed keys using the KDF and the key k. @@ -88,29 +87,29 @@ srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const unsigned int current_mki_index); /* - * srtp_stream_init_all_master_keys(s, k, m) (re)initializes the srtp_stream_t s by - * deriving all of the needed keys for all the master keys using the KDF and the keys from k. + * srtp_stream_init_all_master_keys(s, k, m) (re)initializes the srtp_stream_t s + * by deriving all of the needed keys for all the master keys using the KDF and + * the keys from k. */ -srtp_err_status_t srtp_steam_init_all_master_keys(srtp_stream_ctx_t *srtp, - unsigned char *key, - srtp_master_key_t **keys, - const unsigned int max_master_keys); +srtp_err_status_t srtp_steam_init_all_master_keys( + srtp_stream_ctx_t *srtp, + unsigned char *key, + srtp_master_key_t **keys, + const unsigned int max_master_keys); /* - * srtp_stream_init(s, p) initializes the srtp_stream_t s to + * srtp_stream_init(s, p) initializes the srtp_stream_t s to * use the policy at the location p */ srtp_err_status_t srtp_stream_init(srtp_stream_t srtp, const srtp_policy_t *p); - /* - * libsrtp internal datatypes + * libsrtp internal datatypes */ - -typedef enum direction_t { - dir_unknown = 0, - dir_srtp_sender = 1, - dir_srtp_receiver = 2 +typedef enum direction_t { + dir_unknown = 0, + dir_srtp_sender = 1, + dir_srtp_receiver = 2 } direction_t; /* @@ -119,56 +118,52 @@ typedef enum direction_t { * MKI ID which is used to identify the session keys. */ typedef struct srtp_session_keys_t { - srtp_cipher_t *rtp_cipher; - srtp_cipher_t *rtp_xtn_hdr_cipher; - srtp_auth_t *rtp_auth; - srtp_cipher_t *rtcp_cipher; - srtp_auth_t *rtcp_auth; - uint8_t salt[SRTP_AEAD_SALT_LEN]; - uint8_t c_salt[SRTP_AEAD_SALT_LEN]; - uint8_t *mki_id; - unsigned int mki_size; - srtp_key_limit_ctx_t *limit; + srtp_cipher_t *rtp_cipher; + srtp_cipher_t *rtp_xtn_hdr_cipher; + srtp_auth_t *rtp_auth; + srtp_cipher_t *rtcp_cipher; + srtp_auth_t *rtcp_auth; + uint8_t salt[SRTP_AEAD_SALT_LEN]; + uint8_t c_salt[SRTP_AEAD_SALT_LEN]; + uint8_t *mki_id; + unsigned int mki_size; + srtp_key_limit_ctx_t *limit; } srtp_session_keys_t; - -/* +/* * an srtp_stream_t has its own SSRC, encryption key, authentication * key, sequence number, and replay database - * + * * note that the keys might not actually be unique, in which case the * srtp_cipher_t and srtp_auth_t pointers will point to the same structures */ - typedef struct srtp_stream_ctx_t_ { - uint32_t ssrc; - srtp_session_keys_t *session_keys; - unsigned int num_master_keys; - srtp_rdbx_t rtp_rdbx; - srtp_sec_serv_t rtp_services; - srtp_rdb_t rtcp_rdb; - srtp_sec_serv_t rtcp_services; - direction_t direction; - int allow_repeat_tx; - srtp_ekt_stream_t ekt; - int *enc_xtn_hdr; - int enc_xtn_hdr_count; - uint32_t pending_roc; - struct srtp_stream_ctx_t_ *next; /* linked list of streams */ + uint32_t ssrc; + srtp_session_keys_t *session_keys; + unsigned int num_master_keys; + srtp_rdbx_t rtp_rdbx; + srtp_sec_serv_t rtp_services; + srtp_rdb_t rtcp_rdb; + srtp_sec_serv_t rtcp_services; + direction_t direction; + int allow_repeat_tx; + srtp_ekt_stream_t ekt; + int *enc_xtn_hdr; + int enc_xtn_hdr_count; + uint32_t pending_roc; + struct srtp_stream_ctx_t_ *next; /* linked list of streams */ } strp_stream_ctx_t_; - /* * an srtp_ctx_t holds a stream list and a service description */ - typedef struct srtp_ctx_t_ { - struct srtp_stream_ctx_t_ *stream_list; /* linked list of streams */ - struct srtp_stream_ctx_t_ *stream_template; /* act as template for other streams */ - void *user_data; /* user custom data */ + struct srtp_stream_ctx_t_ *stream_list; /* linked list of streams */ + struct srtp_stream_ctx_t_ *stream_template; /* act as template for other */ + /* streams */ + void *user_data; /* user custom data */ } srtp_ctx_t_; - /* * srtp_hdr_t represents an RTP or SRTP header. The bit-fields in * this structure should be declared "unsigned int" instead of @@ -181,10 +176,6 @@ typedef struct srtp_ctx_t_ { * is not identical) */ -#ifdef _MSC_VER -#pragma pack(push, r1, 1) -#endif - #ifndef WORDS_BIGENDIAN typedef struct { @@ -194,9 +185,9 @@ typedef struct { unsigned version : 2; /* protocol version */ unsigned pt : 7; /* payload type */ unsigned m : 1; /* marker bit */ - unsigned seq : 16; /* sequence number */ - unsigned ts : 32; /* timestamp */ - uint32_t ssrc; /* synchronization source */ + uint16_t seq; /* sequence number */ + uint32_t ts; /* timestamp */ + uint32_t ssrc; /* synchronization source */ } srtp_hdr_t; #else /* BIG_ENDIAN */ @@ -208,19 +199,18 @@ typedef struct { unsigned cc : 4; /* CSRC count */ unsigned m : 1; /* marker bit */ unsigned pt : 7; /* payload type */ - unsigned seq: 16; /* sequence number */ - unsigned ts : 32; /* timestamp */ - uint32_t ssrc; /* synchronization source */ + uint16_t seq; /* sequence number */ + uint32_t ts; /* timestamp */ + uint32_t ssrc; /* synchronization source */ } srtp_hdr_t; #endif typedef struct { - uint16_t profile_specific; /* profile-specific info */ - uint16_t length; /* number of 32-bit words in extension */ + uint16_t profile_specific; /* profile-specific info */ + uint16_t length; /* number of 32-bit words in extension */ } srtp_hdr_xtnd_t; - /* * srtcp_hdr_t represents a secure rtcp header * @@ -231,61 +221,57 @@ typedef struct { #ifndef WORDS_BIGENDIAN typedef struct { - unsigned rc : 5; /* reception report count */ - unsigned p : 1; /* padding flag */ - unsigned version : 2; /* protocol version */ - unsigned pt : 8; /* payload type */ - unsigned len : 16; /* length */ + unsigned rc : 5; /* reception report count */ + unsigned p : 1; /* padding flag */ + unsigned version : 2; /* protocol version */ + unsigned pt : 8; /* payload type */ + uint16_t len; /* length */ uint32_t ssrc; /* synchronization source */ } srtcp_hdr_t; typedef struct { - unsigned int index : 31; /* srtcp packet index in network order! */ - unsigned int e : 1; /* encrypted? 1=yes */ - /* optional mikey/etc go here */ - /* and then the variable-length auth tag */ + unsigned int index : 31; /* srtcp packet index in network order! */ + unsigned int e : 1; /* encrypted? 1=yes */ + /* optional mikey/etc go here */ + /* and then the variable-length auth tag */ } srtcp_trailer_t; #else /* BIG_ENDIAN */ typedef struct { - unsigned version : 2; /* protocol version */ - unsigned p : 1; /* padding flag */ - unsigned rc : 5; /* reception report count */ - unsigned pt : 8; /* payload type */ - unsigned len : 16; /* length */ + unsigned version : 2; /* protocol version */ + unsigned p : 1; /* padding flag */ + unsigned rc : 5; /* reception report count */ + unsigned pt : 8; /* payload type */ + uint16_t len; /* length */ uint32_t ssrc; /* synchronization source */ } srtcp_hdr_t; typedef struct { - unsigned int e : 1; /* encrypted? 1=yes */ - unsigned int index : 31; /* srtcp packet index */ - /* optional mikey/etc go here */ - /* and then the variable-length auth tag */ + unsigned int e : 1; /* encrypted? 1=yes */ + unsigned int index : 31; /* srtcp packet index */ + /* optional mikey/etc go here */ + /* and then the variable-length auth tag */ } srtcp_trailer_t; #endif -#ifdef _MSC_VER -#pragma pack(pop, r1) -#endif - /* * srtp_handle_event(srtp, srtm, evnt) calls the event handling * function, if there is one. * - * This macro is not included in the documentation as it is + * This macro is not included in the documentation as it is * an internal-only function. */ -#define srtp_handle_event(srtp, strm, evnt) \ - if(srtp_event_handler) { \ - srtp_event_data_t data; \ - data.session = srtp; \ - data.ssrc = ntohl(strm->ssrc); \ - data.event = evnt; \ - srtp_event_handler(&data); \ -} +#define srtp_handle_event(srtp, strm, evnt) \ + if (srtp_event_handler) { \ + srtp_event_data_t data; \ + data.session = srtp; \ + data.ssrc = ntohl(strm->ssrc); \ + data.event = evnt; \ + srtp_event_handler(&data); \ + } #ifdef __cplusplus } diff --git a/libs/srtp/include/ut_sim.h b/libs/srtp/include/ut_sim.h index d5c04baee7..e678b5fdf7 100644 --- a/libs/srtp/include/ut_sim.h +++ b/libs/srtp/include/ut_sim.h @@ -9,26 +9,26 @@ */ /* - * + * * 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 @@ -44,41 +44,37 @@ * */ - - #ifndef UT_SIM_H #define UT_SIM_H -#include "integers.h" /* for uint32_t */ +#include "integers.h" /* for uint32_t */ #ifdef __cplusplus extern "C" { #endif -#define UT_BUF 160 /* maximum amount of packet reorder */ +#define UT_BUF 160 /* maximum amount of packet reorder */ typedef struct { - uint32_t index; - uint32_t buffer[UT_BUF]; + uint32_t index; + uint32_t buffer[UT_BUF]; } ut_connection; /* - * ut_init(&u) initializes the ut_connection + * ut_init(&u) initializes the ut_connection * * this function should always be the first one called on a new * ut_connection */ -void -ut_init(ut_connection *utc); +void ut_init(ut_connection *utc); /* * ut_next_index(&u) returns the next index from the simulated * unreliable connection */ -uint32_t -ut_next_index(ut_connection *utc); +uint32_t ut_next_index(ut_connection *utc); #ifdef __cplusplus } diff --git a/libs/srtp/libsrtp.2017.vcxproj b/libs/srtp/libsrtp.2017.vcxproj index 576bcd8cb2..db7e71a8e3 100644 --- a/libs/srtp/libsrtp.2017.vcxproj +++ b/libs/srtp/libsrtp.2017.vcxproj @@ -392,6 +392,7 @@ <ClInclude Include="crypto\include\alloc.h" /> <ClInclude Include="crypto\include\auth.h" /> <ClInclude Include="crypto\include\cipher.h" /> + <ClInclude Include="crypto\include\cipher_types.h" /> <ClInclude Include="crypto\include\config.h" /> <ClInclude Include="crypto\include\crypto_kernel.h" /> <ClInclude Include="crypto\include\crypto_types.h" /> diff --git a/libs/srtp/srtp-1.42.pc.in b/libs/srtp/srtp-1.42.pc.in deleted file mode 100644 index bef2c422ff..0000000000 --- a/libs/srtp/srtp-1.42.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix = @prefix@ -exec_prefix = @exec_prefix@ -libdir = @libdir@ -includedir = @includedir@ - -Name: srtp -Description: Secure RTP (SRTP) and UST Reference Implementations -Version: @VERSION@ -Libs: -L${libdir} -lsrtp.so -Cflags: -I${includedir}/srtp diff --git a/libs/srtp/srtp/ekt.c b/libs/srtp/srtp/ekt.c index cd2c05d9c7..b54ecf64eb 100644 --- a/libs/srtp/srtp/ekt.c +++ b/libs/srtp/srtp/ekt.c @@ -2,31 +2,31 @@ * ekt.c * * Encrypted Key Transport for SRTP - * + * * 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 @@ -42,7 +42,6 @@ * */ - #include "srtp_priv.h" #include "err.h" #include "ekt.h" @@ -64,195 +63,219 @@ extern srtp_debug_module_t mod_srtp; * | Initial Sequence Number | Security Parameter Index | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * - */ + */ #define EKT_OCTETS_AFTER_BASE_TAG 24 -#define EKT_OCTETS_AFTER_EMK 8 -#define EKT_OCTETS_AFTER_ROC 4 -#define EKT_SPI_LEN 2 +#define EKT_OCTETS_AFTER_EMK 8 +#define EKT_OCTETS_AFTER_ROC 4 +#define EKT_SPI_LEN 2 -unsigned srtp_ekt_octets_after_base_tag(srtp_ekt_stream_t ekt) { - /* - * if the pointer ekt is NULL, then EKT is not in effect, so we - * indicate this by returning zero - */ - if (!ekt) +unsigned srtp_ekt_octets_after_base_tag(srtp_ekt_stream_t ekt) +{ + /* + * if the pointer ekt is NULL, then EKT is not in effect, so we + * indicate this by returning zero + */ + if (!ekt) + return 0; + + switch (ekt->data->ekt_cipher_type) { + case SRTP_EKT_CIPHER_AES_128_ECB: + return 16 + EKT_OCTETS_AFTER_EMK; + break; + default: + break; + } return 0; - - switch(ekt->data->ekt_cipher_type) { - case SRTP_EKT_CIPHER_AES_128_ECB: - return 16 + EKT_OCTETS_AFTER_EMK; - break; - default: - break; - } - return 0; } -static inline srtp_ekt_spi_t srtcp_packet_get_ekt_spi(const uint8_t *packet_start, unsigned pkt_octet_len) { - const uint8_t *spi_location; - - spi_location = packet_start + (pkt_octet_len - EKT_SPI_LEN); - - return *((const srtp_ekt_spi_t *)spi_location); +static inline srtp_ekt_spi_t srtcp_packet_get_ekt_spi( + const uint8_t *packet_start, + unsigned pkt_octet_len) +{ + const uint8_t *spi_location; + + spi_location = packet_start + (pkt_octet_len - EKT_SPI_LEN); + + return *((const srtp_ekt_spi_t *)spi_location); } -static inline uint32_t srtcp_packet_get_ekt_roc(const uint8_t *packet_start, unsigned pkt_octet_len) { - const uint8_t *roc_location; - - roc_location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_ROC); - - return *((const uint32_t *)roc_location); +static inline uint32_t srtcp_packet_get_ekt_roc(const uint8_t *packet_start, + unsigned pkt_octet_len) +{ + const uint8_t *roc_location; + + roc_location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_ROC); + + return *((const uint32_t *)roc_location); } -static inline const uint8_t * srtcp_packet_get_emk_location(const uint8_t *packet_start, unsigned pkt_octet_len) { - const uint8_t *location; - - location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_BASE_TAG); +static inline const uint8_t *srtcp_packet_get_emk_location( + const uint8_t *packet_start, + unsigned pkt_octet_len) +{ + const uint8_t *location; - return location; + location = packet_start + (pkt_octet_len - EKT_OCTETS_AFTER_BASE_TAG); + + return location; } +srtp_err_status_t srtp_ekt_alloc(srtp_ekt_stream_t *stream_data, + srtp_ekt_policy_t policy) +{ + /* + * if the policy pointer is NULL, then EKT is not in use + * so we just set the EKT stream data pointer to NULL + */ + if (!policy) { + *stream_data = NULL; + return srtp_err_status_ok; + } -srtp_err_status_t srtp_ekt_alloc(srtp_ekt_stream_t *stream_data, srtp_ekt_policy_t policy) { - - /* - * if the policy pointer is NULL, then EKT is not in use - * so we just set the EKT stream data pointer to NULL - */ - if (!policy) { + /* TODO */ *stream_data = NULL; + return srtp_err_status_ok; - } - - /* TODO */ - *stream_data = NULL; - - return srtp_err_status_ok; } -srtp_err_status_t srtp_ekt_stream_init_from_policy(srtp_ekt_stream_t stream_data, srtp_ekt_policy_t policy) { - if (!stream_data) - return srtp_err_status_ok; +srtp_err_status_t srtp_ekt_stream_init_from_policy( + srtp_ekt_stream_t stream_data, + srtp_ekt_policy_t policy) +{ + if (!stream_data) + return srtp_err_status_ok; - return srtp_err_status_ok; + return srtp_err_status_ok; } - -void aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) { +void aes_decrypt_with_raw_key(void *ciphertext, const void *key, int key_len) +{ #ifndef OPENSSL -//FIXME: need to get this working through the crypto module interface - srtp_aes_expanded_key_t expanded_key; + // FIXME: need to get this working through the crypto module interface + srtp_aes_expanded_key_t expanded_key; - srtp_aes_expand_decryption_key(key, key_len, &expanded_key); - srtp_aes_decrypt(ciphertext, &expanded_key); + srtp_aes_expand_decryption_key(key, key_len, &expanded_key); + srtp_aes_decrypt(ciphertext, &expanded_key); #endif } /* * The function srtp_stream_init_from_ekt() initializes a stream using - * the EKT data from an SRTCP trailer. + * the EKT data from an SRTCP trailer. */ -srtp_err_status_t srtp_stream_init_from_ekt(srtp_stream_t stream, const void *srtcp_hdr, unsigned pkt_octet_len) { - srtp_err_status_t err; - const uint8_t *master_key; - srtp_policy_t srtp_policy; - uint32_t roc; +srtp_err_status_t srtp_stream_init_from_ekt(srtp_stream_t stream, + const void *srtcp_hdr, + unsigned pkt_octet_len) +{ + srtp_err_status_t err; + const uint8_t *master_key; + srtp_policy_t srtp_policy; + uint32_t roc; - /* - * NOTE: at present, we only support a single ekt_policy at a time. - */ - if (stream->ekt->data->spi != - srtcp_packet_get_ekt_spi(srtcp_hdr, pkt_octet_len)) - return srtp_err_status_no_ctx; + /* + * NOTE: at present, we only support a single ekt_policy at a time. + */ + if (stream->ekt->data->spi != + srtcp_packet_get_ekt_spi(srtcp_hdr, pkt_octet_len)) + return srtp_err_status_no_ctx; - if (stream->ekt->data->ekt_cipher_type != SRTP_EKT_CIPHER_AES_128_ECB) - return srtp_err_status_bad_param; + if (stream->ekt->data->ekt_cipher_type != SRTP_EKT_CIPHER_AES_128_ECB) + return srtp_err_status_bad_param; - /* decrypt the Encrypted Master Key field */ - master_key = srtcp_packet_get_emk_location(srtcp_hdr, pkt_octet_len); - /* FIX!? This decrypts the master key in-place, and never uses it */ - /* FIX!? It's also passing to ekt_dec_key (which is an aes_expanded_key_t) - * to a function which expects a raw (unexpanded) key */ - aes_decrypt_with_raw_key((void*)master_key, &stream->ekt->data->ekt_dec_key, 16); + /* decrypt the Encrypted Master Key field */ + master_key = srtcp_packet_get_emk_location(srtcp_hdr, pkt_octet_len); + /* FIX!? This decrypts the master key in-place, and never uses it */ + /* FIX!? It's also passing to ekt_dec_key (which is an aes_expanded_key_t) + * to a function which expects a raw (unexpanded) key */ + aes_decrypt_with_raw_key((void *)master_key, + &stream->ekt->data->ekt_dec_key, 16); - /* set the SRTP ROC */ - roc = srtcp_packet_get_ekt_roc(srtcp_hdr, pkt_octet_len); - err = srtp_rdbx_set_roc(&stream->rtp_rdbx, roc); - if (err) return err; + /* set the SRTP ROC */ + roc = srtcp_packet_get_ekt_roc(srtcp_hdr, pkt_octet_len); + err = srtp_rdbx_set_roc(&stream->rtp_rdbx, roc); + if (err) + return err; - err = srtp_stream_init(stream, &srtp_policy); - if (err) return err; + err = srtp_stream_init(stream, &srtp_policy); + if (err) + return err; - return srtp_err_status_ok; + return srtp_err_status_ok; } -void srtp_ekt_write_data(srtp_ekt_stream_t ekt, uint8_t *base_tag, unsigned base_tag_len, int *packet_len, srtp_xtd_seq_num_t pkt_index) { - uint32_t roc; - uint16_t isn; - unsigned emk_len; - uint8_t *packet; +void srtp_ekt_write_data(srtp_ekt_stream_t ekt, + uint8_t *base_tag, + unsigned base_tag_len, + int *packet_len, + srtp_xtd_seq_num_t pkt_index) +{ + uint32_t roc; + uint16_t isn; + unsigned emk_len; + uint8_t *packet; - /* if the pointer ekt is NULL, then EKT is not in effect */ - if (!ekt) { - debug_print(mod_srtp, "EKT not in use", NULL); - return; - } + /* if the pointer ekt is NULL, then EKT is not in effect */ + if (!ekt) { + debug_print(mod_srtp, "EKT not in use", NULL); + return; + } - /* write zeros into the location of the base tag */ - octet_string_set_to_zero(base_tag, base_tag_len); - packet = base_tag + base_tag_len; + /* write zeros into the location of the base tag */ + octet_string_set_to_zero(base_tag, base_tag_len); + packet = base_tag + base_tag_len; - /* copy encrypted master key into packet */ - emk_len = srtp_ekt_octets_after_base_tag(ekt); - memcpy(packet, ekt->encrypted_master_key, emk_len); - debug_print(mod_srtp, "writing EKT EMK: %s,", - srtp_octet_string_hex_string(packet, emk_len)); - packet += emk_len; + /* copy encrypted master key into packet */ + emk_len = srtp_ekt_octets_after_base_tag(ekt); + memcpy(packet, ekt->encrypted_master_key, emk_len); + debug_print(mod_srtp, "writing EKT EMK: %s,", + srtp_octet_string_hex_string(packet, emk_len)); + packet += emk_len; - /* copy ROC into packet */ - roc = (uint32_t)(pkt_index >> 16); - *((uint32_t *)packet) = be32_to_cpu(roc); - debug_print(mod_srtp, "writing EKT ROC: %s,", - srtp_octet_string_hex_string(packet, sizeof(roc))); - packet += sizeof(roc); + /* copy ROC into packet */ + roc = (uint32_t)(pkt_index >> 16); + *((uint32_t *)packet) = be32_to_cpu(roc); + debug_print(mod_srtp, "writing EKT ROC: %s,", + srtp_octet_string_hex_string(packet, sizeof(roc))); + packet += sizeof(roc); - /* copy ISN into packet */ - isn = (uint16_t)pkt_index; - *((uint16_t *)packet) = htons(isn); - debug_print(mod_srtp, "writing EKT ISN: %s,", - srtp_octet_string_hex_string(packet, sizeof(isn))); - packet += sizeof(isn); + /* copy ISN into packet */ + isn = (uint16_t)pkt_index; + *((uint16_t *)packet) = htons(isn); + debug_print(mod_srtp, "writing EKT ISN: %s,", + srtp_octet_string_hex_string(packet, sizeof(isn))); + packet += sizeof(isn); - /* copy SPI into packet */ - *((uint16_t *)packet) = htons(ekt->data->spi); - debug_print(mod_srtp, "writing EKT SPI: %s,", - srtp_octet_string_hex_string(packet, sizeof(ekt->data->spi))); + /* copy SPI into packet */ + *((uint16_t *)packet) = htons(ekt->data->spi); + debug_print(mod_srtp, "writing EKT SPI: %s,", + srtp_octet_string_hex_string(packet, sizeof(ekt->data->spi))); - /* increase packet length appropriately */ - *packet_len += EKT_OCTETS_AFTER_EMK + emk_len; + /* increase packet length appropriately */ + *packet_len += EKT_OCTETS_AFTER_EMK + emk_len; } - /* * The function call srtcp_ekt_trailer(ekt, auth_len, auth_tag ) - * + * * If the pointer ekt is NULL, then the other inputs are unaffected. * * auth_tag is a pointer to the pointer to the location of the * authentication tag in the packet. If EKT is in effect, then the - * auth_tag pointer is set to the location + * auth_tag pointer is set to the location */ -void srtcp_ekt_trailer(srtp_ekt_stream_t ekt, unsigned *auth_len, void **auth_tag, void *tag_copy) { - /* - * if there is no EKT policy, then the other inputs are unaffected - */ - if (!ekt) - return; - - /* copy auth_tag into temporary location */ - -} +void srtcp_ekt_trailer(srtp_ekt_stream_t ekt, + unsigned *auth_len, + void **auth_tag, + void *tag_copy) +{ + /* + * if there is no EKT policy, then the other inputs are unaffected + */ + if (!ekt) + return; + /* copy auth_tag into temporary location */ +} diff --git a/libs/srtp/srtp/srtp.c b/libs/srtp/srtp/srtp.c index ede804f1d0..44625015e7 100644 --- a/libs/srtp/srtp/srtp.c +++ b/libs/srtp/srtp/srtp.c @@ -7,26 +7,26 @@ * 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 @@ -48,66 +48,67 @@ #include "srtp_priv.h" #include "crypto_types.h" #include "err.h" -#include "ekt.h" /* for SRTP Encrypted Key Transport */ -#include "alloc.h" /* for srtp_crypto_alloc() */ +#include "ekt.h" /* for SRTP Encrypted Key Transport */ +#include "alloc.h" /* for srtp_crypto_alloc() */ + #ifdef OPENSSL -#include "aes_gcm_ossl.h" /* for AES GCM mode */ -# ifdef OPENSSL_KDF -# include <openssl/kdf.h> -# include "aes_icm_ossl.h" /* for AES GCM mode */ -# endif +#include "aes_gcm_ossl.h" /* for AES GCM mode */ +#ifdef OPENSSL_KDF +#include <openssl/kdf.h> +#include "aes_icm_ossl.h" /* for AES GCM mode */ +#endif #endif #include <limits.h> #ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> +#include <netinet/in.h> #elif defined(HAVE_WINSOCK2_H) -# include <winsock2.h> +#include <winsock2.h> #endif - /* the debug module for srtp */ - srtp_debug_module_t mod_srtp = { - 0, /* debugging is off by default */ - "srtp" /* printable name for module */ + 0, /* debugging is off by default */ + "srtp" /* printable name for module */ }; -#define octets_in_rtp_header 12 -#define uint32s_in_rtp_header 3 -#define octets_in_rtcp_header 8 +#define octets_in_rtp_header 12 +#define uint32s_in_rtp_header 3 +#define octets_in_rtcp_header 8 #define uint32s_in_rtcp_header 2 #define octets_in_rtp_extn_hdr 4 -static srtp_err_status_t -srtp_validate_rtp_header(void *rtp_hdr, int *pkt_octet_len) { - if (*pkt_octet_len < octets_in_rtp_header) - return srtp_err_status_bad_param; +static srtp_err_status_t srtp_validate_rtp_header(void *rtp_hdr, + int *pkt_octet_len) +{ + if (*pkt_octet_len < octets_in_rtp_header) + return srtp_err_status_bad_param; - srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; + srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; - /* Check RTP header length */ - int rtp_header_len = octets_in_rtp_header + 4 * hdr->cc; - if (hdr->x == 1) - rtp_header_len += octets_in_rtp_extn_hdr; + /* Check RTP header length */ + int rtp_header_len = octets_in_rtp_header + 4 * hdr->cc; + if (hdr->x == 1) + rtp_header_len += octets_in_rtp_extn_hdr; - if (*pkt_octet_len < rtp_header_len) - return srtp_err_status_bad_param; - - /* Verifing profile length. */ - if (hdr->x == 1) { - srtp_hdr_xtnd_t *xtn_hdr = - (srtp_hdr_xtnd_t *)((uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc); - int profile_len = ntohs(xtn_hdr->length); - rtp_header_len += profile_len * 4; - /* profile length counts the number of 32-bit words */ if (*pkt_octet_len < rtp_header_len) - return srtp_err_status_bad_param; - } - return srtp_err_status_ok; + return srtp_err_status_bad_param; + + /* Verifing profile length. */ + if (hdr->x == 1) { + srtp_hdr_xtnd_t *xtn_hdr = + (srtp_hdr_xtnd_t *)((uint32_t *)hdr + uint32s_in_rtp_header + + hdr->cc); + int profile_len = ntohs(xtn_hdr->length); + rtp_header_len += profile_len * 4; + /* profile length counts the number of 32-bit words */ + if (*pkt_octet_len < rtp_header_len) + return srtp_err_status_bad_param; + } + return srtp_err_status_ok; } -const char *srtp_get_version_string () +const char *srtp_get_version_string() { /* * Simply return the autotools generated string @@ -115,29 +116,29 @@ const char *srtp_get_version_string () return SRTP_VER_STRING; } -unsigned int srtp_get_version () +unsigned int srtp_get_version() { unsigned int major = 0, minor = 0, micro = 0; unsigned int rv = 0; int parse_rv; /* - * Parse the autotools generated version + * Parse the autotools generated version */ parse_rv = sscanf(SRTP_VERSION, "%u.%u.%u", &major, &minor, &micro); if (parse_rv != 3) { - /* - * We're expected to parse all 3 version levels. - * If not, then this must not be an official release. - * Return all zeros on the version - */ - return (0); + /* + * We're expected to parse all 3 version levels. + * If not, then this must not be an official release. + * Return all zeros on the version + */ + return (0); } - /* + /* * We allow 8 bits for the major and minor, while * allowing 16 bits for the micro. 16 bits for the micro - * may be beneficial for a continuous delivery model + * may be beneficial for a continuous delivery model * in the future. */ rv |= (major & 0xFF) << 24; @@ -146,446 +147,410 @@ unsigned int srtp_get_version () return rv; } -/* Release (maybe partially allocated) stream. */ -static void -srtp_stream_free(srtp_stream_ctx_t *str) { - unsigned int i = 0; - srtp_session_keys_t *session_keys = NULL; - - for (i = 0; i < str->num_master_keys; i++) { - session_keys = &str->session_keys[i]; - - if (session_keys->rtp_xtn_hdr_cipher) { - srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); - } - - if (session_keys->rtcp_cipher) { - srtp_cipher_dealloc(session_keys->rtcp_cipher); - } - - if (session_keys->rtcp_auth) { - srtp_auth_dealloc(session_keys->rtcp_auth); - } - - if (session_keys->rtp_cipher) { - srtp_cipher_dealloc(session_keys->rtp_cipher); - } - - if (session_keys->rtp_auth) { - srtp_auth_dealloc(session_keys->rtp_auth); - } - - if (session_keys->mki_id) { - srtp_crypto_free(session_keys->mki_id); - } - - if (session_keys->limit) { - srtp_crypto_free(session_keys->limit); - } - } - - srtp_crypto_free(str->session_keys); - - if (str->enc_xtn_hdr) { - srtp_crypto_free(str->enc_xtn_hdr); - } - - srtp_crypto_free(str); -} - -srtp_err_status_t -srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, - const srtp_policy_t *p) { - srtp_stream_ctx_t *str; - srtp_err_status_t stat; - unsigned int i = 0; - srtp_session_keys_t *session_keys = NULL; - - /* - * This function allocates the stream context, rtp and rtcp ciphers - * and auth functions, and key limit structure. If there is a - * failure during allocation, we free all previously allocated - * memory and return a failure code. The code could probably - * be improved, but it works and should be clear. - */ - - /* allocate srtp stream and set str_ptr */ - str = (srtp_stream_ctx_t *) srtp_crypto_alloc(sizeof(srtp_stream_ctx_t)); - if (str == NULL) - return srtp_err_status_alloc_fail; - - memset(str, 0, sizeof(srtp_stream_ctx_t)); - *str_ptr = str; - - /* To keep backwards API compatible if someone is using multiple master - * keys then key should be set to NULL - */ - if (p->key != NULL) { - str->num_master_keys = 1; - } else { - str->num_master_keys = p->num_master_keys; - } - - str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( - sizeof(srtp_session_keys_t) * str->num_master_keys); - - if (str->session_keys == NULL) { - srtp_stream_free(str); - return srtp_err_status_alloc_fail; - } - - memset(str->session_keys, 0, sizeof(srtp_session_keys_t) * str->num_master_keys); - - for (i = 0; i < str->num_master_keys; i++) { - session_keys = &str->session_keys[i]; - - /* allocate cipher */ - stat = srtp_crypto_kernel_alloc_cipher(p->rtp.cipher_type, - &session_keys->rtp_cipher, - p->rtp.cipher_key_len, - p->rtp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; - } - - /* allocate auth function */ - stat = srtp_crypto_kernel_alloc_auth(p->rtp.auth_type, - &session_keys->rtp_auth, - p->rtp.auth_key_len, - p->rtp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; - } +srtp_err_status_t srtp_stream_dealloc(srtp_stream_ctx_t *stream, + const srtp_stream_ctx_t *stream_template) +{ + srtp_err_status_t status; + unsigned int i = 0; + srtp_session_keys_t *session_keys = NULL; + srtp_session_keys_t *template_session_keys = NULL; /* - * ...and now the RTCP-specific initialization - first, allocate - * the cipher + * we use a conservative deallocation strategy - if any deallocation + * fails, then we report that fact without trying to deallocate + * anything else */ - stat = srtp_crypto_kernel_alloc_cipher(p->rtcp.cipher_type, - &session_keys->rtcp_cipher, - p->rtcp.cipher_key_len, - p->rtcp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; + if (stream->session_keys) { + for (i = 0; i < stream->num_master_keys; i++) { + session_keys = &stream->session_keys[i]; + + if (stream_template && + stream->num_master_keys == stream_template->num_master_keys) { + template_session_keys = &stream_template->session_keys[i]; + } else { + template_session_keys = NULL; + } + + /* + * deallocate cipher, if it is not the same as that in template + */ + if (template_session_keys && + session_keys->rtp_cipher == template_session_keys->rtp_cipher) { + /* do nothing */ + } else if (session_keys->rtp_cipher) { + status = srtp_cipher_dealloc(session_keys->rtp_cipher); + if (status) + return status; + } + + /* + * deallocate auth function, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->rtp_auth == template_session_keys->rtp_auth) { + /* do nothing */ + } else if (session_keys->rtp_auth) { + status = srtp_auth_dealloc(session_keys->rtp_auth); + if (status) + return status; + } + + if (template_session_keys && + session_keys->rtp_xtn_hdr_cipher == + template_session_keys->rtp_xtn_hdr_cipher) { + /* do nothing */ + } else if (session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); + if (status) + return status; + } + + /* + * deallocate rtcp cipher, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->rtcp_cipher == + template_session_keys->rtcp_cipher) { + /* do nothing */ + } else if (session_keys->rtcp_cipher) { + status = srtp_cipher_dealloc(session_keys->rtcp_cipher); + if (status) + return status; + } + + /* + * deallocate rtcp auth function, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->rtcp_auth == template_session_keys->rtcp_auth) { + /* do nothing */ + } else if (session_keys->rtcp_auth) { + status = srtp_auth_dealloc(session_keys->rtcp_auth); + if (status) + return status; + } + + /* + * zeroize the salt value + */ + octet_string_set_to_zero(session_keys->salt, SRTP_AEAD_SALT_LEN); + octet_string_set_to_zero(session_keys->c_salt, SRTP_AEAD_SALT_LEN); + + if (session_keys->mki_id) { + octet_string_set_to_zero(session_keys->mki_id, + session_keys->mki_size); + srtp_crypto_free(session_keys->mki_id); + session_keys->mki_id = NULL; + } + + /* + * deallocate key usage limit, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->limit == template_session_keys->limit) { + /* do nothing */ + } else if (session_keys->limit) { + srtp_crypto_free(session_keys->limit); + } + } + srtp_crypto_free(stream->session_keys); } - /* allocate auth function */ - stat = srtp_crypto_kernel_alloc_auth(p->rtcp.auth_type, - &session_keys->rtcp_auth, - p->rtcp.auth_key_len, - p->rtcp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; - } - - session_keys->mki_id = NULL; + status = srtp_rdbx_dealloc(&stream->rtp_rdbx); + if (status) + return status; - /* allocate key limit structure */ - session_keys->limit = (srtp_key_limit_ctx_t*) srtp_crypto_alloc(sizeof(srtp_key_limit_ctx_t)); - if (session_keys->limit == NULL) { - srtp_stream_free(str); + /* DAM - need to deallocate EKT here */ + + if (stream_template && + stream->enc_xtn_hdr == stream_template->enc_xtn_hdr) { + /* do nothing */ + } else if (stream->enc_xtn_hdr) { + srtp_crypto_free(stream->enc_xtn_hdr); + } + + /* deallocate srtp stream context */ + srtp_crypto_free(stream); + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, + const srtp_policy_t *p) +{ + srtp_stream_ctx_t *str; + srtp_err_status_t stat; + unsigned int i = 0; + srtp_session_keys_t *session_keys = NULL; + + /* + * This function allocates the stream context, rtp and rtcp ciphers + * and auth functions, and key limit structure. If there is a + * failure during allocation, we free all previously allocated + * memory and return a failure code. The code could probably + * be improved, but it works and should be clear. + */ + + /* allocate srtp stream and set str_ptr */ + str = (srtp_stream_ctx_t *)srtp_crypto_alloc(sizeof(srtp_stream_ctx_t)); + if (str == NULL) + return srtp_err_status_alloc_fail; + + *str_ptr = str; + + /* + *To keep backwards API compatible if someone is using multiple master + * keys then key should be set to NULL + */ + if (p->key != NULL) { + str->num_master_keys = 1; + } else { + str->num_master_keys = p->num_master_keys; + } + + str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( + sizeof(srtp_session_keys_t) * str->num_master_keys); + + if (str->session_keys == NULL) { + srtp_stream_dealloc(str, NULL); return srtp_err_status_alloc_fail; } - } - - /* allocate ekt data associated with stream */ - stat = srtp_ekt_alloc(&str->ekt, p->ekt); - if (stat) { - srtp_stream_free(str); - return stat; - } - - if (p->enc_xtn_hdr && p->enc_xtn_hdr_count > 0) { - srtp_cipher_type_id_t enc_xtn_hdr_cipher_type; - int enc_xtn_hdr_cipher_key_len; - - str->enc_xtn_hdr = (int*) srtp_crypto_alloc(p->enc_xtn_hdr_count * sizeof(p->enc_xtn_hdr[0])); - if (!str->enc_xtn_hdr) { - srtp_stream_free(str); - return srtp_err_status_alloc_fail; - } - memcpy(str->enc_xtn_hdr, p->enc_xtn_hdr, p->enc_xtn_hdr_count * sizeof(p->enc_xtn_hdr[0])); - str->enc_xtn_hdr_count = p->enc_xtn_hdr_count; - - /* For GCM ciphers, the corresponding ICM cipher is used for header extensions encryption. */ - switch (p->rtp.cipher_type) { - case SRTP_AES_GCM_128: - enc_xtn_hdr_cipher_type = SRTP_AES_ICM_128; - enc_xtn_hdr_cipher_key_len = SRTP_AES_ICM_128_KEY_LEN_WSALT; - break; - case SRTP_AES_GCM_256: - enc_xtn_hdr_cipher_type = SRTP_AES_ICM_256; - enc_xtn_hdr_cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; - break; - default: - enc_xtn_hdr_cipher_type = p->rtp.cipher_type; - enc_xtn_hdr_cipher_key_len = p->rtp.cipher_key_len; - break; - } for (i = 0; i < str->num_master_keys; i++) { - session_keys = &str->session_keys[i]; + session_keys = &str->session_keys[i]; - /* allocate cipher for extensions header encryption */ - stat = srtp_crypto_kernel_alloc_cipher(enc_xtn_hdr_cipher_type, - &session_keys->rtp_xtn_hdr_cipher, - enc_xtn_hdr_cipher_key_len, - 0); - if (stat) { - srtp_stream_free(str); + /* allocate cipher */ + stat = srtp_crypto_kernel_alloc_cipher( + p->rtp.cipher_type, &session_keys->rtp_cipher, + p->rtp.cipher_key_len, p->rtp.auth_tag_len); + if (stat) { + srtp_stream_dealloc(str, NULL); + return stat; + } + + /* allocate auth function */ + stat = srtp_crypto_kernel_alloc_auth( + p->rtp.auth_type, &session_keys->rtp_auth, p->rtp.auth_key_len, + p->rtp.auth_tag_len); + if (stat) { + srtp_stream_dealloc(str, NULL); + return stat; + } + + /* + * ...and now the RTCP-specific initialization - first, allocate + * the cipher + */ + stat = srtp_crypto_kernel_alloc_cipher( + p->rtcp.cipher_type, &session_keys->rtcp_cipher, + p->rtcp.cipher_key_len, p->rtcp.auth_tag_len); + if (stat) { + srtp_stream_dealloc(str, NULL); + return stat; + } + + /* allocate auth function */ + stat = srtp_crypto_kernel_alloc_auth( + p->rtcp.auth_type, &session_keys->rtcp_auth, p->rtcp.auth_key_len, + p->rtcp.auth_tag_len); + if (stat) { + srtp_stream_dealloc(str, NULL); + return stat; + } + + session_keys->mki_id = NULL; + + /* allocate key limit structure */ + session_keys->limit = (srtp_key_limit_ctx_t *)srtp_crypto_alloc( + sizeof(srtp_key_limit_ctx_t)); + if (session_keys->limit == NULL) { + srtp_stream_dealloc(str, NULL); + return srtp_err_status_alloc_fail; + } + } + + /* allocate ekt data associated with stream */ + stat = srtp_ekt_alloc(&str->ekt, p->ekt); + if (stat) { + srtp_stream_dealloc(str, NULL); return stat; - } - } - } else { - for (i = 0; i < str->num_master_keys; i++) { - session_keys = &str->session_keys[i]; - session_keys->rtp_xtn_hdr_cipher = NULL; } - str->enc_xtn_hdr = NULL; - str->enc_xtn_hdr_count = 0; - } + if (p->enc_xtn_hdr && p->enc_xtn_hdr_count > 0) { + srtp_cipher_type_id_t enc_xtn_hdr_cipher_type; + int enc_xtn_hdr_cipher_key_len; - return srtp_err_status_ok; + str->enc_xtn_hdr = (int *)srtp_crypto_alloc(p->enc_xtn_hdr_count * + sizeof(p->enc_xtn_hdr[0])); + if (!str->enc_xtn_hdr) { + srtp_stream_dealloc(str, NULL); + return srtp_err_status_alloc_fail; + } + memcpy(str->enc_xtn_hdr, p->enc_xtn_hdr, + p->enc_xtn_hdr_count * sizeof(p->enc_xtn_hdr[0])); + str->enc_xtn_hdr_count = p->enc_xtn_hdr_count; + + /* + * For GCM ciphers, the corresponding ICM cipher is used for header + * extensions encryption. + */ + switch (p->rtp.cipher_type) { + case SRTP_AES_GCM_128: + enc_xtn_hdr_cipher_type = SRTP_AES_ICM_128; + enc_xtn_hdr_cipher_key_len = SRTP_AES_ICM_128_KEY_LEN_WSALT; + break; + case SRTP_AES_GCM_256: + enc_xtn_hdr_cipher_type = SRTP_AES_ICM_256; + enc_xtn_hdr_cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; + break; + default: + enc_xtn_hdr_cipher_type = p->rtp.cipher_type; + enc_xtn_hdr_cipher_key_len = p->rtp.cipher_key_len; + break; + } + + for (i = 0; i < str->num_master_keys; i++) { + session_keys = &str->session_keys[i]; + + /* allocate cipher for extensions header encryption */ + stat = srtp_crypto_kernel_alloc_cipher( + enc_xtn_hdr_cipher_type, &session_keys->rtp_xtn_hdr_cipher, + enc_xtn_hdr_cipher_key_len, 0); + if (stat) { + srtp_stream_dealloc(str, NULL); + return stat; + } + } + } else { + for (i = 0; i < str->num_master_keys; i++) { + session_keys = &str->session_keys[i]; + session_keys->rtp_xtn_hdr_cipher = NULL; + } + + str->enc_xtn_hdr = NULL; + str->enc_xtn_hdr_count = 0; + } + + return srtp_err_status_ok; } -srtp_err_status_t -srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_template) { - srtp_err_status_t status; - unsigned int i = 0; - srtp_session_keys_t *session_keys = NULL; - srtp_session_keys_t *template_session_keys = NULL; - - /* - * we use a conservative deallocation strategy - if any deallocation - * fails, then we report that fact without trying to deallocate - * anything else - */ - for ( i = 0; i < stream->num_master_keys; i++) { - session_keys = &stream->session_keys[i]; - - if (stream_template) { - template_session_keys = &stream_template->session_keys[i]; - } else { - template_session_keys = NULL; - } - - /* deallocate cipher, if it is not the same as that in template */ - if (template_session_keys - && session_keys->rtp_cipher == template_session_keys->rtp_cipher) { - /* do nothing */ - } else { - status = srtp_cipher_dealloc(session_keys->rtp_cipher); - if (status) - return status; - } - - /* deallocate auth function, if it is not the same as that in template */ - if (template_session_keys - && session_keys->rtp_auth == template_session_keys->rtp_auth) { - /* do nothing */ - } else { - status = srtp_auth_dealloc(session_keys->rtp_auth); - if (status) - return status; - } - - if (template_session_keys - && session_keys->rtp_xtn_hdr_cipher == template_session_keys->rtp_xtn_hdr_cipher) { - /* do nothing */ - } else if (session_keys->rtp_xtn_hdr_cipher) { - status = srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); - if (status) - return status; - } - - /* - * deallocate rtcp cipher, if it is not the same as that in - * template - */ - if (template_session_keys - && session_keys->rtcp_cipher == template_session_keys->rtcp_cipher) { - /* do nothing */ - } else { - status = srtp_cipher_dealloc(session_keys->rtcp_cipher); - if (status) - return status; - } - - /* - * deallocate rtcp auth function, if it is not the same as that in - * template - */ - if (template_session_keys - && session_keys->rtcp_auth == template_session_keys->rtcp_auth) { - /* do nothing */ - } else { - status = srtp_auth_dealloc(session_keys->rtcp_auth); - if (status) - return status; - } - - /* - * zeroize the salt value - */ - octet_string_set_to_zero(session_keys->salt, SRTP_AEAD_SALT_LEN); - octet_string_set_to_zero(session_keys->c_salt, SRTP_AEAD_SALT_LEN); - - if (session_keys->mki_id) { - octet_string_set_to_zero(session_keys->mki_id, session_keys->mki_size); - srtp_crypto_free(session_keys->mki_id); - session_keys->mki_id = NULL; - } - - /* deallocate key usage limit, if it is not the same as that in template */ - if (template_session_keys - && session_keys->limit == template_session_keys->limit) { - /* do nothing */ - } else { - srtp_crypto_free(session_keys->limit); - } - - } - - if (stream_template - && stream->session_keys == stream_template->session_keys) { - /* do nothing */ - } else { - srtp_crypto_free(stream->session_keys); - } - - status = srtp_rdbx_dealloc(&stream->rtp_rdbx); - if (status) - return status; - - /* DAM - need to deallocate EKT here */ - - if (stream_template - && stream->enc_xtn_hdr == stream_template->enc_xtn_hdr) { - /* do nothing */ - } else if (stream->enc_xtn_hdr) { - srtp_crypto_free(stream->enc_xtn_hdr); - } - - /* deallocate srtp stream context */ - srtp_crypto_free(stream); - - return srtp_err_status_ok; -} - - /* * srtp_stream_clone(stream_template, new) allocates a new stream and * initializes it using the cipher and auth of the stream_template - * + * * the only unique data in a cloned stream is the replay database and * the SSRC */ -srtp_err_status_t -srtp_stream_clone(const srtp_stream_ctx_t *stream_template, - uint32_t ssrc, - srtp_stream_ctx_t **str_ptr) { - srtp_err_status_t status; - srtp_stream_ctx_t *str; - unsigned int i = 0; - srtp_session_keys_t *session_keys = NULL; - const srtp_session_keys_t *template_session_keys = NULL; +srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template, + uint32_t ssrc, + srtp_stream_ctx_t **str_ptr) +{ + srtp_err_status_t status; + srtp_stream_ctx_t *str; + unsigned int i = 0; + srtp_session_keys_t *session_keys = NULL; + const srtp_session_keys_t *template_session_keys = NULL; - debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ntohl(ssrc)); + debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ntohl(ssrc)); - /* allocate srtp stream and set str_ptr */ - str = (srtp_stream_ctx_t *) srtp_crypto_alloc(sizeof(srtp_stream_ctx_t)); - if (str == NULL) - return srtp_err_status_alloc_fail; - *str_ptr = str; + /* allocate srtp stream and set str_ptr */ + str = (srtp_stream_ctx_t *)srtp_crypto_alloc(sizeof(srtp_stream_ctx_t)); + if (str == NULL) + return srtp_err_status_alloc_fail; + *str_ptr = str; - str->num_master_keys = stream_template->num_master_keys; - str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( - sizeof(srtp_session_keys_t) * str->num_master_keys); + str->num_master_keys = stream_template->num_master_keys; + str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( + sizeof(srtp_session_keys_t) * str->num_master_keys); - if (str->session_keys == NULL) { - srtp_crypto_free(*str_ptr); - *str_ptr = NULL; - return srtp_err_status_alloc_fail; - } - - for (i = 0; i < stream_template->num_master_keys; i++){ - session_keys = &str->session_keys[i]; - template_session_keys = &stream_template->session_keys[i]; - - /* set cipher and auth pointers to those of the template */ - session_keys->rtp_cipher = template_session_keys->rtp_cipher; - session_keys->rtp_auth = template_session_keys->rtp_auth; - session_keys->rtp_xtn_hdr_cipher = template_session_keys->rtp_xtn_hdr_cipher; - session_keys->rtcp_cipher = template_session_keys->rtcp_cipher; - session_keys->rtcp_auth = template_session_keys->rtcp_auth; - session_keys->mki_size = template_session_keys->mki_size; - - if (template_session_keys->mki_size == 0) { - session_keys->mki_id = NULL; - } else { - session_keys->mki_id = srtp_crypto_alloc(template_session_keys->mki_size); - - if (session_keys->mki_id == NULL) { - return srtp_err_status_init_fail; - } - memset(session_keys->mki_id, 0x0, session_keys->mki_size); - memcpy(session_keys->mki_id, template_session_keys->mki_id, session_keys->mki_size); + if (str->session_keys == NULL) { + srtp_stream_dealloc(*str_ptr, stream_template); + *str_ptr = NULL; + return srtp_err_status_alloc_fail; } - /* Copy the salt values */ - memcpy(session_keys->salt, template_session_keys->salt, SRTP_AEAD_SALT_LEN); - memcpy(session_keys->c_salt, template_session_keys->c_salt, SRTP_AEAD_SALT_LEN); - /* set key limit to point to that of the template */ - status = srtp_key_limit_clone(template_session_keys->limit, &session_keys->limit); - if (status) { - srtp_crypto_free(*str_ptr); - *str_ptr = NULL; - return status; + for (i = 0; i < stream_template->num_master_keys; i++) { + session_keys = &str->session_keys[i]; + template_session_keys = &stream_template->session_keys[i]; + + /* set cipher and auth pointers to those of the template */ + session_keys->rtp_cipher = template_session_keys->rtp_cipher; + session_keys->rtp_auth = template_session_keys->rtp_auth; + session_keys->rtp_xtn_hdr_cipher = + template_session_keys->rtp_xtn_hdr_cipher; + session_keys->rtcp_cipher = template_session_keys->rtcp_cipher; + session_keys->rtcp_auth = template_session_keys->rtcp_auth; + session_keys->mki_size = template_session_keys->mki_size; + + if (template_session_keys->mki_size == 0) { + session_keys->mki_id = NULL; + } else { + session_keys->mki_id = + srtp_crypto_alloc(template_session_keys->mki_size); + + if (session_keys->mki_id == NULL) { + srtp_stream_dealloc(*str_ptr, stream_template); + *str_ptr = NULL; + return srtp_err_status_init_fail; + } + memcpy(session_keys->mki_id, template_session_keys->mki_id, + session_keys->mki_size); + } + /* Copy the salt values */ + memcpy(session_keys->salt, template_session_keys->salt, + SRTP_AEAD_SALT_LEN); + memcpy(session_keys->c_salt, template_session_keys->c_salt, + SRTP_AEAD_SALT_LEN); + + /* set key limit to point to that of the template */ + status = srtp_key_limit_clone(template_session_keys->limit, + &session_keys->limit); + if (status) { + srtp_stream_dealloc(*str_ptr, stream_template); + *str_ptr = NULL; + return status; + } } - } + /* initialize replay databases */ + status = srtp_rdbx_init( + &str->rtp_rdbx, srtp_rdbx_get_window_size(&stream_template->rtp_rdbx)); + if (status) { + srtp_stream_dealloc(*str_ptr, stream_template); + *str_ptr = NULL; + return status; + } + srtp_rdb_init(&str->rtcp_rdb); + str->allow_repeat_tx = stream_template->allow_repeat_tx; - /* initialize replay databases */ - status = srtp_rdbx_init(&str->rtp_rdbx, - srtp_rdbx_get_window_size(&stream_template->rtp_rdbx)); - if (status) { - srtp_crypto_free(*str_ptr); - *str_ptr = NULL; - return status; - } - srtp_rdb_init(&str->rtcp_rdb); - str->allow_repeat_tx = stream_template->allow_repeat_tx; + /* set ssrc to that provided */ + str->ssrc = ssrc; - /* set ssrc to that provided */ - str->ssrc = ssrc; + /* reset pending ROC */ + str->pending_roc = 0; - /* reset pending ROC */ - str->pending_roc = 0; + /* set direction and security services */ + str->direction = stream_template->direction; + str->rtp_services = stream_template->rtp_services; + str->rtcp_services = stream_template->rtcp_services; - /* set direction and security services */ - str->direction = stream_template->direction; - str->rtp_services = stream_template->rtp_services; - str->rtcp_services = stream_template->rtcp_services; + /* set pointer to EKT data associated with stream */ + str->ekt = stream_template->ekt; - /* set pointer to EKT data associated with stream */ - str->ekt = stream_template->ekt; + /* copy information about extensions header encryption */ + str->enc_xtn_hdr = stream_template->enc_xtn_hdr; + str->enc_xtn_hdr_count = stream_template->enc_xtn_hdr_count; - /* copy information about extensions header encryption */ - str->enc_xtn_hdr = stream_template->enc_xtn_hdr; - str->enc_xtn_hdr_count = stream_template->enc_xtn_hdr_count; - - /* defensive coding */ - str->next = NULL; - return srtp_err_status_ok; + /* defensive coding */ + str->next = NULL; + return srtp_err_status_ok; } - /* * key derivation functions, internal to libSRTP * @@ -593,7 +558,7 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, * * srtp_kdf_init(&kdf, cipher_id, k, keylen) initializes kdf to use cipher * described by cipher_id, with the master key k with length in octets keylen. - * + * * srtp_kdf_generate(&kdf, l, kl, keylen) derives the key * corresponding to label l and puts it into kl; the length * of the key in octets is provided as keylen. this function @@ -603,39 +568,42 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, */ typedef enum { - label_rtp_encryption = 0x00, - label_rtp_msg_auth = 0x01, - label_rtp_salt = 0x02, - label_rtcp_encryption = 0x03, - label_rtcp_msg_auth = 0x04, - label_rtcp_salt = 0x05, - label_rtp_header_encryption = 0x06, - label_rtp_header_salt = 0x07 + label_rtp_encryption = 0x00, + label_rtp_msg_auth = 0x01, + label_rtp_salt = 0x02, + label_rtcp_encryption = 0x03, + label_rtcp_msg_auth = 0x04, + label_rtcp_salt = 0x05, + label_rtp_header_encryption = 0x06, + label_rtp_header_salt = 0x07 } srtp_prf_label; #define MAX_SRTP_KEY_LEN 256 #if defined(OPENSSL) && defined(OPENSSL_KDF) #define MAX_SRTP_AESKEY_LEN 32 -#define MAX_SRTP_SALT_LEN 14 +#define MAX_SRTP_SALT_LEN 14 /* * srtp_kdf_t represents a key derivation function. The SRTP * default KDF is the only one implemented at present. */ -typedef struct { +typedef struct { uint8_t master_key[MAX_SRTP_AESKEY_LEN]; uint8_t master_salt[MAX_SRTP_SALT_LEN]; const EVP_CIPHER *evp; } srtp_kdf_t; - -static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t *key, int key_len, int salt_len) +static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, + const uint8_t *key, + int key_len, + int salt_len) { memset(kdf, 0x0, sizeof(srtp_kdf_t)); /* The NULL cipher has zero key length */ - if (key_len == 0) return srtp_err_status_ok; + if (key_len == 0) + return srtp_err_status_ok; if ((key_len > MAX_SRTP_AESKEY_LEN) || (salt_len > MAX_SRTP_SALT_LEN)) { return srtp_err_status_bad_param; @@ -654,17 +622,21 @@ static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t *key, int return srtp_err_status_bad_param; break; } - memcpy(kdf->master_key, key, key_len); - memcpy(kdf->master_salt, key+key_len, salt_len); + memcpy(kdf->master_key, key, key_len); + memcpy(kdf->master_salt, key + key_len, salt_len); return srtp_err_status_ok; } -static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label, uint8_t *key, unsigned int length) +static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf, + srtp_prf_label label, + uint8_t *key, + unsigned int length) { int ret; /* The NULL cipher will not have an EVP */ - if (!kdf->evp) return srtp_err_status_ok; + if (!kdf->evp) + return srtp_err_status_ok; octet_string_set_to_zero(key, length); /* @@ -672,7 +644,8 @@ static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label * This is useful if OpenSSL is in FIPS mode and FIP * compliance is required for SRTP. */ - ret = kdf_srtp(kdf->evp, (char *)&kdf->master_key, (char *)&kdf->master_salt, NULL, NULL, label, (char *)key); + ret = kdf_srtp(kdf->evp, (char *)&kdf->master_key, + (char *)&kdf->master_salt, NULL, NULL, label, (char *)key); if (ret == -1) { return (srtp_err_status_algo_fail); } @@ -680,25 +653,28 @@ static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label return srtp_err_status_ok; } -static srtp_err_status_t srtp_kdf_clear(srtp_kdf_t *kdf) { +static srtp_err_status_t srtp_kdf_clear(srtp_kdf_t *kdf) +{ octet_string_set_to_zero(kdf->master_key, MAX_SRTP_AESKEY_LEN); octet_string_set_to_zero(kdf->master_salt, MAX_SRTP_SALT_LEN); kdf->evp = NULL; - return srtp_err_status_ok; + return srtp_err_status_ok; } -#else /* if OPENSSL_KDF */ +#else /* if OPENSSL_KDF */ /* * srtp_kdf_t represents a key derivation function. The SRTP * default KDF is the only one implemented at present. */ -typedef struct { - srtp_cipher_t *cipher; /* cipher used for key derivation */ +typedef struct { + srtp_cipher_t *cipher; /* cipher used for key derivation */ } srtp_kdf_t; -static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t *key, int key_len) +static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, + const uint8_t *key, + int key_len) { srtp_cipher_type_id_t cipher_id; switch (key_len) { @@ -718,7 +694,8 @@ static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t *key, int srtp_err_status_t stat; stat = srtp_crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, key_len, 0); - if (stat) return stat; + if (stat) + return stat; stat = srtp_cipher_init(kdf->cipher, key); if (stat) { @@ -728,105 +705,113 @@ static srtp_err_status_t srtp_kdf_init(srtp_kdf_t *kdf, const uint8_t *key, int return srtp_err_status_ok; } -static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label, uint8_t *key, unsigned int length) +static srtp_err_status_t srtp_kdf_generate(srtp_kdf_t *kdf, + srtp_prf_label label, + uint8_t *key, + unsigned int length) { srtp_err_status_t status; v128_t nonce; - + /* set eigth octet of nonce to <label>, set the rest of it to zero */ v128_set_to_zero(&nonce); nonce.v8[7] = label; - - status = srtp_cipher_set_iv(kdf->cipher, (uint8_t*)&nonce, srtp_direction_encrypt); - if (status) return status; - + + status = srtp_cipher_set_iv(kdf->cipher, (uint8_t *)&nonce, + srtp_direction_encrypt); + if (status) + return status; + /* generate keystream output */ octet_string_set_to_zero(key, length); status = srtp_cipher_encrypt(kdf->cipher, key, &length); - if (status) return status; + if (status) + return status; return srtp_err_status_ok; } -static srtp_err_status_t srtp_kdf_clear(srtp_kdf_t *kdf) { +static srtp_err_status_t srtp_kdf_clear(srtp_kdf_t *kdf) +{ srtp_err_status_t status; status = srtp_cipher_dealloc(kdf->cipher); - if (status) return status; + if (status) + return status; kdf->cipher = NULL; - return srtp_err_status_ok; + return srtp_err_status_ok; } #endif /* else OPENSSL_KDF */ /* - * end of key derivation functions + * end of key derivation functions */ - - /* Get the base key length corresponding to a given combined key+salt * length for the given cipher. * TODO: key and salt lengths should be separate fields in the policy. */ -static inline int base_key_length(const srtp_cipher_type_t *cipher, int key_length) +static inline int base_key_length(const srtp_cipher_type_t *cipher, + int key_length) { - switch (cipher->id) { - case SRTP_AES_ICM_128: - case SRTP_AES_ICM_192: - case SRTP_AES_ICM_256: - /* The legacy modes are derived from - * the configured key length on the policy */ - return key_length - SRTP_SALT_LEN; - break; - case SRTP_AES_GCM_128: - return key_length - SRTP_AEAD_SALT_LEN; - break; - case SRTP_AES_GCM_256: - return key_length - SRTP_AEAD_SALT_LEN; - break; - default: - return key_length; - break; - } + switch (cipher->id) { + case SRTP_AES_ICM_128: + case SRTP_AES_ICM_192: + case SRTP_AES_ICM_256: + /* The legacy modes are derived from + * the configured key length on the policy */ + return key_length - SRTP_SALT_LEN; + break; + case SRTP_AES_GCM_128: + return key_length - SRTP_AEAD_SALT_LEN; + break; + case SRTP_AES_GCM_256: + return key_length - SRTP_AEAD_SALT_LEN; + break; + default: + return key_length; + break; + } } -unsigned int -srtp_validate_policy_master_keys(const srtp_policy_t *policy) +unsigned int srtp_validate_policy_master_keys(const srtp_policy_t *policy) { - int i = 0; + unsigned long i = 0; if (policy->key == NULL) { if (policy->num_master_keys <= 0) return 0; if (policy->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS) - return 0; - + return 0; + for (i = 0; i < policy->num_master_keys; i++) { if (policy->keys[i]->key == NULL) return 0; - if (policy->keys[i]->mki_size > SRTP_MAX_MKI_LEN) - return 0; + if (policy->keys[i]->mki_size > SRTP_MAX_MKI_LEN) + return 0; } } return 1; } -srtp_session_keys_t* -srtp_get_session_keys_with_mki_index(srtp_stream_ctx_t *stream, - unsigned int use_mki, - unsigned int mki_index) { +srtp_session_keys_t *srtp_get_session_keys_with_mki_index( + srtp_stream_ctx_t *stream, + unsigned int use_mki, + unsigned int mki_index) +{ if (use_mki) { - if (mki_index < stream->num_master_keys) { - return &stream->session_keys[mki_index]; + if (mki_index >= stream->num_master_keys) { + return NULL; } + return &stream->session_keys[mki_index]; } return &stream->session_keys[0]; } -unsigned int -srtp_inject_mki(uint8_t *mki_tag_location, srtp_session_keys_t* session_keys, - unsigned int use_mki) +unsigned int srtp_inject_mki(uint8_t *mki_tag_location, + srtp_session_keys_t *session_keys, + unsigned int use_mki) { unsigned int mki_size = 0; @@ -842,16 +827,17 @@ srtp_inject_mki(uint8_t *mki_tag_location, srtp_session_keys_t* session_keys, return mki_size; } -srtp_err_status_t -srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, - unsigned char *key, - srtp_master_key_t **keys, - const unsigned int max_master_keys) { - int i = 0; +srtp_err_status_t srtp_stream_init_all_master_keys( + srtp_stream_ctx_t *srtp, + unsigned char *key, + srtp_master_key_t **keys, + const unsigned int max_master_keys) +{ + unsigned int i = 0; srtp_err_status_t status = srtp_err_status_ok; srtp_master_key_t single_master_key; - if ( key != NULL ) { + if (key != NULL) { srtp->num_master_keys = 1; single_master_key.key = key; single_master_key.mki_id = NULL; @@ -860,7 +846,8 @@ srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, } else { srtp->num_master_keys = max_master_keys; - for (i = 0; i < srtp->num_master_keys && i < SRTP_MAX_NUM_MASTER_KEYS; i++) { + for (i = 0; i < srtp->num_master_keys && i < SRTP_MAX_NUM_MASTER_KEYS; + i++) { status = srtp_stream_init_keys(srtp, keys[i], i); if (status) { @@ -872,577 +859,609 @@ srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, return status; } -srtp_err_status_t -srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, - const unsigned int current_mki_index) { - srtp_err_status_t stat; - srtp_kdf_t kdf; - uint8_t tmp_key[MAX_SRTP_KEY_LEN]; - int kdf_keylen = 30, rtp_keylen, rtcp_keylen; - int rtp_base_key_len, rtp_salt_len; - int rtcp_base_key_len, rtcp_salt_len; - srtp_session_keys_t *session_keys = NULL; - unsigned char *key = master_key->key; - - /* If RTP or RTCP have a key length > AES-128, assume matching kdf. */ - /* TODO: kdf algorithm, master key length, and master salt length should - * be part of srtp_policy_t. */ - session_keys = &srtp->session_keys[current_mki_index]; - - /* initialize key limit to maximum value */ -#ifdef NO_64BIT_MATH +srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, + srtp_master_key_t *master_key, + const unsigned int current_mki_index) { - uint64_t temp; - temp = make64(UINT_MAX,UINT_MAX); - srtp_key_limit_set(session_keys->limit, temp); -} -#else - srtp_key_limit_set(session_keys->limit, 0xffffffffffffLL); -#endif + srtp_err_status_t stat; + srtp_kdf_t kdf; + uint8_t tmp_key[MAX_SRTP_KEY_LEN]; + int kdf_keylen = 30, rtp_keylen, rtcp_keylen; + int rtp_base_key_len, rtp_salt_len; + int rtcp_base_key_len, rtcp_salt_len; + srtp_session_keys_t *session_keys = NULL; + unsigned char *key = master_key->key; + /* If RTP or RTCP have a key length > AES-128, assume matching kdf. */ + /* TODO: kdf algorithm, master key length, and master salt length should + * be part of srtp_policy_t. + */ + session_keys = &srtp->session_keys[current_mki_index]; - if ( master_key->mki_size != 0 ) { - session_keys->mki_id = srtp_crypto_alloc(master_key->mki_size); - - if (session_keys->mki_id == NULL) { - return srtp_err_status_init_fail; - } - memset(session_keys->mki_id, 0x0, master_key->mki_size); - memcpy(session_keys->mki_id, master_key->mki_id, master_key->mki_size); - } else { - session_keys->mki_id = NULL; - } - - session_keys->mki_size = master_key->mki_size; - - rtp_keylen = srtp_cipher_get_key_length(session_keys->rtp_cipher); - rtcp_keylen = srtp_cipher_get_key_length(session_keys->rtcp_cipher); - rtp_base_key_len = base_key_length(session_keys->rtp_cipher->type, rtp_keylen); - rtp_salt_len = rtp_keylen - rtp_base_key_len; - - if (rtp_keylen > kdf_keylen) { - kdf_keylen = 46; /* AES-CTR mode is always used for KDF */ - } - - if (rtcp_keylen > kdf_keylen) { - kdf_keylen = 46; /* AES-CTR mode is always used for KDF */ - } - - debug_print(mod_srtp, "srtp key len: %d", rtp_keylen); - debug_print(mod_srtp, "srtcp key len: %d", rtcp_keylen); - debug_print(mod_srtp, "base key len: %d", rtp_base_key_len); - debug_print(mod_srtp, "kdf key len: %d", kdf_keylen); - debug_print(mod_srtp, "rtp salt len: %d", rtp_salt_len); - - /* - * Make sure the key given to us is 'zero' appended. GCM - * mode uses a shorter master SALT (96 bits), but still relies on - * the legacy CTR mode KDF, which uses a 112 bit master SALT. - */ - memset(tmp_key, 0x0, MAX_SRTP_KEY_LEN); - memcpy(tmp_key, key, (rtp_base_key_len + rtp_salt_len)); - - /* initialize KDF state */ -#if defined(OPENSSL) && defined(OPENSSL_KDF) - stat = srtp_kdf_init(&kdf, (const uint8_t *)tmp_key, rtp_base_key_len, rtp_salt_len); -#else - stat = srtp_kdf_init(&kdf, (const uint8_t *)tmp_key, kdf_keylen); -#endif - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - - /* generate encryption key */ - stat = srtp_kdf_generate(&kdf, label_rtp_encryption, - tmp_key, rtp_base_key_len); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - debug_print(mod_srtp, "cipher key: %s", - srtp_octet_string_hex_string(tmp_key, rtp_base_key_len)); - - /* - * if the cipher in the srtp context uses a salt, then we need - * to generate the salt value - */ - if (rtp_salt_len > 0) { - debug_print(mod_srtp, "found rtp_salt_len > 0, generating salt", NULL); - - /* generate encryption salt, put after encryption key */ - stat = srtp_kdf_generate(&kdf, label_rtp_salt, - tmp_key + rtp_base_key_len, rtp_salt_len); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; +/* initialize key limit to maximum value */ +#ifdef NO_64BIT_MATH + { + uint64_t temp; + temp = make64(UINT_MAX, UINT_MAX); + srtp_key_limit_set(session_keys->limit, temp); } - memcpy(session_keys->salt, tmp_key + rtp_base_key_len, SRTP_AEAD_SALT_LEN); - } - if (rtp_salt_len > 0) { - debug_print(mod_srtp, "cipher salt: %s", - srtp_octet_string_hex_string(tmp_key + rtp_base_key_len, rtp_salt_len)); - } - - /* initialize cipher */ - stat = srtp_cipher_init(session_keys->rtp_cipher, tmp_key); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - - if (session_keys->rtp_xtn_hdr_cipher) { - /* generate extensions header encryption key */ - int rtp_xtn_hdr_keylen; - int rtp_xtn_hdr_base_key_len; - int rtp_xtn_hdr_salt_len; - srtp_kdf_t tmp_kdf; - srtp_kdf_t *xtn_hdr_kdf; - - if (session_keys->rtp_xtn_hdr_cipher->type != session_keys->rtp_cipher->type) { - /* With GCM ciphers, the header extensions are still encrypted using the corresponding ICM cipher. */ - /* See https://tools.ietf.org/html/rfc7714#section-8.3 */ - uint8_t tmp_xtn_hdr_key[MAX_SRTP_KEY_LEN]; - rtp_xtn_hdr_keylen = srtp_cipher_get_key_length(session_keys->rtp_xtn_hdr_cipher); - rtp_xtn_hdr_base_key_len = base_key_length(session_keys->rtp_xtn_hdr_cipher->type, - rtp_xtn_hdr_keylen); - rtp_xtn_hdr_salt_len = rtp_xtn_hdr_keylen - rtp_xtn_hdr_base_key_len; - if (rtp_xtn_hdr_salt_len > rtp_salt_len) { - switch (session_keys->rtp_cipher->type->id) { - case SRTP_AES_GCM_128: - case SRTP_AES_GCM_256: - /* The shorter GCM salt is padded to the required ICM salt length. */ - rtp_xtn_hdr_salt_len = rtp_salt_len; - break; - default: - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_bad_param; - } - } - memset(tmp_xtn_hdr_key, 0x0, MAX_SRTP_KEY_LEN); - memcpy(tmp_xtn_hdr_key, key, (rtp_xtn_hdr_base_key_len + rtp_xtn_hdr_salt_len)); - xtn_hdr_kdf = &tmp_kdf; - - /* initialize KDF state */ -#if defined(OPENSSL) && defined(OPENSSL_KDF) - stat = srtp_kdf_init(xtn_hdr_kdf, (const uint8_t *)tmp_xtn_hdr_key, rtp_xtn_hdr_base_key_len, rtp_xtn_hdr_salt_len); #else - stat = srtp_kdf_init(xtn_hdr_kdf, (const uint8_t *)tmp_xtn_hdr_key, kdf_keylen); + srtp_key_limit_set(session_keys->limit, 0xffffffffffffLL); #endif - octet_string_set_to_zero(tmp_xtn_hdr_key, MAX_SRTP_KEY_LEN); - if (stat) { + + if (master_key->mki_size != 0) { + session_keys->mki_id = srtp_crypto_alloc(master_key->mki_size); + + if (session_keys->mki_id == NULL) { + return srtp_err_status_init_fail; + } + memcpy(session_keys->mki_id, master_key->mki_id, master_key->mki_size); + } else { + session_keys->mki_id = NULL; + } + + session_keys->mki_size = master_key->mki_size; + + rtp_keylen = srtp_cipher_get_key_length(session_keys->rtp_cipher); + rtcp_keylen = srtp_cipher_get_key_length(session_keys->rtcp_cipher); + rtp_base_key_len = + base_key_length(session_keys->rtp_cipher->type, rtp_keylen); + rtp_salt_len = rtp_keylen - rtp_base_key_len; + + if (rtp_keylen > kdf_keylen) { + kdf_keylen = 46; /* AES-CTR mode is always used for KDF */ + } + + if (rtcp_keylen > kdf_keylen) { + kdf_keylen = 46; /* AES-CTR mode is always used for KDF */ + } + + debug_print(mod_srtp, "srtp key len: %d", rtp_keylen); + debug_print(mod_srtp, "srtcp key len: %d", rtcp_keylen); + debug_print(mod_srtp, "base key len: %d", rtp_base_key_len); + debug_print(mod_srtp, "kdf key len: %d", kdf_keylen); + debug_print(mod_srtp, "rtp salt len: %d", rtp_salt_len); + + /* + * Make sure the key given to us is 'zero' appended. GCM + * mode uses a shorter master SALT (96 bits), but still relies on + * the legacy CTR mode KDF, which uses a 112 bit master SALT. + */ + memset(tmp_key, 0x0, MAX_SRTP_KEY_LEN); + memcpy(tmp_key, key, (rtp_base_key_len + rtp_salt_len)); + +/* initialize KDF state */ +#if defined(OPENSSL) && defined(OPENSSL_KDF) + stat = srtp_kdf_init(&kdf, (const uint8_t *)tmp_key, rtp_base_key_len, + rtp_salt_len); +#else + stat = srtp_kdf_init(&kdf, (const uint8_t *)tmp_key, kdf_keylen); +#endif + if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); return srtp_err_status_init_fail; - } - } else { - /* Reuse main KDF. */ - rtp_xtn_hdr_keylen = rtp_keylen; - rtp_xtn_hdr_base_key_len = rtp_base_key_len; - rtp_xtn_hdr_salt_len = rtp_salt_len; - xtn_hdr_kdf = &kdf; } - stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_encryption, - tmp_key, rtp_xtn_hdr_base_key_len); + /* generate encryption key */ + stat = srtp_kdf_generate(&kdf, label_rtp_encryption, tmp_key, + rtp_base_key_len); if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; } - debug_print(mod_srtp, "extensions cipher key: %s", - srtp_octet_string_hex_string(tmp_key, rtp_xtn_hdr_base_key_len)); + debug_print(mod_srtp, "cipher key: %s", + srtp_octet_string_hex_string(tmp_key, rtp_base_key_len)); /* * if the cipher in the srtp context uses a salt, then we need * to generate the salt value */ - if (rtp_xtn_hdr_salt_len > 0) { - debug_print(mod_srtp, "found rtp_xtn_hdr_salt_len > 0, generating salt", NULL); + if (rtp_salt_len > 0) { + debug_print(mod_srtp, "found rtp_salt_len > 0, generating salt", NULL); - /* generate encryption salt, put after encryption key */ - stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_salt, - tmp_key + rtp_xtn_hdr_base_key_len, rtp_xtn_hdr_salt_len); - if (stat) { + /* generate encryption salt, put after encryption key */ + stat = srtp_kdf_generate(&kdf, label_rtp_salt, + tmp_key + rtp_base_key_len, rtp_salt_len); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + memcpy(session_keys->salt, tmp_key + rtp_base_key_len, + SRTP_AEAD_SALT_LEN); + } + if (rtp_salt_len > 0) { + debug_print(mod_srtp, "cipher salt: %s", + srtp_octet_string_hex_string(tmp_key + rtp_base_key_len, + rtp_salt_len)); + } + + /* initialize cipher */ + stat = srtp_cipher_init(session_keys->rtp_cipher, tmp_key); + if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); return srtp_err_status_init_fail; - } - } - if (rtp_xtn_hdr_salt_len > 0) { - debug_print(mod_srtp, "extensions cipher salt: %s", - srtp_octet_string_hex_string(tmp_key + rtp_xtn_hdr_base_key_len, rtp_xtn_hdr_salt_len)); } - /* initialize extensions header cipher */ - stat = srtp_cipher_init(session_keys->rtp_xtn_hdr_cipher, tmp_key); + if (session_keys->rtp_xtn_hdr_cipher) { + /* generate extensions header encryption key */ + int rtp_xtn_hdr_keylen; + int rtp_xtn_hdr_base_key_len; + int rtp_xtn_hdr_salt_len; + srtp_kdf_t tmp_kdf; + srtp_kdf_t *xtn_hdr_kdf; + + if (session_keys->rtp_xtn_hdr_cipher->type != + session_keys->rtp_cipher->type) { + /* + * With GCM ciphers, the header extensions are still encrypted using + * the corresponding ICM cipher. + * See https://tools.ietf.org/html/rfc7714#section-8.3 + */ + uint8_t tmp_xtn_hdr_key[MAX_SRTP_KEY_LEN]; + rtp_xtn_hdr_keylen = + srtp_cipher_get_key_length(session_keys->rtp_xtn_hdr_cipher); + rtp_xtn_hdr_base_key_len = base_key_length( + session_keys->rtp_xtn_hdr_cipher->type, rtp_xtn_hdr_keylen); + rtp_xtn_hdr_salt_len = + rtp_xtn_hdr_keylen - rtp_xtn_hdr_base_key_len; + if (rtp_xtn_hdr_salt_len > rtp_salt_len) { + switch (session_keys->rtp_cipher->type->id) { + case SRTP_AES_GCM_128: + case SRTP_AES_GCM_256: + /* + * The shorter GCM salt is padded to the required ICM salt + * length. + */ + rtp_xtn_hdr_salt_len = rtp_salt_len; + break; + default: + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_bad_param; + } + } + memset(tmp_xtn_hdr_key, 0x0, MAX_SRTP_KEY_LEN); + memcpy(tmp_xtn_hdr_key, key, + (rtp_xtn_hdr_base_key_len + rtp_xtn_hdr_salt_len)); + xtn_hdr_kdf = &tmp_kdf; + +/* initialize KDF state */ +#if defined(OPENSSL) && defined(OPENSSL_KDF) + stat = + srtp_kdf_init(xtn_hdr_kdf, (const uint8_t *)tmp_xtn_hdr_key, + rtp_xtn_hdr_base_key_len, rtp_xtn_hdr_salt_len); +#else + stat = srtp_kdf_init(xtn_hdr_kdf, (const uint8_t *)tmp_xtn_hdr_key, + kdf_keylen); +#endif + octet_string_set_to_zero(tmp_xtn_hdr_key, MAX_SRTP_KEY_LEN); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + } else { + /* Reuse main KDF. */ + rtp_xtn_hdr_keylen = rtp_keylen; + rtp_xtn_hdr_base_key_len = rtp_base_key_len; + rtp_xtn_hdr_salt_len = rtp_salt_len; + xtn_hdr_kdf = &kdf; + } + + stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_encryption, + tmp_key, rtp_xtn_hdr_base_key_len); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + debug_print( + mod_srtp, "extensions cipher key: %s", + srtp_octet_string_hex_string(tmp_key, rtp_xtn_hdr_base_key_len)); + + /* + * if the cipher in the srtp context uses a salt, then we need + * to generate the salt value + */ + if (rtp_xtn_hdr_salt_len > 0) { + debug_print(mod_srtp, + "found rtp_xtn_hdr_salt_len > 0, generating salt", + NULL); + + /* generate encryption salt, put after encryption key */ + stat = srtp_kdf_generate(xtn_hdr_kdf, label_rtp_header_salt, + tmp_key + rtp_xtn_hdr_base_key_len, + rtp_xtn_hdr_salt_len); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + } + if (rtp_xtn_hdr_salt_len > 0) { + debug_print( + mod_srtp, "extensions cipher salt: %s", + srtp_octet_string_hex_string(tmp_key + rtp_xtn_hdr_base_key_len, + rtp_xtn_hdr_salt_len)); + } + + /* initialize extensions header cipher */ + stat = srtp_cipher_init(session_keys->rtp_xtn_hdr_cipher, tmp_key); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + + if (xtn_hdr_kdf != &kdf) { + /* release memory for custom header extension encryption kdf */ + stat = srtp_kdf_clear(xtn_hdr_kdf); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + } + } + + /* generate authentication key */ + stat = srtp_kdf_generate(&kdf, label_rtp_msg_auth, tmp_key, + srtp_auth_get_key_length(session_keys->rtp_auth)); if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - - if (xtn_hdr_kdf != &kdf) { - /* release memory for custom header extension encryption kdf */ - stat = srtp_kdf_clear(xtn_hdr_kdf); - if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); return srtp_err_status_init_fail; - } } - } + debug_print(mod_srtp, "auth key: %s", + srtp_octet_string_hex_string( + tmp_key, srtp_auth_get_key_length(session_keys->rtp_auth))); - /* generate authentication key */ - stat = srtp_kdf_generate(&kdf, label_rtp_msg_auth, - tmp_key, srtp_auth_get_key_length(session_keys->rtp_auth)); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - debug_print(mod_srtp, "auth key: %s", - srtp_octet_string_hex_string(tmp_key, - srtp_auth_get_key_length(session_keys->rtp_auth))); - - /* initialize auth function */ - stat = srtp_auth_init(session_keys->rtp_auth, tmp_key); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - - /* - * ...now initialize SRTCP keys - */ - - rtcp_base_key_len = base_key_length(session_keys->rtcp_cipher->type, rtcp_keylen); - rtcp_salt_len = rtcp_keylen - rtcp_base_key_len; - debug_print(mod_srtp, "rtcp salt len: %d", rtcp_salt_len); - - /* generate encryption key */ - stat = srtp_kdf_generate(&kdf, label_rtcp_encryption, - tmp_key, rtcp_base_key_len); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - - /* - * if the cipher in the srtp context uses a salt, then we need - * to generate the salt value - */ - if (rtcp_salt_len > 0) { - debug_print(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt", - NULL); - - /* generate encryption salt, put after encryption key */ - stat = srtp_kdf_generate(&kdf, label_rtcp_salt, - tmp_key + rtcp_base_key_len, rtcp_salt_len); + /* initialize auth function */ + stat = srtp_auth_init(session_keys->rtp_auth, tmp_key); if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; } - memcpy(session_keys->c_salt, tmp_key + rtcp_base_key_len, SRTP_AEAD_SALT_LEN); - } - debug_print(mod_srtp, "rtcp cipher key: %s", - srtp_octet_string_hex_string(tmp_key, rtcp_base_key_len)); - if (rtcp_salt_len > 0) { - debug_print(mod_srtp, "rtcp cipher salt: %s", - srtp_octet_string_hex_string(tmp_key + rtcp_base_key_len, rtcp_salt_len)); - } - /* initialize cipher */ - stat = srtp_cipher_init(session_keys->rtcp_cipher, tmp_key); - if (stat) { - /* zeroize temp buffer */ + /* + * ...now initialize SRTCP keys + */ + + rtcp_base_key_len = + base_key_length(session_keys->rtcp_cipher->type, rtcp_keylen); + rtcp_salt_len = rtcp_keylen - rtcp_base_key_len; + debug_print(mod_srtp, "rtcp salt len: %d", rtcp_salt_len); + + /* generate encryption key */ + stat = srtp_kdf_generate(&kdf, label_rtcp_encryption, tmp_key, + rtcp_base_key_len); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + + /* + * if the cipher in the srtp context uses a salt, then we need + * to generate the salt value + */ + if (rtcp_salt_len > 0) { + debug_print(mod_srtp, "found rtcp_salt_len > 0, generating rtcp salt", + NULL); + + /* generate encryption salt, put after encryption key */ + stat = srtp_kdf_generate(&kdf, label_rtcp_salt, + tmp_key + rtcp_base_key_len, rtcp_salt_len); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + memcpy(session_keys->c_salt, tmp_key + rtcp_base_key_len, + SRTP_AEAD_SALT_LEN); + } + debug_print(mod_srtp, "rtcp cipher key: %s", + srtp_octet_string_hex_string(tmp_key, rtcp_base_key_len)); + if (rtcp_salt_len > 0) { + debug_print(mod_srtp, "rtcp cipher salt: %s", + srtp_octet_string_hex_string(tmp_key + rtcp_base_key_len, + rtcp_salt_len)); + } + + /* initialize cipher */ + stat = srtp_cipher_init(session_keys->rtcp_cipher, tmp_key); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + + /* generate authentication key */ + stat = srtp_kdf_generate(&kdf, label_rtcp_msg_auth, tmp_key, + srtp_auth_get_key_length(session_keys->rtcp_auth)); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + + debug_print( + mod_srtp, "rtcp auth key: %s", + srtp_octet_string_hex_string( + tmp_key, srtp_auth_get_key_length(session_keys->rtcp_auth))); + + /* initialize auth function */ + stat = srtp_auth_init(session_keys->rtcp_auth, tmp_key); + if (stat) { + /* zeroize temp buffer */ + octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); + return srtp_err_status_init_fail; + } + + /* clear memory then return */ + stat = srtp_kdf_clear(&kdf); octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } + if (stat) + return srtp_err_status_init_fail; - /* generate authentication key */ - stat = srtp_kdf_generate(&kdf, label_rtcp_msg_auth, - tmp_key, srtp_auth_get_key_length(session_keys->rtcp_auth)); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - - debug_print(mod_srtp, "rtcp auth key: %s", - srtp_octet_string_hex_string(tmp_key, - srtp_auth_get_key_length(session_keys->rtcp_auth))); - - /* initialize auth function */ - stat = srtp_auth_init(session_keys->rtcp_auth, tmp_key); - if (stat) { - /* zeroize temp buffer */ - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - return srtp_err_status_init_fail; - } - - /* clear memory then return */ - stat = srtp_kdf_clear(&kdf); - octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); - if (stat) - return srtp_err_status_init_fail; - - return srtp_err_status_ok; + return srtp_err_status_ok; } -srtp_err_status_t -srtp_stream_init(srtp_stream_ctx_t *srtp, - const srtp_policy_t *p) { - srtp_err_status_t err; +srtp_err_status_t srtp_stream_init(srtp_stream_ctx_t *srtp, + const srtp_policy_t *p) +{ + srtp_err_status_t err; - debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)", - p->ssrc.value); + debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)", p->ssrc.value); - /* initialize replay database */ - /* window size MUST be at least 64. MAY be larger. Values more than - * 2^15 aren't meaningful due to how extended sequence numbers are - * calculated. Let a window size of 0 imply the default value. */ + /* initialize replay database */ + /* + * window size MUST be at least 64. MAY be larger. Values more than + * 2^15 aren't meaningful due to how extended sequence numbers are + * calculated. + * Let a window size of 0 imply the default value. + */ - if (p->window_size != 0 && (p->window_size < 64 || p->window_size >= 0x8000)) - return srtp_err_status_bad_param; + if (p->window_size != 0 && + (p->window_size < 64 || p->window_size >= 0x8000)) + return srtp_err_status_bad_param; - if (p->window_size != 0) - err = srtp_rdbx_init(&srtp->rtp_rdbx, p->window_size); - else - err = srtp_rdbx_init(&srtp->rtp_rdbx, 128); - if (err) return err; + if (p->window_size != 0) + err = srtp_rdbx_init(&srtp->rtp_rdbx, p->window_size); + else + err = srtp_rdbx_init(&srtp->rtp_rdbx, 128); + if (err) + return err; - /* set the SSRC value */ - srtp->ssrc = htonl(p->ssrc.value); + /* set the SSRC value */ + srtp->ssrc = htonl(p->ssrc.value); - /* reset pending ROC */ - srtp->pending_roc = 0; + /* reset pending ROC */ + srtp->pending_roc = 0; - /* set the security service flags */ - srtp->rtp_services = p->rtp.sec_serv; - srtp->rtcp_services = p->rtcp.sec_serv; + /* set the security service flags */ + srtp->rtp_services = p->rtp.sec_serv; + srtp->rtcp_services = p->rtcp.sec_serv; - /* - * set direction to unknown - this flag gets checked in srtp_protect(), - * srtp_unprotect(), srtp_protect_rtcp(), and srtp_unprotect_rtcp(), and - * gets set appropriately if it is set to unknown. - */ - srtp->direction = dir_unknown; + /* + * set direction to unknown - this flag gets checked in srtp_protect(), + * srtp_unprotect(), srtp_protect_rtcp(), and srtp_unprotect_rtcp(), and + * gets set appropriately if it is set to unknown. + */ + srtp->direction = dir_unknown; - /* initialize SRTCP replay database */ - srtp_rdb_init(&srtp->rtcp_rdb); + /* initialize SRTCP replay database */ + srtp_rdb_init(&srtp->rtcp_rdb); - /* initialize allow_repeat_tx */ - /* guard against uninitialized memory: allow only 0 or 1 here */ - if (p->allow_repeat_tx != 0 && p->allow_repeat_tx != 1) { - srtp_rdbx_dealloc(&srtp->rtp_rdbx); - return srtp_err_status_bad_param; - } - srtp->allow_repeat_tx = p->allow_repeat_tx; + /* initialize allow_repeat_tx */ + /* guard against uninitialized memory: allow only 0 or 1 here */ + if (p->allow_repeat_tx != 0 && p->allow_repeat_tx != 1) { + srtp_rdbx_dealloc(&srtp->rtp_rdbx); + return srtp_err_status_bad_param; + } + srtp->allow_repeat_tx = p->allow_repeat_tx; - /* DAM - no RTCP key limit at present */ + /* DAM - no RTCP key limit at present */ - /* initialize keys */ - err = srtp_stream_init_all_master_keys(srtp, p->key, p->keys, p->num_master_keys); - if (err) { - srtp_rdbx_dealloc(&srtp->rtp_rdbx); - return err; - } + /* initialize keys */ + err = srtp_stream_init_all_master_keys(srtp, p->key, p->keys, + p->num_master_keys); + if (err) { + srtp_rdbx_dealloc(&srtp->rtp_rdbx); + return err; + } - /* - * if EKT is in use, then initialize the EKT data associated with - * the stream - */ - err = srtp_ekt_stream_init_from_policy(srtp->ekt, p->ekt); - if (err) { - srtp_rdbx_dealloc(&srtp->rtp_rdbx); - return err; - } + /* + * if EKT is in use, then initialize the EKT data associated with + * the stream + */ + err = srtp_ekt_stream_init_from_policy(srtp->ekt, p->ekt); + if (err) { + srtp_rdbx_dealloc(&srtp->rtp_rdbx); + return err; + } - return srtp_err_status_ok; - } + return srtp_err_status_ok; +} +/* + * srtp_event_reporter is an event handler function that merely + * reports the events that are reported by the callbacks + */ - /* - * srtp_event_reporter is an event handler function that merely - * reports the events that are reported by the callbacks - */ +void srtp_event_reporter(srtp_event_data_t *data) +{ + srtp_err_report(srtp_err_level_warning, "srtp: in stream 0x%x: ", + data->ssrc); - void - srtp_event_reporter(srtp_event_data_t *data) { + switch (data->event) { + case event_ssrc_collision: + srtp_err_report(srtp_err_level_warning, "\tSSRC collision\n"); + break; + case event_key_soft_limit: + srtp_err_report(srtp_err_level_warning, + "\tkey usage soft limit reached\n"); + break; + case event_key_hard_limit: + srtp_err_report(srtp_err_level_warning, + "\tkey usage hard limit reached\n"); + break; + case event_packet_index_limit: + srtp_err_report(srtp_err_level_warning, + "\tpacket index limit reached\n"); + break; + default: + srtp_err_report(srtp_err_level_warning, + "\tunknown event reported to handler\n"); + } +} - srtp_err_report(srtp_err_level_warning, "srtp: in stream 0x%x: ", - data->ssrc); +/* + * srtp_event_handler is a global variable holding a pointer to the + * event handler function; this function is called for any unexpected + * event that needs to be handled out of the SRTP data path. see + * srtp_event_t in srtp.h for more info + * + * it is okay to set srtp_event_handler to NULL, but we set + * it to the srtp_event_reporter. + */ - switch(data->event) { - case event_ssrc_collision: - srtp_err_report(srtp_err_level_warning, "\tSSRC collision\n"); - break; - case event_key_soft_limit: - srtp_err_report(srtp_err_level_warning, "\tkey usage soft limit reached\n"); - break; - case event_key_hard_limit: - srtp_err_report(srtp_err_level_warning, "\tkey usage hard limit reached\n"); - break; - case event_packet_index_limit: - srtp_err_report(srtp_err_level_warning, "\tpacket index limit reached\n"); - break; - default: - srtp_err_report(srtp_err_level_warning, "\tunknown event reported to handler\n"); - } - } +static srtp_event_handler_func_t *srtp_event_handler = srtp_event_reporter; - /* - * srtp_event_handler is a global variable holding a pointer to the - * event handler function; this function is called for any unexpected - * event that needs to be handled out of the SRTP data path. see - * srtp_event_t in srtp.h for more info - * - * it is okay to set srtp_event_handler to NULL, but we set - * it to the srtp_event_reporter. - */ - - static srtp_event_handler_func_t *srtp_event_handler = srtp_event_reporter; - - srtp_err_status_t - srtp_install_event_handler(srtp_event_handler_func_t func) { - - /* - * note that we accept NULL arguments intentionally - calling this - * function with a NULL arguments removes an event handler that's - * been previously installed - */ - - /* set global event handling function */ - srtp_event_handler = func; - return srtp_err_status_ok; - } +srtp_err_status_t srtp_install_event_handler(srtp_event_handler_func_t func) +{ + /* + * note that we accept NULL arguments intentionally - calling this + * function with a NULL arguments removes an event handler that's + * been previously installed + */ + /* set global event handling function */ + srtp_event_handler = func; + return srtp_err_status_ok; +} /* * Check if the given extension header id is / should be encrypted. * Returns 1 if yes, otherwise 0. */ -static int -srtp_protect_extension_header(srtp_stream_ctx_t *stream, int id) { - int* enc_xtn_hdr = stream->enc_xtn_hdr; - int count = stream->enc_xtn_hdr_count; +static int srtp_protect_extension_header(srtp_stream_ctx_t *stream, int id) +{ + int *enc_xtn_hdr = stream->enc_xtn_hdr; + int count = stream->enc_xtn_hdr_count; - if (!enc_xtn_hdr || count <= 0) { - return 0; - } - - while (count > 0) { - if (*enc_xtn_hdr == id) { - return 1; + if (!enc_xtn_hdr || count <= 0) { + return 0; } - enc_xtn_hdr++; - count--; - } - return 0; -} + while (count > 0) { + if (*enc_xtn_hdr == id) { + return 1; + } + enc_xtn_hdr++; + count--; + } + return 0; +} /* * extensions header encryption RFC 6904 */ -static srtp_err_status_t -srtp_process_header_encryption(srtp_stream_ctx_t *stream, - srtp_hdr_xtnd_t *xtn_hdr, - srtp_session_keys_t *session_keys) { - srtp_err_status_t status; - uint8_t keystream[257]; /* Maximum 2 bytes header + 255 bytes data. */ - int keystream_pos; - uint8_t* xtn_hdr_data = ((uint8_t *)xtn_hdr) + octets_in_rtp_extn_hdr; - uint8_t* xtn_hdr_end = xtn_hdr_data + (ntohs(xtn_hdr->length) * sizeof(uint32_t)); +static srtp_err_status_t srtp_process_header_encryption( + srtp_stream_ctx_t *stream, + srtp_hdr_xtnd_t *xtn_hdr, + srtp_session_keys_t *session_keys) +{ + srtp_err_status_t status; + uint8_t keystream[257]; /* Maximum 2 bytes header + 255 bytes data. */ + int keystream_pos; + uint8_t *xtn_hdr_data = ((uint8_t *)xtn_hdr) + octets_in_rtp_extn_hdr; + uint8_t *xtn_hdr_end = + xtn_hdr_data + (ntohs(xtn_hdr->length) * sizeof(uint32_t)); - if (ntohs(xtn_hdr->profile_specific) == 0xbede) { - /* RFC 5285, section 4.2. One-Byte Header */ - while (xtn_hdr_data < xtn_hdr_end) { - uint8_t xid = (*xtn_hdr_data & 0xf0) >> 4; - unsigned int xlen = (*xtn_hdr_data & 0x0f) + 1; - uint32_t xlen_with_header = 1+xlen; - xtn_hdr_data++; + if (ntohs(xtn_hdr->profile_specific) == 0xbede) { + /* RFC 5285, section 4.2. One-Byte Header */ + while (xtn_hdr_data < xtn_hdr_end) { + uint8_t xid = (*xtn_hdr_data & 0xf0) >> 4; + unsigned int xlen = (*xtn_hdr_data & 0x0f) + 1; + uint32_t xlen_with_header = 1 + xlen; + xtn_hdr_data++; - if (xtn_hdr_data + xlen > xtn_hdr_end) - return srtp_err_status_parse_err; + if (xtn_hdr_data + xlen > xtn_hdr_end) + return srtp_err_status_parse_err; - if (xid == 15) { - /* found header 15, stop further processing. */ - break; - } + if (xid == 15) { + /* found header 15, stop further processing. */ + break; + } - status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, - keystream, &xlen_with_header); - if (status) - return srtp_err_status_cipher_fail; + status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, + keystream, &xlen_with_header); + if (status) + return srtp_err_status_cipher_fail; - if (srtp_protect_extension_header(stream, xid)) { - keystream_pos = 1; - while (xlen > 0) { - *xtn_hdr_data ^= keystream[keystream_pos++]; - xtn_hdr_data++; - xlen--; + if (srtp_protect_extension_header(stream, xid)) { + keystream_pos = 1; + while (xlen > 0) { + *xtn_hdr_data ^= keystream[keystream_pos++]; + xtn_hdr_data++; + xlen--; + } + } else { + xtn_hdr_data += xlen; + } + + /* skip padding bytes. */ + while (xtn_hdr_data < xtn_hdr_end && *xtn_hdr_data == 0) { + xtn_hdr_data++; + } } - } else { - xtn_hdr_data += xlen; - } + } else if ((ntohs(xtn_hdr->profile_specific) & 0x1fff) == 0x100) { + /* RFC 5285, section 4.3. Two-Byte Header */ + while (xtn_hdr_data + 1 < xtn_hdr_end) { + uint8_t xid = *xtn_hdr_data; + unsigned int xlen = *(xtn_hdr_data + 1); + uint32_t xlen_with_header = 2 + xlen; + xtn_hdr_data += 2; - /* skip padding bytes. */ - while (xtn_hdr_data < xtn_hdr_end && *xtn_hdr_data == 0) { - xtn_hdr_data++; - } - } - } else if ((ntohs(xtn_hdr->profile_specific) & 0x1fff) == 0x100) { - /* RFC 5285, section 4.3. Two-Byte Header */ - while (xtn_hdr_data + 1 < xtn_hdr_end) { - uint8_t xid = *xtn_hdr_data; - unsigned int xlen = *(xtn_hdr_data+1); - uint32_t xlen_with_header = 2+xlen; - xtn_hdr_data += 2; + if (xtn_hdr_data + xlen > xtn_hdr_end) + return srtp_err_status_parse_err; - if (xtn_hdr_data + xlen > xtn_hdr_end) - return srtp_err_status_parse_err; + status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, + keystream, &xlen_with_header); + if (status) + return srtp_err_status_cipher_fail; - status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, - keystream, &xlen_with_header); - if (status) - return srtp_err_status_cipher_fail; + if (xlen > 0 && srtp_protect_extension_header(stream, xid)) { + keystream_pos = 2; + while (xlen > 0) { + *xtn_hdr_data ^= keystream[keystream_pos++]; + xtn_hdr_data++; + xlen--; + } + } else { + xtn_hdr_data += xlen; + } - if (xlen > 0 && srtp_protect_extension_header(stream, xid)) { - keystream_pos = 2; - while (xlen > 0) { - *xtn_hdr_data ^= keystream[keystream_pos++]; - xtn_hdr_data++; - xlen--; + /* skip padding bytes. */ + while (xtn_hdr_data < xtn_hdr_end && *xtn_hdr_data == 0) { + xtn_hdr_data++; + } } - } else { - xtn_hdr_data += xlen; - } - - /* skip padding bytes. */ - while (xtn_hdr_data < xtn_hdr_end && *xtn_hdr_data == 0) { - xtn_hdr_data++; - } + } else { + /* unsupported extension header format. */ + return srtp_err_status_parse_err; } - } else { - /* unsupported extension header format. */ - return srtp_err_status_parse_err; - } - return srtp_err_status_ok; + return srtp_err_status_ok; } - /* * AEAD uses a new IV formation method. This function implements * section 8.1. (SRTP IV Formation for AES-GCM) of RFC7714. @@ -1464,7 +1483,7 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, * +--+--+--+--+--+--+--+--+--+--+--+--+* * * Input: *session_keys - pointer to SRTP stream context session keys, - * used to retrieve the SALT + * used to retrieve the SALT * *iv - Pointer to receive the calculated IV * *seq - The ROC and SEQ value to use for the * IV calculation. @@ -1472,19 +1491,20 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, * */ -static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys, v128_t *iv, - srtp_xtd_seq_num_t *seq, srtp_hdr_t *hdr) +static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys, + v128_t *iv, + srtp_xtd_seq_num_t *seq, + srtp_hdr_t *hdr) { - v128_t in; - v128_t salt; + v128_t in; + v128_t salt; #ifdef NO_64BIT_MATH - uint32_t local_roc = ((high32(*seq) << 16) | - (low32(*seq) >> 16)); - uint16_t local_seq = (uint16_t) (low32(*seq)); + uint32_t local_roc = ((high32(*seq) << 16) | (low32(*seq) >> 16)); + uint16_t local_seq = (uint16_t)(low32(*seq)); #else uint32_t local_roc = (uint32_t)(*seq >> 16); - uint16_t local_seq = (uint16_t) *seq; + uint16_t local_seq = (uint16_t)*seq; #endif memset(&in, 0, sizeof(v128_t)); @@ -1512,149 +1532,145 @@ static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys, v128_t *iv, v128_xor(iv, &in, &salt); } +srtp_session_keys_t *srtp_get_session_keys(srtp_stream_ctx_t *stream, + uint8_t *hdr, + const unsigned int *pkt_octet_len, + unsigned int *mki_size) +{ + unsigned int base_mki_start_location = *pkt_octet_len; + unsigned int mki_start_location = 0; + unsigned int tag_len = 0; + unsigned int i = 0; -srtp_session_keys_t* -srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr, - const unsigned int* pkt_octet_len, - unsigned int* mki_size) { - unsigned int base_mki_start_location = *pkt_octet_len; - unsigned int mki_start_location = 0; - unsigned int tag_len = 0; - unsigned int i = 0; + // Determine the authentication tag size + if (stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_GCM_128 || + stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_GCM_256) { + tag_len = 0; + } else { + tag_len = srtp_auth_get_tag_length(stream->session_keys[0].rtp_auth); + } - // Determine the authentication tag size - if (stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_GCM_128 || - stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_GCM_256) { - tag_len = 0; - } else { - tag_len = srtp_auth_get_tag_length(stream->session_keys[0].rtp_auth); - } + if (tag_len > base_mki_start_location) { + *mki_size = 0; + return NULL; + } - if (tag_len > base_mki_start_location) { - *mki_size = 0; - return NULL; - } + base_mki_start_location -= tag_len; - base_mki_start_location -= tag_len; + for (i = 0; i < stream->num_master_keys; i++) { + if (stream->session_keys[i].mki_size != 0 && + stream->session_keys[i].mki_size <= base_mki_start_location) { + *mki_size = stream->session_keys[i].mki_size; + mki_start_location = base_mki_start_location - *mki_size; - for (i = 0; i < stream->num_master_keys; i++) { - if (stream->session_keys[i].mki_size != 0) { - *mki_size = stream->session_keys[i].mki_size; - mki_start_location = base_mki_start_location - *mki_size; + if (memcmp(hdr + mki_start_location, stream->session_keys[i].mki_id, + *mki_size) == 0) { + return &stream->session_keys[i]; + } + } + } - if ( mki_start_location >= *mki_size && - memcmp(hdr + mki_start_location, stream->session_keys[i].mki_id, *mki_size) == 0 ) { - return &stream->session_keys[i]; - } - } - } - - *mki_size = 0; - return NULL; + *mki_size = 0; + return NULL; } -static srtp_err_status_t -srtp_estimate_index(srtp_rdbx_t *rdbx, - uint32_t roc, - srtp_xtd_seq_num_t *est, - srtp_sequence_number_t seq, - int *delta) +static srtp_err_status_t srtp_estimate_index(srtp_rdbx_t *rdbx, + uint32_t roc, + srtp_xtd_seq_num_t *est, + srtp_sequence_number_t seq, + int *delta) { #ifdef NO_64BIT_MATH - uint32_t internal_pkt_idx_reduced; - uint32_t external_pkt_idx_reduced; - uint32_t internal_roc; - uint32_t roc_difference; + uint32_t internal_pkt_idx_reduced; + uint32_t external_pkt_idx_reduced; + uint32_t internal_roc; + uint32_t roc_difference; #endif #ifdef NO_64BIT_MATH - *est = (srtp_xtd_seq_num_t)make64(roc >> 16, (roc << 16) | seq); - *delta = low32(est) - rdbx->index; + *est = (srtp_xtd_seq_num_t)make64(roc >> 16, (roc << 16) | seq); + *delta = low32(est) - rdbx->index; #else - *est = (srtp_xtd_seq_num_t)(((uint64_t)roc) << 16) | seq; - *delta = (int)(*est - rdbx->index); + *est = (srtp_xtd_seq_num_t)(((uint64_t)roc) << 16) | seq; + *delta = (int)(*est - rdbx->index); #endif - if (*est > rdbx->index) { + if (*est > rdbx->index) { #ifdef NO_64BIT_MATH - internal_roc = (uint32_t)(rdbx->index >> 16); - roc_difference = roc - internal_roc; - if (roc_difference > 1) { - *delta = 0; - return srtp_err_status_pkt_idx_adv; - } + internal_roc = (uint32_t)(rdbx->index >> 16); + roc_difference = roc - internal_roc; + if (roc_difference > 1) { + *delta = 0; + return srtp_err_status_pkt_idx_adv; + } - internal_pkt_idx_reduced = (uint32_t)(rdbx->index & 0xFFFF); - external_pkt_idx_reduced = (uint32_t)((roc_difference << 16) | seq); + internal_pkt_idx_reduced = (uint32_t)(rdbx->index & 0xFFFF); + external_pkt_idx_reduced = (uint32_t)((roc_difference << 16) | seq); - if (external_pkt_idx_reduced - internal_pkt_idx_reduced > - seq_num_median) { - *delta = 0; - return srtp_err_status_pkt_idx_adv; - } + if (external_pkt_idx_reduced - internal_pkt_idx_reduced > + seq_num_median) { + *delta = 0; + return srtp_err_status_pkt_idx_adv; + } #else - if (*est - rdbx->index > seq_num_median) { - *delta = 0; - return srtp_err_status_pkt_idx_adv; - } + if (*est - rdbx->index > seq_num_median) { + *delta = 0; + return srtp_err_status_pkt_idx_adv; + } #endif - } else if (*est < rdbx->index) { + } else if (*est < rdbx->index) { #ifdef NO_64BIT_MATH - internal_roc = (uint32_t)(rdbx->index >> 16); - roc_difference = internal_roc - roc; - if (roc_difference > 1) { - *delta = 0; - return srtp_err_status_pkt_idx_adv; - } + internal_roc = (uint32_t)(rdbx->index >> 16); + roc_difference = internal_roc - roc; + if (roc_difference > 1) { + *delta = 0; + return srtp_err_status_pkt_idx_adv; + } - internal_pkt_idx_reduced = - (uint32_t)((roc_difference << 16) | rdbx->index & 0xFFFF); - external_pkt_idx_reduced = (uint32_t)(seq); + internal_pkt_idx_reduced = + (uint32_t)((roc_difference << 16) | rdbx->index & 0xFFFF); + external_pkt_idx_reduced = (uint32_t)(seq); - if (internal_pkt_idx_reduced - external_pkt_idx_reduced > - seq_num_median) { - *delta = 0; - return srtp_err_status_pkt_idx_old; - } + if (internal_pkt_idx_reduced - external_pkt_idx_reduced > + seq_num_median) { + *delta = 0; + return srtp_err_status_pkt_idx_old; + } #else - if (rdbx->index - *est > seq_num_median) { - *delta = 0; - return srtp_err_status_pkt_idx_old; - } + if (rdbx->index - *est > seq_num_median) { + *delta = 0; + return srtp_err_status_pkt_idx_old; + } #endif - } + } - return srtp_err_status_ok; + return srtp_err_status_ok; } -static srtp_err_status_t -srtp_get_est_pkt_index(srtp_hdr_t *hdr, - srtp_stream_ctx_t *stream, - srtp_xtd_seq_num_t *est, - int *delta) +static srtp_err_status_t srtp_get_est_pkt_index(srtp_hdr_t *hdr, + srtp_stream_ctx_t *stream, + srtp_xtd_seq_num_t *est, + int *delta) { - srtp_err_status_t result = srtp_err_status_ok; + srtp_err_status_t result = srtp_err_status_ok; - if (stream->pending_roc) { - result = srtp_estimate_index(&stream->rtp_rdbx, - stream->pending_roc, - est, - ntohs(hdr->seq), - delta); - } else { - /* estimate packet index from seq. num. in header */ - *delta = srtp_rdbx_estimate_index(&stream->rtp_rdbx, - est, - ntohs(hdr->seq)); - } + if (stream->pending_roc) { + result = srtp_estimate_index(&stream->rtp_rdbx, stream->pending_roc, + est, ntohs(hdr->seq), delta); + } else { + /* estimate packet index from seq. num. in header */ + *delta = + srtp_rdbx_estimate_index(&stream->rtp_rdbx, est, ntohs(hdr->seq)); + } #ifdef NO_64BIT_MATH - debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(*est), low32(*est)); + debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(*est), + low32(*est)); #else - debug_print(mod_srtp, "estimated u_packet index: %016llx", *est); + debug_print(mod_srtp, "estimated u_packet index: %016llx", *est); #endif - return result; + return result; } /* @@ -1662,16 +1678,18 @@ srtp_get_est_pkt_index(srtp_hdr_t *hdr, * which currently supports AES-GCM encryption. All packets are * encrypted and authenticated. */ -static srtp_err_status_t -srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, - void *rtp_hdr, unsigned int *pkt_octet_len, - srtp_session_keys_t *session_keys, unsigned int use_mki) +static srtp_err_status_t srtp_protect_aead(srtp_ctx_t *ctx, + srtp_stream_ctx_t *stream, + void *rtp_hdr, + unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, + unsigned int use_mki) { - srtp_hdr_t *hdr = (srtp_hdr_t*)rtp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ - int enc_octet_len = 0; /* number of octets in encrypted portion */ - srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ - int delta; /* delta of local pkt idx and that in hdr */ + srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ + int enc_octet_len = 0; /* number of octets in encrypted portion */ + srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ + int delta; /* delta of local pkt idx and that in hdr */ srtp_err_status_t status; uint32_t tag_len; v128_t iv; @@ -1708,17 +1726,18 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, * extension, if present; otherwise, it starts after the last csrc, * if any are present */ - enc_start = (uint32_t*)hdr + uint32s_in_rtp_header + hdr->cc; - if (hdr->x == 1) { - xtn_hdr = (srtp_hdr_xtnd_t*)enc_start; - enc_start += (ntohs(xtn_hdr->length) + 1); - } - /* note: the passed size is without the auth tag */ - if (!((uint8_t*)enc_start <= (uint8_t*)hdr + *pkt_octet_len)) - return srtp_err_status_parse_err; - enc_octet_len = (int)(*pkt_octet_len - - ((uint8_t*)enc_start - (uint8_t*)hdr)); - if (enc_octet_len < 0) return srtp_err_status_parse_err; + enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc; + if (hdr->x == 1) { + xtn_hdr = (srtp_hdr_xtnd_t *)enc_start; + enc_start += (ntohs(xtn_hdr->length) + 1); + } + /* note: the passed size is without the auth tag */ + if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len)) + return srtp_err_status_parse_err; + enc_octet_len = + (int)(*pkt_octet_len - ((uint8_t *)enc_start - (uint8_t *)hdr)); + if (enc_octet_len < 0) + return srtp_err_status_parse_err; /* * estimate the packet index using the start of the replay window @@ -1727,16 +1746,16 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, delta = srtp_rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq)); status = srtp_rdbx_check(&stream->rtp_rdbx, delta); if (status) { - if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx) { - return status; /* we've been asked to reuse an index */ - } + if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx) { + return status; /* we've been asked to reuse an index */ + } } else { - srtp_rdbx_add_index(&stream->rtp_rdbx, delta); + srtp_rdbx_add_index(&stream->rtp_rdbx, delta); } #ifdef NO_64BIT_MATH - debug_print2(mod_srtp, "estimated packet index: %08x%08x", - high32(est), low32(est)); + debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est), + low32(est)); #else debug_print(mod_srtp, "estimated packet index: %016llx", est); #endif @@ -1745,50 +1764,50 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, * AEAD uses a new IV formation method */ srtp_calc_aead_iv(session_keys, &iv, &est, hdr); - /* shift est, put into network byte order */ +/* shift est, put into network byte order */ #ifdef NO_64BIT_MATH - est = be64_to_cpu(make64((high32(est) << 16) | - (low32(est) >> 16), - low32(est) << 16)); + est = be64_to_cpu( + make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); #else est = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(session_keys->rtp_cipher, - (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv, + srtp_direction_encrypt); if (!status && session_keys->rtp_xtn_hdr_cipher) { - iv.v32[0] = 0; - iv.v32[1] = hdr->ssrc; - iv.v64[1] = est; - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, - (uint8_t*)&iv, srtp_direction_encrypt); + iv.v32[0] = 0; + iv.v32[1] = hdr->ssrc; + iv.v64[1] = est; + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t *)&iv, srtp_direction_encrypt); } if (status) { return srtp_err_status_cipher_fail; } if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { - /* - * extensions header encryption RFC 6904 - */ - status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); - if (status) { - return status; - } + /* + * extensions header encryption RFC 6904 + */ + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); + if (status) { + return status; + } } /* - * Set the AAD over the RTP header + * Set the AAD over the RTP header */ aad_len = (uint8_t *)enc_start - (uint8_t *)hdr; - status = srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t*)hdr, aad_len); + status = + srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } /* Encrypt the payload */ - status = srtp_cipher_encrypt(session_keys->rtp_cipher, - (uint8_t*)enc_start, (unsigned int *)&enc_octet_len); + status = srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t *)enc_start, + (unsigned int *)&enc_octet_len); if (status) { return srtp_err_status_cipher_fail; } @@ -1796,10 +1815,11 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, * If we're doing GCM, we need to get the tag * and append that to the output */ - status = srtp_cipher_get_tag(session_keys->rtp_cipher, - (uint8_t*)enc_start+enc_octet_len, &tag_len); + status = + srtp_cipher_get_tag(session_keys->rtp_cipher, + (uint8_t *)enc_start + enc_octet_len, &tag_len); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } mki_location = (uint8_t *)hdr + *pkt_octet_len + tag_len; @@ -1814,7 +1834,6 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, return srtp_err_status_ok; } - /* * This function handles incoming SRTP packets while in AEAD mode, * which currently supports AES-GCM encryption. All packets are @@ -1822,13 +1841,17 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, * of the packet stream and is automatically checked by GCM * when decrypting the payload. */ -static srtp_err_status_t -srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, - srtp_xtd_seq_num_t est, void *srtp_hdr, unsigned int *pkt_octet_len, - srtp_session_keys_t *session_keys, unsigned int mki_size) +static srtp_err_status_t srtp_unprotect_aead(srtp_ctx_t *ctx, + srtp_stream_ctx_t *stream, + int delta, + srtp_xtd_seq_num_t est, + void *srtp_hdr, + unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, + unsigned int mki_size) { - srtp_hdr_t *hdr = (srtp_hdr_t*)srtp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ + srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ v128_t iv; srtp_err_status_t status; @@ -1839,7 +1862,8 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, debug_print(mod_srtp, "function srtp_unprotect_aead", NULL); #ifdef NO_64BIT_MATH - debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est), low32(est)); + debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est), + low32(est)); #else debug_print(mod_srtp, "estimated u_packet index: %016llx", est); #endif @@ -1848,21 +1872,22 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); /* - * AEAD uses a new IV formation method + * AEAD uses a new IV formation method */ srtp_calc_aead_iv(session_keys, &iv, &est, hdr); - status = srtp_cipher_set_iv(session_keys->rtp_cipher, - (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv, + srtp_direction_decrypt); if (!status && session_keys->rtp_xtn_hdr_cipher) { - iv.v32[0] = 0; - iv.v32[1] = hdr->ssrc; + iv.v32[0] = 0; + iv.v32[1] = hdr->ssrc; #ifdef NO_64BIT_MATH - iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16), - low32(est) << 16)); + iv.v64[1] = be64_to_cpu( + make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); #else - iv.v64[1] = be64_to_cpu(est << 16); + iv.v64[1] = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t *)&iv, srtp_direction_encrypt); } if (status) { return srtp_err_status_cipher_fail; @@ -1874,25 +1899,26 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * extension, if present; otherwise, it starts after the last csrc, * if any are present */ - enc_start = (uint32_t*)hdr + uint32s_in_rtp_header + hdr->cc; + enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc; if (hdr->x == 1) { - xtn_hdr = (srtp_hdr_xtnd_t*)enc_start; + xtn_hdr = (srtp_hdr_xtnd_t *)enc_start; enc_start += (ntohs(xtn_hdr->length) + 1); } - if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len - mki_size))) + if (!((uint8_t *)enc_start <= + (uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size))) return srtp_err_status_parse_err; /* - * We pass the tag down to the cipher when doing GCM mode + * We pass the tag down to the cipher when doing GCM mode */ enc_octet_len = (unsigned int)(*pkt_octet_len - mki_size - - ((uint8_t*)enc_start - (uint8_t*)hdr)); + ((uint8_t *)enc_start - (uint8_t *)hdr)); /* * Sanity check the encrypted payload length against * the tag size. It must always be at least as large * as the tag length. */ - if (enc_octet_len < (unsigned int) tag_len) { + if (enc_octet_len < (unsigned int)tag_len) { return srtp_err_status_cipher_fail; } @@ -1918,27 +1944,28 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * Set the AAD for AES-GCM, which is the RTP header */ aad_len = (uint8_t *)enc_start - (uint8_t *)hdr; - status = srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t*)hdr, aad_len); + status = + srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t *)hdr, aad_len); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } /* Decrypt the ciphertext. This also checks the auth tag based * on the AAD we just specified above */ - status = srtp_cipher_decrypt(session_keys->rtp_cipher, - (uint8_t*)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtp_cipher, (uint8_t *)enc_start, + &enc_octet_len); if (status) { return status; } if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { - /* - * extensions header encryption RFC 6904 - */ - status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); - if (status) { - return status; - } + /* + * extensions header encryption RFC 6904 + */ + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); + if (status) { + return status; + } } /* @@ -1974,7 +2001,8 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * stream, and some implementations will want to not return * failure here */ - status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + status = + srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) { return status; } @@ -2002,724 +2030,730 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, return srtp_err_status_ok; } - - srtp_err_status_t - srtp_protect(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len) { - return srtp_protect_mki(ctx, rtp_hdr, pkt_octet_len, 0, 0); - } - -srtp_err_status_t -srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len, - unsigned int use_mki, unsigned int mki_index ) { - srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *auth_start; /* pointer to start of auth. portion */ - int enc_octet_len = 0; /* number of octets in encrypted portion */ - srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ - int delta; /* delta of local pkt idx and that in hdr */ - uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ - srtp_err_status_t status; - int tag_len; - srtp_stream_ctx_t *stream; - uint32_t prefix_len; - srtp_hdr_xtnd_t *xtn_hdr = NULL; - unsigned int mki_size = 0; - srtp_session_keys_t *session_keys = NULL; - uint8_t* mki_location = NULL; - int advance_packet_index = 0; - - debug_print(mod_srtp, "function srtp_protect", NULL); - - /* we assume the hdr is 32-bit aligned to start */ - - /* Verify RTP header */ - status = srtp_validate_rtp_header(rtp_hdr, pkt_octet_len); - if (status) - return status; - - /* check the packet length - it must at least contain a full header */ - if (*pkt_octet_len < octets_in_rtp_header) - return srtp_err_status_bad_param; - - /* - * look up ssrc in srtp_stream list, and process the packet with - * the appropriate stream. if we haven't seen this stream before, - * there's a template key for this srtp_session, and the cipher - * supports key-sharing, then we assume that a new stream using - * that key has just started up - */ - stream = srtp_get_stream(ctx, hdr->ssrc); - if (stream == NULL) { - if (ctx->stream_template != NULL) { - srtp_stream_ctx_t *new_stream; - - /* allocate and initialize a new stream */ - status = srtp_stream_clone(ctx->stream_template, - hdr->ssrc, &new_stream); - if (status) - return status; - - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; - - /* set direction to outbound */ - new_stream->direction = dir_srtp_sender; - - /* set stream (the pointer used in this function) */ - stream = new_stream; - } else { - /* no template stream, so we return an error */ - return srtp_err_status_no_ctx; - } - } - - /* - * verify that stream is for sending traffic - this check will - * detect SSRC collisions, since a stream that appears in both - * srtp_protect() and srtp_unprotect() will fail this test in one of - * those functions. - */ - - if (stream->direction != dir_srtp_sender) { - if (stream->direction == dir_unknown) { - stream->direction = dir_srtp_sender; - } else { - srtp_handle_event(ctx, stream, event_ssrc_collision); - } - } - - session_keys = srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index); - - /* - * Check if this is an AEAD stream (GCM mode). If so, then dispatch - * the request to our AEAD handler. - */ - if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || - session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { - return srtp_protect_aead(ctx, stream, rtp_hdr, - (unsigned int*)pkt_octet_len, session_keys, - use_mki); - } - - /* - * update the key usage limit, and check it to make sure that we - * didn't just hit either the soft limit or the hard limit, and call - * the event handler if we hit either. - */ - switch(srtp_key_limit_update(session_keys->limit)) { - case srtp_key_event_normal: - break; - case srtp_key_event_soft_limit: - srtp_handle_event(ctx, stream, event_key_soft_limit); - break; - case srtp_key_event_hard_limit: - srtp_handle_event(ctx, stream, event_key_hard_limit); - return srtp_err_status_key_expired; - default: - break; - } - - /* get tag length from stream */ - tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); - - /* - * find starting point for encryption and length of data to be - * encrypted - the encrypted portion starts after the rtp header - * extension, if present; otherwise, it starts after the last csrc, - * if any are present - * - * if we're not providing confidentiality, set enc_start to NULL - */ - if (stream->rtp_services & sec_serv_conf) { - enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc; - if (hdr->x == 1) { - xtn_hdr = (srtp_hdr_xtnd_t *)enc_start; - enc_start += (ntohs(xtn_hdr->length) + 1); - } - /* note: the passed size is without the auth tag */ - if (!((uint8_t*)enc_start <= (uint8_t*)hdr + *pkt_octet_len)) - return srtp_err_status_parse_err; - enc_octet_len = (int)(*pkt_octet_len - - ((uint8_t*)enc_start - (uint8_t*)hdr)); - if (enc_octet_len < 0) return srtp_err_status_parse_err; - } else { - enc_start = NULL; - } - - mki_location = (uint8_t *)hdr + *pkt_octet_len; - mki_size = srtp_inject_mki(mki_location, session_keys, use_mki); - - /* - * if we're providing authentication, set the auth_start and auth_tag - * pointers to the proper locations; otherwise, set auth_start to NULL - * to indicate that no authentication is needed - */ - if (stream->rtp_services & sec_serv_auth) { - auth_start = (uint32_t *)hdr; - auth_tag = (uint8_t *)hdr + *pkt_octet_len + mki_size; - } else { - auth_start = NULL; - auth_tag = NULL; - } - - /* - * estimate the packet index using the start of the replay window - * and the sequence number from the header - */ - status = srtp_get_est_pkt_index(hdr, - stream, - &est, - &delta); - - if (status && (status != srtp_err_status_pkt_idx_adv)) - return status; - - if (status == srtp_err_status_pkt_idx_adv) - advance_packet_index = 1; - - if (advance_packet_index) { - srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, - (uint32_t)(est >> 16), - (uint16_t)(est & 0xFFFF)); - stream->pending_roc = 0; - srtp_rdbx_add_index(&stream->rtp_rdbx, 0); - } else { - status = srtp_rdbx_check(&stream->rtp_rdbx, delta); - if (status) { - if (status != srtp_err_status_replay_fail || !stream->allow_repeat_tx) - return status; /* we've been asked to reuse an index */ - } - srtp_rdbx_add_index(&stream->rtp_rdbx, delta); - } - -#ifdef NO_64BIT_MATH - debug_print2(mod_srtp, "estimated packet index: %08x%08x", - high32(est),low32(est)); -#else - debug_print(mod_srtp, "estimated packet index: %016llx", est); -#endif - - /* - * if we're using rindael counter mode, set nonce and seq - */ - if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM_128 || - session_keys->rtp_cipher->type->id == SRTP_AES_ICM_192 || - session_keys->rtp_cipher->type->id == SRTP_AES_ICM_256) { - v128_t iv; - - iv.v32[0] = 0; - iv.v32[1] = hdr->ssrc; -#ifdef NO_64BIT_MATH - iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16), - low32(est) << 16)); -#else - iv.v64[1] = be64_to_cpu(est << 16); -#endif - status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); - if (!status && session_keys->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); - } - } else { - v128_t iv; - - /* otherwise, set the index to est */ -#ifdef NO_64BIT_MATH - iv.v32[0] = 0; - iv.v32[1] = 0; -#else - iv.v64[0] = 0; -#endif - iv.v64[1] = be64_to_cpu(est); - status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); - if (!status && session_keys->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); - } - } - if (status) - return srtp_err_status_cipher_fail; - - /* shift est, put into network byte order */ -#ifdef NO_64BIT_MATH - est = be64_to_cpu(make64((high32(est) << 16) | - (low32(est) >> 16), - low32(est) << 16)); -#else - est = be64_to_cpu(est << 16); -#endif - - /* - * if we're authenticating using a universal hash, put the keystream - * prefix into the authentication tag - */ - if (auth_start) { - - prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth); - if (prefix_len) { - status = srtp_cipher_output(session_keys->rtp_cipher, auth_tag, &prefix_len); - if (status) - return srtp_err_status_cipher_fail; - debug_print(mod_srtp, "keystream prefix: %s", - srtp_octet_string_hex_string(auth_tag, prefix_len)); - } - } - - if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { - /* - * extensions header encryption RFC 6904 - */ - status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); - if (status) { - return status; - } - } - - /* if we're encrypting, exor keystream into the message */ - if (enc_start) { - status = srtp_cipher_encrypt(session_keys->rtp_cipher, - (uint8_t *)enc_start, (unsigned int *)&enc_octet_len); - if (status) - return srtp_err_status_cipher_fail; - } - - /* - * if we're authenticating, run authentication function and put result - * into the auth_tag - */ - if (auth_start) { - - /* initialize auth func context */ - status = srtp_auth_start(session_keys->rtp_auth); - if (status) return status; - - /* run auth func over packet */ - status = srtp_auth_update(session_keys->rtp_auth, - (uint8_t *)auth_start, *pkt_octet_len); - if (status) return status; - - /* run auth func over ROC, put result into auth_tag */ - debug_print(mod_srtp, "estimated packet index: %016llx", est); - status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, auth_tag); - debug_print(mod_srtp, "srtp auth tag: %s", - srtp_octet_string_hex_string(auth_tag, tag_len)); - if (status) - return srtp_err_status_auth_fail; - - } - - if (auth_tag) { - - /* increase the packet length by the length of the auth tag */ - *pkt_octet_len += tag_len; - } - - if (use_mki) { - /* increate the packet length by the mki size */ - *pkt_octet_len += mki_size; - } - - return srtp_err_status_ok; +srtp_err_status_t srtp_protect(srtp_ctx_t *ctx, + void *rtp_hdr, + int *pkt_octet_len) +{ + return srtp_protect_mki(ctx, rtp_hdr, pkt_octet_len, 0, 0); } +srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, + void *rtp_hdr, + int *pkt_octet_len, + unsigned int use_mki, + unsigned int mki_index) +{ + srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ + uint32_t *auth_start; /* pointer to start of auth. portion */ + int enc_octet_len = 0; /* number of octets in encrypted portion */ + srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ + int delta; /* delta of local pkt idx and that in hdr */ + uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ + srtp_err_status_t status; + int tag_len; + srtp_stream_ctx_t *stream; + uint32_t prefix_len; + srtp_hdr_xtnd_t *xtn_hdr = NULL; + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; + uint8_t *mki_location = NULL; + int advance_packet_index = 0; -srtp_err_status_t -srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { + debug_print(mod_srtp, "function srtp_protect", NULL); + + /* we assume the hdr is 32-bit aligned to start */ + + /* Verify RTP header */ + status = srtp_validate_rtp_header(rtp_hdr, pkt_octet_len); + if (status) + return status; + + /* check the packet length - it must at least contain a full header */ + if (*pkt_octet_len < octets_in_rtp_header) + return srtp_err_status_bad_param; + + /* + * look up ssrc in srtp_stream list, and process the packet with + * the appropriate stream. if we haven't seen this stream before, + * there's a template key for this srtp_session, and the cipher + * supports key-sharing, then we assume that a new stream using + * that key has just started up + */ + stream = srtp_get_stream(ctx, hdr->ssrc); + if (stream == NULL) { + if (ctx->stream_template != NULL) { + srtp_stream_ctx_t *new_stream; + + /* allocate and initialize a new stream */ + status = + srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + if (status) + return status; + + /* add new stream to the head of the stream_list */ + new_stream->next = ctx->stream_list; + ctx->stream_list = new_stream; + + /* set direction to outbound */ + new_stream->direction = dir_srtp_sender; + + /* set stream (the pointer used in this function) */ + stream = new_stream; + } else { + /* no template stream, so we return an error */ + return srtp_err_status_no_ctx; + } + } + + /* + * verify that stream is for sending traffic - this check will + * detect SSRC collisions, since a stream that appears in both + * srtp_protect() and srtp_unprotect() will fail this test in one of + * those functions. + */ + + if (stream->direction != dir_srtp_sender) { + if (stream->direction == dir_unknown) { + stream->direction = dir_srtp_sender; + } else { + srtp_handle_event(ctx, stream, event_ssrc_collision); + } + } + + session_keys = + srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index); + + if (session_keys == NULL) + return srtp_err_status_bad_mki; + + /* + * Check if this is an AEAD stream (GCM mode). If so, then dispatch + * the request to our AEAD handler. + */ + if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || + session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { + return srtp_protect_aead(ctx, stream, rtp_hdr, + (unsigned int *)pkt_octet_len, session_keys, + use_mki); + } + + /* + * update the key usage limit, and check it to make sure that we + * didn't just hit either the soft limit or the hard limit, and call + * the event handler if we hit either. + */ + switch (srtp_key_limit_update(session_keys->limit)) { + case srtp_key_event_normal: + break; + case srtp_key_event_soft_limit: + srtp_handle_event(ctx, stream, event_key_soft_limit); + break; + case srtp_key_event_hard_limit: + srtp_handle_event(ctx, stream, event_key_hard_limit); + return srtp_err_status_key_expired; + default: + break; + } + + /* get tag length from stream */ + tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); + + /* + * find starting point for encryption and length of data to be + * encrypted - the encrypted portion starts after the rtp header + * extension, if present; otherwise, it starts after the last csrc, + * if any are present + * + * if we're not providing confidentiality, set enc_start to NULL + */ + if (stream->rtp_services & sec_serv_conf) { + enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc; + if (hdr->x == 1) { + xtn_hdr = (srtp_hdr_xtnd_t *)enc_start; + enc_start += (ntohs(xtn_hdr->length) + 1); + } + /* note: the passed size is without the auth tag */ + if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len)) + return srtp_err_status_parse_err; + enc_octet_len = + (int)(*pkt_octet_len - ((uint8_t *)enc_start - (uint8_t *)hdr)); + if (enc_octet_len < 0) + return srtp_err_status_parse_err; + } else { + enc_start = NULL; + } + + mki_location = (uint8_t *)hdr + *pkt_octet_len; + mki_size = srtp_inject_mki(mki_location, session_keys, use_mki); + + /* + * if we're providing authentication, set the auth_start and auth_tag + * pointers to the proper locations; otherwise, set auth_start to NULL + * to indicate that no authentication is needed + */ + if (stream->rtp_services & sec_serv_auth) { + auth_start = (uint32_t *)hdr; + auth_tag = (uint8_t *)hdr + *pkt_octet_len + mki_size; + } else { + auth_start = NULL; + auth_tag = NULL; + } + + /* + * estimate the packet index using the start of the replay window + * and the sequence number from the header + */ + status = srtp_get_est_pkt_index(hdr, stream, &est, &delta); + + if (status && (status != srtp_err_status_pkt_idx_adv)) + return status; + + if (status == srtp_err_status_pkt_idx_adv) + advance_packet_index = 1; + + if (advance_packet_index) { + srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, (uint32_t)(est >> 16), + (uint16_t)(est & 0xFFFF)); + stream->pending_roc = 0; + srtp_rdbx_add_index(&stream->rtp_rdbx, 0); + } else { + status = srtp_rdbx_check(&stream->rtp_rdbx, delta); + if (status) { + if (status != srtp_err_status_replay_fail || + !stream->allow_repeat_tx) + return status; /* we've been asked to reuse an index */ + } + srtp_rdbx_add_index(&stream->rtp_rdbx, delta); + } + +#ifdef NO_64BIT_MATH + debug_print2(mod_srtp, "estimated packet index: %08x%08x", high32(est), + low32(est)); +#else + debug_print(mod_srtp, "estimated packet index: %016llx", est); +#endif + + /* + * if we're using rindael counter mode, set nonce and seq + */ + if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM_128 || + session_keys->rtp_cipher->type->id == SRTP_AES_ICM_192 || + session_keys->rtp_cipher->type->id == SRTP_AES_ICM_256) { + v128_t iv; + + iv.v32[0] = 0; + iv.v32[1] = hdr->ssrc; +#ifdef NO_64BIT_MATH + iv.v64[1] = be64_to_cpu( + make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); +#else + iv.v64[1] = be64_to_cpu(est << 16); +#endif + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv, + srtp_direction_encrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t *)&iv, srtp_direction_encrypt); + } + } else { + v128_t iv; + +/* otherwise, set the index to est */ +#ifdef NO_64BIT_MATH + iv.v32[0] = 0; + iv.v32[1] = 0; +#else + iv.v64[0] = 0; +#endif + iv.v64[1] = be64_to_cpu(est); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv, + srtp_direction_encrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t *)&iv, srtp_direction_encrypt); + } + } + if (status) + return srtp_err_status_cipher_fail; + +/* shift est, put into network byte order */ +#ifdef NO_64BIT_MATH + est = be64_to_cpu( + make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); +#else + est = be64_to_cpu(est << 16); +#endif + + /* + * if we're authenticating using a universal hash, put the keystream + * prefix into the authentication tag + */ + if (auth_start) { + prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth); + if (prefix_len) { + status = srtp_cipher_output(session_keys->rtp_cipher, auth_tag, + &prefix_len); + if (status) + return srtp_err_status_cipher_fail; + debug_print(mod_srtp, "keystream prefix: %s", + srtp_octet_string_hex_string(auth_tag, prefix_len)); + } + } + + if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { + /* + * extensions header encryption RFC 6904 + */ + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); + if (status) { + return status; + } + } + + /* if we're encrypting, exor keystream into the message */ + if (enc_start) { + status = + srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t *)enc_start, + (unsigned int *)&enc_octet_len); + if (status) + return srtp_err_status_cipher_fail; + } + + /* + * if we're authenticating, run authentication function and put result + * into the auth_tag + */ + if (auth_start) { + /* initialize auth func context */ + status = srtp_auth_start(session_keys->rtp_auth); + if (status) + return status; + + /* run auth func over packet */ + status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start, + *pkt_octet_len); + if (status) + return status; + + /* run auth func over ROC, put result into auth_tag */ + debug_print(mod_srtp, "estimated packet index: %016llx", est); + status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, + auth_tag); + debug_print(mod_srtp, "srtp auth tag: %s", + srtp_octet_string_hex_string(auth_tag, tag_len)); + if (status) + return srtp_err_status_auth_fail; + } + + if (auth_tag) { + /* increase the packet length by the length of the auth tag */ + *pkt_octet_len += tag_len; + } + + if (use_mki) { + /* increate the packet length by the mki size */ + *pkt_octet_len += mki_size; + } + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_unprotect(srtp_ctx_t *ctx, + void *srtp_hdr, + int *pkt_octet_len) +{ return srtp_unprotect_mki(ctx, srtp_hdr, pkt_octet_len, 0); } -srtp_err_status_t -srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, - unsigned int use_mki) { - srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *auth_start; /* pointer to start of auth. portion */ - unsigned int enc_octet_len = 0;/* number of octets in encrypted portion */ - uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ - srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ - int delta; /* delta of local pkt idx and that in hdr */ - v128_t iv; - srtp_err_status_t status; - srtp_stream_ctx_t *stream; - uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; - uint32_t tag_len, prefix_len; - srtp_hdr_xtnd_t *xtn_hdr = NULL; - unsigned int mki_size = 0; - srtp_session_keys_t *session_keys = NULL; - int advance_packet_index = 0; - uint32_t roc_to_set = 0; - uint16_t seq_to_set = 0; +srtp_err_status_t srtp_unprotect_mki(srtp_ctx_t *ctx, + void *srtp_hdr, + int *pkt_octet_len, + unsigned int use_mki) +{ + srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ + uint32_t *auth_start; /* pointer to start of auth. portion */ + unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ + uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ + srtp_xtd_seq_num_t est; /* estimated xtd_seq_num_t of *hdr */ + int delta; /* delta of local pkt idx and that in hdr */ + v128_t iv; + srtp_err_status_t status; + srtp_stream_ctx_t *stream; + uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; + uint32_t tag_len, prefix_len; + srtp_hdr_xtnd_t *xtn_hdr = NULL; + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; + int advance_packet_index = 0; + uint32_t roc_to_set = 0; + uint16_t seq_to_set = 0; - debug_print(mod_srtp, "function srtp_unprotect", NULL); + debug_print(mod_srtp, "function srtp_unprotect", NULL); - /* we assume the hdr is 32-bit aligned to start */ + /* we assume the hdr is 32-bit aligned to start */ - /* Verify RTP header */ - status = srtp_validate_rtp_header(srtp_hdr, pkt_octet_len); - if (status) - return status; - - /* check the packet length - it must at least contain a full header */ - if (*pkt_octet_len < octets_in_rtp_header) - return srtp_err_status_bad_param; - - /* - * look up ssrc in srtp_stream list, and process the packet with - * the appropriate stream. if we haven't seen this stream before, - * there's only one key for this srtp_session, and the cipher - * supports key-sharing, then we assume that a new stream using - * that key has just started up - */ - stream = srtp_get_stream(ctx, hdr->ssrc); - if (stream == NULL) { - if (ctx->stream_template != NULL) { - stream = ctx->stream_template; - debug_print(mod_srtp, "using provisional stream (SSRC: 0x%08x)", - ntohl(hdr->ssrc)); - - /* - * set estimated packet index to sequence number from header, - * and set delta equal to the same value - */ -#ifdef NO_64BIT_MATH - est = (srtp_xtd_seq_num_t) make64(0,ntohs(hdr->seq)); - delta = low32(est); -#else - est = (srtp_xtd_seq_num_t) ntohs(hdr->seq); - delta = (int)est; -#endif - } else { - - /* - * no stream corresponding to SSRC found, and we don't do - * key-sharing, so return an error - */ - return srtp_err_status_no_ctx; - } - } else { - status = srtp_get_est_pkt_index(hdr, - stream, - &est, - &delta); - - if (status && (status != srtp_err_status_pkt_idx_adv)) - return status; - - if (status == srtp_err_status_pkt_idx_adv) { - advance_packet_index = 1; - roc_to_set = (uint32_t)(est >> 16); - seq_to_set = (uint16_t)(est & 0xFFFF); - } - - /* check replay database */ - if (!advance_packet_index) { - status = srtp_rdbx_check(&stream->rtp_rdbx, delta); - if (status) + /* Verify RTP header */ + status = srtp_validate_rtp_header(srtp_hdr, pkt_octet_len); + if (status) return status; - } - } -#ifdef NO_64BIT_MATH - debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),low32(est)); -#else - debug_print(mod_srtp, "estimated u_packet index: %016llx", est); -#endif + /* check the packet length - it must at least contain a full header */ + if (*pkt_octet_len < octets_in_rtp_header) + return srtp_err_status_bad_param; - /* - * Determine if MKI is being used and what session keys should be used - */ - if (use_mki) { - session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, - (const unsigned int*)pkt_octet_len, - &mki_size); - - if (session_keys == NULL) - return srtp_err_status_bad_mki; - } else { - session_keys = &stream->session_keys[0]; - } - - /* - * Check if this is an AEAD stream (GCM mode). If so, then dispatch - * the request to our AEAD handler. - */ - if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || - session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { - return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, - (unsigned int*)pkt_octet_len, session_keys, - mki_size); - } - - /* get tag length from stream */ - tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); - - /* - * set the cipher's IV properly, depending on whatever cipher we - * happen to be using - */ - if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM_128 || - session_keys->rtp_cipher->type->id == SRTP_AES_ICM_192 || - session_keys->rtp_cipher->type->id == SRTP_AES_ICM_256) { - /* aes counter mode */ - iv.v32[0] = 0; - iv.v32[1] = hdr->ssrc; /* still in network order */ -#ifdef NO_64BIT_MATH - iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16), - low32(est) << 16)); -#else - iv.v64[1] = be64_to_cpu(est << 16); -#endif - status = srtp_cipher_set_iv(session_keys->rtp_cipher, - (uint8_t*)&iv, srtp_direction_decrypt); - if (!status && session_keys->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, - (uint8_t*)&iv, srtp_direction_decrypt); - } - } else { - - /* no particular format - set the iv to the pakcet index */ -#ifdef NO_64BIT_MATH - iv.v32[0] = 0; - iv.v32[1] = 0; -#else - iv.v64[0] = 0; -#endif - iv.v64[1] = be64_to_cpu(est); - status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); - if (!status && session_keys->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_decrypt); - } - } - if (status) - return srtp_err_status_cipher_fail; - - /* shift est, put into network byte order */ -#ifdef NO_64BIT_MATH - est = be64_to_cpu(make64((high32(est) << 16) | - (low32(est) >> 16), - low32(est) << 16)); -#else - est = be64_to_cpu(est << 16); -#endif - - /* - * find starting point for decryption and length of data to be - * decrypted - the encrypted portion starts after the rtp header - * extension, if present; otherwise, it starts after the last csrc, - * if any are present - * - * if we're not providing confidentiality, set enc_start to NULL - */ - if (stream->rtp_services & sec_serv_conf) { - enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc; - if (hdr->x == 1) { - xtn_hdr = (srtp_hdr_xtnd_t *)enc_start; - enc_start += (ntohs(xtn_hdr->length) + 1); - } - if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len - mki_size))) - return srtp_err_status_parse_err; - enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - mki_size - - ((uint8_t*)enc_start - (uint8_t*)hdr)); - } else { - enc_start = NULL; - } - - /* - * if we're providing authentication, set the auth_start and auth_tag - * pointers to the proper locations; otherwise, set auth_start to NULL - * to indicate that no authentication is needed - */ - if (stream->rtp_services & sec_serv_auth) { - auth_start = (uint32_t *)hdr; - auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len; - } else { - auth_start = NULL; - auth_tag = NULL; - } - - /* - * if we expect message authentication, run the authentication - * function and compare the result with the value of the auth_tag - */ - if (auth_start) { - - /* - * if we're using a universal hash, then we need to compute the - * keystream prefix for encrypting the universal hash output - * - * if the keystream prefix length is zero, then we know that - * the authenticator isn't using a universal hash function - */ - if (session_keys->rtp_auth->prefix_len != 0) { - - prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth); - status = srtp_cipher_output(session_keys->rtp_cipher, tmp_tag, &prefix_len); - debug_print(mod_srtp, "keystream prefix: %s", - srtp_octet_string_hex_string(tmp_tag, prefix_len)); - if (status) - return srtp_err_status_cipher_fail; - } - - /* initialize auth func context */ - status = srtp_auth_start(session_keys->rtp_auth); - if (status) return status; - - /* now compute auth function over packet */ - status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start, - *pkt_octet_len - tag_len - mki_size); - - /* run auth func over ROC, then write tmp tag */ - status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, tmp_tag); - - debug_print(mod_srtp, "computed auth tag: %s", - srtp_octet_string_hex_string(tmp_tag, tag_len)); - debug_print(mod_srtp, "packet auth tag: %s", - srtp_octet_string_hex_string(auth_tag, tag_len)); - if (status) - return srtp_err_status_auth_fail; - - if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) - return srtp_err_status_auth_fail; - } - - /* - * update the key usage limit, and check it to make sure that we - * didn't just hit either the soft limit or the hard limit, and call - * the event handler if we hit either. - */ - switch(srtp_key_limit_update(session_keys->limit)) { - case srtp_key_event_normal: - break; - case srtp_key_event_soft_limit: - srtp_handle_event(ctx, stream, event_key_soft_limit); - break; - case srtp_key_event_hard_limit: - srtp_handle_event(ctx, stream, event_key_hard_limit); - return srtp_err_status_key_expired; - default: - break; - } - - if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* - * extensions header encryption RFC 6904 + * look up ssrc in srtp_stream list, and process the packet with + * the appropriate stream. if we haven't seen this stream before, + * there's only one key for this srtp_session, and the cipher + * supports key-sharing, then we assume that a new stream using + * that key has just started up */ - status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); - if (status) { - return status; - } - } + stream = srtp_get_stream(ctx, hdr->ssrc); + if (stream == NULL) { + if (ctx->stream_template != NULL) { + stream = ctx->stream_template; + debug_print(mod_srtp, "using provisional stream (SSRC: 0x%08x)", + ntohl(hdr->ssrc)); - /* if we're decrypting, add keystream into ciphertext */ - if (enc_start) { - status = srtp_cipher_decrypt(session_keys->rtp_cipher, - (uint8_t *)enc_start, &enc_octet_len); - if (status) - return srtp_err_status_cipher_fail; - } - - /* - * verify that stream is for received traffic - this check will - * detect SSRC collisions, since a stream that appears in both - * srtp_protect() and srtp_unprotect() will fail this test in one of - * those functions. - * - * we do this check *after* the authentication check, so that the - * latter check will catch any attempts to fool us into thinking - * that we've got a collision - */ - if (stream->direction != dir_srtp_receiver) { - if (stream->direction == dir_unknown) { - stream->direction = dir_srtp_receiver; +/* + * set estimated packet index to sequence number from header, + * and set delta equal to the same value + */ +#ifdef NO_64BIT_MATH + est = (srtp_xtd_seq_num_t)make64(0, ntohs(hdr->seq)); + delta = low32(est); +#else + est = (srtp_xtd_seq_num_t)ntohs(hdr->seq); + delta = (int)est; +#endif + } else { + /* + * no stream corresponding to SSRC found, and we don't do + * key-sharing, so return an error + */ + return srtp_err_status_no_ctx; + } } else { - srtp_handle_event(ctx, stream, event_ssrc_collision); + status = srtp_get_est_pkt_index(hdr, stream, &est, &delta); + + if (status && (status != srtp_err_status_pkt_idx_adv)) + return status; + + if (status == srtp_err_status_pkt_idx_adv) { + advance_packet_index = 1; + roc_to_set = (uint32_t)(est >> 16); + seq_to_set = (uint16_t)(est & 0xFFFF); + } + + /* check replay database */ + if (!advance_packet_index) { + status = srtp_rdbx_check(&stream->rtp_rdbx, delta); + if (status) + return status; + } } - } - /* - * if the stream is a 'provisional' one, in which the template context - * is used, then we need to allocate a new stream at this point, since - * the authentication passed - */ - if (stream == ctx->stream_template) { - srtp_stream_ctx_t *new_stream; +#ifdef NO_64BIT_MATH + debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est), + low32(est)); +#else + debug_print(mod_srtp, "estimated u_packet index: %016llx", est); +#endif - /* - * allocate and initialize a new stream - * - * note that we indicate failure if we can't allocate the new - * stream, and some implementations will want to not return - * failure here + /* Determine if MKI is being used and what session keys should be used */ + if (use_mki) { + session_keys = srtp_get_session_keys( + stream, (uint8_t *)hdr, (const unsigned int *)pkt_octet_len, + &mki_size); + + if (session_keys == NULL) + return srtp_err_status_bad_mki; + } else { + session_keys = &stream->session_keys[0]; + } + + /* + * Check if this is an AEAD stream (GCM mode). If so, then dispatch + * the request to our AEAD handler. */ - status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || + session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { + return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, + (unsigned int *)pkt_octet_len, session_keys, + mki_size); + } + + /* get tag length from stream */ + tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); + + /* + * set the cipher's IV properly, depending on whatever cipher we + * happen to be using + */ + if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM_128 || + session_keys->rtp_cipher->type->id == SRTP_AES_ICM_192 || + session_keys->rtp_cipher->type->id == SRTP_AES_ICM_256) { + /* aes counter mode */ + iv.v32[0] = 0; + iv.v32[1] = hdr->ssrc; /* still in network order */ +#ifdef NO_64BIT_MATH + iv.v64[1] = be64_to_cpu( + make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); +#else + iv.v64[1] = be64_to_cpu(est << 16); +#endif + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv, + srtp_direction_decrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t *)&iv, srtp_direction_decrypt); + } + } else { +/* no particular format - set the iv to the pakcet index */ +#ifdef NO_64BIT_MATH + iv.v32[0] = 0; + iv.v32[1] = 0; +#else + iv.v64[0] = 0; +#endif + iv.v64[1] = be64_to_cpu(est); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t *)&iv, + srtp_direction_decrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t *)&iv, srtp_direction_decrypt); + } + } if (status) - return status; - - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; - - /* set stream (the pointer used in this function) */ - stream = new_stream; - } + return srtp_err_status_cipher_fail; - /* - * the message authentication function passed, so add the packet - * index into the replay database - */ - if (advance_packet_index) { - srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, - roc_to_set, - seq_to_set); - stream->pending_roc = 0; - srtp_rdbx_add_index(&stream->rtp_rdbx, 0); - } else { - srtp_rdbx_add_index(&stream->rtp_rdbx, delta); - } +/* shift est, put into network byte order */ +#ifdef NO_64BIT_MATH + est = be64_to_cpu( + make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); +#else + est = be64_to_cpu(est << 16); +#endif - /* decrease the packet length by the length of the auth tag */ - *pkt_octet_len -= tag_len; + /* + * find starting point for decryption and length of data to be + * decrypted - the encrypted portion starts after the rtp header + * extension, if present; otherwise, it starts after the last csrc, + * if any are present + * + * if we're not providing confidentiality, set enc_start to NULL + */ + if (stream->rtp_services & sec_serv_conf) { + enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc; + if (hdr->x == 1) { + xtn_hdr = (srtp_hdr_xtnd_t *)enc_start; + enc_start += (ntohs(xtn_hdr->length) + 1); + } + if (!((uint8_t *)enc_start <= + (uint8_t *)hdr + (*pkt_octet_len - tag_len - mki_size))) + return srtp_err_status_parse_err; + enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - mki_size - + ((uint8_t *)enc_start - (uint8_t *)hdr)); + } else { + enc_start = NULL; + } - /* decrease the packet length by the mki size */ - *pkt_octet_len -= mki_size; + /* + * if we're providing authentication, set the auth_start and auth_tag + * pointers to the proper locations; otherwise, set auth_start to NULL + * to indicate that no authentication is needed + */ + if (stream->rtp_services & sec_serv_auth) { + auth_start = (uint32_t *)hdr; + auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len; + } else { + auth_start = NULL; + auth_tag = NULL; + } - return srtp_err_status_ok; + /* + * if we expect message authentication, run the authentication + * function and compare the result with the value of the auth_tag + */ + if (auth_start) { + /* + * if we're using a universal hash, then we need to compute the + * keystream prefix for encrypting the universal hash output + * + * if the keystream prefix length is zero, then we know that + * the authenticator isn't using a universal hash function + */ + if (session_keys->rtp_auth->prefix_len != 0) { + prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth); + status = srtp_cipher_output(session_keys->rtp_cipher, tmp_tag, + &prefix_len); + debug_print(mod_srtp, "keystream prefix: %s", + srtp_octet_string_hex_string(tmp_tag, prefix_len)); + if (status) + return srtp_err_status_cipher_fail; + } + + /* initialize auth func context */ + status = srtp_auth_start(session_keys->rtp_auth); + if (status) + return status; + + /* now compute auth function over packet */ + status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start, + *pkt_octet_len - tag_len - mki_size); + + /* run auth func over ROC, then write tmp tag */ + status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, + tmp_tag); + + debug_print(mod_srtp, "computed auth tag: %s", + srtp_octet_string_hex_string(tmp_tag, tag_len)); + debug_print(mod_srtp, "packet auth tag: %s", + srtp_octet_string_hex_string(auth_tag, tag_len)); + if (status) + return srtp_err_status_auth_fail; + + if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) + return srtp_err_status_auth_fail; + } + + /* + * update the key usage limit, and check it to make sure that we + * didn't just hit either the soft limit or the hard limit, and call + * the event handler if we hit either. + */ + switch (srtp_key_limit_update(session_keys->limit)) { + case srtp_key_event_normal: + break; + case srtp_key_event_soft_limit: + srtp_handle_event(ctx, stream, event_key_soft_limit); + break; + case srtp_key_event_hard_limit: + srtp_handle_event(ctx, stream, event_key_hard_limit); + return srtp_err_status_key_expired; + default: + break; + } + + if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { + /* extensions header encryption RFC 6904 */ + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); + if (status) { + return status; + } + } + + /* if we're decrypting, add keystream into ciphertext */ + if (enc_start) { + status = srtp_cipher_decrypt(session_keys->rtp_cipher, + (uint8_t *)enc_start, &enc_octet_len); + if (status) + return srtp_err_status_cipher_fail; + } + + /* + * verify that stream is for received traffic - this check will + * detect SSRC collisions, since a stream that appears in both + * srtp_protect() and srtp_unprotect() will fail this test in one of + * those functions. + * + * we do this check *after* the authentication check, so that the + * latter check will catch any attempts to fool us into thinking + * that we've got a collision + */ + if (stream->direction != dir_srtp_receiver) { + if (stream->direction == dir_unknown) { + stream->direction = dir_srtp_receiver; + } else { + srtp_handle_event(ctx, stream, event_ssrc_collision); + } + } + + /* + * if the stream is a 'provisional' one, in which the template context + * is used, then we need to allocate a new stream at this point, since + * the authentication passed + */ + if (stream == ctx->stream_template) { + srtp_stream_ctx_t *new_stream; + + /* + * allocate and initialize a new stream + * + * note that we indicate failure if we can't allocate the new + * stream, and some implementations will want to not return + * failure here + */ + status = + srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + if (status) + return status; + + /* add new stream to the head of the stream_list */ + new_stream->next = ctx->stream_list; + ctx->stream_list = new_stream; + + /* set stream (the pointer used in this function) */ + stream = new_stream; + } + + /* + * the message authentication function passed, so add the packet + * index into the replay database + */ + if (advance_packet_index) { + srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, roc_to_set, seq_to_set); + stream->pending_roc = 0; + srtp_rdbx_add_index(&stream->rtp_rdbx, 0); + } else { + srtp_rdbx_add_index(&stream->rtp_rdbx, delta); + } + + /* decrease the packet length by the length of the auth tag */ + *pkt_octet_len -= tag_len; + + /* decrease the packet length by the mki size */ + *pkt_octet_len -= mki_size; + + return srtp_err_status_ok; } -srtp_err_status_t -srtp_init() { - srtp_err_status_t status; +srtp_err_status_t srtp_init() +{ + srtp_err_status_t status; - /* initialize crypto kernel */ - status = srtp_crypto_kernel_init(); - if (status) - return status; + /* initialize crypto kernel */ + status = srtp_crypto_kernel_init(); + if (status) + return status; - /* load srtp debug module into the kernel */ - status = srtp_crypto_kernel_load_debug_module(&mod_srtp); - if (status) - return status; + /* load srtp debug module into the kernel */ + status = srtp_crypto_kernel_load_debug_module(&mod_srtp); + if (status) + return status; - return srtp_err_status_ok; + return srtp_err_status_ok; } -srtp_err_status_t -srtp_shutdown() { - srtp_err_status_t status; +srtp_err_status_t srtp_shutdown() +{ + srtp_err_status_t status; - /* shut down crypto kernel */ - status = srtp_crypto_kernel_shutdown(); - if (status) - return status; + /* shut down crypto kernel */ + status = srtp_crypto_kernel_shutdown(); + if (status) + return status; - /* shutting down crypto kernel frees the srtp debug module as well */ + /* shutting down crypto kernel frees the srtp debug module as well */ - return srtp_err_status_ok; + return srtp_err_status_ok; } - -/* +/* * The following code is under consideration for removal. See - * SRTP_MAX_TRAILER_LEN + * SRTP_MAX_TRAILER_LEN */ #if 0 @@ -2740,378 +2774,376 @@ srtp_get_trailer_length(const srtp_stream_t s) { * srtp_get_stream(ssrc) returns a pointer to the stream corresponding * to ssrc, or NULL if no stream exists for that ssrc * - * this is an internal function + * this is an internal function */ -srtp_stream_ctx_t * -srtp_get_stream(srtp_t srtp, uint32_t ssrc) { - srtp_stream_ctx_t *stream; +srtp_stream_ctx_t *srtp_get_stream(srtp_t srtp, uint32_t ssrc) +{ + srtp_stream_ctx_t *stream; - /* walk down list until ssrc is found */ - stream = srtp->stream_list; - while (stream != NULL) { - if (stream->ssrc == ssrc) - return stream; - stream = stream->next; - } - - /* we haven't found our ssrc, so return a null */ - return NULL; + /* walk down list until ssrc is found */ + stream = srtp->stream_list; + while (stream != NULL) { + if (stream->ssrc == ssrc) + return stream; + stream = stream->next; + } + + /* we haven't found our ssrc, so return a null */ + return NULL; } -srtp_err_status_t -srtp_dealloc(srtp_t session) { - srtp_stream_ctx_t *stream; - srtp_err_status_t status; +srtp_err_status_t srtp_dealloc(srtp_t session) +{ + srtp_stream_ctx_t *stream; + srtp_err_status_t status; - /* - * we take a conservative deallocation strategy - if we encounter an - * error deallocating a stream, then we stop trying to deallocate - * memory and just return an error - */ + /* + * we take a conservative deallocation strategy - if we encounter an + * error deallocating a stream, then we stop trying to deallocate + * memory and just return an error + */ - /* walk list of streams, deallocating as we go */ - stream = session->stream_list; - while (stream != NULL) { - srtp_stream_t next = stream->next; + /* walk list of streams, deallocating as we go */ + stream = session->stream_list; + while (stream != NULL) { + srtp_stream_t next = stream->next; + status = srtp_stream_dealloc(stream, session->stream_template); + if (status) + return status; + stream = next; + } + + /* deallocate stream template, if there is one */ + if (session->stream_template != NULL) { + status = srtp_stream_dealloc(session->stream_template, NULL); + if (status) + return status; + } + + /* deallocate session context */ + srtp_crypto_free(session); + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy) +{ + srtp_err_status_t status; + srtp_stream_t tmp; + + /* sanity check arguments */ + if ((session == NULL) || (policy == NULL) || + (!srtp_validate_policy_master_keys(policy))) + return srtp_err_status_bad_param; + + /* allocate stream */ + status = srtp_stream_alloc(&tmp, policy); + if (status) { + return status; + } + + /* initialize stream */ + status = srtp_stream_init(tmp, policy); + if (status) { + srtp_stream_dealloc(tmp, NULL); + return status; + } + + /* + * set the head of the stream list or the template to point to the + * stream that we've just alloced and init'ed, depending on whether + * or not it has a wildcard SSRC value or not + * + * if the template stream has already been set, then the policy is + * inconsistent, so we return a bad_param error code + */ + switch (policy->ssrc.type) { + case (ssrc_any_outbound): + if (session->stream_template) { + srtp_stream_dealloc(tmp, NULL); + return srtp_err_status_bad_param; + } + session->stream_template = tmp; + session->stream_template->direction = dir_srtp_sender; + break; + case (ssrc_any_inbound): + if (session->stream_template) { + srtp_stream_dealloc(tmp, NULL); + return srtp_err_status_bad_param; + } + session->stream_template = tmp; + session->stream_template->direction = dir_srtp_receiver; + break; + case (ssrc_specific): + tmp->next = session->stream_list; + session->stream_list = tmp; + break; + case (ssrc_undefined): + default: + srtp_stream_dealloc(tmp, NULL); + return srtp_err_status_bad_param; + } + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_create(srtp_t *session, /* handle for session */ + const srtp_policy_t *policy) +{ /* SRTP policy (list) */ + srtp_err_status_t stat; + srtp_ctx_t *ctx; + + /* sanity check arguments */ + if (session == NULL) + return srtp_err_status_bad_param; + + /* allocate srtp context and set ctx_ptr */ + ctx = (srtp_ctx_t *)srtp_crypto_alloc(sizeof(srtp_ctx_t)); + if (ctx == NULL) + return srtp_err_status_alloc_fail; + *session = ctx; + + /* + * loop over elements in the policy list, allocating and + * initializing a stream for each element + */ + ctx->stream_template = NULL; + ctx->stream_list = NULL; + ctx->user_data = NULL; + while (policy != NULL) { + stat = srtp_add_stream(ctx, policy); + if (stat) { + /* clean up everything */ + srtp_dealloc(*session); + *session = NULL; + return stat; + } + + /* set policy to next item in list */ + policy = policy->next; + } + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_remove_stream(srtp_t session, uint32_t ssrc) +{ + srtp_stream_ctx_t *stream, *last_stream; + srtp_err_status_t status; + + /* sanity check arguments */ + if (session == NULL) + return srtp_err_status_bad_param; + + /* find stream in list; complain if not found */ + last_stream = stream = session->stream_list; + while ((stream != NULL) && (ssrc != stream->ssrc)) { + last_stream = stream; + stream = stream->next; + } + if (stream == NULL) + return srtp_err_status_no_ctx; + + /* remove stream from the list */ + if (last_stream == stream) + /* stream was first in list */ + session->stream_list = stream->next; + else + last_stream->next = stream->next; + + /* deallocate the stream */ status = srtp_stream_dealloc(stream, session->stream_template); if (status) - return status; - stream = next; - } - - /* deallocate stream template, if there is one */ - if (session->stream_template != NULL) { - status = srtp_stream_dealloc(session->stream_template, NULL); - if (status) - return status; - } + return status; - /* deallocate session context */ - srtp_crypto_free(session); - - return srtp_err_status_ok; + return srtp_err_status_ok; } +srtp_err_status_t srtp_update(srtp_t session, const srtp_policy_t *policy) +{ + srtp_err_status_t stat; -srtp_err_status_t -srtp_add_stream(srtp_t session, - const srtp_policy_t *policy) { - srtp_err_status_t status; - srtp_stream_t tmp; - - /* sanity check arguments */ - if ((session == NULL) || (policy == NULL) || (!srtp_validate_policy_master_keys(policy))) - return srtp_err_status_bad_param; - - /* allocate stream */ - status = srtp_stream_alloc(&tmp, policy); - if (status) { - return status; - } - - /* initialize stream */ - status = srtp_stream_init(tmp, policy); - if (status) { - srtp_crypto_free(tmp); - return status; - } - - /* - * set the head of the stream list or the template to point to the - * stream that we've just alloced and init'ed, depending on whether - * or not it has a wildcard SSRC value or not - * - * if the template stream has already been set, then the policy is - * inconsistent, so we return a bad_param error code - */ - switch (policy->ssrc.type) { - case (ssrc_any_outbound): - if (session->stream_template) { - return srtp_err_status_bad_param; - } - session->stream_template = tmp; - session->stream_template->direction = dir_srtp_sender; - break; - case (ssrc_any_inbound): - if (session->stream_template) { - return srtp_err_status_bad_param; - } - session->stream_template = tmp; - session->stream_template->direction = dir_srtp_receiver; - break; - case (ssrc_specific): - tmp->next = session->stream_list; - session->stream_list = tmp; - break; - case (ssrc_undefined): - default: - srtp_crypto_free(tmp); - return srtp_err_status_bad_param; - } - - return srtp_err_status_ok; -} - - -srtp_err_status_t -srtp_create(srtp_t *session, /* handle for session */ - const srtp_policy_t *policy) { /* SRTP policy (list) */ - srtp_err_status_t stat; - srtp_ctx_t *ctx; - - /* sanity check arguments */ - if (session == NULL) - return srtp_err_status_bad_param; - - /* allocate srtp context and set ctx_ptr */ - ctx = (srtp_ctx_t *) srtp_crypto_alloc(sizeof(srtp_ctx_t)); - if (ctx == NULL) - return srtp_err_status_alloc_fail; - *session = ctx; - - /* - * loop over elements in the policy list, allocating and - * initializing a stream for each element - */ - ctx->stream_template = NULL; - ctx->stream_list = NULL; - ctx->user_data = NULL; - while (policy != NULL) { - - stat = srtp_add_stream(ctx, policy); - if (stat) { - /* clean up everything */ - srtp_dealloc(*session); - *session = NULL; - return stat; - } - - /* set policy to next item in list */ - policy = policy->next; - } - - return srtp_err_status_ok; -} - - -srtp_err_status_t -srtp_remove_stream(srtp_t session, uint32_t ssrc) { - srtp_stream_ctx_t *stream, *last_stream; - srtp_err_status_t status; - - /* sanity check arguments */ - if (session == NULL) - return srtp_err_status_bad_param; - - /* find stream in list; complain if not found */ - last_stream = stream = session->stream_list; - while ((stream != NULL) && (ssrc != stream->ssrc)) { - last_stream = stream; - stream = stream->next; - } - if (stream == NULL) - return srtp_err_status_no_ctx; - - /* remove stream from the list */ - if (last_stream == stream) - /* stream was first in list */ - session->stream_list = stream->next; - else - last_stream->next = stream->next; - - /* deallocate the stream */ - status = srtp_stream_dealloc(stream, session->stream_template); - if (status) - return status; - - return srtp_err_status_ok; -} - - -srtp_err_status_t -srtp_update(srtp_t session, const srtp_policy_t *policy) { - srtp_err_status_t stat; - - /* sanity check arguments */ - if ((session == NULL) || (policy == NULL) || (!srtp_validate_policy_master_keys(policy))) { - return srtp_err_status_bad_param; - } - - while (policy != NULL) { - stat = srtp_update_stream(session, policy); - if (stat) { - return stat; + /* sanity check arguments */ + if ((session == NULL) || (policy == NULL) || + (!srtp_validate_policy_master_keys(policy))) { + return srtp_err_status_bad_param; } - /* set policy to next item in list */ - policy = policy->next; - } - return srtp_err_status_ok; + while (policy != NULL) { + stat = srtp_update_stream(session, policy); + if (stat) { + return stat; + } + + /* set policy to next item in list */ + policy = policy->next; + } + return srtp_err_status_ok; } +static srtp_err_status_t update_template_streams(srtp_t session, + const srtp_policy_t *policy) +{ + srtp_err_status_t status; + srtp_stream_t new_stream_template; + srtp_stream_t new_stream_list = NULL; -static srtp_err_status_t -update_template_streams(srtp_t session, const srtp_policy_t *policy) { - srtp_err_status_t status; - srtp_stream_t new_stream_template; - srtp_stream_t new_stream_list = NULL; + if (session->stream_template == NULL) { + return srtp_err_status_bad_param; + } - if (session->stream_template == NULL) { - return srtp_err_status_bad_param; - } + /* allocate new template stream */ + status = srtp_stream_alloc(&new_stream_template, policy); + if (status) { + return status; + } - /* allocate new template stream */ - status = srtp_stream_alloc(&new_stream_template, policy); - if (status) { + /* initialize new template stream */ + status = srtp_stream_init(new_stream_template, policy); + if (status) { + srtp_crypto_free(new_stream_template); + return status; + } + + /* for all old templated streams */ + for (;;) { + srtp_stream_t stream; + uint32_t ssrc; + srtp_xtd_seq_num_t old_index; + srtp_rdb_t old_rtcp_rdb; + + stream = session->stream_list; + while ((stream != NULL) && + (stream->session_keys[0].rtp_auth != + session->stream_template->session_keys[0].rtp_auth)) { + stream = stream->next; + } + if (stream == NULL) { + /* no more templated streams */ + break; + } + + /* save old extendard seq */ + ssrc = stream->ssrc; + old_index = stream->rtp_rdbx.index; + old_rtcp_rdb = stream->rtcp_rdb; + + /* remove stream */ + status = srtp_remove_stream(session, ssrc); + if (status) { + /* free new allocations */ + while (new_stream_list != NULL) { + srtp_stream_t next = new_stream_list->next; + srtp_stream_dealloc(new_stream_list, new_stream_template); + new_stream_list = next; + } + srtp_stream_dealloc(new_stream_template, NULL); + return status; + } + + /* allocate and initialize a new stream */ + status = srtp_stream_clone(new_stream_template, ssrc, &stream); + if (status) { + /* free new allocations */ + while (new_stream_list != NULL) { + srtp_stream_t next = new_stream_list->next; + srtp_stream_dealloc(new_stream_list, new_stream_template); + new_stream_list = next; + } + srtp_stream_dealloc(new_stream_template, NULL); + return status; + } + + /* add new stream to the head of the new_stream_list */ + stream->next = new_stream_list; + new_stream_list = stream; + + /* restore old extended seq */ + stream->rtp_rdbx.index = old_index; + stream->rtcp_rdb = old_rtcp_rdb; + } + /* dealloc old template */ + srtp_stream_dealloc(session->stream_template, NULL); + /* set new template */ + session->stream_template = new_stream_template; + /* add new list */ + if (new_stream_list) { + srtp_stream_t tail = new_stream_list; + while (tail->next) { + tail = tail->next; + } + tail->next = session->stream_list; + session->stream_list = new_stream_list; + } return status; - } +} - /* initialize new template stream */ - status = srtp_stream_init(new_stream_template, policy); - if (status) { - srtp_crypto_free(new_stream_template); - return status; - } - - /* for all old templated streams */ - for (;;) { - srtp_stream_t stream; - uint32_t ssrc; +static srtp_err_status_t update_stream(srtp_t session, + const srtp_policy_t *policy) +{ + srtp_err_status_t status; srtp_xtd_seq_num_t old_index; srtp_rdb_t old_rtcp_rdb; + srtp_stream_t stream; - stream = session->stream_list; - while ((stream != NULL) && - (stream->session_keys[0].rtp_auth != - session->stream_template->session_keys[0].rtp_auth)) { - stream = stream->next; - } + stream = srtp_get_stream(session, htonl(policy->ssrc.value)); if (stream == NULL) { - /* no more templated streams */ - break; + return srtp_err_status_bad_param; } /* save old extendard seq */ - ssrc = stream->ssrc; old_index = stream->rtp_rdbx.index; old_rtcp_rdb = stream->rtcp_rdb; - /* remove stream */ - status = srtp_remove_stream(session, ssrc); + status = srtp_remove_stream(session, htonl(policy->ssrc.value)); if (status) { - /* free new allocations */ - while (new_stream_list != NULL) { - srtp_stream_t next = new_stream_list->next; - srtp_stream_dealloc(new_stream_list, new_stream_template); - new_stream_list = next; - } - srtp_stream_dealloc(new_stream_template, NULL); - return status; + return status; } - /* allocate and initialize a new stream */ - status = srtp_stream_clone(new_stream_template, ssrc, &stream); + status = srtp_add_stream(session, policy); if (status) { - /* free new allocations */ - while (new_stream_list != NULL) { - srtp_stream_t next = new_stream_list->next; - srtp_stream_dealloc(new_stream_list, new_stream_template); - new_stream_list = next; - } - srtp_stream_dealloc(new_stream_template, NULL); - return status; + return status; } - /* add new stream to the head of the new_stream_list */ - stream->next = new_stream_list; - new_stream_list = stream; + stream = srtp_get_stream(session, htonl(policy->ssrc.value)); + if (stream == NULL) { + return srtp_err_status_fail; + } /* restore old extended seq */ stream->rtp_rdbx.index = old_index; stream->rtcp_rdb = old_rtcp_rdb; - } - /* dealloc old template */ - srtp_stream_dealloc(session->stream_template, NULL); - /* set new template */ - session->stream_template = new_stream_template; - /* add new list */ - if (new_stream_list) { - srtp_stream_t tail = new_stream_list; - while (tail->next) { - tail = tail->next; + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_update_stream(srtp_t session, + const srtp_policy_t *policy) +{ + srtp_err_status_t status; + + /* sanity check arguments */ + if ((session == NULL) || (policy == NULL) || + (!srtp_validate_policy_master_keys(policy))) + return srtp_err_status_bad_param; + + switch (policy->ssrc.type) { + case (ssrc_any_outbound): + case (ssrc_any_inbound): + status = update_template_streams(session, policy); + break; + case (ssrc_specific): + status = update_stream(session, policy); + break; + case (ssrc_undefined): + default: + return srtp_err_status_bad_param; } - tail->next = session->stream_list; - session->stream_list = new_stream_list; - } - return status; -} - -static srtp_err_status_t -update_stream(srtp_t session, const srtp_policy_t *policy) { - srtp_err_status_t status; - srtp_xtd_seq_num_t old_index; - srtp_rdb_t old_rtcp_rdb; - srtp_stream_t stream; - - stream = srtp_get_stream(session, htonl(policy->ssrc.value)); - if (stream == NULL) { - return srtp_err_status_bad_param; - } - - /* save old extendard seq */ - old_index = stream->rtp_rdbx.index; - old_rtcp_rdb = stream->rtcp_rdb; - - status = srtp_remove_stream(session, htonl(policy->ssrc.value)); - if (status) { return status; - } - - status = srtp_add_stream(session, policy); - if (status) { - return status; - } - - stream = srtp_get_stream(session, htonl(policy->ssrc.value)); - if (stream == NULL) { - return srtp_err_status_fail; - } - - /* restore old extended seq */ - stream->rtp_rdbx.index = old_index; - stream->rtcp_rdb = old_rtcp_rdb; - - return srtp_err_status_ok; } - -srtp_err_status_t -srtp_update_stream(srtp_t session, const srtp_policy_t *policy) { - srtp_err_status_t status; - - /* sanity check arguments */ - if ((session == NULL) || (policy == NULL) || (!srtp_validate_policy_master_keys(policy))) - return srtp_err_status_bad_param; - - switch (policy->ssrc.type) { - case (ssrc_any_outbound): - case (ssrc_any_inbound): - status = update_template_streams(session, policy); - break; - case (ssrc_specific): - status = update_stream(session, policy); - break; - case (ssrc_undefined): - default: - return srtp_err_status_bad_param; - } - - return status; -} - - /* * The default policy - provides a convenient way for callers to use * the default security policy @@ -3121,283 +3153,264 @@ srtp_update_stream(srtp_t session, const srtp_policy_t *policy) { * */ -/* +/* * NOTE: cipher_key_len is really key len (128 bits) plus salt len * (112 bits) */ /* There are hard-coded 16's for base_key_len in the key generation code */ -void -srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p) { - - p->cipher_type = SRTP_AES_ICM_128; - p->cipher_key_len = SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; - +void srtp_crypto_policy_set_rtp_default(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_ICM_128; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; } -void -srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p) { - - p->cipher_type = SRTP_AES_ICM_128; - p->cipher_key_len = SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; - +void srtp_crypto_policy_set_rtcp_default(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_ICM_128; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* default 128 bits per RFC 3711 */ + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; } -void -srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p) { +void srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 4568 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ - /* - * corresponds to RFC 4568 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_128; - p->cipher_key_len = SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */ - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* 160 bit key */ - p->auth_tag_len = 4; /* 32 bit tag */ - p->sec_serv = sec_serv_conf_and_auth; - + p->cipher_type = SRTP_AES_ICM_128; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */ + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* 160 bit key */ + p->auth_tag_len = 4; /* 32 bit tag */ + p->sec_serv = sec_serv_conf_and_auth; } +void srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 4568 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ -void -srtp_crypto_policy_set_aes_cm_128_null_auth(srtp_crypto_policy_t *p) { - - /* - * corresponds to RFC 4568 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_128; - p->cipher_key_len = SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */ - p->auth_type = SRTP_NULL_AUTH; - p->auth_key_len = 0; - p->auth_tag_len = 0; - p->sec_serv = sec_serv_conf; - + p->cipher_type = SRTP_AES_ICM_128; + p->cipher_key_len = + SRTP_AES_ICM_128_KEY_LEN_WSALT; /* 128 bit key, 112 bit salt */ + p->auth_type = SRTP_NULL_AUTH; + p->auth_key_len = 0; + p->auth_tag_len = 0; + p->sec_serv = sec_serv_conf; } +void srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 4568 + */ -void -srtp_crypto_policy_set_null_cipher_hmac_sha1_80(srtp_crypto_policy_t *p) { - - /* - * corresponds to RFC 4568 - */ - - p->cipher_type = SRTP_NULL_CIPHER; - p->cipher_key_len = 0; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; - p->auth_tag_len = 10; - p->sec_serv = sec_serv_auth; - + p->cipher_type = SRTP_NULL_CIPHER; + p->cipher_key_len = 0; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; + p->auth_tag_len = 10; + p->sec_serv = sec_serv_auth; } -void -srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p) { +void srtp_crypto_policy_set_null_cipher_hmac_null(srtp_crypto_policy_t *p) +{ + /* + * Should only be used for testing + */ - /* - * Should only be used for testing - */ - - p->cipher_type = SRTP_NULL_CIPHER; - p->cipher_key_len = 0; - p->auth_type = SRTP_NULL_AUTH; - p->auth_key_len = 0; - p->auth_tag_len = 0; - p->sec_serv = sec_serv_none; - + p->cipher_type = SRTP_NULL_CIPHER; + p->cipher_key_len = 0; + p->auth_type = SRTP_NULL_AUTH; + p->auth_key_len = 0; + p->auth_tag_len = 0; + p->sec_serv = sec_serv_none; } +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + */ -void -srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(srtp_crypto_policy_t *p) { - - /* - * corresponds to RFC 6188 - */ - - p->cipher_type = SRTP_AES_ICM_256; - p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; + p->cipher_type = SRTP_AES_ICM_256; + p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; } +void srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ -void -srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(srtp_crypto_policy_t *p) { - - /* - * corresponds to RFC 6188 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_256; - p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; + p->cipher_type = SRTP_AES_ICM_256; + p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; } /* * AES-256 with no authentication. */ -void -srtp_crypto_policy_set_aes_cm_256_null_auth (srtp_crypto_policy_t *p) +void srtp_crypto_policy_set_aes_cm_256_null_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_ICM_256; - p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; - p->auth_key_len = 0; - p->auth_tag_len = 0; - p->sec_serv = sec_serv_conf; + p->cipher_type = SRTP_AES_ICM_256; + p->cipher_key_len = SRTP_AES_ICM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; + p->auth_key_len = 0; + p->auth_tag_len = 0; + p->sec_serv = sec_serv_conf; } #ifdef OPENSSL -void -srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p) { +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_80(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + */ - /* - * corresponds to RFC 6188 - */ - - p->cipher_type = SRTP_AES_ICM_192; - p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; + p->cipher_type = SRTP_AES_ICM_192; + p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; } +void srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p) +{ + /* + * corresponds to RFC 6188 + * + * note that this crypto policy is intended for SRTP, but not SRTCP + */ -void -srtp_crypto_policy_set_aes_cm_192_hmac_sha1_32(srtp_crypto_policy_t *p) { - - /* - * corresponds to RFC 6188 - * - * note that this crypto policy is intended for SRTP, but not SRTCP - */ - - p->cipher_type = SRTP_AES_ICM_192; - p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; - p->auth_type = SRTP_HMAC_SHA1; - p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ - p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ - p->sec_serv = sec_serv_conf_and_auth; + p->cipher_type = SRTP_AES_ICM_192; + p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; + p->auth_type = SRTP_HMAC_SHA1; + p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ + p->auth_tag_len = 4; /* default 80 bits per RFC 3711 */ + p->sec_serv = sec_serv_conf_and_auth; } /* * AES-192 with no authentication. */ -void -srtp_crypto_policy_set_aes_cm_192_null_auth (srtp_crypto_policy_t *p) +void srtp_crypto_policy_set_aes_cm_192_null_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_ICM_192; - p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; - p->auth_key_len = 0; - p->auth_tag_len = 0; - p->sec_serv = sec_serv_conf; + p->cipher_type = SRTP_AES_ICM_192; + p->cipher_key_len = SRTP_AES_ICM_192_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; + p->auth_key_len = 0; + p->auth_tag_len = 0; + p->sec_serv = sec_serv_conf; } /* - * AES-128 GCM mode with 8 octet auth tag. + * AES-128 GCM mode with 8 octet auth tag. */ -void -srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_GCM_128; - p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 8; /* 8 octet tag length */ - p->sec_serv = sec_serv_conf_and_auth; +void srtp_crypto_policy_set_aes_gcm_128_8_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_128; + p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 8; /* 8 octet tag length */ + p->sec_serv = sec_serv_conf_and_auth; } /* - * AES-256 GCM mode with 8 octet auth tag. + * AES-256 GCM mode with 8 octet auth tag. */ -void -srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_GCM_256; - p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 8; /* 8 octet tag length */ - p->sec_serv = sec_serv_conf_and_auth; +void srtp_crypto_policy_set_aes_gcm_256_8_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_256; + p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 8; /* 8 octet tag length */ + p->sec_serv = sec_serv_conf_and_auth; } /* - * AES-128 GCM mode with 8 octet auth tag, no RTCP encryption. + * AES-128 GCM mode with 8 octet auth tag, no RTCP encryption. */ -void -srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_GCM_128; - p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 8; /* 8 octet tag length */ - p->sec_serv = sec_serv_auth; /* This only applies to RTCP */ +void srtp_crypto_policy_set_aes_gcm_128_8_only_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_128; + p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 8; /* 8 octet tag length */ + p->sec_serv = sec_serv_auth; /* This only applies to RTCP */ } /* - * AES-256 GCM mode with 8 octet auth tag, no RTCP encryption. + * AES-256 GCM mode with 8 octet auth tag, no RTCP encryption. */ -void -srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_GCM_256; - p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 8; /* 8 octet tag length */ - p->sec_serv = sec_serv_auth; /* This only applies to RTCP */ +void srtp_crypto_policy_set_aes_gcm_256_8_only_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_256; + p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 8; /* 8 octet tag length */ + p->sec_serv = sec_serv_auth; /* This only applies to RTCP */ } /* - * AES-128 GCM mode with 16 octet auth tag. + * AES-128 GCM mode with 16 octet auth tag. */ -void -srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_GCM_128; - p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 16; /* 16 octet tag length */ - p->sec_serv = sec_serv_conf_and_auth; +void srtp_crypto_policy_set_aes_gcm_128_16_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_128; + p->cipher_key_len = SRTP_AES_GCM_128_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 16; /* 16 octet tag length */ + p->sec_serv = sec_serv_conf_and_auth; } /* - * AES-256 GCM mode with 16 octet auth tag. + * AES-256 GCM mode with 16 octet auth tag. */ -void -srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) { - p->cipher_type = SRTP_AES_GCM_256; - p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; - p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ - p->auth_key_len = 0; - p->auth_tag_len = 16; /* 16 octet tag length */ - p->sec_serv = sec_serv_conf_and_auth; +void srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) +{ + p->cipher_type = SRTP_AES_GCM_256; + p->cipher_key_len = SRTP_AES_GCM_256_KEY_LEN_WSALT; + p->auth_type = SRTP_NULL_AUTH; /* GCM handles the auth for us */ + p->auth_key_len = 0; + p->auth_tag_len = 16; /* 16 octet tag length */ + p->sec_serv = sec_serv_conf_and_auth; } #endif -/* +/* * secure rtcp functions */ @@ -3420,7 +3433,7 @@ srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) { * +--+--+--+--+--+--+--+--+--+--+--+--+* * * Input: *session_keys - pointer to SRTP stream context session keys, - * used to retrieve the SALT + * used to retrieve the SALT * *iv - Pointer to recieve the calculated IV * seq_num - The SEQ value to use for the IV calculation. * *hdr - The RTP header, used to get the SSRC value @@ -3429,12 +3442,14 @@ srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) { * if seq_num is invalid * */ -static srtp_err_status_t -srtp_calc_aead_iv_srtcp(srtp_session_keys_t *session_keys, v128_t *iv, - uint32_t seq_num, srtcp_hdr_t *hdr) +static srtp_err_status_t srtp_calc_aead_iv_srtcp( + srtp_session_keys_t *session_keys, + v128_t *iv, + uint32_t seq_num, + srtcp_hdr_t *hdr) { - v128_t in; - v128_t salt; + v128_t in; + v128_t salt; memset(&in, 0, sizeof(v128_t)); memset(&salt, 0, sizeof(v128_t)); @@ -3470,18 +3485,21 @@ srtp_calc_aead_iv_srtcp(srtp_session_keys_t *session_keys, v128_t *iv, /* * This code handles AEAD ciphers for outgoing RTCP. We currently support - * AES-GCM mode with 128 or 256 bit keys. + * AES-GCM mode with 128 or 256 bit keys. */ -static srtp_err_status_t -srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, - void *rtcp_hdr, unsigned int *pkt_octet_len, - srtp_session_keys_t *session_keys, unsigned int use_mki) +static srtp_err_status_t srtp_protect_rtcp_aead( + srtp_t ctx, + srtp_stream_ctx_t *stream, + void *rtcp_hdr, + unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, + unsigned int use_mki) { - srtcp_hdr_t *hdr = (srtcp_hdr_t*)rtcp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *trailer; /* pointer to start of trailer */ + srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ + uint32_t *trailer; /* pointer to start of trailer */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ - uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ + uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ srtp_err_status_t status; uint32_t tag_len; uint32_t seq_num; @@ -3496,14 +3514,16 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * set encryption start and encryption length - if we're not * providing confidentiality, set enc_start to NULL */ - enc_start = (uint32_t*)hdr + uint32s_in_rtcp_header; + enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header; enc_octet_len = *pkt_octet_len - octets_in_rtcp_header; /* NOTE: hdr->length is not usable - it refers to only the first - RTCP report in the compound packet! */ + * RTCP report in the compound packet! + */ /* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - multiples of 32-bits (RFC 3550 6.1) */ - trailer = (uint32_t*)((char*)enc_start + enc_octet_len + tag_len); + * multiples of 32-bits (RFC 3550 6.1) + */ + trailer = (uint32_t *)((char *)enc_start + enc_octet_len + tag_len); if (stream->rtcp_services & sec_serv_conf) { *trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ @@ -3514,7 +3534,8 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, *trailer = 0x00000000; /* set encrypt bit */ } - mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len + sizeof(srtcp_trailer_t), + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len + + sizeof(srtcp_trailer_t), session_keys, use_mki); /* @@ -3523,7 +3544,7 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * (note that srtpc *always* provides authentication, unlike srtp) */ /* Note: This would need to change for optional mikey data */ - auth_tag = (uint8_t*)hdr + *pkt_octet_len; + auth_tag = (uint8_t *)hdr + *pkt_octet_len; /* * check sequence number for overruns, and copy it into the packet @@ -3544,8 +3565,8 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, if (status) { return srtp_err_status_cipher_fail; } - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, - (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv, + srtp_direction_encrypt); if (status) { return srtp_err_status_cipher_fail; } @@ -3558,10 +3579,10 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * If payload encryption is enabled, then the AAD consist of * the RTCP header and the seq# at the end of the packet */ - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, - (uint8_t*)hdr, octets_in_rtcp_header); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr, + octets_in_rtcp_header); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } } else { /* @@ -3569,36 +3590,36 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * the entire packet as described in RFC 7714 (Section 9.3. Data * Types in Unencrypted SRTCP Compound Packets) */ - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, - (uint8_t*)hdr, *pkt_octet_len); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr, + *pkt_octet_len); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } } /* * Process the sequence# as AAD */ tseq = *trailer; - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)&tseq, + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq, sizeof(srtcp_trailer_t)); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } /* if we're encrypting, exor keystream into the message */ if (enc_start) { status = srtp_cipher_encrypt(session_keys->rtcp_cipher, - (uint8_t*)enc_start, &enc_octet_len); + (uint8_t *)enc_start, &enc_octet_len); if (status) { return srtp_err_status_cipher_fail; } /* * Get the tag and append that to the output */ - status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, - &tag_len); + status = srtp_cipher_get_tag(session_keys->rtcp_cipher, + (uint8_t *)auth_tag, &tag_len); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } enc_octet_len += tag_len; } else { @@ -3614,10 +3635,10 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, /* * Get the tag and append that to the output */ - status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, - &tag_len); + status = srtp_cipher_get_tag(session_keys->rtcp_cipher, + (uint8_t *)auth_tag, &tag_len); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } enc_octet_len += tag_len; } @@ -3633,20 +3654,23 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, /* * This function handles incoming SRTCP packets while in AEAD mode, - * which currently supports AES-GCM encryption. Note, the auth tag is + * which currently supports AES-GCM encryption. Note, the auth tag is * at the end of the packet stream and is automatically checked by GCM * when decrypting the payload. */ -static srtp_err_status_t -srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, - void *srtcp_hdr, unsigned int *pkt_octet_len, - srtp_session_keys_t *session_keys, unsigned int use_mki) +static srtp_err_status_t srtp_unprotect_rtcp_aead( + srtp_t ctx, + srtp_stream_ctx_t *stream, + void *srtcp_hdr, + unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, + unsigned int use_mki) { - srtcp_hdr_t *hdr = (srtcp_hdr_t*)srtcp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *trailer; /* pointer to start of trailer */ + srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ + uint32_t *trailer; /* pointer to start of trailer */ unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ - uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ + uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ srtp_err_status_t status; int tag_len; unsigned int tmp_len; @@ -3659,31 +3683,33 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); if (use_mki) { - mki_size = session_keys->mki_size; + mki_size = session_keys->mki_size; } /* * set encryption start, encryption length, and trailer */ - /* index & E (encryption) bit follow normal data. hdr->len - is the number of words (32-bit) in the normal packet minus 1 */ - /* This should point trailer to the word past the end of the - normal data. */ + /* index & E (encryption) bit follow normal data. hdr->len is the number of + * words (32-bit) in the normal packet minus 1 + */ + /* This should point trailer to the word past the end of the normal data. */ /* This would need to be modified for optional mikey data */ /* * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - * multiples of 32-bits (RFC 3550 6.1) + * multiples of 32-bits (RFC 3550 6.1) */ - trailer = (uint32_t*)((char*)hdr + *pkt_octet_len - sizeof(srtcp_trailer_t) - mki_size); + trailer = (uint32_t *)((char *)hdr + *pkt_octet_len - + sizeof(srtcp_trailer_t) - mki_size); /* - * We pass the tag down to the cipher when doing GCM mode + * We pass the tag down to the cipher when doing GCM mode */ - enc_octet_len = *pkt_octet_len - (octets_in_rtcp_header + + enc_octet_len = *pkt_octet_len - (octets_in_rtcp_header + sizeof(srtcp_trailer_t) + mki_size); - auth_tag = (uint8_t*)hdr + *pkt_octet_len - tag_len - mki_size - sizeof(srtcp_trailer_t); + auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len - mki_size - + sizeof(srtcp_trailer_t); - if (*((unsigned char*)trailer) & SRTCP_E_BYTE_BIT) { - enc_start = (uint32_t*)hdr + uint32s_in_rtcp_header; + if (*((unsigned char *)trailer) & SRTCP_E_BYTE_BIT) { + enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header; } else { enc_octet_len = 0; enc_start = NULL; /* this indicates that there's no encryption */ @@ -3707,8 +3733,8 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, if (status) { return srtp_err_status_cipher_fail; } - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, - (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv, + srtp_direction_decrypt); if (status) { return srtp_err_status_cipher_fail; } @@ -3721,10 +3747,10 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * If payload encryption is enabled, then the AAD consist of * the RTCP header and the seq# at the end of the packet */ - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, - (uint8_t*)hdr, octets_in_rtcp_header); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr, + octets_in_rtcp_header); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } } else { /* @@ -3733,10 +3759,10 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Types in Unencrypted SRTCP Compound Packets) */ status = srtp_cipher_set_aad( - session_keys->rtcp_cipher, (uint8_t*)hdr, - (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t) - mki_size)); + session_keys->rtcp_cipher, (uint8_t *)hdr, + (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t) - mki_size)); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } } @@ -3744,15 +3770,16 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Process the sequence# as AAD */ tseq = *trailer; - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, - (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)&tseq, + sizeof(srtcp_trailer_t)); if (status) { - return ( srtp_err_status_cipher_fail); + return (srtp_err_status_cipher_fail); } /* if we're decrypting, exor keystream into the message */ if (enc_start) { - status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t*)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtcp_cipher, + (uint8_t *)enc_start, &enc_octet_len); if (status) { return status; } @@ -3761,7 +3788,8 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Still need to run the cipher to check the tag */ tmp_len = tag_len; - status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t*)auth_tag, &tmp_len); + status = srtp_cipher_decrypt(session_keys->rtcp_cipher, + (uint8_t *)auth_tag, &tmp_len); if (status) { return status; } @@ -3803,7 +3831,8 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * stream, and some implementations will want to not return * failure here */ - status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + status = + srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) { return status; } @@ -3822,754 +3851,790 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, return srtp_err_status_ok; } -srtp_err_status_t -srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { - return srtp_protect_rtcp_mki(ctx, rtcp_hdr, pkt_octet_len, 0, 0); +srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, + void *rtcp_hdr, + int *pkt_octet_len) +{ + return srtp_protect_rtcp_mki(ctx, rtcp_hdr, pkt_octet_len, 0, 0); } -srtp_err_status_t -srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, - unsigned int use_mki, unsigned int mki_index) { - srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *auth_start; /* pointer to start of auth. portion */ - uint32_t *trailer; /* pointer to start of trailer */ - unsigned int enc_octet_len = 0;/* number of octets in encrypted portion */ - uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ - srtp_err_status_t status; - int tag_len; - srtp_stream_ctx_t *stream; - uint32_t prefix_len; - uint32_t seq_num; - unsigned int mki_size = 0; - srtp_session_keys_t *session_keys = NULL; +srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, + void *rtcp_hdr, + int *pkt_octet_len, + unsigned int use_mki, + unsigned int mki_index) +{ + srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ + uint32_t *auth_start; /* pointer to start of auth. portion */ + uint32_t *trailer; /* pointer to start of trailer */ + unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ + uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ + srtp_err_status_t status; + int tag_len; + srtp_stream_ctx_t *stream; + uint32_t prefix_len; + uint32_t seq_num; + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; - /* we assume the hdr is 32-bit aligned to start */ + /* we assume the hdr is 32-bit aligned to start */ - /* check the packet length - it must at least contain a full header */ - if (*pkt_octet_len < octets_in_rtcp_header) - return srtp_err_status_bad_param; + /* check the packet length - it must at least contain a full header */ + if (*pkt_octet_len < octets_in_rtcp_header) + return srtp_err_status_bad_param; - /* - * look up ssrc in srtp_stream list, and process the packet with - * the appropriate stream. if we haven't seen this stream before, - * there's only one key for this srtp_session, and the cipher - * supports key-sharing, then we assume that a new stream using - * that key has just started up - */ - stream = srtp_get_stream(ctx, hdr->ssrc); - if (stream == NULL) { - if (ctx->stream_template != NULL) { - srtp_stream_ctx_t *new_stream; - - /* allocate and initialize a new stream */ - status = srtp_stream_clone(ctx->stream_template, - hdr->ssrc, &new_stream); - if (status) - return status; - - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; - - /* set stream (the pointer used in this function) */ - stream = new_stream; - } else { - /* no template stream, so we return an error */ - return srtp_err_status_no_ctx; - } - } - - /* - * verify that stream is for sending traffic - this check will - * detect SSRC collisions, since a stream that appears in both - * srtp_protect() and srtp_unprotect() will fail this test in one of - * those functions. - */ - if (stream->direction != dir_srtp_sender) { - if (stream->direction == dir_unknown) { - stream->direction = dir_srtp_sender; - } else { - srtp_handle_event(ctx, stream, event_ssrc_collision); + /* + * look up ssrc in srtp_stream list, and process the packet with + * the appropriate stream. if we haven't seen this stream before, + * there's only one key for this srtp_session, and the cipher + * supports key-sharing, then we assume that a new stream using + * that key has just started up + */ + stream = srtp_get_stream(ctx, hdr->ssrc); + if (stream == NULL) { + if (ctx->stream_template != NULL) { + srtp_stream_ctx_t *new_stream; + + /* allocate and initialize a new stream */ + status = + srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + if (status) + return status; + + /* add new stream to the head of the stream_list */ + new_stream->next = ctx->stream_list; + ctx->stream_list = new_stream; + + /* set stream (the pointer used in this function) */ + stream = new_stream; + } else { + /* no template stream, so we return an error */ + return srtp_err_status_no_ctx; + } } - } - session_keys = srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index); + /* + * verify that stream is for sending traffic - this check will + * detect SSRC collisions, since a stream that appears in both + * srtp_protect() and srtp_unprotect() will fail this test in one of + * those functions. + */ + if (stream->direction != dir_srtp_sender) { + if (stream->direction == dir_unknown) { + stream->direction = dir_srtp_sender; + } else { + srtp_handle_event(ctx, stream, event_ssrc_collision); + } + } - /* - * Check if this is an AEAD stream (GCM mode). If so, then dispatch - * the request to our AEAD handler. - */ - if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || - session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { - return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr, - (unsigned int*)pkt_octet_len, session_keys, - use_mki); - } + session_keys = + srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index); - /* get tag length from stream context */ - tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); + if (session_keys == NULL) + return srtp_err_status_bad_mki; - /* - * set encryption start and encryption length - if we're not - * providing confidentiality, set enc_start to NULL - */ - enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header; - enc_octet_len = *pkt_octet_len - octets_in_rtcp_header; + /* + * Check if this is an AEAD stream (GCM mode). If so, then dispatch + * the request to our AEAD handler. + */ + if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || + session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { + return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr, + (unsigned int *)pkt_octet_len, + session_keys, use_mki); + } - /* all of the packet, except the header, gets encrypted */ - /* NOTE: hdr->length is not usable - it refers to only the first - RTCP report in the compound packet! */ - /* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - multiples of 32-bits (RFC 3550 6.1) */ - trailer = (uint32_t *) ((char *)enc_start + enc_octet_len); + /* get tag length from stream context */ + tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); - if (stream->rtcp_services & sec_serv_conf) { - *trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ - } else { - enc_start = NULL; - enc_octet_len = 0; - /* 0 is network-order independant */ - *trailer = 0x00000000; /* set encrypt bit */ - } + /* + * set encryption start and encryption length - if we're not + * providing confidentiality, set enc_start to NULL + */ + enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header; + enc_octet_len = *pkt_octet_len - octets_in_rtcp_header; - mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t), - session_keys, use_mki); + /* all of the packet, except the header, gets encrypted */ + /* + * NOTE: hdr->length is not usable - it refers to only the first RTCP report + * in the compound packet! + */ + /* + * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always + * multiples of 32-bits (RFC 3550 6.1) + */ + trailer = (uint32_t *)((char *)enc_start + enc_octet_len); - /* - * set the auth_start and auth_tag pointers to the proper locations - * (note that srtpc *always* provides authentication, unlike srtp) - */ - /* Note: This would need to change for optional mikey data */ - auth_start = (uint32_t *)hdr; - auth_tag = (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t) + mki_size; + if (stream->rtcp_services & sec_serv_conf) { + *trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */ + } else { + enc_start = NULL; + enc_octet_len = 0; + /* 0 is network-order independant */ + *trailer = 0x00000000; /* set encrypt bit */ + } - /* perform EKT processing if needed */ - srtp_ekt_write_data(stream->ekt, auth_tag, tag_len, pkt_octet_len, - srtp_rdbx_get_packet_index(&stream->rtp_rdbx)); + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + + sizeof(srtcp_trailer_t), + session_keys, use_mki); - /* - * check sequence number for overruns, and copy it into the packet - * if its value isn't too big - */ - status = srtp_rdb_increment(&stream->rtcp_rdb); - if (status) - return status; - seq_num = srtp_rdb_get_value(&stream->rtcp_rdb); - *trailer |= htonl(seq_num); - debug_print(mod_srtp, "srtcp index: %x", seq_num); + /* + * set the auth_start and auth_tag pointers to the proper locations + * (note that srtpc *always* provides authentication, unlike srtp) + */ + /* Note: This would need to change for optional mikey data */ + auth_start = (uint32_t *)hdr; + auth_tag = + (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t) + mki_size; - /* - * if we're using rindael counter mode, set nonce and seq - */ - if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_128 || - session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_192 || - session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_256) { - v128_t iv; - - iv.v32[0] = 0; - iv.v32[1] = hdr->ssrc; /* still in network order! */ - iv.v32[2] = htonl(seq_num >> 16); - iv.v32[3] = htonl(seq_num << 16); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, - srtp_direction_encrypt); - - } else { - v128_t iv; - - /* otherwise, just set the index to seq_num */ - iv.v32[0] = 0; - iv.v32[1] = 0; - iv.v32[2] = 0; - iv.v32[3] = htonl(seq_num); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, - (uint8_t*)&iv, srtp_direction_encrypt); - } - if (status) - return srtp_err_status_cipher_fail; - - /* - * if we're authenticating using a universal hash, put the keystream - * prefix into the authentication tag - */ - - /* if auth_start is non-null, then put keystream into tag */ - if (auth_start) { - - /* put keystream prefix into auth_tag */ - prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth); - status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag, &prefix_len); - - debug_print(mod_srtp, "keystream prefix: %s", - srtp_octet_string_hex_string(auth_tag, prefix_len)); + /* perform EKT processing if needed */ + srtp_ekt_write_data(stream->ekt, auth_tag, tag_len, pkt_octet_len, + srtp_rdbx_get_packet_index(&stream->rtp_rdbx)); + /* + * check sequence number for overruns, and copy it into the packet + * if its value isn't too big + */ + status = srtp_rdb_increment(&stream->rtcp_rdb); if (status) - return srtp_err_status_cipher_fail; - } + return status; + seq_num = srtp_rdb_get_value(&stream->rtcp_rdb); + *trailer |= htonl(seq_num); + debug_print(mod_srtp, "srtcp index: %x", seq_num); - /* if we're encrypting, exor keystream into the message */ - if (enc_start) { - status = srtp_cipher_encrypt(session_keys->rtcp_cipher, - (uint8_t *)enc_start, &enc_octet_len); + /* + * if we're using rindael counter mode, set nonce and seq + */ + if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_128 || + session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_192 || + session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_256) { + v128_t iv; + + iv.v32[0] = 0; + iv.v32[1] = hdr->ssrc; /* still in network order! */ + iv.v32[2] = htonl(seq_num >> 16); + iv.v32[3] = htonl(seq_num << 16); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv, + srtp_direction_encrypt); + + } else { + v128_t iv; + + /* otherwise, just set the index to seq_num */ + iv.v32[0] = 0; + iv.v32[1] = 0; + iv.v32[2] = 0; + iv.v32[3] = htonl(seq_num); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv, + srtp_direction_encrypt); + } if (status) - return srtp_err_status_cipher_fail; - } + return srtp_err_status_cipher_fail; - /* initialize auth func context */ - srtp_auth_start(session_keys->rtcp_auth); + /* + * if we're authenticating using a universal hash, put the keystream + * prefix into the authentication tag + */ - /* - * run auth func over packet (including trailer), and write the - * result at auth_tag - */ - status = srtp_auth_compute(session_keys->rtcp_auth, - (uint8_t *)auth_start, - (*pkt_octet_len) + sizeof(srtcp_trailer_t), - auth_tag); - debug_print(mod_srtp, "srtcp auth tag: %s", - srtp_octet_string_hex_string(auth_tag, tag_len)); - if (status) - return srtp_err_status_auth_fail; - - /* increase the packet length by the length of the auth tag and seq_num*/ - *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t)); + /* if auth_start is non-null, then put keystream into tag */ + if (auth_start) { + /* put keystream prefix into auth_tag */ + prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth); + status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag, + &prefix_len); - /* increase the packet by the mki_size */ - *pkt_octet_len += mki_size; - - return srtp_err_status_ok; + debug_print(mod_srtp, "keystream prefix: %s", + srtp_octet_string_hex_string(auth_tag, prefix_len)); + + if (status) + return srtp_err_status_cipher_fail; + } + + /* if we're encrypting, exor keystream into the message */ + if (enc_start) { + status = srtp_cipher_encrypt(session_keys->rtcp_cipher, + (uint8_t *)enc_start, &enc_octet_len); + if (status) + return srtp_err_status_cipher_fail; + } + + /* initialize auth func context */ + srtp_auth_start(session_keys->rtcp_auth); + + /* + * run auth func over packet (including trailer), and write the + * result at auth_tag + */ + status = + srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start, + (*pkt_octet_len) + sizeof(srtcp_trailer_t), auth_tag); + debug_print(mod_srtp, "srtcp auth tag: %s", + srtp_octet_string_hex_string(auth_tag, tag_len)); + if (status) + return srtp_err_status_auth_fail; + + /* increase the packet length by the length of the auth tag and seq_num*/ + *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t)); + + /* increase the packet by the mki_size */ + *pkt_octet_len += mki_size; + + return srtp_err_status_ok; } - -srtp_err_status_t -srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { +srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, + void *srtcp_hdr, + int *pkt_octet_len) +{ return srtp_unprotect_rtcp_mki(ctx, srtcp_hdr, pkt_octet_len, 0); } -srtp_err_status_t -srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, - unsigned int use_mki) { - srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; - uint32_t *enc_start; /* pointer to start of encrypted portion */ - uint32_t *auth_start; /* pointer to start of auth. portion */ - uint32_t *trailer; /* pointer to start of trailer */ - unsigned int enc_octet_len = 0;/* number of octets in encrypted portion */ - uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ - uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; - uint8_t tag_copy[SRTP_MAX_TAG_LEN]; - srtp_err_status_t status; - unsigned int auth_len; - int tag_len; - srtp_stream_ctx_t *stream; - uint32_t prefix_len; - uint32_t seq_num; - int e_bit_in_packet; /* whether the E-bit was found in the packet */ - int sec_serv_confidentiality; /* whether confidentiality was requested */ - unsigned int mki_size = 0; - srtp_session_keys_t *session_keys = NULL; +srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, + void *srtcp_hdr, + int *pkt_octet_len, + unsigned int use_mki) +{ + srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; + uint32_t *enc_start; /* pointer to start of encrypted portion */ + uint32_t *auth_start; /* pointer to start of auth. portion */ + uint32_t *trailer; /* pointer to start of trailer */ + unsigned int enc_octet_len = 0; /* number of octets in encrypted portion */ + uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ + uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; + uint8_t tag_copy[SRTP_MAX_TAG_LEN]; + srtp_err_status_t status; + unsigned int auth_len; + int tag_len; + srtp_stream_ctx_t *stream; + uint32_t prefix_len; + uint32_t seq_num; + int e_bit_in_packet; /* whether the E-bit was found in the packet */ + int sec_serv_confidentiality; /* whether confidentiality was requested */ + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; - /* we assume the hdr is 32-bit aligned to start */ + /* we assume the hdr is 32-bit aligned to start */ - /* check that the length value is sane; we'll check again once we - know the tag length, but we at least want to know that it is - a positive value */ - if (*pkt_octet_len < octets_in_rtcp_header + sizeof(srtcp_trailer_t)) - return srtp_err_status_bad_param; + if (*pkt_octet_len < 0) + return srtp_err_status_bad_param; - /* - * look up ssrc in srtp_stream list, and process the packet with - * the appropriate stream. if we haven't seen this stream before, - * there's only one key for this srtp_session, and the cipher - * supports key-sharing, then we assume that a new stream using - * that key has just started up - */ - stream = srtp_get_stream(ctx, hdr->ssrc); - if (stream == NULL) { - if (ctx->stream_template != NULL) { - stream = ctx->stream_template; - - /* - * check to see if stream_template has an EKT data structure, in - * which case we initialize the template using the EKT policy - * referenced by that data (which consists of decrypting the - * master key from the EKT field) - * - * this function initializes a *provisional* stream, and this - * stream should not be accepted until and unless the packet - * passes its authentication check - */ - if (stream->ekt != NULL) { - status = srtp_stream_init_from_ekt(stream, srtcp_hdr, *pkt_octet_len); - if (status) - return status; - } - - debug_print(mod_srtp, "srtcp using provisional stream (SSRC: 0x%08x)", - ntohl(hdr->ssrc)); - } else { - /* no template stream, so we return an error */ - return srtp_err_status_no_ctx; - } - } - - /* - * Determine if MKI is being used and what session keys should be used - */ - if (use_mki) { - session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, - (const unsigned int*)pkt_octet_len, - &mki_size); - - if (session_keys == NULL) - return srtp_err_status_bad_mki; - } else { - session_keys = &stream->session_keys[0]; - } - - - /* get tag length from stream context */ - tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); - - /* check the packet length - it must contain at least a full RTCP - header, an auth tag (if applicable), and the SRTCP encrypted flag - and 31-bit index value */ - if (*pkt_octet_len < (int) (octets_in_rtcp_header + tag_len + mki_size + sizeof(srtcp_trailer_t))) { - return srtp_err_status_bad_param; - } - - /* - * Check if this is an AEAD stream (GCM mode). If so, then dispatch - * the request to our AEAD handler. - */ - if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || - session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { - return srtp_unprotect_rtcp_aead(ctx, stream, srtcp_hdr, - (unsigned int*)pkt_octet_len, session_keys, - mki_size); - } - - sec_serv_confidentiality = stream->rtcp_services == sec_serv_conf || - stream->rtcp_services == sec_serv_conf_and_auth; - - /* - * set encryption start, encryption length, and trailer - */ - enc_octet_len = *pkt_octet_len - - (octets_in_rtcp_header + tag_len + mki_size + sizeof(srtcp_trailer_t)); - /* index & E (encryption) bit follow normal data. hdr->len - is the number of words (32-bit) in the normal packet minus 1 */ - /* This should point trailer to the word past the end of the - normal data. */ - /* This would need to be modified for optional mikey data */ - /* - * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always - * multiples of 32-bits (RFC 3550 6.1) - */ - trailer = (uint32_t *) ((char *) hdr + - *pkt_octet_len -(tag_len + mki_size + sizeof(srtcp_trailer_t))); - e_bit_in_packet = - (*((unsigned char *) trailer) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT; - if (e_bit_in_packet != sec_serv_confidentiality) { - return srtp_err_status_cant_check; - } - if (sec_serv_confidentiality) { - enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header; - } else { - enc_octet_len = 0; - enc_start = NULL; /* this indicates that there's no encryption */ - } - - /* - * set the auth_start and auth_tag pointers to the proper locations - * (note that srtcp *always* uses authentication, unlike srtp) - */ - auth_start = (uint32_t *)hdr; - - /* - * The location of the auth tag in the packet needs to know MKI - * could be present. The data needed to calculate the Auth tag - * must not include the MKI - */ - auth_len = *pkt_octet_len - tag_len - mki_size; - auth_tag = (uint8_t *)hdr + auth_len + mki_size; - - /* - * if EKT is in use, then we make a copy of the tag from the packet, - * and then zeroize the location of the base tag - * - * we first re-position the auth_tag pointer so that it points to - * the base tag - */ - if (stream->ekt) { - auth_tag -= srtp_ekt_octets_after_base_tag(stream->ekt); - memcpy(tag_copy, auth_tag, tag_len); - octet_string_set_to_zero(auth_tag, tag_len); - auth_tag = tag_copy; - auth_len += tag_len; - } - - /* - * check the sequence number for replays - */ - /* this is easier than dealing with bitfield access */ - seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK; - debug_print(mod_srtp, "srtcp index: %x", seq_num); - status = srtp_rdb_check(&stream->rtcp_rdb, seq_num); - if (status) - return status; - - /* - * if we're using aes counter mode, set nonce and seq - */ - if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_128 || - session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_192 || - session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_256) { - v128_t iv; - - iv.v32[0] = 0; - iv.v32[1] = hdr->ssrc; /* still in network order! */ - iv.v32[2] = htonl(seq_num >> 16); - iv.v32[3] = htonl(seq_num << 16); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, - (uint8_t*)&iv, srtp_direction_decrypt); - - } else { - v128_t iv; - - /* otherwise, just set the index to seq_num */ - iv.v32[0] = 0; - iv.v32[1] = 0; - iv.v32[2] = 0; - iv.v32[3] = htonl(seq_num); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, - (uint8_t*)&iv, srtp_direction_decrypt); - - } - if (status) - return srtp_err_status_cipher_fail; - - /* initialize auth func context */ - srtp_auth_start(session_keys->rtcp_auth); - - /* run auth func over packet, put result into tmp_tag */ - status = srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start, - auth_len, tmp_tag); - debug_print(mod_srtp, "srtcp computed tag: %s", - srtp_octet_string_hex_string(tmp_tag, tag_len)); - if (status) - return srtp_err_status_auth_fail; - - /* compare the tag just computed with the one in the packet */ - debug_print(mod_srtp, "srtcp tag from packet: %s", - srtp_octet_string_hex_string(auth_tag, tag_len)); - if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) - return srtp_err_status_auth_fail; - - /* - * if we're authenticating using a universal hash, put the keystream - * prefix into the authentication tag - */ - prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth); - if (prefix_len) { - status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag, &prefix_len); - debug_print(mod_srtp, "keystream prefix: %s", - srtp_octet_string_hex_string(auth_tag, prefix_len)); - if (status) - return srtp_err_status_cipher_fail; - } - - /* if we're decrypting, exor keystream into the message */ - if (enc_start) { - status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t *)enc_start, - &enc_octet_len); - if (status) - return srtp_err_status_cipher_fail; - } - - /* decrease the packet length by the length of the auth tag and seq_num */ - *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t)); - - /* decrease the packet length by the length of the mki_size */ - *pkt_octet_len -= mki_size; - - /* - * if EKT is in effect, subtract the EKT data out of the packet - * length - */ - *pkt_octet_len -= srtp_ekt_octets_after_base_tag(stream->ekt); - - /* - * verify that stream is for received traffic - this check will - * detect SSRC collisions, since a stream that appears in both - * srtp_protect() and srtp_unprotect() will fail this test in one of - * those functions. - * - * we do this check *after* the authentication check, so that the - * latter check will catch any attempts to fool us into thinking - * that we've got a collision - */ - if (stream->direction != dir_srtp_receiver) { - if (stream->direction == dir_unknown) { - stream->direction = dir_srtp_receiver; - } else { - srtp_handle_event(ctx, stream, event_ssrc_collision); - } - } - - /* - * if the stream is a 'provisional' one, in which the template context - * is used, then we need to allocate a new stream at this point, since - * the authentication passed - */ - if (stream == ctx->stream_template) { - srtp_stream_ctx_t *new_stream; - - /* - * allocate and initialize a new stream - * - * note that we indicate failure if we can't allocate the new - * stream, and some implementations will want to not return - * failure here + /* + * check that the length value is sane; we'll check again once we + * know the tag length, but we at least want to know that it is + * a positive value */ - status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + if ((unsigned int)(*pkt_octet_len) < + octets_in_rtcp_header + sizeof(srtcp_trailer_t)) + return srtp_err_status_bad_param; + + /* + * look up ssrc in srtp_stream list, and process the packet with + * the appropriate stream. if we haven't seen this stream before, + * there's only one key for this srtp_session, and the cipher + * supports key-sharing, then we assume that a new stream using + * that key has just started up + */ + stream = srtp_get_stream(ctx, hdr->ssrc); + if (stream == NULL) { + if (ctx->stream_template != NULL) { + stream = ctx->stream_template; + + /* + * check to see if stream_template has an EKT data structure, in + * which case we initialize the template using the EKT policy + * referenced by that data (which consists of decrypting the + * master key from the EKT field) + * + * this function initializes a *provisional* stream, and this + * stream should not be accepted until and unless the packet + * passes its authentication check + */ + if (stream->ekt != NULL) { + status = srtp_stream_init_from_ekt(stream, srtcp_hdr, + *pkt_octet_len); + if (status) + return status; + } + + debug_print(mod_srtp, + "srtcp using provisional stream (SSRC: 0x%08x)", + ntohl(hdr->ssrc)); + } else { + /* no template stream, so we return an error */ + return srtp_err_status_no_ctx; + } + } + + /* + * Determine if MKI is being used and what session keys should be used + */ + if (use_mki) { + session_keys = srtp_get_session_keys( + stream, (uint8_t *)hdr, (const unsigned int *)pkt_octet_len, + &mki_size); + + if (session_keys == NULL) + return srtp_err_status_bad_mki; + } else { + session_keys = &stream->session_keys[0]; + } + + /* get tag length from stream context */ + tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); + + /* check the packet length - it must contain at least a full RTCP + header, an auth tag (if applicable), and the SRTCP encrypted flag + and 31-bit index value */ + if (*pkt_octet_len < (int)(octets_in_rtcp_header + tag_len + mki_size + + sizeof(srtcp_trailer_t))) { + return srtp_err_status_bad_param; + } + + /* + * Check if this is an AEAD stream (GCM mode). If so, then dispatch + * the request to our AEAD handler. + */ + if (session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_128 || + session_keys->rtp_cipher->algorithm == SRTP_AES_GCM_256) { + return srtp_unprotect_rtcp_aead(ctx, stream, srtcp_hdr, + (unsigned int *)pkt_octet_len, + session_keys, mki_size); + } + + sec_serv_confidentiality = stream->rtcp_services == sec_serv_conf || + stream->rtcp_services == sec_serv_conf_and_auth; + + /* + * set encryption start, encryption length, and trailer + */ + enc_octet_len = *pkt_octet_len - (octets_in_rtcp_header + tag_len + + mki_size + sizeof(srtcp_trailer_t)); + /* + *index & E (encryption) bit follow normal data. hdr->len is the number of + * words (32-bit) in the normal packet minus 1 + */ + /* This should point trailer to the word past the end of the normal data. */ + /* This would need to be modified for optional mikey data */ + /* + * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always + * multiples of 32-bits (RFC 3550 6.1) + */ + trailer = (uint32_t *)((char *)hdr + *pkt_octet_len - + (tag_len + mki_size + sizeof(srtcp_trailer_t))); + e_bit_in_packet = + (*((unsigned char *)trailer) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT; + if (e_bit_in_packet != sec_serv_confidentiality) { + return srtp_err_status_cant_check; + } + if (sec_serv_confidentiality) { + enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header; + } else { + enc_octet_len = 0; + enc_start = NULL; /* this indicates that there's no encryption */ + } + + /* + * set the auth_start and auth_tag pointers to the proper locations + * (note that srtcp *always* uses authentication, unlike srtp) + */ + auth_start = (uint32_t *)hdr; + + /* + * The location of the auth tag in the packet needs to know MKI + * could be present. The data needed to calculate the Auth tag + * must not include the MKI + */ + auth_len = *pkt_octet_len - tag_len - mki_size; + auth_tag = (uint8_t *)hdr + auth_len + mki_size; + + /* + * if EKT is in use, then we make a copy of the tag from the packet, + * and then zeroize the location of the base tag + * + * we first re-position the auth_tag pointer so that it points to + * the base tag + */ + if (stream->ekt) { + auth_tag -= srtp_ekt_octets_after_base_tag(stream->ekt); + memcpy(tag_copy, auth_tag, tag_len); + octet_string_set_to_zero(auth_tag, tag_len); + auth_tag = tag_copy; + auth_len += tag_len; + } + + /* + * check the sequence number for replays + */ + /* this is easier than dealing with bitfield access */ + seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK; + debug_print(mod_srtp, "srtcp index: %x", seq_num); + status = srtp_rdb_check(&stream->rtcp_rdb, seq_num); if (status) - return status; - - /* add new stream to the head of the stream_list */ - new_stream->next = ctx->stream_list; - ctx->stream_list = new_stream; - - /* set stream (the pointer used in this function) */ - stream = new_stream; - } + return status; - /* we've passed the authentication check, so add seq_num to the rdb */ - srtp_rdb_add_index(&stream->rtcp_rdb, seq_num); - - - return srtp_err_status_ok; + /* + * if we're using aes counter mode, set nonce and seq + */ + if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_128 || + session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_192 || + session_keys->rtcp_cipher->type->id == SRTP_AES_ICM_256) { + v128_t iv; + + iv.v32[0] = 0; + iv.v32[1] = hdr->ssrc; /* still in network order! */ + iv.v32[2] = htonl(seq_num >> 16); + iv.v32[3] = htonl(seq_num << 16); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv, + srtp_direction_decrypt); + + } else { + v128_t iv; + + /* otherwise, just set the index to seq_num */ + iv.v32[0] = 0; + iv.v32[1] = 0; + iv.v32[2] = 0; + iv.v32[3] = htonl(seq_num); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv, + srtp_direction_decrypt); + } + if (status) + return srtp_err_status_cipher_fail; + + /* initialize auth func context */ + srtp_auth_start(session_keys->rtcp_auth); + + /* run auth func over packet, put result into tmp_tag */ + status = srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start, + auth_len, tmp_tag); + debug_print(mod_srtp, "srtcp computed tag: %s", + srtp_octet_string_hex_string(tmp_tag, tag_len)); + if (status) + return srtp_err_status_auth_fail; + + /* compare the tag just computed with the one in the packet */ + debug_print(mod_srtp, "srtcp tag from packet: %s", + srtp_octet_string_hex_string(auth_tag, tag_len)); + if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) + return srtp_err_status_auth_fail; + + /* + * if we're authenticating using a universal hash, put the keystream + * prefix into the authentication tag + */ + prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth); + if (prefix_len) { + status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag, + &prefix_len); + debug_print(mod_srtp, "keystream prefix: %s", + srtp_octet_string_hex_string(auth_tag, prefix_len)); + if (status) + return srtp_err_status_cipher_fail; + } + + /* if we're decrypting, exor keystream into the message */ + if (enc_start) { + status = srtp_cipher_decrypt(session_keys->rtcp_cipher, + (uint8_t *)enc_start, &enc_octet_len); + if (status) + return srtp_err_status_cipher_fail; + } + + /* decrease the packet length by the length of the auth tag and seq_num */ + *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t)); + + /* decrease the packet length by the length of the mki_size */ + *pkt_octet_len -= mki_size; + + /* + * if EKT is in effect, subtract the EKT data out of the packet + * length + */ + *pkt_octet_len -= srtp_ekt_octets_after_base_tag(stream->ekt); + + /* + * verify that stream is for received traffic - this check will + * detect SSRC collisions, since a stream that appears in both + * srtp_protect() and srtp_unprotect() will fail this test in one of + * those functions. + * + * we do this check *after* the authentication check, so that the + * latter check will catch any attempts to fool us into thinking + * that we've got a collision + */ + if (stream->direction != dir_srtp_receiver) { + if (stream->direction == dir_unknown) { + stream->direction = dir_srtp_receiver; + } else { + srtp_handle_event(ctx, stream, event_ssrc_collision); + } + } + + /* + * if the stream is a 'provisional' one, in which the template context + * is used, then we need to allocate a new stream at this point, since + * the authentication passed + */ + if (stream == ctx->stream_template) { + srtp_stream_ctx_t *new_stream; + + /* + * allocate and initialize a new stream + * + * note that we indicate failure if we can't allocate the new + * stream, and some implementations will want to not return + * failure here + */ + status = + srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); + if (status) + return status; + + /* add new stream to the head of the stream_list */ + new_stream->next = ctx->stream_list; + ctx->stream_list = new_stream; + + /* set stream (the pointer used in this function) */ + stream = new_stream; + } + + /* we've passed the authentication check, so add seq_num to the rdb */ + srtp_rdb_add_index(&stream->rtcp_rdb, seq_num); + + return srtp_err_status_ok; } - /* * user data within srtp_t context */ -void -srtp_set_user_data(srtp_t ctx, void *data) { - ctx->user_data = data; +void srtp_set_user_data(srtp_t ctx, void *data) +{ + ctx->user_data = data; } -void* -srtp_get_user_data(srtp_t ctx) { - return ctx->user_data; +void *srtp_get_user_data(srtp_t ctx) +{ + return ctx->user_data; } - /* - * dtls keying for srtp + * dtls keying for srtp */ -srtp_err_status_t -srtp_crypto_policy_set_from_profile_for_rtp(srtp_crypto_policy_t *policy, - srtp_profile_t profile) { - - /* set SRTP policy from the SRTP profile in the key set */ - switch(profile) { - case srtp_profile_aes128_cm_sha1_80: - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); - break; - case srtp_profile_aes128_cm_sha1_32: - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(policy); - break; - case srtp_profile_null_sha1_80: - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); - break; -#if defined(OPENSSL) - case srtp_profile_aead_aes_128_gcm: - srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); - break; - case srtp_profile_aead_aes_256_gcm: - srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); - break; -#endif - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return srtp_err_status_bad_param; - } - - return srtp_err_status_ok; -} - -srtp_err_status_t -srtp_crypto_policy_set_from_profile_for_rtcp(srtp_crypto_policy_t *policy, - srtp_profile_t profile) { - - /* set SRTP policy from the SRTP profile in the key set */ - switch(profile) { - case srtp_profile_aes128_cm_sha1_80: - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); - break; - case srtp_profile_aes128_cm_sha1_32: - /* We do not honor the 32-bit auth tag request since - * this is not compliant with RFC 3711 */ - srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); - break; - case srtp_profile_null_sha1_80: - srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); - break; -#if defined(OPENSSL) - case srtp_profile_aead_aes_128_gcm: - srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); - break; - case srtp_profile_aead_aes_256_gcm: - srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); - break; -#endif - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return srtp_err_status_bad_param; - } - - return srtp_err_status_ok; -} - -void srtp_append_salt_to_key(uint8_t *key, unsigned int bytes_in_key, uint8_t *salt, unsigned int bytes_in_salt) { - memcpy(key + bytes_in_key, salt, bytes_in_salt); -} - -unsigned int -srtp_profile_get_master_key_length(srtp_profile_t profile) { - - switch(profile) { - case srtp_profile_aes128_cm_sha1_80: - return SRTP_AES_128_KEY_LEN; - break; - case srtp_profile_aes128_cm_sha1_32: - return SRTP_AES_128_KEY_LEN; - break; - case srtp_profile_null_sha1_80: - return SRTP_AES_128_KEY_LEN; - break; - case srtp_profile_aead_aes_128_gcm: - return SRTP_AES_128_KEY_LEN; - break; - case srtp_profile_aead_aes_256_gcm: - return SRTP_AES_256_KEY_LEN; - break; - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return 0; /* indicate error by returning a zero */ - } -} - -unsigned int -srtp_profile_get_master_salt_length(srtp_profile_t profile) { - - switch(profile) { - case srtp_profile_aes128_cm_sha1_80: - return SRTP_SALT_LEN; - break; - case srtp_profile_aes128_cm_sha1_32: - return SRTP_SALT_LEN; - break; - case srtp_profile_null_sha1_80: - return SRTP_SALT_LEN; - break; - case srtp_profile_aead_aes_128_gcm: - return SRTP_AEAD_SALT_LEN; - break; - case srtp_profile_aead_aes_256_gcm: - return SRTP_AEAD_SALT_LEN; - break; - /* the following profiles are not (yet) supported */ - case srtp_profile_null_sha1_32: - default: - return 0; /* indicate error by returning a zero */ - } -} - -srtp_err_status_t -srtp_get_protect_trailer_length(srtp_t session, - uint32_t use_mki, - uint32_t mki_index, - uint32_t *length) +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile) { - srtp_stream_ctx_t *stream; - - if (session == NULL) - return srtp_err_status_bad_param; - - *length = 0; - - /* Try obtaining stream from stream_list */ - stream = session->stream_list; - - if (stream == NULL) { - /* Try obtaining the template stream */ - stream = session->stream_template; - } - - if (stream == NULL) { + /* set SRTP policy from the SRTP profile in the key set */ + switch (profile) { + case srtp_profile_aes128_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); + break; + case srtp_profile_aes128_cm_sha1_32: + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(policy); + break; + case srtp_profile_null_sha1_80: + srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); + break; +#if defined(OPENSSL) + case srtp_profile_aead_aes_128_gcm: + srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); + break; + case srtp_profile_aead_aes_256_gcm: + srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); + break; +#endif + /* the following profiles are not (yet) supported */ + case srtp_profile_null_sha1_32: + default: return srtp_err_status_bad_param; } - if (use_mki) { - if (mki_index > stream->num_master_keys) - return srtp_err_status_bad_mki; - - *length += stream->session_keys[mki_index].mki_size; - *length += srtp_auth_get_tag_length(stream->session_keys[mki_index].rtp_auth); - } else { - *length += srtp_auth_get_tag_length(stream->session_keys[0].rtp_auth); - } - return srtp_err_status_ok; } -srtp_err_status_t -srtp_get_protect_rtcp_trailer_length(srtp_t session, - uint32_t use_mki, - uint32_t mki_index, - uint32_t *length) +srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp( + srtp_crypto_policy_t *policy, + srtp_profile_t profile) { - srtp_stream_ctx_t *stream; - - if (session == NULL) - return srtp_err_status_bad_param; - - *length = 0; - - /* Try obtaining stream from stream_list */ - stream = session->stream_list; - - if (stream == NULL) { - /* Try obtaining the template stream */ - stream = session->stream_template; - } - - if (stream == NULL) { + /* set SRTP policy from the SRTP profile in the key set */ + switch (profile) { + case srtp_profile_aes128_cm_sha1_80: + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); + break; + case srtp_profile_aes128_cm_sha1_32: + /* We do not honor the 32-bit auth tag request since + * this is not compliant with RFC 3711 */ + srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); + break; + case srtp_profile_null_sha1_80: + srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); + break; +#if defined(OPENSSL) + case srtp_profile_aead_aes_128_gcm: + srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); + break; + case srtp_profile_aead_aes_256_gcm: + srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); + break; +#endif + /* the following profiles are not (yet) supported */ + case srtp_profile_null_sha1_32: + default: return srtp_err_status_bad_param; } - if (use_mki) { - if (mki_index > stream->num_master_keys) - return srtp_err_status_bad_mki; - - *length += stream->session_keys[mki_index].mki_size; - *length += srtp_auth_get_tag_length(stream->session_keys[mki_index].rtcp_auth); - } else { - *length += srtp_auth_get_tag_length(stream->session_keys[0].rtcp_auth); - } - - *length += sizeof(srtcp_trailer_t); - return srtp_err_status_ok; } +void srtp_append_salt_to_key(uint8_t *key, + unsigned int bytes_in_key, + uint8_t *salt, + unsigned int bytes_in_salt) +{ + memcpy(key + bytes_in_key, salt, bytes_in_salt); +} + +unsigned int srtp_profile_get_master_key_length(srtp_profile_t profile) +{ + switch (profile) { + case srtp_profile_aes128_cm_sha1_80: + return SRTP_AES_128_KEY_LEN; + break; + case srtp_profile_aes128_cm_sha1_32: + return SRTP_AES_128_KEY_LEN; + break; + case srtp_profile_null_sha1_80: + return SRTP_AES_128_KEY_LEN; + break; + case srtp_profile_aead_aes_128_gcm: + return SRTP_AES_128_KEY_LEN; + break; + case srtp_profile_aead_aes_256_gcm: + return SRTP_AES_256_KEY_LEN; + break; + /* the following profiles are not (yet) supported */ + case srtp_profile_null_sha1_32: + default: + return 0; /* indicate error by returning a zero */ + } +} + +unsigned int srtp_profile_get_master_salt_length(srtp_profile_t profile) +{ + switch (profile) { + case srtp_profile_aes128_cm_sha1_80: + return SRTP_SALT_LEN; + break; + case srtp_profile_aes128_cm_sha1_32: + return SRTP_SALT_LEN; + break; + case srtp_profile_null_sha1_80: + return SRTP_SALT_LEN; + break; + case srtp_profile_aead_aes_128_gcm: + return SRTP_AEAD_SALT_LEN; + break; + case srtp_profile_aead_aes_256_gcm: + return SRTP_AEAD_SALT_LEN; + break; + /* the following profiles are not (yet) supported */ + case srtp_profile_null_sha1_32: + default: + return 0; /* indicate error by returning a zero */ + } +} + +srtp_err_status_t stream_get_protect_trailer_length(srtp_stream_ctx_t *stream, + uint32_t is_rtp, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length) +{ + *length = 0; + + srtp_session_keys_t *session_key; + + if (use_mki) { + if (mki_index >= stream->num_master_keys) { + return srtp_err_status_bad_mki; + } + session_key = &stream->session_keys[mki_index]; + + *length += session_key->mki_size; + + } else { + session_key = &stream->session_keys[0]; + } + if (is_rtp) { + *length += srtp_auth_get_tag_length(session_key->rtp_auth); + } else { + *length += srtp_auth_get_tag_length(session_key->rtcp_auth); + *length += sizeof(srtcp_trailer_t); + } + + return srtp_err_status_ok; +} + +srtp_err_status_t get_protect_trailer_length(srtp_t session, + uint32_t is_rtp, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length) +{ + srtp_stream_ctx_t *stream; + + if (session == NULL) { + return srtp_err_status_bad_param; + } + + if (session->stream_template == NULL && session->stream_list == NULL) { + return srtp_err_status_bad_param; + } + + *length = 0; + + stream = session->stream_template; + + if (stream != NULL) { + stream_get_protect_trailer_length(stream, is_rtp, use_mki, mki_index, + length); + } + + stream = session->stream_list; + + while (stream != NULL) { + uint32_t temp_length; + if (stream_get_protect_trailer_length(stream, is_rtp, use_mki, + mki_index, &temp_length) == + srtp_err_status_ok) { + if (temp_length > *length) { + *length = temp_length; + } + } + stream = stream->next; + } + + return srtp_err_status_ok; +} + +srtp_err_status_t srtp_get_protect_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length) +{ + return get_protect_trailer_length(session, 1, use_mki, mki_index, length); +} + +srtp_err_status_t srtp_get_protect_rtcp_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length) +{ + return get_protect_trailer_length(session, 0, use_mki, mki_index, length); +} /* * SRTP debug interface @@ -4591,26 +4656,34 @@ srtp_err_status_t srtp_list_debug_modules(void) */ static srtp_log_handler_func_t *srtp_log_handler = NULL; -static void * srtp_log_handler_data = NULL; +static void *srtp_log_handler_data = NULL; -void srtp_err_handler(srtp_err_reporting_level_t level, const char * msg) +void srtp_err_handler(srtp_err_reporting_level_t level, const char *msg) { if (srtp_log_handler) { srtp_log_level_t log_level = srtp_log_level_error; - switch(level) { - case srtp_err_level_error: log_level = srtp_log_level_error; break; - case srtp_err_level_warning: log_level = srtp_log_level_warning; break; - case srtp_err_level_info: log_level = srtp_log_level_info; break; - case srtp_err_level_debug: log_level = srtp_log_level_debug; break; + switch (level) { + case srtp_err_level_error: + log_level = srtp_log_level_error; + break; + case srtp_err_level_warning: + log_level = srtp_log_level_warning; + break; + case srtp_err_level_info: + log_level = srtp_log_level_info; + break; + case srtp_err_level_debug: + log_level = srtp_log_level_debug; + break; } srtp_log_handler(log_level, msg, srtp_log_handler_data); } } -srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func, void * data) +srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func, + void *data) { - /* * note that we accept NULL arguments intentionally - calling this * function with a NULL arguments removes a log handler that's @@ -4628,8 +4701,10 @@ srtp_err_status_t srtp_install_log_handler(srtp_log_handler_func_t func, void * return srtp_err_status_ok; } -srtp_err_status_t -srtp_set_stream_roc(srtp_t session, uint32_t ssrc, uint32_t roc) { +srtp_err_status_t srtp_set_stream_roc(srtp_t session, + uint32_t ssrc, + uint32_t roc) +{ srtp_stream_t stream; stream = srtp_get_stream(session, htonl(ssrc)); @@ -4641,8 +4716,10 @@ srtp_set_stream_roc(srtp_t session, uint32_t ssrc, uint32_t roc) { return srtp_err_status_ok; } -srtp_err_status_t -srtp_get_stream_roc(srtp_t session, uint32_t ssrc, uint32_t *roc) { +srtp_err_status_t srtp_get_stream_roc(srtp_t session, + uint32_t ssrc, + uint32_t *roc) +{ srtp_stream_t stream; stream = srtp_get_stream(session, htonl(ssrc)); diff --git a/libs/srtp/srtp2.vcxproj b/libs/srtp/srtp2.vcxproj index 2cae3ea7e3..a6ac642546 100644 --- a/libs/srtp/srtp2.vcxproj +++ b/libs/srtp/srtp2.vcxproj @@ -370,6 +370,7 @@ <ClInclude Include="crypto\include\alloc.h" /> <ClInclude Include="crypto\include\auth.h" /> <ClInclude Include="crypto\include\cipher.h" /> + <ClInclude Include="crypto\include\cipher_types.h" /> <ClInclude Include="crypto\include\config.h" /> <ClInclude Include="crypto\include\crypto.h" /> <ClInclude Include="crypto\include\cryptoalg.h" /> @@ -401,4 +402,4 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> diff --git a/libs/srtp/srtp2.vcxproj.filters b/libs/srtp/srtp2.vcxproj.filters index 6daa0d9f23..24e040fb5b 100644 --- a/libs/srtp/srtp2.vcxproj.filters +++ b/libs/srtp/srtp2.vcxproj.filters @@ -107,6 +107,9 @@ <ClInclude Include="crypto\include\cipher.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="crypto\include\cipher_types.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="crypto\include\config.h"> <Filter>Header Files</Filter> </ClInclude> @@ -183,4 +186,4 @@ <Filter>Source Files</Filter> </None> </ItemGroup> -</Project> \ No newline at end of file +</Project> diff --git a/libs/srtp/test/cutest.h b/libs/srtp/test/cutest.h index a94e144ab5..f46626d395 100644 --- a/libs/srtp/test/cutest.h +++ b/libs/srtp/test/cutest.h @@ -10,10 +10,10 @@ * 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 @@ -26,7 +26,6 @@ #ifndef CUTEST_H__ #define CUTEST_H__ - /************************ *** Public interface *** ************************/ @@ -56,8 +55,7 @@ * * void test_func(void); */ -#define TEST_LIST const struct test__ test_list__[] - +#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. @@ -78,9 +76,9 @@ * 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) - +#define TEST_CHECK_(cond, ...) \ + test_check__((cond), __FILE__, __LINE__, __VA_ARGS__) +#define TEST_CHECK(cond) test_check__((cond), __FILE__, __LINE__, "%s", #cond) /********************** *** Implementation *** @@ -94,47 +92,43 @@ #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> +#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> +#define CUTEST_WIN__ 1 +#include <windows.h> +#include <io.h> #endif #ifdef __cplusplus - #include <exception> +#include <exception> #endif - /* Note our global private identifiers end with '__' to mitigate risk of clash * with the unit tests implementation. */ - #ifdef __cplusplus - extern "C" { +extern "C" { #endif - struct test__ { - const char* name; + 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, ...); - +int test_check__(int cond, const char *file, int line, const char *fmt, ...); #ifndef TEST_NO_MAIN -static char* test_argv0__ = NULL; +static char *test_argv0__ = NULL; static int test_count__ = 0; static int test_no_exec__ = 0; static int test_no_summary__ = 0; @@ -143,21 +137,20 @@ 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 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 +#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, ...) +static size_t test_print_in_color__(int color, const char *fmt, ...) { va_list args; char buffer[256]; @@ -166,22 +159,34 @@ test_print_in_color__(int color, const char* fmt, ...) va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); - buffer[sizeof(buffer)-1] = '\0'; + buffer[sizeof(buffer) - 1] = '\0'; - if(!test_colorize__) { + 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; + 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); @@ -197,15 +202,28 @@ test_print_in_color__(int color, const char* fmt, ...) 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; + 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) + if (attr != 0) SetConsoleTextAttribute(h, attr); n = printf("%s", buffer); SetConsoleTextAttribute(h, info.wAttributes); @@ -217,19 +235,18 @@ test_print_in_color__(int color, const char* fmt, ...) #endif } -int -test_check__(int cond, const char* file, int line, const char* fmt, ...) +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) { + if (cond) { result_str = "ok"; result_color = CUTEST_COLOR_GREEN__; verbose_level = 3; } else { - if(!test_current_already_logged__ && test_current_unit__ != NULL) { + if (!test_current_already_logged__ && test_current_unit__ != NULL) { printf("[ "); test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, "FAILED"); printf(" ]\n"); @@ -241,13 +258,13 @@ test_check__(int cond, const char* file, int line, const char* fmt, ...) test_current_already_logged__++; } - if(test_verbose_level__ >= verbose_level) { + if (test_verbose_level__ >= verbose_level) { size_t n = 0; va_list args; printf(" "); - if(file != NULL) + if (file != NULL) n += printf("%s:%d: Check ", file, line); va_start(args, fmt); @@ -263,23 +280,21 @@ test_check__(int cond, const char* file, int line, const char* fmt, ...) return (cond != 0); } -static void -test_list_names__(void) +static void test_list_names__(void) { - const struct test__* test; + const struct test__ *test; printf("Unit tests:\n"); - for(test = &test_list__[0]; test->func != NULL; test++) + for (test = &test_list__[0]; test->func != NULL; test++) printf(" %s\n", test->name); } -static const struct test__* -test_by_name__(const char* name) +static const struct test__ *test_by_name__(const char *name) { - const struct test__* test; + const struct test__ *test; - for(test = &test_list__[0]; test->func != NULL; test++) { - if(strcmp(test->name, name) == 0) + for (test = &test_list__[0]; test->func != NULL; test++) { + if (strcmp(test->name, name) == 0) return test; } @@ -287,24 +302,25 @@ test_by_name__(const char* name) } /* Call directly the given test unit function. */ -static int -test_do_run__(const struct test__* test) +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); + 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) { + } 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); + 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); + if (n < sizeof(spaces)) + printf("%.*s", (int)(sizeof(spaces) - n), spaces); } else { test_current_already_logged__ = 1; } @@ -320,24 +336,34 @@ test_do_run__(const struct test__* test) test->func(); #ifdef __cplusplus - } catch(std::exception& e) { - const char* what = e.what(); - if(what != NULL) + } 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(...) { + } 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; + 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) { + } else if (test_verbose_level__ >= 1 && test_current_failures__ == 0) { printf("[ "); test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__, "OK"); printf(" ]\n"); @@ -351,21 +377,21 @@ test_do_run__(const struct test__* test) /* 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, ...) +static void test_error__(const char *fmt, ...) { va_list args; - if(test_verbose_level__ == 0) + if (test_verbose_level__ == 0) return; - if(test_verbose_level__ <= 2 && !test_current_already_logged__ && test_current_unit__ != NULL) { + 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) { + if (test_verbose_level__ >= 2) { test_print_in_color__(CUTEST_COLOR_RED_INTENSIVE__, " Error: "); va_start(args, fmt); vprintf(fmt, args); @@ -378,51 +404,73 @@ test_error__(const char* fmt, ...) /* 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) +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 (!test_no_exec__) { #if defined(CUTEST_UNIX__) pid_t pid; int exit_code; pid = fork(); - if(pid == (pid_t)-1) { + if (pid == (pid_t)-1) { test_error__("Cannot fork. %s [%d]", strerror(errno), errno); failed = 1; - } else if(pid == 0) { + } 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)); + 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)) { + } 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; + 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 { @@ -432,26 +480,28 @@ test_run__(const struct test__* test) #elif defined(CUTEST_WIN__) - char buffer[512] = {0}; - STARTUPINFOA startupInfo = {0}; + 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); + _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)) { + 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()); + test_error__("Cannot create unit test subprocess [%ld].", + GetLastError()); failed = 1; } @@ -470,14 +520,13 @@ test_run__(const struct test__* test) test_current_unit__ = NULL; test_stat_run_units__++; - if(failed) + if (failed) test_stat_failed_units__++; } #if defined(CUTEST_WIN__) /* Callback for SEH events. */ -static LONG CALLBACK -test_exception_filter__(EXCEPTION_POINTERS *ptrs) +static LONG CALLBACK test_exception_filter__(EXCEPTION_POINTERS *ptrs) { test_error__("Unhandled SEH exception %08lx at %p.", ptrs->ExceptionRecord->ExceptionCode, @@ -488,35 +537,42 @@ test_exception_filter__(EXCEPTION_POINTERS *ptrs) } #endif -static void -test_help__(void) +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("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( + " -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(" 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) +int main(int argc, char **argv) { - const struct test__** tests = NULL; + const struct test__ **tests = NULL; int i, j, n = 0; int seen_double_dash = 0; @@ -531,42 +587,50 @@ main(int argc, char** argv) #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) { + 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]); + 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) { + } else if (strcmp(argv[i], "--") == 0) { seen_double_dash = 1; - } else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { + } 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) { + } else if (strcmp(argv[i], "--verbose") == 0 || + strcmp(argv[i], "-v") == 0) { test_verbose_level__++; - } else if(strncmp(argv[i], "--verbose=", 10) == 0) { + } else if (strncmp(argv[i], "--verbose=", 10) == 0) { test_verbose_level__ = atoi(argv[i] + 10); - } else if(strcmp(argv[i], "--color=auto") == 0) { + } 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) { + } else if (strcmp(argv[i], "--color=always") == 0 || + strcmp(argv[i], "--color") == 0) { test_colorize__ = 1; - } else if(strcmp(argv[i], "--color=never") == 0) { + } else if (strcmp(argv[i], "--color=never") == 0) { test_colorize__ = 0; - } else if(strcmp(argv[i], "--skip") == 0 || strcmp(argv[i], "-s") == 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) { + } else if (strcmp(argv[i], "--no-exec") == 0) { test_no_exec__ = 1; - } else if(strcmp(argv[i], "--no-summary") == 0) { + } else if (strcmp(argv[i], "--no-summary") == 0) { test_no_summary__ = 1; - } else if(strcmp(argv[i], "--list") == 0 || strcmp(argv[i], "-l") == 0) { + } else if (strcmp(argv[i], "--list") == 0 || + strcmp(argv[i], "-l") == 0) { test_list_names__(); exit(0); } else { @@ -582,66 +646,68 @@ main(int argc, char** argv) /* Count all test units */ test_count__ = 0; - for(i = 0; test_list__[i].func != NULL; i++) + for (i = 0; test_list__[i].func != NULL; i++) test_count__++; /* Run the tests */ - if(n == 0) { + if (n == 0) { /* Run all tests */ - for(i = 0; test_list__[i].func != NULL; i++) + for (i = 0; test_list__[i].func != NULL; i++) test_run__(&test_list__[i]); - } else if(!test_skip_mode__) { + } else if (!test_skip_mode__) { /* Run the listed tests */ - for(i = 0; i < n; i++) + 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++) { + 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]) { + for (j = 0; j < n; j++) { + if (tests[j] == &test_list__[i]) { want_skip = 1; break; } } - if(!want_skip) + if (!want_skip) test_run__(&test_list__[i]); } } /* Write a summary */ - if(!test_no_summary__ && test_verbose_level__ >= 1) { + if (!test_no_summary__ && test_verbose_level__ >= 1) { test_print_in_color__(CUTEST_COLOR_DEFAULT_INTENSIVE__, "\nSummary:\n"); - if(test_verbose_level__ >= 3) { + 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__); + 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) { + if (test_stat_failed_units__ == 0) { test_print_in_color__(CUTEST_COLOR_GREEN_INTENSIVE__, - " SUCCESS: All unit tests have passed.\n"); + " 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__); + 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); + if (tests != NULL) + free((void *)tests); return (test_stat_failed_units__ == 0) ? 0 : 1; } - -#endif /* #ifndef TEST_NO_MAIN */ +#endif /* #ifndef TEST_NO_MAIN */ #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif - -#endif /* #ifndef CUTEST_H__ */ +#endif /* #ifndef CUTEST_H__ */ diff --git a/libs/srtp/test/dtls_srtp_driver.c b/libs/srtp/test/dtls_srtp_driver.c index ebf73f9fc5..4f4d0a39b3 100644 --- a/libs/srtp/test/dtls_srtp_driver.c +++ b/libs/srtp/test/dtls_srtp_driver.c @@ -7,26 +7,26 @@ * 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 @@ -46,172 +46,171 @@ #include "getopt_s.h" /* for local getopt() */ #include "srtp_priv.h" -srtp_err_status_t -test_dtls_srtp(void); +srtp_err_status_t test_dtls_srtp(void); -srtp_hdr_t * -srtp_create_test_packet(int pkt_octet_len, uint32_t ssrc); +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); +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; +int main(int argc, char *argv[]) +{ + unsigned do_list_mods = 0; + int q; + srtp_err_status_t err; - printf("dtls_srtp_driver\n"); + 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(); + /* initialize srtp library */ + err = srtp_init(); if (err) { - printf("error: list of debug modules failed\n"); - exit(1); + printf("error: srtp init failed with error code %d\n", err); + 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); - } + /* 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]); + } + } - return 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; -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)); - memset(&policy, 0x0, sizeof(srtp_policy_t)); + /* create a 'null' SRTP session */ + err = srtp_create(&s, NULL); + if (err) + return err; - /* 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; - /* - * 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; - } + 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; + } - /* - * 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; + 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; + } - /* 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; + 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; + } - free(test_packet); + /* + * 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; - return srtp_err_status_ok; + /* 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 @@ -225,39 +224,38 @@ test_dtls_srtp(void) { * 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; +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 */ + /* allocate memory for test packet */ + hdr = malloc(pkt_octet_len + bytes_in_hdr + SRTP_MAX_TRAILER_LEN + 4); + if (!hdr) + return NULL; - buffer = (uint8_t *)hdr; - buffer += bytes_in_hdr; + 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 */ - /* set RTP data to 0xab */ - for (i=0; i < pkt_octet_len; i++) - *buffer++ = 0xab; + buffer = (uint8_t *)hdr; + buffer += bytes_in_hdr; - /* set post-data value to 0xffff to enable overrun checking */ - for (i=0; i < SRTP_MAX_TRAILER_LEN+4; i++) - *buffer++ = 0xff; + /* set RTP data to 0xab */ + for (i = 0; i < pkt_octet_len; i++) + *buffer++ = 0xab; - return hdr; + /* set post-data value to 0xffff to enable overrun checking */ + for (i = 0; i < SRTP_MAX_TRAILER_LEN + 4; i++) + *buffer++ = 0xff; + + return hdr; } diff --git a/libs/srtp/test/getopt_s.c b/libs/srtp/test/getopt_s.c index 35e8871f9f..ab631878a4 100644 --- a/libs/srtp/test/getopt_s.c +++ b/libs/srtp/test/getopt_s.c @@ -3,30 +3,30 @@ * * a minimal implementation of the getopt() function, written so that * test applications that use that function can run on non-POSIX - * platforms + * 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 @@ -42,71 +42,67 @@ * */ -#include <stdlib.h> /* for NULL */ +#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 +#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; +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 '?'; + while (*string != 0) { + if (max_string_len == 0) { + return '?'; + } + if (*string++ == c) { + if (*string == ':') { + return GETOPT_FOUND_WITH_ARGUMENT; + } else { + return GETOPT_FOUND_WITHOUT_ARGUMENT; + } + } } - if (*string++ == c) { - if (*string == ':') { - return GETOPT_FOUND_WITH_ARGUMENT; - } else { - return GETOPT_FOUND_WITHOUT_ARGUMENT; - } - } - } - return GETOPT_NOT_FOUND; + return GETOPT_NOT_FOUND; } -int -getopt_s(int argc, - char * const argv[], - const char *optstring) { +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]; - 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 == NULL) - return '?'; /* NULL argument string */ + if (string[0] != '-') + return -1; /* found an unexpected character */ - 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; + 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; + return -1; } diff --git a/libs/srtp/test/rdbx_driver.c b/libs/srtp/test/rdbx_driver.c index 8ecbf9f49b..609ce9c8e4 100644 --- a/libs/srtp/test/rdbx_driver.c +++ b/libs/srtp/test/rdbx_driver.c @@ -6,28 +6,27 @@ * 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 @@ -44,7 +43,7 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif #include <stdio.h> /* for printf() */ @@ -58,90 +57,85 @@ #include "ut_sim.h" -srtp_err_status_t -test_replay_dbx(int num_trials, unsigned long ws); +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); +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); +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; +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); + /* 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("passed\n"); - printf("testing srtp_rdbx_t (ws=1024)...\n"); + printf("rdbx (replay database w/ extended range) test driver\n" + "David A. McGrew\n" + "Cisco Systems, Inc.\n"); - status = test_replay_dbx(1 << 12, 1024); - if (status) { - printf("failed\n"); - exit(1); + 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"); } - 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; + 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)) -); +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 @@ -150,217 +144,214 @@ print_rdbx(srtp_rdbx_t *rdbx) { * */ -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; - } +srtp_err_status_t rdbx_check_add(srtp_rdbx_t *rdbx, uint32_t idx) +{ + int delta; + srtp_xtd_seq_num_t est; - /* - * 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; - } + delta = srtp_index_guess(&rdbx->index, &est, idx); - return srtp_err_status_ok; + 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; +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); + 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; - } + 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; + 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; +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); + 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; - } + 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; + 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; +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); - } + 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 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"); + /* + * 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); + /* 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; - } + 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); + /* + * 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"); + 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); + /* 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; - } + 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 << (rand() % 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"); + /* + * 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 << (rand() % 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); + srtp_rdbx_dealloc(&rdbx); - return srtp_err_status_ok; + return srtp_err_status_ok; } +#include <time.h> /* for clock() */ +#include <stdlib.h> /* for random() */ +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 */ -#include <time.h> /* for clock() */ -#include <stdlib.h> /* for random() */ + if (srtp_rdbx_init(&rdbx, ws) != srtp_err_status_ok) { + printf("replay_init failed\n"); + exit(1); + } -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); - 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 (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; - printf("number of failures: %d \n", failures); + printf("number of failures: %d \n", failures); - srtp_rdbx_dealloc(&rdbx); + srtp_rdbx_dealloc(&rdbx); - return (double) CLOCKS_PER_SEC * num_trials / timer; + return (double)CLOCKS_PER_SEC * num_trials / timer; } - diff --git a/libs/srtp/test/replay_driver.c b/libs/srtp/test/replay_driver.c index b964a4a03e..a88224684f 100644 --- a/libs/srtp/test/replay_driver.c +++ b/libs/srtp/test/replay_driver.c @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -44,7 +44,7 @@ */ #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif #include <stdio.h> @@ -59,226 +59,225 @@ unsigned num_trials = 1 << 16; -srtp_err_status_t -test_rdb_db(void); +srtp_err_status_t test_rdb_db(void); -double -rdb_check_adds_per_second(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"); +int main(void) +{ + srtp_err_status_t err; - printf("rdb_check/rdb_adds per second: %e\n", - rdb_check_adds_per_second()); - - return 0; + 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)); +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) { +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; + } - 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; + 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; - } +srtp_err_status_t rdb_check_expect_failure(srtp_rdb_t *rdb, uint32_t idx) +{ + srtp_err_status_t err; - return srtp_err_status_ok; + 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; +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; - } + /* 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; + 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; +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; - } + 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 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; - } + /* 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; - } + /* 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; - } + /* test non-sequential insertion */ + ut_init(&utc); - /* re-initialize */ - if (srtp_rdb_init(&rdb) != srtp_err_status_ok) { - printf("rdb_init failed\n"); - return srtp_err_status_fail; - } + 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; + } - /* test insertion with large gaps */ - for (idx=0, ircvd=0; idx < num_trials; idx++, ircvd += (1 << (rand() % 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; + } - /* 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 << (rand() % 10))) { + err = rdb_check_add(&rdb, ircvd); + if (err) + return err; + err = rdb_check_expect_failure(&rdb, ircvd); + if (err) + return err; + } - /* test loss of first 513 packets */ - for (idx=0; idx < num_trials; idx++) { - err = rdb_check_add(&rdb, idx + 513); - 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 for false positives */ - for (idx=0; idx < num_trials + 513; idx++) { - err = rdb_check_expect_failure(&rdb, idx); - if (err) - return err; - } + /* 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 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; - } + /* 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; + return srtp_err_status_ok; } -#include <time.h> /* for clock() */ -#include <stdlib.h> /* for random() */ +#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); - } +double rdb_check_adds_per_second(void) +{ + uint32_t i; + srtp_rdb_t rdb; + clock_t timer; + int failures = 0; /* count number of failures */ - 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; + if (srtp_rdb_init(&rdb) != srtp_err_status_ok) { + printf("rdb_init failed\n"); + exit(1); + } - return (double) CLOCKS_PER_SEC * REPLAY_NUM_TRIALS / timer; + 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; } diff --git a/libs/srtp/test/roc_driver.c b/libs/srtp/test/roc_driver.c index c23113adc9..d61ba8ef24 100644 --- a/libs/srtp/test/roc_driver.c +++ b/libs/srtp/test/roc_driver.c @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -43,9 +43,8 @@ * */ - #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif #include <stdio.h> @@ -55,121 +54,117 @@ * srtp_xtd_seq_num_t - this allows the functions to be exhaustively tested. */ #if ROC_NEEDS_TO_BE_TESTED -#define ROC_TEST +#define ROC_TEST #endif #include "rdbx.h" #include "ut_sim.h" -srtp_err_status_t -roc_test(int num_trials); +srtp_err_status_t roc_test(int num_trials); -int -main (void) { - srtp_err_status_t status; +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; + 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_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); + srtp_index_init(&local); + srtp_index_init(&ref); + srtp_index_init(&est); - printf("\n\ttesting sequential insertion..."); - for (i=0; i < 2048; i++) { - delta = srtp_index_guess(&local, &est, (uint16_t) ref); + printf("\n\ttesting sequential insertion..."); + for (i = 0; i < 2048; i++) { + delta = srtp_index_guess(&local, &est, (uint16_t)ref); #if ROC_VERBOSE - printf("%lld, %lld, %d\n", ref, est, i); + printf("%lld, %lld, %d\n", ref, est, i); #endif - if (ref != est) { + if (ref != est) { #if ROC_VERBOSE - printf(" *bad estimate*\n"); + printf(" *bad estimate*\n"); #endif - ++num_bad_est; + ++num_bad_est; + } + srtp_index_advance(&ref, 1); } - 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; + 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"); - /* now update local srtp_xtd_seq_num_t as necessary */ - if (delta > 0) - srtp_index_advance(&local, delta); + printf("\ttesting non-sequential insertion..."); + srtp_index_init(&local); + srtp_index_init(&ref); + srtp_index_init(&est); + ut_init(&utc); - if (ref != est) { + 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(" *bad estimate*\n"); + printf("ref: %lld, local: %lld, est: %lld, ircvd: %d, delta: %d\n", ref, + local, est, ircvd, delta); #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; + 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; } diff --git a/libs/srtp/test/rtp.c b/libs/srtp/test/rtp.c index 74cb902179..f60a9b11b2 100644 --- a/libs/srtp/test/rtp.c +++ b/libs/srtp/test/rtp.c @@ -8,26 +8,26 @@ */ /* - * + * * 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 @@ -50,178 +50,178 @@ #include <sys/types.h> #ifdef HAVE_SYS_SOCKET_H -# include <sys/socket.h> +#include <sys/socket.h> #endif -#define PRINT_DEBUG 0 /* set to 1 to print out debugging data */ -#define VERBOSE_DEBUG 0 /* set to 1 to print out more data */ +#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; +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) { + /* 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); + fprintf(stderr, "error: srtp protection failed with code %d\n", stat); #endif - return -1; - } + return -1; + } #if VERBOSE_DEBUG - srtp_print_packet(&sender->message.header, pkt_len); + 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)); + 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 (octets_sent != pkt_len) { #if PRINT_DEBUG - fprintf(stderr, "error: couldn't send message %s", (char *)msg); - perror(""); + fprintf(stderr, "error: couldn't send message %s", (char *)msg); + perror(""); #endif - } + } - return octets_sent; + 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); +int rtp_recvfrom(rtp_receiver_t receiver, void *msg, int *len) +{ + int octets_recvd; + srtp_err_status_t stat; - if (octets_recvd == -1) { - *len = 0; - return -1; - } + octets_recvd = recvfrom(receiver->socket, (void *)&receiver->message, *len, + 0, (struct sockaddr *)NULL, 0); - /* verify rtp header */ - if (receiver->message.header.version != 2) { - *len = 0; - return -1; - } + 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); + 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); + 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; + /* 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) { +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)rand(); + 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 header values */ - sender->message.header.ssrc = htonl(ssrc); - sender->message.header.ts = 0; - sender->message.header.seq = (uint16_t) rand(); - 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; - /* set other stuff */ - sender->socket = sock; - sender->addr = addr; - - return 0; + 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; +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; + /* set other stuff */ + rcvr->socket = sock; + rcvr->addr = addr; - return 0; + 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_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_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_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); +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)); +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); +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)); +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); +void rtp_receiver_dealloc(rtp_receiver_t rtp_ctx) +{ + free(rtp_ctx); } diff --git a/libs/srtp/test/rtp.h b/libs/srtp/test/rtp.h index d010508de3..37921a665c 100644 --- a/libs/srtp/test/rtp.h +++ b/libs/srtp/test/rtp.h @@ -1,6 +1,6 @@ /* * rtp.h - * + * * rtp interface for srtp reference implementation * * David A. McGrew @@ -15,26 +15,26 @@ */ /* - * + * * 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 @@ -50,14 +50,13 @@ * */ - #ifndef SRTP_RTP_H #define SRTP_RTP_H #ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> +#include <netinet/in.h> #elif defined HAVE_WINSOCK2_H -# include <winsock2.h> +#include <winsock2.h> #endif #include "srtp_priv.h" @@ -69,98 +68,85 @@ extern "C" { /* * RTP_HEADER_LEN indicates the size of an RTP header */ -#define RTP_HEADER_LEN 12 +#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 - +#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]; + 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_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_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_sendto(rtp_sender_t sender, const void *msg, int len); -int -rtp_recvfrom(rtp_receiver_t receiver, 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_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); +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_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 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_init_srtp(rtp_sender_t sender, const srtp_policy_t *policy); +int rtp_sender_deinit_srtp(rtp_sender_t sender); -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_init_srtp(rtp_receiver_t sender, const srtp_policy_t *policy); +int rtp_receiver_deinit_srtp(rtp_receiver_t sender); -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_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); +rtp_receiver_t rtp_receiver_alloc(void); +void rtp_receiver_dealloc(rtp_receiver_t rtp_ctx); #ifdef __cplusplus } diff --git a/libs/srtp/test/rtp_decoder.c b/libs/srtp/test/rtp_decoder.c index 94cd19e0ab..d718a2b3ad 100644 --- a/libs/srtp/test/rtp_decoder.c +++ b/libs/srtp/test/rtp_decoder.c @@ -4,14 +4,19 @@ * 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 + * $ 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 ... + * $ ./test/rtp_decoder -s AES_CM_128_HMAC_SHA1_80 -b \ + * aSBrbm93IGFsbCB5b3VyIGxpdHRsZSBzZWNyZXRz ... * * Audio can be extracted using extractaudio utility from the RTPproxy * package: @@ -23,26 +28,26 @@ * 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 @@ -57,471 +62,506 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * */ -#include "getopt_s.h" /* for local getopt() */ -#include <assert.h> /* for assert() */ +#include "getopt_s.h" /* for local getopt() */ +#include <assert.h> /* for assert() */ #include <pcap.h> #include "rtp_decoder.h" #include "util.h" -#define MAX_KEY_LEN 96 +#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 struct srtp_crypto_suite { - const char *can_name; - int key_size; - int tag_size; + const char *can_name; + int key_size; + int tag_size; }; static struct srtp_crypto_suite srtp_crypto_suites[] = { - {.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4}, + {.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4 }, #if 0 {.can_name = "F8_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4}, #endif - {.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4}, - {.can_name = "AES_CM_128_HMAC_SHA1_80", .key_size = 128, .tag_size = 10}, - {.can_name = NULL} + {.can_name = "AES_CM_128_HMAC_SHA1_32", .key_size = 128, .tag_size = 4 }, + {.can_name = "AES_CM_128_HMAC_SHA1_80", .key_size = 128, .tag_size = 10 }, + {.can_name = NULL } }; -int -main (int argc, char *argv[]) { - char errbuf[PCAP_ERRBUF_SIZE]; - bpf_u_int32 pcap_net = 0; - pcap_t *pcap_handle; +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; + 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 = 8; - 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] = ""; - rtp_decoder_t dec; - srtp_policy_t policy; - srtp_err_status_t status; - int len; - int expected_len; - int do_list_mods = 0; + 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 = 8; + 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] = ""; + rtp_decoder_t dec; + srtp_policy_t policy; + 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()); + 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); - } - - /* check args */ - while (1) { - c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:s:"); - if (c == -1) { - break; + /* initialize srtp library */ + status = srtp_init(); + if (status) { + fprintf(stderr, + "error: srtp initialization failed with error code %d\n", + status); + exit(1); } - 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 != 256) { - fprintf(stderr, "error: encryption key size must be 128 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_crypto_kernel_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) { + + /* check args */ + while (1) { + c = getopt_s(argc, argv, "b:k:gt:ae:ld:f:s:"); + if (c == -1) { 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; - break; - default: - usage(argv[0]); + 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 != 256) { + fprintf(stderr, + "error: encryption key size must be 128 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_crypto_kernel_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; + break; + default: + usage(argv[0]); + } } - } - 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 (do_list_mods) { - status = srtp_crypto_kernel_list_debug_modules(); - if (status) { - fprintf(stderr, "error: list of debug modules failed\n"); - exit(1); + 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); } - 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]); - } + if (do_list_mods) { + status = srtp_crypto_kernel_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"); - /* 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) { + /* 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: - 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; - } + switch (scs.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 - fprintf(stderr, "error: GCM mode only supported when using the OpenSSL crypto engine.\n"); - return 0; + fprintf(stderr, "error: GCM mode only supported when using the " + "OpenSSL crypto engine.\n"); + return 0; #endif - } else { - switch (scs.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) { - 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_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) { + } else { + switch (scs.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) { + 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_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 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; - } + 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; + 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; - } + } 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; + 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, "setted tag len %d\n", scs.tag_size); - policy.rtp.auth_tag_len = scs.tag_size; - } + if (gcm_on && scs.tag_size != 8) { + fprintf(stderr, "setted 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, + 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 (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); + } + + fprintf(stderr, "set master key/salt to %s/", + octet_string_hex_string(key, 16)); + fprintf(stderr, "%s\n", octet_string_hex_string(key + 16, 14)); - /* - * 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 (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); + fprintf(stderr, + "error: neither encryption or authentication were selected"); + exit(1); } - fprintf(stderr, "set master key/salt to %s/", octet_string_hex_string(key, 16)); - fprintf(stderr, "%s\n", octet_string_hex_string(key+16, 14)); + pcap_handle = pcap_open_offline("-", errbuf); - } else { - fprintf(stderr, "error: neither encryption or authentication were selected"); - exit(1); - } + 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"); + rtp_decoder_init(dec, policy); - pcap_handle = pcap_open_offline("-", errbuf); + pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec); - 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"); - rtp_decoder_init(dec, policy); + rtp_decoder_deinit_srtp(dec); + rtp_decoder_dealloc(dec); - pcap_loop(pcap_handle, 0, rtp_decoder_handle_pkt, (u_char *)dec); + status = srtp_shutdown(); + if (status) { + fprintf(stderr, "error: srtp shutdown failed with error code %d\n", + status); + exit(1); + } - rtp_decoder_deinit_srtp(dec); - rtp_decoder_dealloc(dec); + return 0; +} - status = srtp_shutdown(); - if (status) { - fprintf(stderr, "error: srtp shutdown failed with error code %d\n", status); +void usage(char *string) +{ + fprintf( + stderr, + "usage: %s [-d <debug>]* [[-k][-b] <key> [-a][-e]]\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", + string, string); exit(1); - } - - return 0; } - -void -usage(char *string) { - - fprintf(stderr, "usage: %s [-d <debug>]* [[-k][-b] <key> [-a][-e]]\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", - string, string); - exit(1); - +rtp_decoder_t rtp_decoder_alloc(void) +{ + return (rtp_decoder_t)malloc(sizeof(rtp_decoder_ctx_t)); } -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); } -void -rtp_decoder_dealloc(rtp_decoder_t rtp_ctx) { - free(rtp_ctx); +srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder, + unsigned int ssrc) +{ + decoder->policy.ssrc.value = htonl(ssrc); + return srtp_create(&decoder->srtp_ctx, &decoder->policy); } -srtp_err_status_t -rtp_decoder_init_srtp(rtp_decoder_t decoder, unsigned int ssrc) { - decoder->policy.ssrc.value = htonl(ssrc); - return srtp_create(&decoder->srtp_ctx, &decoder->policy); +int rtp_decoder_deinit_srtp(rtp_decoder_t decoder) +{ + return srtp_dealloc(decoder->srtp_ctx); } -int -rtp_decoder_deinit_srtp(rtp_decoder_t decoder) { - return srtp_dealloc(decoder->srtp_ctx); -} - -int -rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy) { - dcdr->rtp_offset = DEFAULT_RTP_OFFSET; - dcdr->srtp_ctx = NULL; - dcdr->start_tv.tv_usec = 0; - dcdr->start_tv.tv_sec = 0; - dcdr->frame_nr = -1; - dcdr->policy = policy; - dcdr->policy.ssrc.type = ssrc_specific; - return 0; +int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy) +{ + dcdr->rtp_offset = DEFAULT_RTP_OFFSET; + dcdr->srtp_ctx = NULL; + dcdr->start_tv.tv_usec = 0; + dcdr->start_tv.tv_sec = 0; + dcdr->frame_nr = -1; + dcdr->policy = policy; + dcdr->policy.ssrc.type = ssrc_specific; + return 0; } /* * decodes key as base64 */ -void hexdump(const void *ptr, size_t size) { - int i, j; - const unsigned char *cptr = ptr; +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]); + 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"); } - 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; - int pktsize; - struct timeval delta; - int octets_recvd; - srtp_err_status_t status; - dcdr->frame_nr++; +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; + 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 ((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; + if (hdr->caplen < dcdr->rtp_offset) { + return; + } + const void *rtp_packet = bytes + dcdr->rtp_offset; - memcpy((void *)&dcdr->message, rtp_packet, hdr->caplen - dcdr->rtp_offset); - pktsize = hdr->caplen - dcdr->rtp_offset; - octets_recvd = pktsize; + memcpy((void *)&dcdr->message, rtp_packet, hdr->caplen - dcdr->rtp_offset); + pktsize = hdr->caplen - dcdr->rtp_offset; + octets_recvd = pktsize; - if (octets_recvd == -1) { - return; - } + if (octets_recvd == -1) { + return; + } - /* verify rtp header */ - if (dcdr->message.header.version != 2) { - return; - } - if(dcdr->srtp_ctx == NULL) { - status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc); + /* verify rtp header */ + if (dcdr->message.header.version != 2) { + return; + } + if (dcdr->srtp_ctx == NULL) { + status = rtp_decoder_init_srtp(dcdr, dcdr->message.header.ssrc); + if (status) { + exit(1); + } + } + status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd); if (status) { - exit(1); + return; } - } - status = srtp_unprotect(dcdr->srtp_ctx, &dcdr->message, &octets_recvd); - if (status) { - return; - } - 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(&dcdr->message, octets_recvd); + 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(&dcdr->message, octets_recvd); } -void rtp_print_error(srtp_err_status_t status, char *message) { +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)" : @@ -530,4 +570,5 @@ void rtp_print_error(srtp_err_status_t status, char *message) { 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 } diff --git a/libs/srtp/test/rtp_decoder.h b/libs/srtp/test/rtp_decoder.h index 604ff3efea..c8c31dd773 100644 --- a/libs/srtp/test/rtp_decoder.h +++ b/libs/srtp/test/rtp_decoder.h @@ -9,26 +9,26 @@ * */ /* - * + * * 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 @@ -44,7 +44,6 @@ * */ - #ifndef RTP_DECODER_H #define RTP_DECODER_H @@ -54,12 +53,12 @@ #define DEFAULT_RTP_OFFSET 42 typedef struct rtp_decoder_ctx_t { - srtp_policy_t policy; - srtp_ctx_t *srtp_ctx; - int rtp_offset; - struct timeval start_tv; - int frame_nr; - rtp_msg_t message; + srtp_policy_t policy; + srtp_ctx_t *srtp_ctx; + int rtp_offset; + struct timeval start_tv; + int frame_nr; + rtp_msg_t message; } rtp_decoder_ctx_t; typedef struct rtp_decoder_ctx_t *rtp_decoder_t; @@ -69,7 +68,7 @@ typedef struct rtp_decoder_ctx_t *rtp_decoder_t; */ 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); @@ -85,10 +84,12 @@ void usage(char *prog_name); */ 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); +void rtp_decoder_handle_pkt(u_char *arg, + const struct pcap_pkthdr *hdr, + const u_char *bytes); rtp_decoder_t rtp_decoder_alloc(void); @@ -96,9 +97,9 @@ void rtp_decoder_dealloc(rtp_decoder_t rtp_ctx); int rtp_decoder_init(rtp_decoder_t dcdr, srtp_policy_t policy); -srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder, unsigned int ssrc); +srtp_err_status_t rtp_decoder_init_srtp(rtp_decoder_t decoder, + unsigned int ssrc); -int -rtp_decoder_deinit_srtp(rtp_decoder_t decoder); +int rtp_decoder_deinit_srtp(rtp_decoder_t decoder); #endif /* RTP_DECODER_H */ diff --git a/libs/srtp/test/rtpw.c b/libs/srtp/test/rtpw.c index 3b7ac6700b..6e7416c7f5 100644 --- a/libs/srtp/test/rtpw.c +++ b/libs/srtp/test/rtpw.c @@ -8,33 +8,33 @@ * * 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), and sends one word out + * 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 @@ -50,82 +50,76 @@ * */ - #ifdef HAVE_CONFIG_H - #include <config.h> +#include <config.h> #endif -#include "getopt_s.h" /* for local getopt() */ +#include "getopt_s.h" /* for local getopt() */ -#include <stdio.h> /* for printf, fprintf */ -#include <stdlib.h> /* for atoi() */ +#include <stdio.h> /* for printf, fprintf */ +#include <stdlib.h> /* for atoi() */ #include <errno.h> -#include <signal.h> /* for signal() */ +#include <signal.h> /* for signal() */ -#include <string.h> /* for strncpy() */ -#include <time.h> /* for usleep() */ +#include <string.h> /* for strncpy() */ +#include <time.h> /* for usleep() */ #ifdef HAVE_UNISTD_H -#include <unistd.h> /* for close() */ +#include <unistd.h> /* for close() */ #elif defined(_MSC_VER) -#include <io.h> /* for _close() */ +#include <io.h> /* for _close() */ #define close _close #endif #ifdef HAVE_SYS_SOCKET_H -# include <sys/socket.h> +#include <sys/socket.h> #endif #ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> +#include <netinet/in.h> #elif defined HAVE_WINSOCK2_H -# include <winsock2.h> -# include <ws2tcpip.h> -# define RTPW_USE_WINSOCK2 1 +#include <winsock2.h> +#include <ws2tcpip.h> +#define RTPW_USE_WINSOCK2 1 #endif #ifdef HAVE_ARPA_INET_H -# include <arpa/inet.h> +#include <arpa/inet.h> #endif -#include "srtp.h" +#include "srtp.h" #include "rtp.h" #include "util.h" -#define DICT_FILE "words.txt" -#define USEC_RATE (5e5) -#define MAX_WORD_LEN 128 +#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 - +#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 +#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); +void usage(char *prog_name); /* * leave_group(...) de-registers from a multicast group */ -void -leave_group(int sock, struct ip_mreq mreq, char *name); - +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); +int setup_signal_handler(char *name); /* * handle_signal(...) handles interrupt signal to trigger cleanups @@ -139,561 +133,568 @@ volatile int interrupted = 0; 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; +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 */ + 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; + 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:"); - 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); + ret = WSAStartup(wVersionRequested, &wsaData); + if (ret != 0) { + fprintf(stderr, "error: WSAStartup() failed: %d\n", ret); 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); + } +#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); - } - 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); + } + + /* initialize srtp library */ + status = srtp_init(); + if (status) { + printf("error: srtp initialization failed with error code %d\n", + status); exit(1); - } - break; - case 'l': - do_list_mods = 1; - 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); - } - - 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 OPENSSL - 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 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 OPENSSL - 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); + /* 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); + } + + 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 OPENSSL + 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 " + "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 OPENSSL + 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 { - expected_len = policy.rtp.cipher_key_len*2; - len = hex_string_to_octet_string(key, input_key, expected_len); + /* + * 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; } - /* 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 (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); - } + /* 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); + /* 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); } - 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); + if (ADDR_IS_MULTICAST(rcvr_addr.s_addr)) { + leave_group(sock, mreq, argv[0]); } - 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); + ret = closesocket(sock); #else - ret = close(sock); + ret = close(sock); #endif - if (ret < 0) { - fprintf(stderr, "%s: Failed to close socket", argv[0]); - perror(""); - } + 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); - } + status = srtp_shutdown(); + if (status) { + printf("error: srtp shutdown failed with error code %d\n", status); + exit(1); + } #ifdef RTPW_USE_WINSOCK2 - WSACleanup(); + WSACleanup(); #endif - return 0; + 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", - string, string); - exit(1); - +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; -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(""); - } + 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); + 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) +int setup_signal_handler(char *name) { #if HAVE_SIGACTION - struct sigaction act; - memset(&act, 0, sizeof(act)); + struct sigaction act; + memset(&act, 0, sizeof(act)); - act.sa_handler = handle_signal; - sigemptyset(&act.sa_mask); + act.sa_handler = handle_signal; + sigemptyset(&act.sa_mask); #if defined(SA_RESETHAND) - act.sa_flags = SA_RESETHAND; + act.sa_flags = SA_RESETHAND; #else - act.sa_flags = 0; + 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; - } + /* 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; - } + if (signal(SIGTERM, handle_signal) == SIG_ERR) { + fprintf(stderr, "%s: error setting up signal handler", name); + perror(""); + return -1; + } #endif - return 0; + return 0; } diff --git a/libs/srtp/test/srtp_driver.c b/libs/srtp/test/srtp_driver.c index 56052a6321..4ea8fe5302 100644 --- a/libs/srtp/test/srtp_driver.c +++ b/libs/srtp/test/srtp_driver.c @@ -1,5 +1,3 @@ - - /* * srtp_driver.c * @@ -44,7 +42,6 @@ * */ - #include <string.h> /* for memcpy() */ #include <time.h> /* for clock() */ #include <stdlib.h> /* for malloc(), free() */ @@ -55,96 +52,73 @@ #include "util.h" #ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> +#include <netinet/in.h> #elif defined HAVE_WINSOCK2_H -# include <winsock2.h> +#include <winsock2.h> #endif #define PRINT_REFERENCE_PACKET 1 -srtp_err_status_t -srtp_validate(void); +srtp_err_status_t srtp_validate(void); #ifdef OPENSSL -srtp_err_status_t -srtp_validate_gcm(void); +srtp_err_status_t srtp_validate_gcm(void); #endif -srtp_err_status_t -srtp_validate_encrypted_extensions_headers(void); +srtp_err_status_t srtp_validate_encrypted_extensions_headers(void); #ifdef OPENSSL -srtp_err_status_t -srtp_validate_encrypted_extensions_headers_gcm(void); +srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm(void); #endif -srtp_err_status_t -srtp_validate_aes_256(void); +srtp_err_status_t srtp_validate_aes_256(void); -srtp_err_status_t -srtp_create_big_policy(srtp_policy_t **list); +srtp_err_status_t srtp_create_big_policy(srtp_policy_t **list); -srtp_err_status_t -srtp_dealloc_big_policy(srtp_policy_t *list); +srtp_err_status_t srtp_dealloc_big_policy(srtp_policy_t *list); -srtp_err_status_t -srtp_test_empty_payload(void); +srtp_err_status_t srtp_test_empty_payload(void); #ifdef OPENSSL -srtp_err_status_t -srtp_test_empty_payload_gcm(void); +srtp_err_status_t srtp_test_empty_payload_gcm(void); #endif -srtp_err_status_t -srtp_test_remove_stream(void); +srtp_err_status_t srtp_test_remove_stream(void); -srtp_err_status_t -srtp_test_update(void); +srtp_err_status_t srtp_test_update(void); -srtp_err_status_t -srtp_test_protect_trailer_length(void); +srtp_err_status_t srtp_test_protect_trailer_length(void); -srtp_err_status_t -srtp_test_protect_rtcp_trailer_length(void); +srtp_err_status_t srtp_test_protect_rtcp_trailer_length(void); -srtp_err_status_t -srtp_test_get_roc(void); +srtp_err_status_t srtp_test_get_roc(void); -srtp_err_status_t -srtp_test_set_receiver_roc(void); +srtp_err_status_t srtp_test_set_receiver_roc(void); -srtp_err_status_t -srtp_test_set_sender_roc(void); +srtp_err_status_t srtp_test_set_sender_roc(void); -double -srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy); +double srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy); -double -srtp_rejections_per_second(int msg_len_octets, const srtp_policy_t *policy); +double srtp_rejections_per_second(int msg_len_octets, + const srtp_policy_t *policy); -void -srtp_do_timing(const srtp_policy_t *policy); +void srtp_do_timing(const srtp_policy_t *policy); -void -srtp_do_rejection_timing(const srtp_policy_t *policy); +void srtp_do_rejection_timing(const srtp_policy_t *policy); -srtp_err_status_t -srtp_test(const srtp_policy_t *policy, int extension_header, int mki_index); +srtp_err_status_t srtp_test(const srtp_policy_t *policy, + int extension_header, + int mki_index); -srtp_err_status_t -srtcp_test(const srtp_policy_t *policy, int mki_index); +srtp_err_status_t srtcp_test(const srtp_policy_t *policy, int mki_index); -srtp_err_status_t -srtp_session_print_policy(srtp_t srtp); +srtp_err_status_t srtp_session_print_policy(srtp_t srtp); -srtp_err_status_t -srtp_print_policy(const srtp_policy_t *policy); +srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy); -char * -srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len); +char *srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len); -double -mips_estimate(int num_trials, int *ignore); +double mips_estimate(int num_trials, int *ignore); #define TEST_MKI_ID_SIZE 4 @@ -153,6 +127,7 @@ extern uint8_t test_key_2[46]; extern uint8_t test_mki_id[TEST_MKI_ID_SIZE]; extern uint8_t test_mki_id_2[TEST_MKI_ID_SIZE]; +// clang-format off srtp_master_key_t master_key_1 = { test_key, test_mki_id, @@ -169,9 +144,9 @@ srtp_master_key_t *test_keys[2] = { &master_key_1, &master_key_2 }; +// clang-format on -void -usage (char *prog_name) +void usage(char *prog_name) { printf("usage: %s [ -t ][ -c ][ -v ][ -o ][-d <debug_module> ]* [ -l ]\n" " -t run timing test\n" @@ -180,19 +155,27 @@ usage (char *prog_name) " -v run validation tests\n" " -o output logging to stdout\n" " -d <mod> turn on debugging module <mod>\n" - " -l list debugging modules\n", prog_name); + " -l list debugging modules\n", + prog_name); exit(1); } -void -log_handler (srtp_log_level_t level, const char * msg, void * data) +void log_handler(srtp_log_level_t level, const char *msg, void *data) { char level_char = '?'; - switch(level) { - case srtp_log_level_error: level_char = 'e'; break; - case srtp_log_level_warning: level_char = 'w'; break; - case srtp_log_level_info: level_char = 'i'; break; - case srtp_log_level_debug: level_char = 'd'; break; + switch (level) { + case srtp_log_level_error: + level_char = 'e'; + break; + case srtp_log_level_warning: + level_char = 'w'; + break; + case srtp_log_level_info: + level_char = 'i'; + break; + case srtp_log_level_debug: + level_char = 'd'; + break; } printf("SRTP-LOG [%c]: %s\n", level_char, msg); } @@ -204,7 +187,6 @@ log_handler (srtp_log_level_t level, const char * msg, void * data) extern const srtp_policy_t *policy_array[]; - /* the wildcard_policy is declared below; it has a wildcard ssrc */ extern const srtp_policy_t wildcard_policy; @@ -217,20 +199,19 @@ extern const srtp_policy_t wildcard_policy; */ srtp_debug_module_t mod_driver = { - 0, /* debugging is off by default */ - "driver" /* printable name for module */ + 0, /* debugging is off by default */ + "driver" /* printable name for module */ }; -int -main (int argc, char *argv[]) +int main(int argc, char *argv[]) { int q; - unsigned do_timing_test = 0; + unsigned do_timing_test = 0; unsigned do_rejection_test = 0; - unsigned do_codec_timing = 0; - unsigned do_validation = 0; - unsigned do_list_mods = 0; - unsigned do_log_stdout = 0; + unsigned do_codec_timing = 0; + unsigned do_validation = 0; + unsigned do_list_mods = 0; + unsigned do_log_stdout = 0; srtp_err_status_t status; /* @@ -255,7 +236,8 @@ main (int argc, char *argv[]) status = srtp_crypto_kernel_load_debug_module(&mod_driver); if (status) { printf("error: load of srtp_driver debug module failed " - "with error code %d\n", status); + "with error code %d\n", + status); exit(1); } @@ -296,8 +278,8 @@ main (int argc, char *argv[]) } } - if (!do_validation && !do_timing_test && !do_codec_timing - && !do_list_mods && !do_rejection_test) { + if (!do_validation && !do_timing_test && !do_codec_timing && + !do_list_mods && !do_rejection_test) { usage(argv[0]); } @@ -326,51 +308,56 @@ main (int argc, char *argv[]) printf("testing srtp_protect and srtp_unprotect\n"); if (srtp_test(*policy, 0, -1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } - printf("testing srtp_protect and srtp_unprotect with encrypted extensions headers\n"); + printf("testing srtp_protect and srtp_unprotect with encrypted " + "extensions headers\n"); if (srtp_test(*policy, 1, -1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n"); if (srtcp_test(*policy, -1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } - printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI index set to 0\n"); + printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI " + "index set to 0\n"); if (srtp_test(*policy, 0, 0) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } - printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI index set to 1\n"); + printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI " + "index set to 1\n"); if (srtp_test(*policy, 0, 1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } - printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI index set to 0\n"); + printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI " + "index set to 0\n"); if (srtcp_test(*policy, 0) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } - printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI index set to 1\n"); + printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI " + "index set to 1\n"); if (srtcp_test(*policy, 1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -386,14 +373,15 @@ main (int argc, char *argv[]) printf("testing srtp_protect and srtp_unprotect with big policy\n"); if (srtp_test(big_policy, 0, -1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } - printf("testing srtp_protect and srtp_unprotect with big policy and encrypted extensions headers\n"); + printf("testing srtp_protect and srtp_unprotect with big policy and " + "encrypted extensions headers\n"); if (srtp_test(big_policy, 1, -1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -408,7 +396,7 @@ main (int argc, char *argv[]) "wildcard ssrc policy\n"); if (srtp_test(&wildcard_policy, 0, -1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -416,7 +404,7 @@ main (int argc, char *argv[]) "wildcard ssrc policy and encrypted extensions headers\n"); if (srtp_test(&wildcard_policy, 1, -1) == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -429,7 +417,7 @@ main (int argc, char *argv[]) "reference packet\n"); if (srtp_validate() == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -439,7 +427,7 @@ main (int argc, char *argv[]) "reference packet using GCM\n"); if (srtp_validate_gcm() == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -457,9 +445,10 @@ main (int argc, char *argv[]) #ifdef OPENSSL printf("testing srtp_protect and srtp_unprotect against " "reference packet with encrypted extension headers (GCM)\n"); - if (srtp_validate_encrypted_extensions_headers_gcm() == srtp_err_status_ok) { + if (srtp_validate_encrypted_extensions_headers_gcm() == + srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -473,7 +462,7 @@ main (int argc, char *argv[]) "reference packet (AES-256)\n"); if (srtp_validate_aes_256() == srtp_err_status_ok) { printf("passed\n\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -485,7 +474,7 @@ main (int argc, char *argv[]) "packet with empty payload\n"); if (srtp_test_empty_payload() == srtp_err_status_ok) { printf("passed\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -494,7 +483,7 @@ main (int argc, char *argv[]) "packet with empty payload (GCM)\n"); if (srtp_test_empty_payload_gcm() == srtp_err_status_ok) { printf("passed\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -506,7 +495,7 @@ main (int argc, char *argv[]) printf("testing srtp_remove_stream()..."); if (srtp_test_remove_stream() == srtp_err_status_ok) { printf("passed\n"); - } else{ + } else { printf("failed\n"); exit(1); } @@ -565,7 +554,6 @@ main (int argc, char *argv[]) printf("failed\n"); exit(1); } - } if (do_timing_test) { @@ -598,7 +586,7 @@ main (int argc, char *argv[]) memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xdecafbad; policy.key = test_key; policy.ekt = NULL; @@ -612,28 +600,28 @@ main (int argc, char *argv[]) printf("codec\t\tlength (octets)\t\tsrtp instructions/second\n"); printf("G.711\t\t%d\t\t\t%e\n", 80, (double)mips_value * (80 * 8) / - srtp_bits_per_second(80, &policy) / .01 ); + srtp_bits_per_second(80, &policy) / .01); printf("G.711\t\t%d\t\t\t%e\n", 160, (double)mips_value * (160 * 8) / - srtp_bits_per_second(160, &policy) / .02); + srtp_bits_per_second(160, &policy) / .02); printf("G.726-32\t%d\t\t\t%e\n", 40, (double)mips_value * (40 * 8) / - srtp_bits_per_second(40, &policy) / .01 ); + srtp_bits_per_second(40, &policy) / .01); printf("G.726-32\t%d\t\t\t%e\n", 80, (double)mips_value * (80 * 8) / - srtp_bits_per_second(80, &policy) / .02); + srtp_bits_per_second(80, &policy) / .02); printf("G.729\t\t%d\t\t\t%e\n", 10, (double)mips_value * (10 * 8) / - srtp_bits_per_second(10, &policy) / .01 ); + srtp_bits_per_second(10, &policy) / .01); printf("G.729\t\t%d\t\t\t%e\n", 20, (double)mips_value * (20 * 8) / - srtp_bits_per_second(20, &policy) / .02 ); + srtp_bits_per_second(20, &policy) / .02); printf("Wideband\t%d\t\t\t%e\n", 320, (double)mips_value * (320 * 8) / - srtp_bits_per_second(320, &policy) / .01 ); + srtp_bits_per_second(320, &policy) / .01); printf("Wideband\t%d\t\t\t%e\n", 640, (double)mips_value * (640 * 8) / - srtp_bits_per_second(640, &policy) / .02 ); + srtp_bits_per_second(640, &policy) / .02); } status = srtp_shutdown(); @@ -645,8 +633,6 @@ main (int argc, char *argv[]) return 0; } - - /* * srtp_create_test_packet(len, ssrc) returns a pointer to a * (malloced) example RTP packet whose data field has the length given @@ -660,8 +646,9 @@ main (int argc, char *argv[]) * 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) +srtp_hdr_t *srtp_create_test_packet(int pkt_octet_len, + uint32_t ssrc, + int *pkt_len) { int i; uint8_t *buffer; @@ -669,23 +656,23 @@ srtp_create_test_packet (int pkt_octet_len, uint32_t ssrc) int bytes_in_hdr = 12; /* allocate memory for test packet */ - hdr = (srtp_hdr_t*)malloc(pkt_octet_len + bytes_in_hdr - + SRTP_MAX_TRAILER_LEN + 4); + hdr = (srtp_hdr_t *)malloc(pkt_octet_len + bytes_in_hdr + + SRTP_MAX_TRAILER_LEN + 4); if (!hdr) { return NULL; } - hdr->version = 2; /* RTP version two */ - hdr->p = 0; /* no padding needed */ - hdr->x = 0; /* no header extension */ - hdr->cc = 0; /* no CSRCs */ - hdr->m = 0; /* marker bit */ - hdr->pt = 0xf; /* payload type */ - hdr->seq = htons(0x1234); /* sequence number */ - hdr->ts = htonl(0xdecafbad); /* timestamp */ - hdr->ssrc = htonl(ssrc); /* synch. source */ + 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 = (uint8_t *)hdr; buffer += bytes_in_hdr; /* set RTP data to 0xab */ @@ -698,85 +685,91 @@ srtp_create_test_packet (int pkt_octet_len, uint32_t ssrc) *buffer++ = 0xff; } + *pkt_len = bytes_in_hdr + pkt_octet_len; + return hdr; } -static srtp_hdr_t * -srtp_create_test_packet_extended (int pkt_octet_len, uint32_t ssrc, uint16_t seq, uint32_t ts) +static srtp_hdr_t *srtp_create_test_packet_extended(int pkt_octet_len, + uint32_t ssrc, + uint16_t seq, + uint32_t ts, + int *pkt_len) { - srtp_hdr_t *hdr; + srtp_hdr_t *hdr; - hdr = srtp_create_test_packet(pkt_octet_len, ssrc); - if (hdr == NULL) + hdr = srtp_create_test_packet(pkt_octet_len, ssrc, pkt_len); + if (hdr == NULL) + return hdr; + + hdr->seq = htons(seq); + hdr->ts = htonl(ts); return hdr; - - hdr->seq = htons(seq); - hdr->ts = htonl(ts); - return hdr; } -srtp_hdr_t * -srtp_create_test_packet_ext_hdr(int pkt_octet_len, uint32_t ssrc) { - int i; - uint8_t *buffer; - srtp_hdr_t *hdr; - int bytes_in_hdr = 12; - uint8_t extension_header[12] = { - /* one-byte header */ - 0xbe, 0xde, - /* size */ - 0x00, 0x02, - /* id 1, length 1 (i.e. 2 bytes) */ - 0x11, - /* payload */ - 0xca, - 0xfe, - /* padding */ - 0x00, - /* id 2, length 0 (i.e. 1 byte) */ - 0x20, - /* payload */ - 0xba, - /* padding */ - 0x00, - 0x00 - }; +srtp_hdr_t *srtp_create_test_packet_ext_hdr(int pkt_octet_len, + uint32_t ssrc, + int *pkt_len) +{ + int i; + uint8_t *buffer; + srtp_hdr_t *hdr; + int bytes_in_hdr = 12; + uint8_t extension_header[12] = { /* one-byte header */ + 0xbe, 0xde, + /* size */ + 0x00, 0x02, + /* id 1, length 1 (i.e. 2 bytes) */ + 0x11, + /* payload */ + 0xca, 0xfe, + /* padding */ + 0x00, + /* id 2, length 0 (i.e. 1 byte) */ + 0x20, + /* payload */ + 0xba, + /* padding */ + 0x00, 0x00 + }; - /* allocate memory for test packet */ - hdr = (srtp_hdr_t*) malloc(pkt_octet_len + bytes_in_hdr - + sizeof(extension_header) + SRTP_MAX_TRAILER_LEN + 4); - if (!hdr) - return NULL; + /* allocate memory for test packet */ + hdr = (srtp_hdr_t *)malloc(pkt_octet_len + bytes_in_hdr + + sizeof(extension_header) + SRTP_MAX_TRAILER_LEN + + 4); + if (!hdr) + return NULL; - hdr->version = 2; /* RTP version two */ - hdr->p = 0; /* no padding needed */ - hdr->x = 1; /* no header extension */ - hdr->cc = 0; /* no CSRCs */ - hdr->m = 0; /* marker bit */ - hdr->pt = 0xf; /* payload type */ - hdr->seq = htons(0x1234); /* sequence number */ - hdr->ts = htonl(0xdecafbad); /* timestamp */ - hdr->ssrc = htonl(ssrc); /* synch. source */ + hdr->version = 2; /* RTP version two */ + hdr->p = 0; /* no padding needed */ + hdr->x = 1; /* no header extension */ + hdr->cc = 0; /* no CSRCs */ + hdr->m = 0; /* marker bit */ + hdr->pt = 0xf; /* payload type */ + hdr->seq = htons(0x1234); /* sequence number */ + hdr->ts = htonl(0xdecafbad); /* timestamp */ + hdr->ssrc = htonl(ssrc); /* synch. source */ - buffer = (uint8_t *)hdr; - buffer += bytes_in_hdr; + buffer = (uint8_t *)hdr; + buffer += bytes_in_hdr; - memcpy(buffer, extension_header, sizeof(extension_header)); - buffer += sizeof(extension_header); + memcpy(buffer, extension_header, sizeof(extension_header)); + buffer += sizeof(extension_header); - /* set RTP data to 0xab */ - for (i=0; i < pkt_octet_len; i++) - *buffer++ = 0xab; + /* set 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; + /* set post-data value to 0xffff to enable overrun checking */ + for (i = 0; i < SRTP_MAX_TRAILER_LEN + 4; i++) + *buffer++ = 0xff; - return hdr; + *pkt_len = bytes_in_hdr + sizeof(extension_header) + pkt_octet_len; + + return hdr; } -void -srtp_do_timing (const srtp_policy_t *policy) +void srtp_do_timing(const srtp_policy_t *policy) { int len; @@ -796,11 +789,9 @@ srtp_do_timing (const srtp_policy_t *policy) /* these extra linefeeds let gnuplot know that a dataset is done */ printf("\r\n\r\n"); - } -void -srtp_do_rejection_timing (const srtp_policy_t *policy) +void srtp_do_rejection_timing(const srtp_policy_t *policy) { int len; @@ -819,21 +810,18 @@ srtp_do_rejection_timing (const srtp_policy_t *policy) /* these extra linefeeds let gnuplot know that a dataset is done */ printf("\r\n\r\n"); - } - #define MAX_MSG_LEN 1024 -double -srtp_bits_per_second (int msg_len_octets, const srtp_policy_t *policy) +double srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy) { srtp_t srtp; srtp_hdr_t *mesg; int i; clock_t timer; int num_trials = 100000; - int len; + int input_len, len; uint32_t ssrc; srtp_err_status_t status; @@ -858,15 +846,13 @@ srtp_bits_per_second (int msg_len_octets, const srtp_policy_t *policy) /* * create a test packet */ - mesg = srtp_create_test_packet(msg_len_octets, ssrc); + mesg = srtp_create_test_packet(msg_len_octets, ssrc, &input_len); if (mesg == NULL) { return 0.0; /* indicate failure by returning zero */ - } timer = clock(); for (i = 0; i < num_trials; i++) { - len = msg_len_octets + 12; /* add in rtp header length */ - + len = input_len; /* srtp protect message */ status = srtp_protect(srtp, mesg, &len); if (status) { @@ -876,7 +862,8 @@ srtp_bits_per_second (int msg_len_octets, const srtp_policy_t *policy) /* increment message number */ { - /* hack sequence to avoid problems with macros for htons/ntohs on some systems */ + /* hack sequence to avoid problems with macros for htons/ntohs on + * some systems */ short new_seq = ntohs(mesg->seq) + 1; mesg->seq = htons(new_seq); } @@ -891,12 +878,11 @@ srtp_bits_per_second (int msg_len_octets, const srtp_policy_t *policy) exit(1); } - return (double)(msg_len_octets) * 8 * - num_trials * CLOCKS_PER_SEC / timer; + return (double)(msg_len_octets)*8 * num_trials * CLOCKS_PER_SEC / timer; } -double -srtp_rejections_per_second (int msg_len_octets, const srtp_policy_t *policy) +double srtp_rejections_per_second(int msg_len_octets, + const srtp_policy_t *policy) { srtp_ctx_t *srtp; srtp_hdr_t *mesg; @@ -916,18 +902,16 @@ srtp_rejections_per_second (int msg_len_octets, const srtp_policy_t *policy) exit(1); } - mesg = srtp_create_test_packet(msg_len_octets, ssrc); + mesg = srtp_create_test_packet(msg_len_octets, ssrc, &len); if (mesg == NULL) { return 0.0; /* indicate failure by returning zero */ - } - len = msg_len_octets; - srtp_protect(srtp, (srtp_hdr_t*)mesg, &len); + srtp_protect(srtp, (srtp_hdr_t *)mesg, &len); timer = clock(); for (i = 0; i < num_trials; i++) { len = msg_len_octets; - srtp_unprotect(srtp, (srtp_hdr_t*)mesg, &len); + srtp_unprotect(srtp, (srtp_hdr_t *)mesg, &len); } timer = clock() - timer; @@ -942,56 +926,67 @@ srtp_rejections_per_second (int msg_len_octets, const srtp_policy_t *policy) return (double)num_trials * CLOCKS_PER_SEC / timer; } - -void -err_check (srtp_err_status_t s) +void err_check(srtp_err_status_t s) { if (s == srtp_err_status_ok) { return; - } else{ + } else { fprintf(stderr, "error: unexpected srtp failure (code %d)\n", s); } exit(1); } -srtp_err_status_t -srtp_test_call_protect(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int mki_index) { +srtp_err_status_t srtp_test_call_protect(srtp_t srtp_sender, + srtp_hdr_t *hdr, + int *len, + int mki_index) +{ if (mki_index == -1) { - return srtp_protect(srtp_sender, hdr, len); + return srtp_protect(srtp_sender, hdr, len); } else { - return srtp_protect_mki(srtp_sender, hdr, len, 1, mki_index); + return srtp_protect_mki(srtp_sender, hdr, len, 1, mki_index); } } -srtp_err_status_t -srtp_test_call_protect_rtcp(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int mki_index) { +srtp_err_status_t srtp_test_call_protect_rtcp(srtp_t srtp_sender, + srtp_hdr_t *hdr, + int *len, + int mki_index) +{ if (mki_index == -1) { - return srtp_protect_rtcp(srtp_sender, hdr, len); + return srtp_protect_rtcp(srtp_sender, hdr, len); } else { - return srtp_protect_rtcp_mki(srtp_sender, hdr, len, 1, mki_index); + return srtp_protect_rtcp_mki(srtp_sender, hdr, len, 1, mki_index); } } -srtp_err_status_t -srtp_test_call_unprotect(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int use_mki) { +srtp_err_status_t srtp_test_call_unprotect(srtp_t srtp_sender, + srtp_hdr_t *hdr, + int *len, + int use_mki) +{ if (use_mki == -1) { - return srtp_unprotect(srtp_sender, hdr, len); + return srtp_unprotect(srtp_sender, hdr, len); } else { - return srtp_unprotect_mki(srtp_sender, hdr, len, use_mki); + return srtp_unprotect_mki(srtp_sender, hdr, len, use_mki); } } -srtp_err_status_t -srtp_test_call_unprotect_rtcp(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int use_mki) { +srtp_err_status_t srtp_test_call_unprotect_rtcp(srtp_t srtp_sender, + srtp_hdr_t *hdr, + int *len, + int use_mki) +{ if (use_mki == -1) { - return srtp_unprotect_rtcp(srtp_sender, hdr, len); + return srtp_unprotect_rtcp(srtp_sender, hdr, len); } else { - return srtp_unprotect_rtcp_mki(srtp_sender, hdr, len, use_mki); + return srtp_unprotect_rtcp_mki(srtp_sender, hdr, len, use_mki); } } -srtp_err_status_t -srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) +srtp_err_status_t srtp_test(const srtp_policy_t *policy, + int extension_header, + int mki_index) { int i; srtp_t srtp_sender; @@ -1000,9 +995,9 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) srtp_hdr_t *hdr, *hdr2; uint8_t hdr_enc[64]; uint8_t *pkt_end; - int msg_len_octets, msg_len_enc; - int len; - int tag_length = policy->rtp.auth_tag_len; + int msg_len_octets, msg_len_enc, msg_len; + int len, len2; + uint32_t tag_length; uint32_t ssrc; srtp_policy_t *rcvr_policy; srtp_policy_t tmp_policy; @@ -1010,7 +1005,7 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) int use_mki = 0; if (mki_index >= 0) - use_mki = 1; + use_mki = 1; if (extension_header) { memcpy(&tmp_policy, policy, sizeof(srtp_policy_t)); @@ -1031,18 +1026,21 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) */ if (policy->ssrc.type != ssrc_specific) { ssrc = 0xdecafbad; - } else{ + } else { ssrc = policy->ssrc.value; } msg_len_octets = 28; if (extension_header) { - hdr = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc); - hdr2 = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc); + hdr = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc, &len); + hdr2 = srtp_create_test_packet_ext_hdr(msg_len_octets, ssrc, &len2); } else { - hdr = srtp_create_test_packet(msg_len_octets, ssrc); - hdr2 = srtp_create_test_packet(msg_len_octets, ssrc); + hdr = srtp_create_test_packet(msg_len_octets, ssrc, &len); + hdr2 = srtp_create_test_packet(msg_len_octets, ssrc, &len2); } + /* save original msg len */ + msg_len = len; + if (hdr == NULL) { free(hdr2); return srtp_err_status_alloc_fail; @@ -1052,18 +1050,12 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) return srtp_err_status_alloc_fail; } - /* set message length */ - len = msg_len_octets; - if (extension_header) { - len += 12; - } - debug_print(mod_driver, "before protection:\n%s", srtp_packet_to_string(hdr, len)); #if PRINT_REFERENCE_PACKET debug_print(mod_driver, "reference packet before protection:\n%s", - octet_string_hex_string((uint8_t*)hdr, len)); + octet_string_hex_string((uint8_t *)hdr, len)); #endif err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index)); @@ -1071,7 +1063,7 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) srtp_packet_to_string(hdr, len)); #if PRINT_REFERENCE_PACKET debug_print(mod_driver, "after protection:\n%s", - octet_string_hex_string((uint8_t*)hdr, len)); + octet_string_hex_string((uint8_t *)hdr, len)); #endif /* save protected message and length */ @@ -1085,16 +1077,14 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) * data following the packet is different, then we know that the * protect function is overwriting the end of the packet. */ - pkt_end = (uint8_t*)hdr + sizeof(srtp_hdr_t) - + msg_len_octets + tag_length; - if (extension_header) { - pkt_end += 12; - } + err_check(srtp_get_protect_trailer_length(srtp_sender, use_mki, mki_index, + &tag_length)); + pkt_end = (uint8_t *)hdr + msg_len + tag_length; for (i = 0; i < 4; i++) { if (pkt_end[i] != 0xff) { fprintf(stdout, "overwrite in srtp_protect() function " - "(expected %x, found %x in trailing octet %d)\n", - 0xff, ((uint8_t*)hdr)[i], i); + "(expected %x, found %x in trailing octet %d)\n", + 0xff, ((uint8_t *)hdr)[i], i); free(hdr); free(hdr2); return srtp_err_status_algo_fail; @@ -1114,7 +1104,7 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) printf("testing that ciphertext is distinct from plaintext..."); status = srtp_err_status_algo_fail; for (i = 12; i < msg_len_octets + 12; i++) { - if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) { + if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) { status = srtp_err_status_ok; } } @@ -1134,7 +1124,7 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) * we always copy the policy into the rcvr_policy, since otherwise * the compiler would fret about the constness of the policy */ - rcvr_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t)); + rcvr_policy = (srtp_policy_t *)malloc(sizeof(srtp_policy_t)); if (rcvr_policy == NULL) { free(hdr); free(hdr2); @@ -1160,8 +1150,8 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) srtp_packet_to_string(hdr, len)); /* verify that the unprotected packet matches the origial one */ - for (i = 0; i < msg_len_octets; i++) { - if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) { + for (i = 0; i < len; i++) { + if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) { fprintf(stdout, "mismatch at octet %d\n", i); status = srtp_err_status_algo_fail; } @@ -1177,15 +1167,13 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) * if the policy includes authentication, then test for false positives */ if (policy->rtp.sec_serv & sec_serv_auth) { - char *data = ((char*)hdr) + 12; + char *data = ((char *)hdr) + (extension_header ? 24 : 12); printf("testing for false positives in replay check..."); - /* set message length */ - len = msg_len_enc; - /* unprotect a second time - should fail with a replay error */ - status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki); + status = + srtp_test_call_unprotect(srtp_rcvr, hdr, &msg_len_enc, use_mki); if (status != srtp_err_status_replay_fail) { printf("failed with error code %d\n", status); free(hdr); @@ -1201,17 +1189,11 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) /* increment sequence number in header */ hdr->seq++; - /* set message length */ - len = msg_len_octets; - if (extension_header) { - len += 12; - } - /* apply protection */ err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index)); /* flip bits in packet */ - data[extension_header ? 12 : 0] ^= 0xff; + data[0] ^= 0xff; /* unprotect, and check for authentication failure */ status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki); @@ -1224,7 +1206,6 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) } else { printf("passed\n"); } - } err_check(srtp_dealloc(srtp_sender)); @@ -1236,9 +1217,7 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) return srtp_err_status_ok; } - -srtp_err_status_t -srtcp_test (const srtp_policy_t *policy, int mki_index) +srtp_err_status_t srtcp_test(const srtp_policy_t *policy, int mki_index) { int i; srtp_t srtcp_sender; @@ -1247,9 +1226,9 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) srtp_hdr_t *hdr, *hdr2; uint8_t hdr_enc[64]; uint8_t *pkt_end; - int msg_len_octets, msg_len_enc; - int len; - int tag_length = policy->rtp.auth_tag_len; + int msg_len_octets, msg_len_enc, msg_len; + int len, len2; + uint32_t tag_length; uint32_t ssrc; srtp_policy_t *rcvr_policy; int use_mki = 0; @@ -1269,30 +1248,29 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) */ if (policy->ssrc.type != ssrc_specific) { ssrc = 0xdecafbad; - } else{ + } else { ssrc = policy->ssrc.value; } msg_len_octets = 28; - hdr = srtp_create_test_packet(msg_len_octets, ssrc); + hdr = srtp_create_test_packet(msg_len_octets, ssrc, &len); + /* save message len */ + msg_len = len; if (hdr == NULL) { return srtp_err_status_alloc_fail; } - hdr2 = srtp_create_test_packet(msg_len_octets, ssrc); + hdr2 = srtp_create_test_packet(msg_len_octets, ssrc, &len2); if (hdr2 == NULL) { free(hdr); return srtp_err_status_alloc_fail; } - /* set message length */ - len = msg_len_octets; - debug_print(mod_driver, "before protection:\n%s", srtp_packet_to_string(hdr, len)); #if PRINT_REFERENCE_PACKET debug_print(mod_driver, "reference packet before protection:\n%s", - octet_string_hex_string((uint8_t*)hdr, len)); + octet_string_hex_string((uint8_t *)hdr, len)); #endif err_check(srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index)); @@ -1300,7 +1278,7 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) srtp_packet_to_string(hdr, len)); #if PRINT_REFERENCE_PACKET debug_print(mod_driver, "after protection:\n%s", - octet_string_hex_string((uint8_t*)hdr, len)); + octet_string_hex_string((uint8_t *)hdr, len)); #endif /* save protected message and length */ @@ -1314,13 +1292,14 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) * data following the packet is different, then we know that the * protect function is overwriting the end of the packet. */ - pkt_end = (uint8_t*)hdr + sizeof(srtp_hdr_t) - + msg_len_octets + tag_length; + srtp_get_protect_rtcp_trailer_length(srtcp_sender, use_mki, mki_index, + &tag_length); + pkt_end = (uint8_t *)hdr + msg_len + tag_length; for (i = 0; i < 4; i++) { if (pkt_end[i] != 0xff) { fprintf(stdout, "overwrite in srtp_protect_rtcp() function " - "(expected %x, found %x in trailing octet %d)\n", - 0xff, ((uint8_t*)hdr)[i], i); + "(expected %x, found %x in trailing octet %d)\n", + 0xff, ((uint8_t *)hdr)[i], i); free(hdr); free(hdr2); return srtp_err_status_algo_fail; @@ -1336,11 +1315,11 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) * reason, we skip this check if the plaintext is less than four * octets long. */ - if ((policy->rtp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) { + if ((policy->rtcp.sec_serv & sec_serv_conf) && (msg_len_octets >= 4)) { printf("testing that ciphertext is distinct from plaintext..."); status = srtp_err_status_algo_fail; for (i = 12; i < msg_len_octets + 12; i++) { - if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) { + if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) { status = srtp_err_status_ok; } } @@ -1360,7 +1339,7 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) * we always copy the policy into the rcvr_policy, since otherwise * the compiler would fret about the constness of the policy */ - rcvr_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t)); + rcvr_policy = (srtp_policy_t *)malloc(sizeof(srtp_policy_t)); if (rcvr_policy == NULL) { return srtp_err_status_alloc_fail; } @@ -1377,8 +1356,8 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) srtp_packet_to_string(hdr, len)); /* verify that the unprotected packet matches the origial one */ - for (i = 0; i < msg_len_octets; i++) { - if (((uint8_t*)hdr)[i] != ((uint8_t*)hdr2)[i]) { + for (i = 0; i < len; i++) { + if (((uint8_t *)hdr)[i] != ((uint8_t *)hdr2)[i]) { fprintf(stdout, "mismatch at octet %d\n", i); status = srtp_err_status_algo_fail; } @@ -1394,15 +1373,13 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) * if the policy includes authentication, then test for false positives */ if (policy->rtp.sec_serv & sec_serv_auth) { - char *data = ((char*)hdr) + 12; + char *data = ((char *)hdr) + 12; printf("testing for false positives in replay check..."); - /* set message length */ - len = msg_len_enc; - /* unprotect a second time - should fail with a replay error */ - status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki); + status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &msg_len_enc, + use_mki); if (status != srtp_err_status_replay_fail) { printf("failed with error code %d\n", status); free(hdr); @@ -1418,11 +1395,9 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) /* increment sequence number in header */ hdr->seq++; - /* set message length */ - len = msg_len_octets; - /* apply protection */ - err_check(srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index)); + err_check( + srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index)); /* flip bits in packet */ data[0] ^= 0xff; @@ -1438,7 +1413,6 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) } else { printf("passed\n"); } - } err_check(srtp_dealloc(srtcp_sender)); @@ -1450,21 +1424,11 @@ srtcp_test (const srtp_policy_t *policy, int mki_index) return srtp_err_status_ok; } - -srtp_err_status_t -srtp_session_print_policy (srtp_t srtp) +srtp_err_status_t srtp_session_print_policy(srtp_t srtp) { - char *serv_descr[4] = { - "none", - "confidentiality", - "authentication", - "confidentiality and authentication" - }; - char *direction[3] = { - "unknown", - "outbound", - "inbound" - }; + char *serv_descr[4] = { "none", "confidentiality", "authentication", + "confidentiality and authentication" }; + char *direction[3] = { "unknown", "outbound", "inbound" }; srtp_stream_t stream; srtp_session_keys_t *session_keys = NULL; @@ -1498,7 +1462,7 @@ srtp_session_print_policy (srtp_t srtp) printf("# Encrypted extension headers: "); if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) { - int* enc_xtn_hdr = stream->enc_xtn_hdr; + int *enc_xtn_hdr = stream->enc_xtn_hdr; int count = stream->enc_xtn_hdr_count; while (count > 0) { printf("%d ", *enc_xtn_hdr); @@ -1528,8 +1492,7 @@ srtp_session_print_policy (srtp_t srtp) "# rtcp services: %s\r\n" "# window size: %lu\r\n" "# tx rtx allowed:%s\r\n", - stream->ssrc, - session_keys->rtp_cipher->type->description, + stream->ssrc, session_keys->rtp_cipher->type->description, session_keys->rtp_auth->type->description, serv_descr[stream->rtp_services], session_keys->rtcp_cipher->type->description, @@ -1540,7 +1503,7 @@ srtp_session_print_policy (srtp_t srtp) printf("# Encrypted extension headers: "); if (stream->enc_xtn_hdr && stream->enc_xtn_hdr_count > 0) { - int* enc_xtn_hdr = stream->enc_xtn_hdr; + int *enc_xtn_hdr = stream->enc_xtn_hdr; int count = stream->enc_xtn_hdr_count; while (count > 0) { printf("%d ", *enc_xtn_hdr); @@ -1558,8 +1521,7 @@ srtp_session_print_policy (srtp_t srtp) return srtp_err_status_ok; } -srtp_err_status_t -srtp_print_policy (const srtp_policy_t *policy) +srtp_err_status_t srtp_print_policy(const srtp_policy_t *policy) { srtp_err_status_t status; srtp_t session; @@ -1592,11 +1554,10 @@ srtp_print_policy (const srtp_policy_t *policy) char packet_string[MTU]; -char * -srtp_packet_to_string (srtp_hdr_t *hdr, int pkt_octet_len) +char *srtp_packet_to_string(srtp_hdr_t *hdr, int pkt_octet_len) { int octets_in_rtp_header = 12; - uint8_t *data = ((uint8_t*)hdr) + octets_in_rtp_header; + uint8_t *data = ((uint8_t *)hdr) + octets_in_rtp_header; int hex_len = pkt_octet_len - octets_in_rtp_header; /* sanity checking */ @@ -1605,29 +1566,20 @@ srtp_packet_to_string (srtp_hdr_t *hdr, int pkt_octet_len) } /* write packet into string */ - sprintf(packet_string, - "(s)rtp packet: {\n" - " version:\t%d\n" - " p:\t\t%d\n" - " x:\t\t%d\n" - " cc:\t\t%d\n" - " m:\t\t%d\n" - " pt:\t\t%x\n" - " seq:\t\t%x\n" - " ts:\t\t%x\n" - " ssrc:\t%x\n" - " data:\t%s\n" - "} (%d octets in total)\n", - hdr->version, - hdr->p, - hdr->x, - hdr->cc, - hdr->m, - hdr->pt, - hdr->seq, - hdr->ts, - hdr->ssrc, - octet_string_hex_string(data, hex_len), + sprintf(packet_string, "(s)rtp packet: {\n" + " version:\t%d\n" + " p:\t\t%d\n" + " x:\t\t%d\n" + " cc:\t\t%d\n" + " m:\t\t%d\n" + " pt:\t\t%x\n" + " seq:\t\t%x\n" + " ts:\t\t%x\n" + " ssrc:\t%x\n" + " data:\t%s\n" + "} (%d octets in total)\n", + hdr->version, hdr->p, hdr->x, hdr->cc, hdr->m, hdr->pt, hdr->seq, + hdr->ts, hdr->ssrc, octet_string_hex_string(data, hex_len), pkt_octet_len); return packet_string; @@ -1643,8 +1595,7 @@ srtp_packet_to_string (srtp_hdr_t *hdr, int pkt_octet_len) * optimize away the function */ -double -mips_estimate (int num_trials, int *ignore) +double mips_estimate(int num_trials, int *ignore) { clock_t t; volatile int i, sum; @@ -1656,23 +1607,21 @@ mips_estimate (int num_trials, int *ignore) } t = clock() - t; -/* printf("%d\n", sum); */ + /* printf("%d\n", sum); */ *ignore = sum; return (double)num_trials * CLOCKS_PER_SEC / t; } - /* * srtp_validate() verifies the correctness of libsrtp by comparing * some computed packets against some pre-computed reference values. * These packets were made with the default SRTP policy. */ - -srtp_err_status_t -srtp_validate () +srtp_err_status_t srtp_validate() { + // clang-format off uint8_t srtp_plaintext_ref[28] = { 0x80, 0x0f, 0x12, 0x34, 0xde, 0xca, 0xfb, 0xad, 0xca, 0xfe, 0xba, 0xbe, 0xab, 0xab, 0xab, 0xab, @@ -1712,6 +1661,8 @@ srtp_validate () 0x80, 0x00, 0x00, 0x01, 0x99, 0x3e, 0x08, 0xcd, 0x54, 0xd6, 0xc1, 0x23, 0x07, 0x98 }; + // clang-format on + srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; int len; @@ -1724,7 +1675,7 @@ srtp_validate () memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = test_key; policy.ekt = NULL; @@ -1826,9 +1777,9 @@ srtp_validate () * srtp_validate_gcm() verifies the correctness of libsrtp by comparing * an computed packet against the known ciphertext for the plaintext. */ -srtp_err_status_t -srtp_validate_gcm () +srtp_err_status_t srtp_validate_gcm() { + // clang-format off unsigned char test_key_gcm[28] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, @@ -1878,6 +1829,7 @@ srtp_validate_gcm () 0xea, 0x31, 0x12, 0x3b, 0xa8, 0x8c, 0xe6, 0x1e, 0x80, 0x00, 0x00, 0x01 }; + // clang-format on srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; @@ -1891,9 +1843,9 @@ srtp_validate_gcm () memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = test_key_gcm; + policy.key = test_key_gcm; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -1993,8 +1945,9 @@ srtp_validate_gcm () /* * Test vectors taken from RFC 6904, Appendix A */ -srtp_err_status_t -srtp_validate_encrypted_extensions_headers() { +srtp_err_status_t srtp_validate_encrypted_extensions_headers() +{ + // clang-format off unsigned char test_key_ext_headers[30] = { 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, @@ -2032,11 +1985,13 @@ srtp_validate_encrypted_extensions_headers() { 0x5a, 0x46, 0xb3, 0xca, 0x35, 0xc5, 0x35, 0xa8, 0x91, 0xc7 }; + // clang-format on + srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; int len; srtp_policy_t policy; - int headers[3] = {1, 3, 4}; + int headers[3] = { 1, 3, 4 }; /* * create a session with a single stream using the default srtp @@ -2045,7 +2000,7 @@ srtp_validate_encrypted_extensions_headers() { memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = test_key_ext_headers; policy.ekt = NULL; @@ -2108,14 +2063,14 @@ srtp_validate_encrypted_extensions_headers() { return srtp_err_status_ok; } - #ifdef OPENSSL /* * Headers of test vectors taken from RFC 6904, Appendix A */ -srtp_err_status_t -srtp_validate_encrypted_extensions_headers_gcm() { +srtp_err_status_t srtp_validate_encrypted_extensions_headers_gcm() +{ + // clang-format off unsigned char test_key_ext_headers[30] = { 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, @@ -2151,11 +2106,13 @@ srtp_validate_encrypted_extensions_headers_gcm() { 0x6c, 0xd3, 0xd2, 0x88, 0xb4, 0x9f, 0x6c, 0xa9, 0xf4, 0xb1, 0xb7, 0x59, 0x71, 0x9e, 0xb5, 0xbc }; + // clang-format on + srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; int len; srtp_policy_t policy; - int headers[3] = {1, 3, 4}; + int headers[3] = { 1, 3, 4 }; /* * create a session with a single stream using the default srtp @@ -2164,7 +2121,7 @@ srtp_validate_encrypted_extensions_headers_gcm() { memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = test_key_ext_headers; policy.ekt = NULL; @@ -2234,10 +2191,9 @@ srtp_validate_encrypted_extensions_headers_gcm() { * These packets were made with the AES-CM-256/HMAC-SHA-1-80 policy. */ - -srtp_err_status_t -srtp_validate_aes_256 () +srtp_err_status_t srtp_validate_aes_256() { + // clang-format off unsigned char aes_256_test_key[46] = { 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76, 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29, @@ -2267,6 +2223,8 @@ srtp_validate_aes_256 () 0xb0, 0xb4, 0xb4, 0x0d, 0xa0, 0x8d, 0x9d, 0x9a, 0x5b, 0x3a, 0x55, 0xd8, 0x87, 0x3b }; + // clang-format on + srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; int len; @@ -2279,7 +2237,7 @@ srtp_validate_aes_256 () memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtp); srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = aes_256_test_key; policy.ekt = NULL; @@ -2345,9 +2303,7 @@ srtp_validate_aes_256 () return srtp_err_status_ok; } - -srtp_err_status_t -srtp_create_big_policy (srtp_policy_t **list) +srtp_err_status_t srtp_create_big_policy(srtp_policy_t **list) { extern const srtp_policy_t *policy_array[]; srtp_policy_t *p, *tmp; @@ -2365,7 +2321,7 @@ srtp_create_big_policy (srtp_policy_t **list) */ tmp = NULL; while (policy_array[i] != NULL) { - p = (srtp_policy_t*)malloc(sizeof(srtp_policy_t)); + p = (srtp_policy_t *)malloc(sizeof(srtp_policy_t)); if (p == NULL) { return srtp_err_status_bad_param; } @@ -2381,8 +2337,7 @@ srtp_create_big_policy (srtp_policy_t **list) return srtp_err_status_ok; } -srtp_err_status_t -srtp_dealloc_big_policy (srtp_policy_t *list) +srtp_err_status_t srtp_dealloc_big_policy(srtp_policy_t *list) { srtp_policy_t *p, *next; @@ -2394,8 +2349,7 @@ srtp_dealloc_big_policy (srtp_policy_t *list) return srtp_err_status_ok; } -srtp_err_status_t -srtp_test_empty_payload() +srtp_err_status_t srtp_test_empty_payload() { srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; @@ -2410,7 +2364,7 @@ srtp_test_empty_payload() memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = test_key; policy.ekt = NULL; @@ -2423,12 +2377,11 @@ srtp_test_empty_payload() return status; } - mesg = srtp_create_test_packet(0, policy.ssrc.value); + mesg = srtp_create_test_packet(0, policy.ssrc.value, &len); if (mesg == NULL) { return srtp_err_status_fail; } - len = 12; /* only the header */ status = srtp_protect(srtp_snd, mesg, &len); if (status) { return status; @@ -2472,8 +2425,7 @@ srtp_test_empty_payload() } #ifdef OPENSSL -srtp_err_status_t -srtp_test_empty_payload_gcm() +srtp_err_status_t srtp_test_empty_payload_gcm() { srtp_t srtp_snd, srtp_recv; srtp_err_status_t status; @@ -2488,7 +2440,7 @@ srtp_test_empty_payload_gcm() memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtp); srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = test_key; policy.ekt = NULL; @@ -2501,12 +2453,11 @@ srtp_test_empty_payload_gcm() return status; } - mesg = srtp_create_test_packet(0, policy.ssrc.value); + mesg = srtp_create_test_packet(0, policy.ssrc.value, &len); if (mesg == NULL) { return srtp_err_status_fail; } - len = 12; /* only the header */ status = srtp_protect(srtp_snd, mesg, &len); if (status) { return status; @@ -2548,10 +2499,9 @@ srtp_test_empty_payload_gcm() return srtp_err_status_ok; } -#endif // OPENSSL +#endif // OPENSSL -srtp_err_status_t -srtp_test_remove_stream () +srtp_err_status_t srtp_test_remove_stream() { srtp_err_status_t status; srtp_policy_t *policy_list, policy; @@ -2565,7 +2515,6 @@ srtp_test_remove_stream () */ extern srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc); - status = srtp_create_big_policy(&policy_list); if (status) { return status; @@ -2616,7 +2565,7 @@ srtp_test_remove_stream () memset(&policy, 0, sizeof(policy)); srtp_crypto_policy_set_rtp_default(&policy.rtp); srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; + policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; policy.key = test_key; policy.ekt = NULL; @@ -2647,7 +2596,7 @@ srtp_test_remove_stream () return srtp_err_status_ok; } - +// clang-format off unsigned char test_alt_key[46] = { 0xe5, 0x19, 0x6f, 0x01, 0x5e, 0xf1, 0x9b, 0xe1, 0xd7, 0x47, 0xa7, 0x27, 0x07, 0xd7, 0x47, 0x33, @@ -2656,6 +2605,7 @@ unsigned char test_alt_key[46] = { 0xc7, 0x15, 0xe2, 0xea, 0xfe, 0x55, 0x67, 0x96, 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 }; +// clang-format on /* * srtp_test_update() verifies updating/rekeying exsisting streams. @@ -2664,748 +2614,776 @@ unsigned char test_alt_key[46] = { * atempts to prove that srtp_update does not reset the ROC. */ -srtp_err_status_t -srtp_test_update() { +srtp_err_status_t srtp_test_update() +{ + srtp_err_status_t status; + uint32_t ssrc = 0x12121212; + int msg_len_octets = 32; + int protected_msg_len_octets; + srtp_hdr_t *msg; + srtp_t srtp_snd, srtp_recv; + srtp_policy_t policy; - srtp_err_status_t status; - uint32_t ssrc = 0x12121212; - int msg_len_octets = 32; - int protected_msg_len_octets; - srtp_hdr_t * msg; - srtp_t srtp_snd, srtp_recv; - srtp_policy_t policy; + memset(&policy, 0, sizeof(policy)); + srtp_crypto_policy_set_rtp_default(&policy.rtp); + srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; + policy.next = NULL; + policy.ssrc.type = ssrc_any_outbound; + policy.key = test_key; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ekt = NULL; - policy.window_size = 128; - policy.allow_repeat_tx = 0; - policy.next = NULL; - policy.ssrc.type = ssrc_any_outbound; - policy.key = test_key; + /* create a send and recive ctx with defualt profile and test_key */ + status = srtp_create(&srtp_recv, &policy); + if (status) + return status; - /* create a send and recive ctx with defualt profile and test_key */ - status = srtp_create(&srtp_recv, &policy); - if (status) - return status; + policy.ssrc.type = ssrc_any_inbound; + status = srtp_create(&srtp_snd, &policy); + if (status) + return status; - policy.ssrc.type = ssrc_any_inbound; - status = srtp_create(&srtp_snd, &policy); - if (status) - return status; + /* protect and unprotect two msg's that will cause the ROC to be equal to 1 + */ + msg = srtp_create_test_packet(msg_len_octets, ssrc, + &protected_msg_len_octets); + if (msg == NULL) + return srtp_err_status_alloc_fail; + msg->seq = htons(65535); - /* protect and unprotect two msg's that will cause the ROC to be equal to 1 */ - msg = srtp_create_test_packet(msg_len_octets, ssrc); - if (msg == NULL) - return srtp_err_status_alloc_fail; - msg->seq = htons(65535); + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); + if (status) + return srtp_err_status_fail; - protected_msg_len_octets = msg_len_octets; - status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); - if (status) - return srtp_err_status_fail; + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); + if (status) + return status; - status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); - if (status) - return status; + free(msg); - free(msg); + msg = srtp_create_test_packet(msg_len_octets, ssrc, + &protected_msg_len_octets); + if (msg == NULL) + return srtp_err_status_alloc_fail; + msg->seq = htons(1); - msg = srtp_create_test_packet(msg_len_octets, ssrc); - if (msg == NULL) - return srtp_err_status_alloc_fail; - msg->seq = htons(1); + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); + if (status) + return srtp_err_status_fail; - protected_msg_len_octets = msg_len_octets; - status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); - if (status) - return srtp_err_status_fail; + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); + if (status) + return status; - status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); - if (status) - return status; + free(msg); - free(msg); + /* update send ctx with same test_key t verify update works*/ + policy.ssrc.type = ssrc_any_outbound; + policy.key = test_key; + status = srtp_update(srtp_snd, &policy); + if (status) + return status; - /* update send ctx with same test_key t verify update works*/ - policy.ssrc.type = ssrc_any_outbound; - policy.key = test_key; - status = srtp_update(srtp_snd, &policy); - if (status) - return status; + msg = srtp_create_test_packet(msg_len_octets, ssrc, + &protected_msg_len_octets); + if (msg == NULL) + return srtp_err_status_alloc_fail; + msg->seq = htons(2); - msg = srtp_create_test_packet(msg_len_octets, ssrc); - if (msg == NULL) - return srtp_err_status_alloc_fail; - msg->seq = htons(2); + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); + if (status) + return srtp_err_status_fail; - protected_msg_len_octets = msg_len_octets; - status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); - if (status) - return srtp_err_status_fail; + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); + if (status) + return status; - status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); - if (status) - return status; + free(msg); - free(msg); - - - /* update send ctx to use test_alt_key */ - policy.ssrc.type = ssrc_any_outbound; - policy.key = test_alt_key; - status = srtp_update(srtp_snd, &policy); - if (status) - return status; - - /* create and protect msg with new key and ROC still equal to 1 */ - msg = srtp_create_test_packet(msg_len_octets, ssrc); - if (msg == NULL) - return srtp_err_status_alloc_fail; - msg->seq = htons(3); - - protected_msg_len_octets = msg_len_octets; - status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); - if (status) - return srtp_err_status_fail; - - /* verify that recive ctx will fail to unprotect as it still uses test_key */ - status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); - if (status == srtp_err_status_ok) - return srtp_err_status_fail; - - /* create a new recvieve ctx with test_alt_key but since it is new it will have ROC equal to 1 - * and therefore should fail to unprotected */ - { - srtp_t srtp_recv_roc_0; - - policy.ssrc.type = ssrc_any_inbound; + /* update send ctx to use test_alt_key */ + policy.ssrc.type = ssrc_any_outbound; policy.key = test_alt_key; - status = srtp_create(&srtp_recv_roc_0, &policy); + status = srtp_update(srtp_snd, &policy); if (status) - return status; + return status; - status = srtp_unprotect(srtp_recv_roc_0, msg, &protected_msg_len_octets); + /* create and protect msg with new key and ROC still equal to 1 */ + msg = srtp_create_test_packet(msg_len_octets, ssrc, + &protected_msg_len_octets); + if (msg == NULL) + return srtp_err_status_alloc_fail; + msg->seq = htons(3); + + status = srtp_protect(srtp_snd, msg, &protected_msg_len_octets); + if (status) + return srtp_err_status_fail; + + /* verify that recive ctx will fail to unprotect as it still uses test_key + */ + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); if (status == srtp_err_status_ok) - return srtp_err_status_fail; + return srtp_err_status_fail; - status = srtp_dealloc(srtp_recv_roc_0); + /* create a new recvieve ctx with test_alt_key but since it is new it will + * have ROC equal to 1 + * and therefore should fail to unprotected */ + { + srtp_t srtp_recv_roc_0; + + policy.ssrc.type = ssrc_any_inbound; + policy.key = test_alt_key; + status = srtp_create(&srtp_recv_roc_0, &policy); + if (status) + return status; + + status = + srtp_unprotect(srtp_recv_roc_0, msg, &protected_msg_len_octets); + if (status == srtp_err_status_ok) + return srtp_err_status_fail; + + status = srtp_dealloc(srtp_recv_roc_0); + if (status) + return status; + } + + /* update recive ctx to use test_alt_key */ + policy.ssrc.type = ssrc_any_inbound; + policy.key = test_alt_key; + status = srtp_update(srtp_recv, &policy); if (status) - return status; - } + return status; - /* update recive ctx to use test_alt_key */ - policy.ssrc.type = ssrc_any_inbound; - policy.key = test_alt_key; - status = srtp_update(srtp_recv, &policy); - if (status) - return status; + /* verify that can still unprotect, therfore key is updated and ROC value is + * preserved */ + status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); + if (status) + return status; - /* verify that can still unprotect, therfore key is updated and ROC value is preserved */ - status = srtp_unprotect(srtp_recv, msg, &protected_msg_len_octets); - if (status) - return status; + free(msg); - free(msg); + status = srtp_dealloc(srtp_snd); + if (status) + return status; - status = srtp_dealloc(srtp_snd); - if (status) - return status; + status = srtp_dealloc(srtp_recv); + if (status) + return status; - status = srtp_dealloc(srtp_recv); - if (status) - return status; - - return srtp_err_status_ok; + return srtp_err_status_ok; } -srtp_err_status_t -srtp_test_setup_protect_trailer_streams(srtp_t *srtp_send, srtp_t *srtp_send_mki, - srtp_t *srtp_send_aes_gcm, srtp_t *srtp_send_aes_gcm_mki) { +srtp_err_status_t srtp_test_setup_protect_trailer_streams( + srtp_t *srtp_send, + srtp_t *srtp_send_mki, + srtp_t *srtp_send_aes_gcm, + srtp_t *srtp_send_aes_gcm_mki) +{ + srtp_err_status_t status; + srtp_policy_t policy; + srtp_policy_t policy_mki; - srtp_err_status_t status; - srtp_policy_t policy; - srtp_policy_t policy_mki; #ifdef OPENSSL - srtp_policy_t policy_aes_gcm; - srtp_policy_t policy_aes_gcm_mki; + srtp_policy_t policy_aes_gcm; + srtp_policy_t policy_aes_gcm_mki; #endif // OPENSSL - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ekt = NULL; - policy.window_size = 128; - policy.allow_repeat_tx = 0; - policy.next = NULL; - policy.ssrc.type = ssrc_any_outbound; - policy.key = test_key; + memset(&policy, 0, sizeof(policy)); + srtp_crypto_policy_set_rtp_default(&policy.rtp); + srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; + policy.next = NULL; + policy.ssrc.type = ssrc_any_outbound; + policy.key = test_key; - memset(&policy_mki, 0, sizeof(policy_mki)); - srtp_crypto_policy_set_rtp_default(&policy_mki.rtp); - srtp_crypto_policy_set_rtcp_default(&policy_mki.rtcp); - policy_mki.ekt = NULL; - policy_mki.window_size = 128; - policy_mki.allow_repeat_tx = 0; - policy_mki.next = NULL; - policy_mki.ssrc.type = ssrc_any_outbound; - policy_mki.key = NULL; - policy_mki.keys = test_keys; - policy_mki.num_master_keys = 2; + memset(&policy_mki, 0, sizeof(policy_mki)); + srtp_crypto_policy_set_rtp_default(&policy_mki.rtp); + srtp_crypto_policy_set_rtcp_default(&policy_mki.rtcp); + policy_mki.ekt = NULL; + policy_mki.window_size = 128; + policy_mki.allow_repeat_tx = 0; + policy_mki.next = NULL; + policy_mki.ssrc.type = ssrc_any_outbound; + policy_mki.key = NULL; + policy_mki.keys = test_keys; + policy_mki.num_master_keys = 2; #ifdef OPENSSL - memset(&policy_aes_gcm, 0, sizeof(policy_aes_gcm)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp); - policy_aes_gcm.ekt = NULL; - policy_aes_gcm.window_size = 128; - policy_aes_gcm.allow_repeat_tx = 0; - policy_aes_gcm.next = NULL; - policy_aes_gcm.ssrc.type = ssrc_any_outbound; - policy_aes_gcm.key = test_key; - - memset(&policy_aes_gcm_mki, 0, sizeof(policy_aes_gcm_mki)); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtp); - srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtcp); - policy_aes_gcm_mki.ekt = NULL; - policy_aes_gcm_mki.window_size = 128; - policy_aes_gcm_mki.allow_repeat_tx = 0; - policy_aes_gcm_mki.next = NULL; - policy_aes_gcm_mki.ssrc.type = ssrc_any_outbound; - policy_aes_gcm_mki.key = NULL; - policy_aes_gcm_mki.keys = test_keys; - policy_aes_gcm_mki.num_master_keys = 2; + memset(&policy_aes_gcm, 0, sizeof(policy_aes_gcm)); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp); + policy_aes_gcm.ekt = NULL; + policy_aes_gcm.window_size = 128; + policy_aes_gcm.allow_repeat_tx = 0; + policy_aes_gcm.next = NULL; + policy_aes_gcm.ssrc.type = ssrc_any_outbound; + policy_aes_gcm.key = test_key; + memset(&policy_aes_gcm_mki, 0, sizeof(policy_aes_gcm_mki)); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtcp); + policy_aes_gcm_mki.ekt = NULL; + policy_aes_gcm_mki.window_size = 128; + policy_aes_gcm_mki.allow_repeat_tx = 0; + policy_aes_gcm_mki.next = NULL; + policy_aes_gcm_mki.ssrc.type = ssrc_any_outbound; + policy_aes_gcm_mki.key = NULL; + policy_aes_gcm_mki.keys = test_keys; + policy_aes_gcm_mki.num_master_keys = 2; #endif - /* create a send ctx with defualt profile and test_key */ - status = srtp_create(srtp_send, &policy); - if (status) - return status; + /* create a send ctx with defualt profile and test_key */ + status = srtp_create(srtp_send, &policy); + if (status) + return status; - status = srtp_create(srtp_send_mki, &policy_mki); - if (status) - return status; + status = srtp_create(srtp_send_mki, &policy_mki); + if (status) + return status; #ifdef OPENSSL - status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm); - if (status) - return status; + status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm); + if (status) + return status; - status = srtp_create(srtp_send_aes_gcm_mki, &policy_aes_gcm_mki); - if (status) - return status; -#endif //OPENSSL + status = srtp_create(srtp_send_aes_gcm_mki, &policy_aes_gcm_mki); + if (status) + return status; +#endif // OPENSSL - return srtp_err_status_ok; + return srtp_err_status_ok; } -srtp_err_status_t -srtp_test_protect_trailer_length() { +srtp_err_status_t srtp_test_protect_trailer_length() +{ + srtp_t srtp_send; + srtp_t srtp_send_mki; + srtp_t srtp_send_aes_gcm; + srtp_t srtp_send_aes_gcm_mki; + uint32_t length = 0; + srtp_err_status_t status; - srtp_t srtp_send; - srtp_t srtp_send_mki; - srtp_t srtp_send_aes_gcm; - srtp_t srtp_send_aes_gcm_mki; - uint32_t length = 0; - srtp_err_status_t status; + srtp_test_setup_protect_trailer_streams( + &srtp_send, &srtp_send_mki, &srtp_send_aes_gcm, &srtp_send_aes_gcm_mki); - srtp_test_setup_protect_trailer_streams(&srtp_send, &srtp_send_mki, - &srtp_send_aes_gcm, &srtp_send_aes_gcm_mki); + status = srtp_get_protect_trailer_length(srtp_send, 0, 0, &length); + if (status) + return status; - status = srtp_get_protect_trailer_length(srtp_send, 0, 0, &length); - if (status) - return status; + /* TAG Length: 10 bytes */ + if (length != 10) + return srtp_err_status_fail; - /* TAG Length: 10 bytes */ - if (length != 10) - return srtp_err_status_fail; + status = srtp_get_protect_trailer_length(srtp_send_mki, 1, 1, &length); + if (status) + return status; - status = srtp_get_protect_trailer_length(srtp_send_mki, 1, 1, &length); - if (status) - return status; - - /* TAG Length: 10 bytes + MKI length: 4 bytes*/ - if (length != 14) - return srtp_err_status_fail; + /* TAG Length: 10 bytes + MKI length: 4 bytes*/ + if (length != 14) + return srtp_err_status_fail; #ifdef OPENSSL - status = srtp_get_protect_trailer_length(srtp_send_aes_gcm, 0, 0, &length); - if (status) - return status; + status = srtp_get_protect_trailer_length(srtp_send_aes_gcm, 0, 0, &length); + if (status) + return status; - /* TAG Length: 16 bytes */ - if (length != 16) - return srtp_err_status_fail; + /* TAG Length: 16 bytes */ + if (length != 16) + return srtp_err_status_fail; + status = + srtp_get_protect_trailer_length(srtp_send_aes_gcm_mki, 1, 1, &length); + if (status) + return status; - status = srtp_get_protect_trailer_length(srtp_send_aes_gcm_mki, 1, 1, &length); - if (status) - return status; + /* TAG Length: 16 bytes + MKI length: 4 bytes*/ + if (length != 20) + return srtp_err_status_fail; +#endif // OPENSSL - /* TAG Length: 16 bytes + MKI length: 4 bytes*/ - if (length != 20) - return srtp_err_status_fail; + srtp_dealloc(srtp_send); + srtp_dealloc(srtp_send_mki); +#ifdef OPENSSL + srtp_dealloc(srtp_send_aes_gcm); + srtp_dealloc(srtp_send_aes_gcm_mki); +#endif -#endif //OPENSSL - return srtp_err_status_ok; + return srtp_err_status_ok; } -srtp_err_status_t -srtp_test_protect_rtcp_trailer_length() { +srtp_err_status_t srtp_test_protect_rtcp_trailer_length() +{ + srtp_t srtp_send; + srtp_t srtp_send_mki; + srtp_t srtp_send_aes_gcm; + srtp_t srtp_send_aes_gcm_mki; + uint32_t length = 0; + srtp_err_status_t status; - srtp_t srtp_send; - srtp_t srtp_send_mki; - srtp_t srtp_send_aes_gcm; - srtp_t srtp_send_aes_gcm_mki; - uint32_t length = 0; - srtp_err_status_t status; + srtp_test_setup_protect_trailer_streams( + &srtp_send, &srtp_send_mki, &srtp_send_aes_gcm, &srtp_send_aes_gcm_mki); - srtp_test_setup_protect_trailer_streams(&srtp_send, &srtp_send_mki, - &srtp_send_aes_gcm, &srtp_send_aes_gcm_mki); + status = srtp_get_protect_rtcp_trailer_length(srtp_send, 0, 0, &length); + if (status) + return status; - status = srtp_get_protect_rtcp_trailer_length(srtp_send, 0, 0, &length); - if (status) - return status; + /* TAG Length: 10 bytes + SRTCP Trailer 4 bytes*/ + if (length != 14) + return srtp_err_status_fail; - /* TAG Length: 10 bytes + SRTCP Trailer 4 bytes*/ - if (length != 14) - return srtp_err_status_fail; + status = srtp_get_protect_rtcp_trailer_length(srtp_send_mki, 1, 1, &length); + if (status) + return status; - status = srtp_get_protect_rtcp_trailer_length(srtp_send_mki, 1, 1, &length); - if (status) - return status; - - /* TAG Length: 10 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ - if (length != 18) - return srtp_err_status_fail; + /* TAG Length: 10 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ + if (length != 18) + return srtp_err_status_fail; #ifdef OPENSSL - status = srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm, 0, 0, &length); - if (status) - return status; + status = + srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm, 0, 0, &length); + if (status) + return status; - /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes*/ - if (length != 20) - return srtp_err_status_fail; + /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes*/ + if (length != 20) + return srtp_err_status_fail; + status = srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm_mki, 1, 1, + &length); + if (status) + return status; - status = srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm_mki, 1, 1, &length); - if (status) - return status; + /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ + if (length != 24) + return srtp_err_status_fail; +#endif // OPENSSL - /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ - if (length != 24) - return srtp_err_status_fail; + srtp_dealloc(srtp_send); + srtp_dealloc(srtp_send_mki); +#ifdef OPENSSL + srtp_dealloc(srtp_send_aes_gcm); + srtp_dealloc(srtp_send_aes_gcm_mki); +#endif -#endif //OPENSSL - return srtp_err_status_ok; + return srtp_err_status_ok; } -srtp_err_status_t -srtp_test_get_roc() { - srtp_err_status_t status; - srtp_policy_t policy; - srtp_t session; - srtp_hdr_t *pkt; - uint32_t i; - uint32_t roc; - uint32_t ts; - uint16_t seq; +srtp_err_status_t srtp_test_get_roc() +{ + srtp_err_status_t status; + srtp_policy_t policy; + srtp_t session; + srtp_hdr_t *pkt; + uint32_t i; + uint32_t roc; + uint32_t ts; + uint16_t seq; - int msg_len_octets = 32; - int protected_msg_len_octets; + int msg_len_octets = 32; + int protected_msg_len_octets; - memset(&policy, 0, sizeof(policy)); - srtp_crypto_policy_set_rtp_default(&policy.rtp); - srtp_crypto_policy_set_rtcp_default(&policy.rtcp); - policy.ssrc.type = ssrc_specific; - policy.ssrc.value = 0xcafebabe; - policy.key = test_key; - policy.window_size = 128; + memset(&policy, 0, sizeof(policy)); + srtp_crypto_policy_set_rtp_default(&policy.rtp); + srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + policy.ssrc.type = ssrc_specific; + policy.ssrc.value = 0xcafebabe; + policy.key = test_key; + policy.window_size = 128; - /* Create a sender session */ - status = srtp_create(&session, &policy); - if (status) { - return status; - } + /* Create a sender session */ + status = srtp_create(&session, &policy); + if (status) { + return status; + } - /* Set start sequence so we roll over */ - seq = 65535; - ts = 0; + /* Set start sequence so we roll over */ + seq = 65535; + ts = 0; + + for (i = 0; i < 2; i++) { + pkt = srtp_create_test_packet_extended(msg_len_octets, + policy.ssrc.value, seq, ts, + &protected_msg_len_octets); + status = srtp_protect(session, pkt, &protected_msg_len_octets); + free(pkt); + if (status) { + return status; + } + + status = srtp_get_stream_roc(session, policy.ssrc.value, &roc); + if (status) { + return status; + } + + if (roc != i) { + return srtp_err_status_fail; + } + + seq++; + ts++; + } + + /* Cleanup */ + status = srtp_dealloc(session); + if (status) { + return status; + } + + return srtp_err_status_ok; +} + +static srtp_err_status_t test_set_receiver_roc(uint32_t packets, + uint32_t roc_to_set) +{ + srtp_err_status_t status; + + srtp_policy_t sender_policy; + srtp_t sender_session; + + srtp_policy_t receiver_policy; + srtp_t receiver_session; + + srtp_hdr_t *pkt_1; + unsigned char *recv_pkt_1; + + srtp_hdr_t *pkt_2; + unsigned char *recv_pkt_2; + + uint32_t i; + uint32_t ts; + uint16_t seq; + + int msg_len_octets = 32; + int protected_msg_len_octets_1; + int protected_msg_len_octets_2; + + /* Create sender */ + memset(&sender_policy, 0, sizeof(sender_policy)); + srtp_crypto_policy_set_rtp_default(&sender_policy.rtp); + srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp); + sender_policy.ssrc.type = ssrc_specific; + sender_policy.ssrc.value = 0xcafebabe; + sender_policy.key = test_key; + sender_policy.window_size = 128; + + status = srtp_create(&sender_session, &sender_policy); + if (status) { + return status; + } + + /* Create and protect packets */ + seq = 0; + ts = 0; + for (i = 0; i < packets; i++) { + srtp_hdr_t *tmp_pkt; + int tmp_len; + + tmp_pkt = srtp_create_test_packet_extended( + msg_len_octets, sender_policy.ssrc.value, seq, ts, &tmp_len); + status = srtp_protect(sender_session, tmp_pkt, &tmp_len); + free(tmp_pkt); + if (status) { + return status; + } + seq++; + ts++; + } + + /* Create the first packet to decrypt and test for ROC change */ + pkt_1 = srtp_create_test_packet_extended(msg_len_octets, + sender_policy.ssrc.value, seq, ts, + &protected_msg_len_octets_1); + status = srtp_protect(sender_session, pkt_1, &protected_msg_len_octets_1); + if (status) { + return status; + } + + /* Create the second packet to decrypt and test for ROC change */ + seq++; + ts++; + pkt_2 = srtp_create_test_packet_extended(msg_len_octets, + sender_policy.ssrc.value, seq, ts, + &protected_msg_len_octets_2); + status = srtp_protect(sender_session, pkt_2, &protected_msg_len_octets_2); + if (status) { + return status; + } + + /* Create the receiver */ + memset(&receiver_policy, 0, sizeof(receiver_policy)); + srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp); + srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp); + receiver_policy.ssrc.type = ssrc_specific; + receiver_policy.ssrc.value = sender_policy.ssrc.value; + receiver_policy.key = test_key; + receiver_policy.window_size = 128; + + status = srtp_create(&receiver_session, &receiver_policy); + if (status) { + return status; + } + + /* Make a copy of the first sent protected packet */ + recv_pkt_1 = malloc(protected_msg_len_octets_1); + if (recv_pkt_1 == NULL) { + return srtp_err_status_fail; + } + memcpy(recv_pkt_1, pkt_1, protected_msg_len_octets_1); + + /* Make a copy of the second sent protected packet */ + recv_pkt_2 = malloc(protected_msg_len_octets_2); + if (recv_pkt_2 == NULL) { + return srtp_err_status_fail; + } + memcpy(recv_pkt_2, pkt_2, protected_msg_len_octets_2); + + /* Set the ROC to the wanted value */ + status = srtp_set_stream_roc(receiver_session, receiver_policy.ssrc.value, + roc_to_set); + if (status) { + return status; + } + + /* Unprotect the first packet */ + status = srtp_unprotect(receiver_session, recv_pkt_1, + &protected_msg_len_octets_1); + if (status) { + return status; + } + + /* Unprotect the second packet */ + status = srtp_unprotect(receiver_session, recv_pkt_2, + &protected_msg_len_octets_2); + if (status) { + return status; + } + + /* Cleanup */ + status = srtp_dealloc(sender_session); + if (status) { + return status; + } + + status = srtp_dealloc(receiver_session); + if (status) { + return status; + } + + free(pkt_1); + free(recv_pkt_1); + free(pkt_2); + free(recv_pkt_2); + + return srtp_err_status_ok; +} + +static srtp_err_status_t test_set_sender_roc(uint16_t seq, uint32_t roc_to_set) +{ + srtp_err_status_t status; + + srtp_policy_t sender_policy; + srtp_t sender_session; + + srtp_policy_t receiver_policy; + srtp_t receiver_session; + + srtp_hdr_t *pkt; + unsigned char *recv_pkt; + + uint32_t ts; + + int msg_len_octets = 32; + int protected_msg_len_octets; + + /* Create sender */ + memset(&sender_policy, 0, sizeof(sender_policy)); + srtp_crypto_policy_set_rtp_default(&sender_policy.rtp); + srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp); + sender_policy.ssrc.type = ssrc_specific; + sender_policy.ssrc.value = 0xcafebabe; + sender_policy.key = test_key; + sender_policy.window_size = 128; + + status = srtp_create(&sender_session, &sender_policy); + if (status) { + return status; + } + + /* Set the ROC before encrypting the first packet */ + status = srtp_set_stream_roc(sender_session, sender_policy.ssrc.value, + roc_to_set); + if (status != srtp_err_status_ok) { + return status; + } + + /* Create the packet to decrypt */ + ts = 0; + pkt = srtp_create_test_packet_extended(msg_len_octets, + sender_policy.ssrc.value, seq, ts, + &protected_msg_len_octets); + status = srtp_protect(sender_session, pkt, &protected_msg_len_octets); + if (status) { + return status; + } + + /* Create the receiver */ + memset(&receiver_policy, 0, sizeof(receiver_policy)); + srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp); + srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp); + receiver_policy.ssrc.type = ssrc_specific; + receiver_policy.ssrc.value = sender_policy.ssrc.value; + receiver_policy.key = test_key; + receiver_policy.window_size = 128; + + status = srtp_create(&receiver_session, &receiver_policy); + if (status) { + return status; + } + + /* Make a copy of the sent protected packet */ + recv_pkt = malloc(protected_msg_len_octets); + if (recv_pkt == NULL) { + return srtp_err_status_fail; + } + memcpy(recv_pkt, pkt, protected_msg_len_octets); + + /* Set the ROC to the wanted value */ + status = srtp_set_stream_roc(receiver_session, receiver_policy.ssrc.value, + roc_to_set); + if (status) { + return status; + } + + status = + srtp_unprotect(receiver_session, recv_pkt, &protected_msg_len_octets); + if (status) { + return status; + } + + /* Cleanup */ + status = srtp_dealloc(sender_session); + if (status) { + return status; + } + + status = srtp_dealloc(receiver_session); + if (status) { + return status; + } - for (i = 0; i < 2; i++) { - pkt = srtp_create_test_packet_extended(msg_len_octets, policy.ssrc.value, seq, ts); - protected_msg_len_octets = msg_len_octets; - status = srtp_protect(session, pkt, &protected_msg_len_octets); free(pkt); - if (status) { - return status; - } + free(recv_pkt); - status = srtp_get_stream_roc(session, policy.ssrc.value, &roc); - if (status) { - return status; - } - - if (roc != i) { - return srtp_err_status_fail; - } - - seq++; - ts++; - } - - /* Cleanup */ - status = srtp_dealloc(session); - if (status) { - return status; - } - - return srtp_err_status_ok; + return srtp_err_status_ok; } -static srtp_err_status_t -test_set_receiver_roc(uint32_t packets, uint32_t roc_to_set) +srtp_err_status_t srtp_test_set_receiver_roc() { - srtp_err_status_t status; + int packets; + uint32_t roc; + srtp_err_status_t status; - srtp_policy_t sender_policy; - srtp_t sender_session; + /* First test does not rollover */ + packets = 1; + roc = 0; - srtp_policy_t receiver_policy; - srtp_t receiver_session; - - srtp_hdr_t *pkt_1; - unsigned char *recv_pkt_1; - - srtp_hdr_t *pkt_2; - unsigned char *recv_pkt_2; - - uint32_t i; - uint32_t ts; - uint16_t seq; - - int msg_len_octets = 32; - int protected_msg_len_octets_1; - int protected_msg_len_octets_2; - - /* Create sender */ - memset(&sender_policy, 0, sizeof(sender_policy)); - srtp_crypto_policy_set_rtp_default(&sender_policy.rtp); - srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp); - sender_policy.ssrc.type = ssrc_specific; - sender_policy.ssrc.value = 0xcafebabe; - sender_policy.key = test_key; - sender_policy.window_size = 128; - - status = srtp_create(&sender_session, &sender_policy); - if (status) { - return status; - } - - /* Create and protect packets */ - seq = 0; - ts = 0; - for (i = 0; i < packets; i++) { - srtp_hdr_t *tmp_pkt; - int tmp_len; - - tmp_pkt = srtp_create_test_packet_extended(msg_len_octets, sender_policy.ssrc.value, seq, ts); - tmp_len = msg_len_octets; - status = srtp_protect(sender_session, tmp_pkt, &tmp_len); - free(tmp_pkt); + status = test_set_receiver_roc(packets - 1, roc); if (status) { - return status; + return status; } - seq++; - ts++; - } - /* Create the first packet to decrypt and test for ROC change */ - pkt_1 = srtp_create_test_packet_extended(msg_len_octets, sender_policy.ssrc.value, seq, ts); - protected_msg_len_octets_1 = msg_len_octets; - status = srtp_protect(sender_session, pkt_1, &protected_msg_len_octets_1); - if (status) { - return status; - } + status = test_set_receiver_roc(packets, roc); + if (status) { + return status; + } - /* Create the second packet to decrypt and test for ROC change */ - seq++; - ts++; - pkt_2 = srtp_create_test_packet_extended(msg_len_octets, sender_policy.ssrc.value, seq, ts); - protected_msg_len_octets_2 = msg_len_octets; - status = srtp_protect(sender_session, pkt_2, &protected_msg_len_octets_2); - if (status) { - return status; - } + status = test_set_receiver_roc(packets + 1, roc); + if (status) { + return status; + } - /* Create the receiver */ - memset(&receiver_policy, 0, sizeof(receiver_policy)); - srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp); - srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp); - receiver_policy.ssrc.type = ssrc_specific; - receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.key = test_key; - receiver_policy.window_size = 128; + status = test_set_receiver_roc(packets + 60000, roc); + if (status) { + return status; + } - status = srtp_create(&receiver_session, &receiver_policy); - if (status) { - return status; - } + /* Second test should rollover */ + packets = 65535; + roc = 0; - /* Make a copy of the first sent protected packet */ - recv_pkt_1 = malloc(protected_msg_len_octets_1); - if (recv_pkt_1 == NULL) { - return srtp_err_status_fail; - } - memcpy(recv_pkt_1, pkt_1, protected_msg_len_octets_1); + status = test_set_receiver_roc(packets - 1, roc); + if (status) { + return status; + } - /* Make a copy of the second sent protected packet */ - recv_pkt_2 = malloc(protected_msg_len_octets_2); - if (recv_pkt_2 == NULL) { - return srtp_err_status_fail; - } - memcpy(recv_pkt_2, pkt_2, protected_msg_len_octets_2); + status = test_set_receiver_roc(packets, roc); + if (status) { + return status; + } - /* Set the ROC to the wanted value */ - status = srtp_set_stream_roc(receiver_session, receiver_policy.ssrc.value, roc_to_set); - if (status) { - return status; - } + /* Now the rollover counter should be 1 */ + roc = 1; + status = test_set_receiver_roc(packets + 1, roc); + if (status) { + return status; + } - /* Unprotect the first packet */ - status = srtp_unprotect(receiver_session, recv_pkt_1, &protected_msg_len_octets_1); - if (status) { - return status; - } + status = test_set_receiver_roc(packets + 60000, roc); + if (status) { + return status; + } - /* Unprotect the second packet */ - status = srtp_unprotect(receiver_session, recv_pkt_2, &protected_msg_len_octets_2); - if (status) { - return status; - } - - /* Cleanup */ - status = srtp_dealloc(sender_session); - if (status) { - return status; - } - - status = srtp_dealloc(receiver_session); - if (status) { - return status; - } - - free(pkt_1); - free(recv_pkt_1); - free(pkt_2); - free(recv_pkt_2); - - return srtp_err_status_ok; + return srtp_err_status_ok; } -static srtp_err_status_t -test_set_sender_roc(uint16_t seq, uint32_t roc_to_set) +srtp_err_status_t srtp_test_set_sender_roc() { - srtp_err_status_t status; + uint32_t roc; + uint16_t seq; + srtp_err_status_t status; - srtp_policy_t sender_policy; - srtp_t sender_session; + seq = 43210; + roc = 0; + status = test_set_sender_roc(seq, roc); + if (status) { + return status; + } - srtp_policy_t receiver_policy; - srtp_t receiver_session; + roc = 65535; + status = test_set_sender_roc(seq, roc); + if (status) { + return status; + } - srtp_hdr_t *pkt; - unsigned char *recv_pkt; + roc = 0xffff; + status = test_set_sender_roc(seq, roc); + if (status) { + return status; + } - uint32_t ts; + roc = 0xffff00; + status = test_set_sender_roc(seq, roc); + if (status) { + return status; + } - int msg_len_octets = 32; - int protected_msg_len_octets; + roc = 0xfffffff0; + status = test_set_sender_roc(seq, roc); + if (status) { + return status; + } - /* Create sender */ - memset(&sender_policy, 0, sizeof(sender_policy)); - srtp_crypto_policy_set_rtp_default(&sender_policy.rtp); - srtp_crypto_policy_set_rtcp_default(&sender_policy.rtcp); - sender_policy.ssrc.type = ssrc_specific; - sender_policy.ssrc.value = 0xcafebabe; - sender_policy.key = test_key; - sender_policy.window_size = 128; - - status = srtp_create(&sender_session, &sender_policy); - if (status) { - return status; - } - - /* Set the ROC before encrypting the first packet */ - status = srtp_set_stream_roc(sender_session, sender_policy.ssrc.value, roc_to_set); - if (status != srtp_err_status_ok) { - return status; - } - - /* Create the packet to decrypt */ - ts = 0; - pkt = srtp_create_test_packet_extended(msg_len_octets, sender_policy.ssrc.value, seq, ts); - protected_msg_len_octets = msg_len_octets; - status = srtp_protect(sender_session, pkt, &protected_msg_len_octets); - if (status) { - return status; - } - - /* Create the receiver */ - memset(&receiver_policy, 0, sizeof(receiver_policy)); - srtp_crypto_policy_set_rtp_default(&receiver_policy.rtp); - srtp_crypto_policy_set_rtcp_default(&receiver_policy.rtcp); - receiver_policy.ssrc.type = ssrc_specific; - receiver_policy.ssrc.value = sender_policy.ssrc.value; - receiver_policy.key = test_key; - receiver_policy.window_size = 128; - - status = srtp_create(&receiver_session, &receiver_policy); - if (status) { - return status; - } - - /* Make a copy of the sent protected packet */ - recv_pkt = malloc(protected_msg_len_octets); - if (recv_pkt == NULL) { - return srtp_err_status_fail; - } - memcpy(recv_pkt, pkt, protected_msg_len_octets); - - /* Set the ROC to the wanted value */ - status = srtp_set_stream_roc(receiver_session, receiver_policy.ssrc.value, roc_to_set); - if (status) { - return status; - } - - status = srtp_unprotect(receiver_session, recv_pkt, &protected_msg_len_octets); - if (status) { - return status; - } - - /* Cleanup */ - status = srtp_dealloc(sender_session); - if (status) { - return status; - } - - status = srtp_dealloc(receiver_session); - if (status) { - return status; - } - - free(pkt); - free(recv_pkt); - - return srtp_err_status_ok; -} - -srtp_err_status_t -srtp_test_set_receiver_roc() { - int packets; - uint32_t roc; - srtp_err_status_t status; - - /* First test does not rollover */ - packets = 1; - roc = 0; - - status = test_set_receiver_roc(packets - 1, roc); - if (status) { - return status; - } - - status = test_set_receiver_roc(packets, roc); - if (status) { - return status; - } - - status = test_set_receiver_roc(packets + 1, roc); - if (status) { - return status; - } - - status = test_set_receiver_roc(packets + 60000, roc); - if (status) { - return status; - } - - /* Second test should rollover */ - packets = 65535; - roc = 0; - - status = test_set_receiver_roc(packets - 1, roc); - if (status) { - return status; - } - - status = test_set_receiver_roc(packets, roc); - if (status) { - return status; - } - - /* Now the rollover counter should be 1 */ - roc = 1; - status = test_set_receiver_roc(packets + 1, roc); - if (status) { - return status; - } - - status = test_set_receiver_roc(packets + 60000, roc); - if (status) { - return status; - } - - return srtp_err_status_ok; -} - -srtp_err_status_t -srtp_test_set_sender_roc() { - uint32_t roc; - uint16_t seq; - srtp_err_status_t status; - - seq = 43210; - roc = 0; - status = test_set_sender_roc(seq, roc); - if (status) { - return status; - } - - roc = 65535; - status = test_set_sender_roc(seq, roc); - if (status) { - return status; - } - - roc = 0xffff; - status = test_set_sender_roc(seq, roc); - if (status) { - return status; - } - - roc = 0xffff00; - status = test_set_sender_roc(seq, roc); - if (status) { - return status; - } - - roc = 0xfffffff0; - status = test_set_sender_roc(seq, roc); - if (status) { - return status; - } - - return srtp_err_status_ok; + return srtp_err_status_ok; } /* * srtp policy definitions - these definitions are used above */ +// clang-format off unsigned char test_key[46] = { 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, @@ -3431,241 +3409,253 @@ unsigned char test_mki_id[TEST_MKI_ID_SIZE] = { unsigned char test_mki_id_2[TEST_MKI_ID_SIZE] = { 0xf3, 0xa1, 0x46, 0x71 }; +// clang-format on const srtp_policy_t default_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { /* SRTP policy */ - SRTP_AES_ICM_128, /* cipher type */ + { ssrc_any_outbound, 0 }, /* SSRC */ + { + /* SRTP policy */ + SRTP_AES_ICM_128, /* cipher type */ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ + SRTP_HMAC_SHA1, /* authentication func type */ + 16, /* auth key length in octets */ + 10, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ }, - { /* SRTCP policy */ - SRTP_AES_ICM_128, /* cipher type */ + { + /* SRTCP policy */ + SRTP_AES_ICM_128, /* cipher type */ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ + SRTP_HMAC_SHA1, /* authentication func type */ + 16, /* auth key length in octets */ + 10, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; const srtp_policy_t aes_only_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { - SRTP_AES_ICM_128, /* cipher type */ + SRTP_AES_ICM_128, /* cipher type */ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 0, /* auth tag length in octets */ - sec_serv_conf /* security services flag */ + SRTP_NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 0, /* auth tag length in octets */ + sec_serv_conf /* security services flag */ }, { - SRTP_AES_ICM_128, /* cipher type */ + SRTP_AES_ICM_128, /* cipher type */ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 0, /* auth tag length in octets */ - sec_serv_conf /* security services flag */ + SRTP_NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 0, /* auth tag length in octets */ + sec_serv_conf /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; const srtp_policy_t hmac_only_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ + { ssrc_any_outbound, 0 }, /* SSRC */ { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 4, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ }, { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 4, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* Number of Master keys associated with the policy */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* Number of Master keys associated with the policy */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; #ifdef OPENSSL const srtp_policy_t aes128_gcm_8_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { /* SRTP policy */ - SRTP_AES_GCM_128, /* cipher type */ + { ssrc_any_outbound, 0 }, /* SSRC */ + { + /* SRTP policy */ + SRTP_AES_GCM_128, /* cipher type */ SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { /* SRTCP policy */ - SRTP_AES_GCM_128, /* cipher type */ + { + /* SRTCP policy */ + SRTP_AES_GCM_128, /* cipher type */ SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; const srtp_policy_t aes128_gcm_8_cauth_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { /* SRTP policy */ - SRTP_AES_GCM_128, /* cipher type */ + { ssrc_any_outbound, 0 }, /* SSRC */ + { + /* SRTP policy */ + SRTP_AES_GCM_128, /* cipher type */ SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { /* SRTCP policy */ - SRTP_AES_GCM_128, /* cipher type */ + { + /* SRTCP policy */ + SRTP_AES_GCM_128, /* cipher type */ SRTP_AES_GCM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; const srtp_policy_t aes256_gcm_8_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { /* SRTP policy */ - SRTP_AES_GCM_256, /* cipher type */ + { ssrc_any_outbound, 0 }, /* SSRC */ + { + /* SRTP policy */ + SRTP_AES_GCM_256, /* cipher type */ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { /* SRTCP policy */ - SRTP_AES_GCM_256, /* cipher type */ + { + /* SRTCP policy */ + SRTP_AES_GCM_256, /* cipher type */ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; const srtp_policy_t aes256_gcm_8_cauth_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { /* SRTP policy */ - SRTP_AES_GCM_256, /* cipher type */ + { ssrc_any_outbound, 0 }, /* SSRC */ + { + /* SRTP policy */ + SRTP_AES_GCM_256, /* cipher type */ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { /* SRTCP policy */ - SRTP_AES_GCM_256, /* cipher type */ + { + /* SRTCP policy */ + SRTP_AES_GCM_256, /* cipher type */ SRTP_AES_GCM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ + SRTP_NULL_AUTH, /* authentication func type */ 0, /* auth key length in octets */ 8, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; #endif const srtp_policy_t null_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ + { ssrc_any_outbound, 0 }, /* SSRC */ { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 0, /* auth tag length in octets */ - sec_serv_none /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + SRTP_NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 0, /* auth tag length in octets */ + sec_serv_none /* security services flag */ }, { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_NULL_AUTH, /* authentication func type */ - 0, /* auth key length in octets */ - 0, /* auth tag length in octets */ - sec_serv_none /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + SRTP_NULL_AUTH, /* authentication func type */ + 0, /* auth key length in octets */ + 0, /* auth tag length in octets */ + sec_serv_none /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; +// clang-format off unsigned char test_256_key[46] = { 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76, 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29, @@ -3701,80 +3691,86 @@ srtp_master_key_t *test_256_keys[2] = { &master_key_1, &master_key_2 }; +// clang-format on const srtp_policy_t aes_256_hmac_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { /* SRTP policy */ + { ssrc_any_outbound, 0 }, /* SSRC */ + { + /* SRTP policy */ SRTP_AES_ICM_256, /* cipher type */ SRTP_AES_ICM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 10, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ }, - { /* SRTCP policy */ + { + /* SRTCP policy */ SRTP_AES_ICM_256, /* cipher type */ SRTP_AES_ICM_256_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 10, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_256_keys, - 2, /* indicates the number of Master keys */ - NULL, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + NULL, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; +// clang-format off uint8_t ekt_test_key[16] = { 0x77, 0x26, 0x9d, 0xac, 0x16, 0xa3, 0x28, 0xca, 0x8e, 0xc9, 0x68, 0x4b, 0xcc, 0xc4, 0xd2, 0x1b }; +// clang-format on #include "ekt.h" +// clang-format off srtp_ekt_policy_ctx_t ekt_test_policy = { 0xa5a5, /* SPI */ SRTP_EKT_CIPHER_AES_128_ECB, ekt_test_key, NULL }; +// clang-format on const srtp_policy_t hmac_only_with_ekt_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ + { ssrc_any_outbound, 0 }, /* SSRC */ { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 4, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ }, { - SRTP_NULL_CIPHER, /* cipher type */ - 0, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 20, /* auth key length in octets */ - 4, /* auth tag length in octets */ - sec_serv_auth /* security services flag */ + SRTP_NULL_CIPHER, /* cipher type */ + 0, /* cipher key length in octets */ + SRTP_HMAC_SHA1, /* authentication func type */ + 20, /* auth key length in octets */ + 4, /* auth tag length in octets */ + sec_serv_auth /* security services flag */ }, NULL, (srtp_master_key_t **)test_keys, - 2, /* indicates the number of Master keys */ - &ekt_test_policy, /* indicates that EKT is not in use */ - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 2, /* indicates the number of Master keys */ + &ekt_test_policy, /* indicates that EKT is not in use */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; - /* * an array of pointers to the policies listed above * @@ -3785,8 +3781,8 @@ const srtp_policy_t hmac_only_with_ekt_policy = { * add to this list, you should do it at the end. */ -const srtp_policy_t * -policy_array[] = { +// clang-format off +const srtp_policy_t *policy_array[] = { &hmac_only_policy, &aes_only_policy, &default_policy, @@ -3801,32 +3797,35 @@ policy_array[] = { &hmac_only_with_ekt_policy, NULL }; +// clang-format on const srtp_policy_t wildcard_policy = { - { ssrc_any_outbound, 0 }, /* SSRC */ - { /* SRTP policy */ - SRTP_AES_ICM_128, /* cipher type */ + { ssrc_any_outbound, 0 }, /* SSRC */ + { + /* SRTP policy */ + SRTP_AES_ICM_128, /* cipher type */ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ + SRTP_HMAC_SHA1, /* authentication func type */ + 16, /* auth key length in octets */ + 10, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ }, - { /* SRTCP policy */ - SRTP_AES_ICM_128, /* cipher type */ + { + /* SRTCP policy */ + SRTP_AES_ICM_128, /* cipher type */ SRTP_AES_ICM_128_KEY_LEN_WSALT, /* cipher key length in octets */ - SRTP_HMAC_SHA1, /* authentication func type */ - 16, /* auth key length in octets */ - 10, /* auth tag length in octets */ - sec_serv_conf_and_auth /* security services flag */ + SRTP_HMAC_SHA1, /* authentication func type */ + 16, /* auth key length in octets */ + 10, /* auth tag length in octets */ + sec_serv_conf_and_auth /* security services flag */ }, test_key, NULL, 0, NULL, - 128, /* replay window size */ - 0, /* retransmission not allowed */ - NULL, /* no encrypted extension headers */ - 0, /* list of encrypted extension headers is empty */ + 128, /* replay window size */ + 0, /* retransmission not allowed */ + NULL, /* no encrypted extension headers */ + 0, /* list of encrypted extension headers is empty */ NULL }; diff --git a/libs/srtp/test/test_srtp.c b/libs/srtp/test/test_srtp.c index 22565573dc..cdc9b5d5b7 100644 --- a/libs/srtp/test/test_srtp.c +++ b/libs/srtp/test/test_srtp.c @@ -72,13 +72,13 @@ void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number(void); * 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 */}; +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. @@ -146,9 +146,9 @@ void srtp_calc_aead_iv_srtcp_seq_num_over_0x7FFFFFFF_bad_param() */ 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. - #define SAMPLE_COUNT (3) srtp_session_keys_t session_keys; srtcp_hdr_t header; v128_t output_iv[SAMPLE_COUNT]; @@ -173,13 +173,13 @@ void srtp_calc_aead_iv_srtcp_distinct_iv_per_sequence_number() size_t i = 0; 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); + 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 +#undef SAMPLE_COUNT } diff --git a/libs/srtp/test/util.c b/libs/srtp/test/util.c index 752a6a4c7a..eb203f4c4a 100644 --- a/libs/srtp/test/util.c +++ b/libs/srtp/test/util.c @@ -49,38 +49,61 @@ char bit_string[MAX_PRINT_STRING_LEN]; -static inline int hex_char_to_nibble (uint8_t c) +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 */ + 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) +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' }; @@ -92,7 +115,7 @@ uint8_t nibble_to_hex_char (uint8_t nibble) * 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) +int hex_string_to_octet_string(char *raw, char *hex, int len) { uint8_t x; int tmp; @@ -118,9 +141,9 @@ int hex_string_to_octet_string (char *raw, char *hex, int len) return hex_len; } -char * octet_string_hex_string (const void *s, int length) +char *octet_string_hex_string(const void *s, int length) { - const uint8_t *str = (const uint8_t*)s; + const uint8_t *str = (const uint8_t *)s; int i; /* double length, since one octet takes two hex characters */ @@ -132,7 +155,7 @@ char * octet_string_hex_string (const void *s, int length) } for (i = 0; i < length; i += 2) { - bit_string[i] = nibble_to_hex_char(*str >> 4); + 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 */ @@ -142,9 +165,9 @@ char * octet_string_hex_string (const void *s, int length) static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz0123456789+/"; -static int base64_block_to_octet_triple (char *out, char *in) +static int base64_block_to_octet_triple(char *out, char *in) { - unsigned char sextets[4] = {0}; + unsigned char sextets[4] = { 0 }; int j = 0; int i; @@ -152,7 +175,9 @@ static int base64_block_to_octet_triple (char *out, char *in) char *p = strchr(b64chars, in[i]); if (p != NULL) { sextets[i] = p - b64chars; - } else{ j++; } + } else { + j++; + } } out[0] = (sextets[0] << 2) | (sextets[1] >> 4); @@ -165,7 +190,7 @@ static int base64_block_to_octet_triple (char *out, char *in) return j; } -int base64_string_to_octet_string (char *out, int *pad, char *in, int len) +int base64_string_to_octet_string(char *out, int *pad, char *in, int len) { int k = 0; int i = 0; diff --git a/libs/srtp/test/util.h b/libs/srtp/test/util.h index db58c24661..d04b279b3a 100644 --- a/libs/srtp/test/util.h +++ b/libs/srtp/test/util.h @@ -47,7 +47,7 @@ #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); +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 diff --git a/w32/Library/FreeSwitchCore.2017.vcxproj b/w32/Library/FreeSwitchCore.2017.vcxproj index 6bd0c5d7af..ad130400aa 100644 --- a/w32/Library/FreeSwitchCore.2017.vcxproj +++ b/w32/Library/FreeSwitchCore.2017.vcxproj @@ -112,6 +112,7 @@ <ItemDefinitionGroup> <ClCompile> <AdditionalIncludeDirectories>..\..\libs\apr\include\arch\win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>HAVE_WINSOCK2_H;%(PreprocessorDefinitions)</PreprocessorDefinitions> </ClCompile> <PostBuildEvent> <Command>if not exist "$(OutDir)conf" xcopy "$(SolutionDir)conf\vanilla\*.*" "$(OutDir)conf\" /C /D /Y /S diff --git a/w32/openssl.props b/w32/openssl.props index 0d927cce7a..1e2040b7d6 100644 --- a/w32/openssl.props +++ b/w32/openssl.props @@ -68,7 +68,7 @@ <AdditionalIncludeDirectories>$(OpenSSLLibDir)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories Condition="'$(Platform)'=='Win32'">$(OpenSSLLibDir)\include_x86;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories Condition="'$(Platform)'=='x64'">$(OpenSSLLibDir)\include_x64;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>HAVE_OPENSSL;HAVE_OPENSSL_DTLS_SRTP;HAVE_OPENSSL_DTLS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>OPENSSL;HAVE_OPENSSL;HAVE_OPENSSL_DTLS_SRTP;HAVE_OPENSSL_DTLS;%(PreprocessorDefinitions)</PreprocessorDefinitions> </ClCompile> <Link> <AdditionalLibraryDirectories>$(OpenSSLLibDir)\binaries\$(Platform)\$(LibraryConfiguration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>